Co je to I2C?

Sběrnice I2C používá pro komunikaci pouze dva signálové vodiče SDA a SCL (někdy také označován jako SCK). Tomu napovídá i alternativní zkratka TWI (používá ji zejména Atmel pro platformy AVR), což je zkratka pro anglický název Two Wire (serial) Interface. Sběrnice používá topologii master/slave.

Po vodiči SCL (serial clock) se posílá všem slave zařízením hodinový signál, čili v případě I2C se jedná o synchroní komunikaci. Druhý vodič SDA (serial data) slouží k přenosu dat (oběma směry).

Předchozí řádky napovídají, že základem veškeré komunikace je zařízení, které má statut master. Master je na sběrnici v daném čase jenom jeden. Proč? V oblasti průmyslových sběrnic totiž existují dva velmi důležité pojmy – determinismus a kolize.

  • Determinismus znamená, že je zaručena doba odezvy (libovolného) zařízení na sběrnici.
  • Kolize je případ, kdy dvě zařízení začnou současně vysílat data a tím ruší celou komunikaci na sběrnici.  V případě, že k nějaké kolizi dojde, je nutné informaci či příkaz odeslat znovu, což už ovšem není deterministické. Opakované odeslání nás totiž stojí nějaký (neurčitý) čas. Při topologii master-slave je zaručeno, že ke kolizi nedojde, jelikož zařízení master určuje, jaké zařízení bude v daný moment vysílat data.

Zařízení typu slave může být naopak hned několik. Ptáte se, jak slave pozná, kdy má poslouchat příkazy od mastera? Stejně jako lidé mají jména, kterými je můžeme oslovit,  I2C zařízení mají  (7bitové) adresování. Pokud máme nějaký požadavek na člověka, zahajíme komunikaci např. "Hynku! Viléme!! Jarmilo!!!". Pokud máme nějaký požadavek na I2C zařízení,  zahajíme komunikaci např. "0x0A! 0x27!! 0x35!!!". Tedy jinak, každý slave má přiřazenou jistou adresu. Jakmile slave zachytí vysílání od mastera zahrnující jeho adresu, začne data přijímat, zpracovávat a na tomto základě vykonávat různé operace.

Adresa I2C zařízení musí být unikátní. Pokud bychom měli na sběrnici dvě Jarmily (dvě zařízení se stejnou adresou), tak by master nevěděl, která Jarmila odpovídá a Jarmily by zase nevěděly, která z nich má odpovědět. Mimochodem, víte kolik zařízení slave můžeme připojit k jedné sběrnici? Jelikož, jak již bylo řečeno, je adresování 7bitové, adres může být maximálně 27, tedy 128. První adresa je 0 (nula) a poslední adresa má hodnotu 127. V některých případech je možné použít i 10bitové kódování, nicméně tato problematika by přesahovala rozměr tohoto článku.

Jak připojit slave zařízení a jak určit mastera?

Tento odstavec bude poměrně krátký. Jak možná víte, Arduino Uno, Nano, Raspberry Pi a další vývojové kity (resp. mikroprocesory) disponují hardwarovou I2C sběrnicí. V případě Una a Nana sběrnici najdete na pinech A4 (SDA) a A5 (SCL). K těmto pinům můžete přímo připojit některé ze zařízení podporující I2C (např. OLED displej 1527497643). V tomto případě bude mít Arduino úlohu master a displej úlohu slave.

Jelikož jste si jistě přečetli předchozí odstavce, musela Vám v hlavě proběhnout otázka, kam případně zapojíme těch zbylých 127 zařízení? Slave zařízení můžeme připojit paralelně – jedno vedle druhého.  

V zapojení na Obrázku 1 se ještě nacházejí dva pull-up rezistory. Ty jsou v zapojení pro správnou funkci sběrnice nezbytné. Vysvětlit proč by však bylo na dalších pár odstavců. V tomto textu se tedy spokojme s informací, že odpor těchto rezistorů je většinou v rozsahu 1,2 až 4,7 kΩ.

Obrázek 1: Znázornění I2C topologie 

I2C topologie

Jak zjistím I2C adresu zařízení, které jsem ve vašem obchodu koupil?

Drtivá většina zařízení má již z výroby přiřazenou nějakou adresu (z rozsahu 0–127). Pro komunikaci s takovým zařízením je tedy nutné tuto adresu zjistit. K tomu nám bude stačit pouze Arduino, napájecí a datové vodiče. Po připojení zařízení na piny SCL a SDA stačí do Arduina nahrát kód uvedený níže, který je volně k dispozici na serveru github.com (autor: Tod E. Kurt). Není nutné stahovat externí knihovny, jelikož tento program pracuje s interní knihovnou Arduina wire.h. Po nahrání programu do vývojové platformy stačí spustit sériový terminál, kde uvidíte výstup programu, který prohledá všech 128 adres. Pokud je na některé adrese detekováno zařízení, bude u příslušného čísla přítomna hláška "found". V případě, že budete hledat adresy u několika slave zařízení, doporučuji připojovat je jednotlivě, jinak po skenování adres nepoznáte, které zařízení je které. Nic Vám ovšem nebrání upravit si program k obrazu svému :). 

#include "Wire.h"
extern "C" { 
#include "utility/twi.h"  
}

void scanI2CBus(byte from_addr, byte to_addr, void(*callback)(byte address, byte result) ) 
{
  byte rc;
  byte data = 0;
  for( byte addr = from_addr; addr <= to_addr; addr++ ) {
    rc = twi_writeTo(addr, &data, 0, 1, 0);
    callback( addr, rc );
  }
}

void scanFunc( byte addr, byte result ) {
  Serial.print("addr: ");
  Serial.print(addr,DEC);
  Serial.print( (result==0) ? " found!":"       ");
  Serial.print( (addr%4) ? "\t":"\n");
}

byte start_address = 8;       
byte end_address = 119;       

void setup()
{
    Wire.begin();
    Serial.begin(9600);                
    Serial.println("\nI2CScanner ready!");

    Serial.print("starting scanning of I2C bus from ");
    Serial.print(start_address,DEC);
    Serial.print(" to ");
    Serial.print(end_address,DEC);
    Serial.println("...");

    scanI2CBus( start_address, end_address, scanFunc );

    Serial.println("\ndone");
    pinMode(13, OUTPUT);
}

void loop() 
{
    digitalWrite(13,HIGH);
    delay(300);
    digitalWrite(13,LOW);
    delay(300);
}

Pro více informací o sběrnici doporučuji navštívit webové stránky www.i2c-bus.org.

FB gp tw

Další podobné články