https://navody.dratek.cz/

Tady jsem si dovolil doslova zkopírovat základní informace o rozhraní I2C z webu dratek.cz. (Ať to nemusím pořád hledat.)

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 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 :). 

// Arduino I2C skener
// navody.dratek.cz

// připojení potřebné knihovny
#include <Wire.h>
// nastavení čísel propojovacích pinů
#define I2C_SDA 21
#define I2C_SCL 22

void setup() {
// zahájení komunikace po I2C sběrnici,
// lze použít buď výchozí piny s variantou ()
// nebo specifikovat piny např. u ESP desek (SDA, SCL)
Wire.begin();
//Wire.begin(I2C_SDA, I2C_SCL);

// zahájení komunikace po sériové lince
Serial.begin(9600);
Serial.println("Start I2C skeneru...");
}

void loop() {
// vytvoření pomocných proměnných
byte chyba, adresa;
int pocetZarizeni = 0;
Serial.println("Zacatek hledani...");
// smyčka pro hledání zařízení
// I2C zařízení mohou mít adresu 1-126
for (adresa = 1; adresa < 127; adresa++ ) {
// zahájení komunikace a jeho následné ukončení,
// při ukončení probíhá detekce zařízení pomocí
// kontroly návratové hodnoty
Wire.beginTransmission(adresa);
chyba = Wire.endTransmission();
// pokud nám zařízení odpoví '0',
// tak funguje správně
if (chyba == 0) {
// vytištění informací o zařízení včetně
// jeho adresy v hexa formátu
Serial.print("I2C zarizeni nalezeno na adrese 0x");
Serial.print(adresa, HEX);
Serial.println(" !");
// inkrementace počítadla zařízení
pocetZarizeni++;
}
// při chybě v komunikaci je chybný výstup 4
else if (chyba == 4) {
// vytištění informací o zařízení včetně
// jeho adresy v hexa formátu
Serial.print("Neznama chyba na adrese 0x");
Serial.println(adresa, HEX);
}
}
// kontrola počítadla zařízení
if (pocetZarizeni == 0) {
// nebylo nalezeno žádné zařízení, protože neproběhla inkrementace
Serial.println("Zadne I2C zarizeni nebylo nalezeno.");
}
else {
// oznámení o konci hledání
Serial.print("Konec hledani, nalezeno ");
Serial.print(pocetZarizeni);
Serial.println(" zarizeni.");
}
// pauza před novým během smyčky
delay(5000);
}