Protocollo I2C ed uso dell’integrato MCP8903

Il mondo dell’elettronica, come sapiamo, è composto da migliaia di componenti che svolgono funzioni dedicate, come un sensore di temperatura, oppure sono capaci di gestire diverse operazioni come nel caso dei microcontrollori.
La tecnologia analogica ha pian piano lasciato il posto a quella digitale e i componenti hanno iniziato a colloquiare tra loro utilizzando vari protocolli di comunicazione (insieme di regole che determinano il funzionamento della comunicazione).
Oggi, la maggior parte dei circuiti utilizza un microcontrollore, il cui compito è quello di gestire il circuito ed i componenti ad esso collegato.
Nel caso di sistemi complessi i componenti che creano il circuito sono diversi e possono saturare la capacità fisica di collegamento del microcontrollore, come nel caso proposto in figura.

Ben presto si è capito che per snellire questo tipo di circuiti era necessario creare un meccanismo capace di ottimizzare l’interconnessione tra componenti e microcontrollore. Il sistema più efficace è certamente quello di adottare un bus di collegamento, che permette lo scambio di dati, tra componenti e microcontrollore, utilizzando pochi fili comuni.
La figura seguente mostra un esempio di bus dove diversi componenti sono interconnessi utilizzando solo 2 fili. Il microcontrollore in questo caso deve gestire la comunicazione utilizzando un protocollo comune a tutti i componenti.
Diverse aziende svilupparono dei protocolli che col tempo sono divenuti degli standard, in questo modo componenti e microcontrollori hanno iniziato a scambiarsi dati in modo semplice ed efficiente.

La Philips negli anni ’80 sviluppò il Bus I2C (Inter Integrated Circuit pronunciato i-quadro-ci o i-due-ci), un protocollo seriale che usa due fili per instaurare la comunicazione con i componenti.

Tipicamente questo protocollo richiede un master (il microcontrollore che gestisce la comunicazione), e uno o più componenti slave (sensori, ADC, DAC, memorie ecc… che inviano i dati al microcontrollore).
Gli slave vengono identificati nel bus tramite un indirizzo univoco. Il master invia sulla linea l’indirizzo dello slave con cui vuole instaurare la comunicazione.
E’ possibile un sistema con più master (multimaster) ma la comunicazione deve sempre essere gestita da un master alla volta.

Il bus I2C permette di collegare agli stessi due fili ben 112 dispositivi. La velocità di comunicazione non è elevatissima e puoi variare, tipicamente, da un minimo di 10Kbits/s fino a 400Kbits/s (sviluppi successivi del bus I2c hanno permesso velocità fino a 3.4Mbits/S e interconnessioni di 1024 componenti).

I segnali presenti sui fili sono chiamati SDA (Signal DAta) per il trasferimento dei dati e SCL (Serial Clock Line) per la sincronizzazione della linea. In figura è rappresentato il diagramma dei segnali:

Il master deve eseguire, per avviare la comunicazione, una commutazione della linea SDA dallo stato alto allo stato basso, quando il segnale SCL è alto (vedi riquadro Start).
Successivamente il master può inviare dati sulla linea SDA.
Quando il segnale SCL è basso il master inizia a scrivere il valore del bit (1 o 0); quando il segnale SCL è alto, il bit è stabile e può essere letto dallo slave (riquadro BIT1).Questo procedimento si ripete per tutti i bit (Riquadro BIT2 e BIT N).
Quando tutti i bit sono stati inviati, la comunicazione termina quando il master riporta la linea SDA a livello alto in concomitanza del livello alto della linea SCL (riquadro Stop).

Questo esempio spiega il comportamento tipico dei segnali sul bus.

La comunicazione tra master e slave è risulta nella pratica più complessa di quanto espresso precedentemente. Per capire meglio è utile analizzare un esempio reale, perciò ho realizzato un semplice circuito che impiega un Pic 16F876 e un sensore di temperatura digitale MCP9803 che colloquiano utilizzando il bus I2C.

Lo schema elettrico è il seguente:

Il circuito utilizza un microcontrollore per comunicare con il sensore di temperatura MCP9803. I dati acquisiti vengono acquisiti e inviati tramite la porta UART del pic al pc. Il Max233 converte i segnali TTL in segnali RS232.

Partiamo con lo studio del datasheet del sensore MCP9803. Le caratteristiche principali sono riassunte nella tanella seguente:

Intervallo di alimentazioneda 2.7Vdc a 5.5Vdc
Selezione risoluzione acquisizioneda 9 bit a 12 bit
Interfaccia di comunicazionebus I2C
Frequenza bus I2Cda 10Khz a 400Khz
Intervallo temperaturada -55°C a +125°C
Precisione+-1°C da  da-10°C a +85°C

Il pin 1 (SDA) del sensore è collegato direttamente al pin 15 del pic (SDA), mentre il pin 2 (SCLK) del sensore è collegato al pin 14 del pic (SCL).

I pin 5, 6, 7 del sensore (A0, A1, A2) permettono di definire l’indirizzo del dispositivo all’interno del bus. Sul datasheet possiamo leggere come viene impostato:

Per comporre l’indirizzo sono necessari 7 bit. Nei modelli 9800/xxxx gli indirizzi sono predefiniti, mentre nell’MCP9803 i bit A3, A4, A5, A6 sono scelti dalla casa costruttrice e i bit A0, A1, A2 sono impostabili dall’utente.

Nel circuito in questione, i pin A0, A1, A2 sono collegati a massa, quindi a valore logico 0, di conseguenza l’indirizzo del nostro sensore è 1001000 (0x48 in esadecimale).

Bene ora l’MCP9803 può essere identificato dal pic usando l’indirizzo a 7 bit.

Scorrendo il datasheet, andiamo nella sezione register:

Il sensore ha un registro che permette di accedere ai vari registri interni, come ad esempio il Configuration Register dove possiamo cambiare la risoluzione del convertitore digitale. Vedremmo poi come cambiare la risoluzione da 9bit (valore di default) a 12bit.
Quello che ci serve ora è leggere il dato del ‘Temperature Register’. Per selezionarlo è sufficiente porre il bit0(P0) e il bit1(P1) a 0 (Questo registro è a 0 per default ma eseguiamo comunque l’operazione ai fini didattici).

Ora studiamo la sezione dove è illustrata la sequenza di comunicazione tra il master ed il sensore MCP9803.

Si inizia con il comando di start (SDA va basso quando SCLK è alto – vedi box rosso ‘S’) poi il master scrive i 7 bit dell’indirizzo dello slave (1001000) più un bit che definisce se vogliamo leggere o scrivere nei registri dello slave (Se questo bit è a 1 leggeremo i dati dallo slave se è a 0 scriveremo i dati nello slave).
Questa informazione del bit che definisce la lettura o la scrittura è presente in questa sezione del datasheet.

Il master invia il seguente valore binario 10010000 (0x90 in esadecimale) per scrivere sullo slave.
Dopo l’invio del byte sul bus I2C, lo slave risponde con un acknowledges (pone la linea SDA bassa quando il SCLK è alto).
Ora il master invia un secondo byte per scrivere sul register point il valore necessario a selezionare il registro Temperature Regiser (Bito e Bit1 a 0). Il sensore risponde con un altro acknowledges.

Adesso che abbiamo impostato il sensore, per leggere dal registro contenente il dato della temperatura, possiamo avviare l’operazione di lettura.
Controlliamo ancora il datasheet  e appuriamo che il dato della temperatura è espresso con due byte.

L’operazione per leggere due byte consecutivi dal registro selezionato è rappresentata in figura:

Inviamo un comando si Start, poi l’indirizzo dello slave (0x48) ed il bit di selezione lettura/Scrittura impostato a 1(lettura). Il valore binario risultante è 10010001 (0x91 in esadecimale).

Il sensore risponde con un acknowledges. Il master esegue la lettura del primo byte, invia un acknowledges, legge il secondo byte ed invia un not acknowledges (indica allo slave la fine della lettura).
Il master termina la comunicazione inviando un comando di stop (riquadro P).

Il codice che permette al pic di eseguire tutte queste operazioni è stato scritto utilizzando MikroC Pro della Mikroelektronika. Il linguaggio, basato sulla sintassi del C, risulta molto semplice e facile da scrivere.
Inoltre sono disponibili molte librerie che svolgono molte operazioni tra le quali quella relativa all’uso del bus I2C.

Il codice caricato sul pic16F876 è il seguente:

 

Il pic acquisisce il segnale ed invia i dati grezzi al pc che dovrà interpretarli ed elaborarli secondo la formula presente nel datasheet:

dove Code è il dato grezzo letto dal sensore, mentre n dipende dal valore di risoluzione del convertitore (-1 per 9bit di risoluzione, -2 per 10bit di risoluzione, -3 per 11bit di risoluzione e -4 per 12bit di risoluzione).

Il datasheet mostra una tabella di esempio che possiamo usare per capire come avviene questo calcolo:

L’esempio con 9bit di risoluzione e una temperatura ambiente di 125°C produce un valore binario formato da 9bit, suddivisi in due byte, il primo con valore binario di 01111101 e il secondo con valore binario 00000000 (vedi riquadri 1° Byte e 2° Byte). Questi due byte devono essere uniti per formare un valore intero.
Il primo byte è quello più significativo mentre il secondo è quello meno significativo, quindi uniamo il bit del secondo byte al primo:

01111101 + 0 = 011111010 => 0xFA (esadeciale) => 250 (Decimale)

Ora applichiamo la formula per calcolare la temperatura

250 * 2^-1 = 250 * 0.5 = 125°C

Nella seconda parte illustrerò come acquisire i dati inviati dal pic con la seriale e come cambiare la risoluzione di campionamento da 9bit a 12bit.

Come sempre aspetto i vostri suggerimenti.