Arduino - wewnętrzny układ scalony
Układ scalony (I2C) to układ do szeregowej wymiany danych pomiędzy mikrokontrolerami a wyspecjalizowanymi układami scalonymi nowej generacji. Jest używany, gdy odległość między nimi jest mała (odbiornik i nadajnik znajdują się zwykle na tej samej płytce drukowanej). Podłączenie odbywa się za pomocą dwóch przewodów. Jeden służy do przesyłania danych, a drugi do synchronizacji (sygnał zegarowy).
Jak widać na poniższym rysunku, jedno urządzenie jest zawsze urządzeniem głównym. Wykonuje adresowanie jednego chipa slave przed rozpoczęciem komunikacji. W ten sposób jeden mikrokontroler może komunikować się z 112 różnymi urządzeniami. Szybkość transmisji wynosi zwykle 100 Kb / s (tryb standardowy) lub 10 Kb / s (tryb małej szybkości transmisji). Niedawno pojawiły się systemy o szybkości transmisji 3,4 Mb / s. Odległość między urządzeniami, które komunikują się po magistrali I2C jest ograniczona do kilku metrów.
Piny płyty I2C
Magistrala I2C składa się z dwóch sygnałów - SCL i SDA. SCL to sygnał zegarowy, a SDA to sygnał danych. Aktualny Bus Master zawsze generuje sygnał zegarowy. Niektóre urządzenia podrzędne mogą czasami wymuszać niski zegar, aby opóźnić wysyłanie większej liczby danych przez urządzenie główne (lub wymagać więcej czasu na przygotowanie danych, zanim urządzenie nadrzędne spróbuje je wyrejestrować). Nazywa się to „rozciąganiem zegara”.
Poniżej znajdują się piny dla różnych płyt Arduino -
- Uno, Pro Mini A4 (SDA), A5 (SCL)
- Mega, Due 20 (SDA), 21 (SCL)
- Leonardo, Yun 2 (SDA), 3 (SCL)
Arduino I2C
Mamy dwa tryby - kod główny i kod podrzędny - do połączenia dwóch płytek Arduino za pomocą I2C. Oni są -
- Nadajnik główny / odbiornik podrzędny
- Odbiornik główny / nadajnik podrzędny
Nadajnik główny / odbiornik podrzędny
Zobaczmy teraz, co jest nadajnikiem głównym i odbiornikiem podrzędnym.
Nadajnik główny
Następujące funkcje służą do inicjalizacji biblioteki Wire i dołączania do magistrali I2C jako master lub slave. Zwykle jest to wywoływane tylko raz.
Wire.begin(address) - Adres to 7-bitowy adres slave w naszym przypadku, ponieważ master nie jest określony i dołączy do magistrali jako master.
Wire.beginTransmission(address) - Rozpocznij transmisję do urządzenia slave I2C z podanym adresem.
Wire.write(value) - Kolejkuje bajty do transmisji z urządzenia głównego do urządzenia podrzędnego (pomiędzy wywołaniami funkcji beginTransmission () i endTransmission ()).
Wire.endTransmission() - Kończy transmisję do urządzenia podrzędnego, która została rozpoczęta przez beginTransmission () i przesyła bajty, które były ustawione w kolejce przez wire.write ().
Example
#include <Wire.h> //include wire library
void setup() //this will run only once {
Wire.begin(); // join i2c bus as master
}
short age = 0;
void loop() {
Wire.beginTransmission(2);
// transmit to device #2
Wire.write("age is = ");
Wire.write(age); // sends one byte
Wire.endTransmission(); // stop transmitting
delay(1000);
}
Slave Receiver
Używane są następujące funkcje -
Wire.begin(address) - Adres to 7-bitowy adres slave.
Wire.onReceive(received data handler) - Funkcja wywoływana, gdy urządzenie slave otrzymuje dane od mastera.
Wire.available() - Zwraca liczbę bajtów dostępnych do pobrania za pomocą Wire.read (). Powinno to zostać wywołane wewnątrz procedury obsługi Wire.onReceive ().
Example
#include <Wire.h> //include wire library
void setup() { //this will run only once
Wire.begin(2); // join i2c bus with address #2
Wire.onReceive(receiveEvent); // call receiveEvent when the master send any thing
Serial.begin(9600); // start serial for output to print what we receive
}
void loop() {
delay(250);
}
//-----this function will execute whenever data is received from master-----//
void receiveEvent(int howMany) {
while (Wire.available()>1) // loop through all but the last {
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
}
Odbiornik główny / nadajnik podrzędny
Zobaczmy teraz, co jest głównym odbiornikiem i nadajnikiem podrzędnym.
Główny odbiornik
Master jest zaprogramowany, aby żądać, a następnie odczytywać bajty danych, które są wysyłane z unikalnie adresowanego Slave Arduino.
Używana jest następująca funkcja -
Wire.requestFrom(address,number of bytes)- Używany przez mastera do żądania bajtów z urządzenia slave. Bajty można następnie pobrać za pomocą funkcji wire.available () i wire.read ().
Example
#include <Wire.h> //include wire library void setup() {
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}
void loop() {
Wire.requestFrom(2, 1); // request 1 bytes from slave device #2
while (Wire.available()) // slave may send less than requested {
char c = Wire.read(); // receive a byte as character
Serial.print(c); // print the character
}
delay(500);
}
Nadajnik Slave
Używana jest następująca funkcja.
Wire.onRequest(handler) - Funkcja jest wywoływana, gdy master żąda danych z tego urządzenia slave.
Example
#include <Wire.h>
void setup() {
Wire.begin(2); // join i2c bus with address #2
Wire.onRequest(requestEvent); // register event
}
Byte x = 0;
void loop() {
delay(100);
}
// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
Wire.write(x); // respond with message of 1 bytes as expected by master
x++;
}