I2C (o IIC) è l’acronimo di Inter-IC Communication ed è uno dei più diffusi protocolli di comunicazione per microcontrollori. L’I2C è tipicamente utilizzato per comunicare con i sensori, ma trova impiego anche in molte altre applicazioni.
L’I2C è un protocollo sincrono, il che significa che dispone di una linea di clock.
Comunicazione I2C
Sebbene I2C utilizzi solo due linee di comunicazione (clock e dati), è in grado di ospitare più dispositivi sullo stesso bus I2C; ciò si ottiene utilizzando uno schema di indirizzamento in cui ogni dispositivo sul bus ha un indirizzo univoco. La comunicazione inizia con l’invio dell’indirizzo del dispositivo a cui si intende comunicare; il dispositivo indirizzato deve quindi confermare di essere presente e pronto a comunicare.
Poiché esiste una sola linea dati (SDA – Serial Data), utilizzata sia per inviare che per ricevere dati (half-duplex), è necessario uno schema che consenta al dispositivo master e a quello slave della comunicazione di controllare la linea dati senza scontri. È necessario evitare le contese sul bus, in cui un dispositivo cerca di scrivere un alto sul bus e un altro cerca di scrivere un basso sul bus, creando un cortocircuito.
Per ottenere questo risultato, si utilizza uno schema open-drain, in cui uno dei due dispositivi può solo pilotare il bus ‘basso’ (low) o altrimenti ‘rilasciarlo’ (release), e si utilizzano resistenze di pull-up per portare la linea in alto quando viene rilasciata. Anche la linea di clock (SCL – Serial Clock) si avvale di questo schema e vengono utilizzate alcune tecniche innovative per aggiungere alcune utili funzionalità al protocollo I2C, ne parleremo fra poco.
Il diagramma seguente illustra le caratteristiche tipiche di una sequenza di comunicazione I2C:
La comunicazione inizia con il bus I2C al minimo, con entrambe le linee di clock e dati non alimentate e quindi tirate in alto dalle resistenze di pull-up. La comunicazione viene quindi avviata dal master (il dispositivo che inizia la comunicazione) tirando prima la linea SDA e poi la linea SCL verso il basso, questa è definita come condizione di avvio.
Quindi il master trasmette l’indirizzo a 7 bit del dispositivo con cui desidera comunicare, seguito da un bit di “lettura o scrittura” (read or write) che indica se il master desidera scrivere (0) (write) o leggere (1) (read) sul dispositivo. La linea di dati è considerata valida (letta dagli slave) sui bordi ascendenti della linea di clock e il primo dato trasmesso è il Most Significant Bit (MSB – bit più significativo).
Dopo la trasmissione dell’indirizzo, e supponendo che lo slave indirizzato sia presente sul bus I2C, il master rilascia la linea dati (open drain) e lo slave tiene bassa la linea dati per un ciclo di clock per confermare (ack) che è presente e pronto a comunicare. Se lo slave non è presente sul bus, la resistenza di pull-up porterà la linea dati in alto e il master saprà che lo slave non è disponibile.
In questa fase, i dati possono essere trasmessi tra il master e lo slave. Se i dati sono in lettura, lo slave li trasmette (mentre il master continua a pilotare la linea di clock); se i dati sono in scrittura, il master li trasmette. Dopo ogni byte di dati è presente un singolo bit di Ack, durante il quale il ricevitore (che può essere il master o lo slave, a seconda di quale lato ha trasmesso i dati) deve tenere bassa la linea dei dati per indicare che ha ricevuto la comunicazione (ed è pronto a procedere con la comunicazione successiva, se applicabile).
Clock Stretching
I dispositivi slave sul bus I2C hanno la possibilità di ritardare le loro risposte (se sono ancora occupati e non sono ancora pronti a rispondere) tenendo bassa la linea di clock (SCL), una caratteristica nota come “clock stretching”; una volta pronto a rispondere, lo slave rilascia la linea di clock e la trasmissione dei dati continua. Si tratta di una funzione simile a quella delle linee di controllo del flusso nell’UART (CTS/RTS), ma senza richiedere linee di comunicazione aggiuntive (si noti che il protocollo SPI non prevede alcuna funzione di controllo del flusso).
È possibile comunicare uno o più byte di dati in sequenza, con un ack dopo ogni byte.
Avvio ripetuto
Poiché i dispositivi slave possono avere una moltitudine di valori disponibili per la lettura (come i valori di lettura di più sensori e i valori delle impostazioni), lo slave può richiedere che il master scriva prima un’istruzione che indichi ciò che desidera leggere prima di procedere con la lettura effettiva. In questo caso, il master emetterà prima una scrittura con i dati che costituiscono l’istruzione che indica cosa deve essere letto, e subito dopo emetterà una lettura. Nel mezzo, tuttavia, non viene emesso alcuno stop, ma il master utilizza una condizione di avvio ripetuto (seguita dall’indirizzo a 7 bit e dal bit di lettura/scrittura a 1 bit, ovviamente ora impostato su lettura) per passare dalla scrittura alla lettura. Per emettere un avvio ripetuto, il master prende prima la linea dati alta, poi la linea di clock, quindi prende la linea dati bassa seguita dalla linea di clock.
Velocità e distanze dei dati
La comunicazione sul bus I2C avviene solitamente a 100 kHz o 400 kHz. Queste velocità relativamente basse vanno bene per la trasmissione di piccole quantità di dati, ma l’SPI (che utilizza clock nell’ordine dei MHz e possibilmente in modalità doppia o quadrupla) è solitamente preferito per le applicazioni ad alta velocità in cui è necessario trasmettere grandi volumi di dati. L’I2C viene solitamente utilizzato solo per comunicazioni a distanza relativamente breve, tuttavia esistono schemi che consentono di trasmettere l’I2C su coppie differenziali per comunicare su distanze maggiori.
Proteus, distribuito da Galgo Electronics, include uno strumento di analisi del protocollo I2C a doppia modalità (master o slave) che viene posizionato e collegato allo schema. In questo modo è possibile digitare e iniettare sequenze I2C nella simulazione in corso e visualizzare i pacchetti ricevuti da altri dispositivi sul bus I2C. Si tratta di un eccellente strumento didattico che consente di testare in modo rapido e semplice il firmware sia in modalità master che in modalità slave. Molti progetti di esempio includono comunicazioni I2C con sensori o progetti multiprocessore. Tutti questi progetti possono essere simulati nella versione demo di Proteus: scarica subito la versione demo qui.