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++; 
}