In questa pagina verranno presentati alcuni brevi programmi scritti in C per utilizzare periferiche I2C con Raspberry Pi tramite le funzioni standard Linux.
Il bus I2C di Raspberry Pi è già stato discusso; se ancora non lo avete fatto, leggete la pagina introduttiva su Raspberry e I2C prima di proseguire in quanto non verrà qui ripreso nulla su come configurare il modulo i2c-dev e come assegnare i permessi agli utenti. I pin utilizzati dal bus I2C sono disponibili sul connettore GPIO.
Il circuito utilizzato per le prove è costituito da due dispositivi, tra di loro assolutamente indipendenti e scelti solo perché "erano nel cassetto":
Ovviamente siete liberi di usare altri circuiti integrati, purché con interfaccia I2C a 3.3 V.
Il circuito è semplicemente costituito dai due integrati con le linee SDA e SCL collegate direttamente al connettore GPIO del Raspberry Pi. Le due resistenze di pull-up, obbligatorie, sono già presenti sul circuito stampato del Raspberry Pi.
Per una prima verifica del funzionamento potete utilizzare il comando i2cdetect, già descritto in questa pagina.
Il programma legge direttamente da LM92 la temperatura rilevata, utilizzando la modalità indicata sui fogli tecnici come 2-Byte Read From Preset Pointer Location (Figura 10), cioè utilizzando una singola operazione di lettura.
vv@vvrpi ~ $ ./LM92
[...]
Reading from LM92 at address 0x4B on /dev/i2c-1
Data read from Power-up default register: 0x0EB8
Temperature: 29.4 °C
(ebbene sì: il laboratorio non ha l'aria condizionata...)
A fondo pagina il codice sorgente. Le operazioni effettuate sono, in estrema sintesi, le seguenti:
Occorre osservare che il protocollo I2C prevede il riscontro di ogni singolo byte trasmesso o ricevuto. Questo permette di identificare errori nella comunicazione quali indirizzo errato oppure periferica spenta, assente o guasta. In questo casi il programma stampa un codice di errore come il seguente:
Failed to read from the i2c bus: Input/output error
Occorre notare che questo programma funziona correttamente solo se non
sono state modificate le configurazioni di LM92 dopo l'accensione.
Il programma, dopo aver configurato il circuito integrato MCP23017, manda in uscita alla porta B gli otto bit letti dalla linea di comando e legge otto bit dalla porta A, visualizzandoli. Rispetto al precedente esempio di aggiunge un livello di difficoltà in più che deriva dalla necessità di dover scrivere dati verso la periferica.
vv@vvrpi ~ $ ./MCP23017 10
[...]
Write 0xA to PortB
Data read from PortA: 0xBB
A fondo pagina il codice sorgente. Descriviamo brevemente il programma
In alternativa alle funzioni read() e write() è possibile l'utilizzo di un altro gruppo di funzioni, specifiche per il bus I2C. Questa seconda strada è quella consigliata nella documentazione del kernel. E' utile anche consultare il file /usr/include/linux/i2c-dev.h.
Le funzioni disponibili permettono di leggere e scrivere byte, word o blocchi da dati:
__s32 i2c_smbus_write_quick(int file, __u8 value);L'uso di queste funzioni è piuttosto intuitivo. L'unica avvertenza riguarda il valore ritornato:
A fondo pagina i codici di esempio, simili nella funzionalità a quelli già presentati.
In parallelo alle funzioni i2c_smbus_*() sono presenti anche le corrispondenti chiamate ioctl. Tra queste è bene citare:
Di seguito è riportato il diagramma temporale misurato durante l'esecuzione del programma dimostrativo che utilizza MCP23017.
Scorrendo il diagramma temporale in parallelo al codice è possibile riconoscere, partendo da sinistra le seguenti operazioni:
La durata complessiva è in linea con le attese: sono infatti trasmessi 4 * 3 + 2 * 2 = 16 byte = 128 bit alla frequenza di 100 kHz (quindi 1,28 ms) a cui vanno aggiunte le condizioni di start e stop tipiche del protocollo I2C, il tempo necessario per l'esecuzione del codice e il tempo richiesto dai passaggi di contesto tra kernel-mode e user-mode.
Un osservatore attento si dovrebbe accorge di una incongruenza: il codice realmente eseguito durante questa misura è infatti stato leggermente modificato rispetto a quanto riportato, togliendo le due righe con le funzioni printf e itoa, particolarmente lente nell'esecuzione...
Data di creazione di questa pagina: luglio 2013
Raspberry Pi: note di hardware - Versione 1.31 - Luglio
2019
Copyright 2013-2019, Vincenzo Villa (https://www.vincenzov.net)
Quest'opera è stata rilasciata con licenza Creative Commons | Attribuzione-Condividi allo stesso modo 3.0 Unported.