Descrizione delle procedure di comunicazione I2C

Analizzando i sorgenti delle librerie I2C del C18 Microchip si nota che alcune contengono dei waiting loop in attesa dell'esecuzione dell'operazione da parte della SSP e non sono quindi compatibili con il sistema pseudo-RTOS

Le procedure non utilizzabili sono quindi state riscritte in modo compatibile usando gli interrupt generati dall'SSP e gestendo il protocollo con flag di stato e variabili globali di appoggio.

ReadI2C wait until byte received
getcI2C idem
getsI2C perform getcI2C() for 'length' number of bytes
check that receive sequence is over
wait until ACK sequence is over
IdleI2C Test and wait until I2C module is idle
WriteI2C wait until write cycle is complete
putI2C idem
putsI2C transmit data until null character
test for idle condition
wait until ninth clock pulse received
AckI2C ok
CloseI2C ok
DataRdyI2C ok
NotAckI2C ok
OpenI2C ok
RestartI2C ok
StopI2C ok
StartI2C ok
Tutto il codice relativo alla comunicazione I2C è stato verificato in pratica con gli I/O expander PCF8574.
E' stato sviluppato e collaudato anche il protocollo, a livello ancora più alto, per pilotare un display LCD e per leggere una tastiera con quattro pulsanti.
Un'ottima traccia di partenza per lo studio di questo tipo di protocollo, è stata l'application note AN736 di Microchip che descrive in modo molto dettagliato questo tipo di tecnica oltre ad una buona descrizione dei principi base della comunicazione I2C.

Per ottenere una procedura generica ed utilizzabile per diversi tipi di device, la comunicazione I2c è stata suddivisa in uno stack di protocolli a più livelli:

-Strato applicativo:
Ogni device I2C ha le sue caratteristiche, la routine relativa al device ha a disposizione 4byte in trasmissione e 2byte in ricezione per ogni turno.
Ad esempio: verso la EEPROM si trasmetteranno due byte per l'indirizzo della locazione di memoria e si riceveranno o trasmetteranno uno o due byte (variabile char o int). Questo è il device che richiede più byte in trasmissione e determina quindi la dimensione del buffer.
La funzione I2cDeviceXX prepara i dati da scambiare nel buffer ed alza i flag relativi alle azioni da svolgere:
I2c[I2cDevPtr].Flag.Rx
I2c[I2cDevPtr].Flag.Tx .

-Strato I2cHighLevel:
E' eseguito se il deviceXX ha qualcosa da scambiare: I2c[I2cDevPtr].Flag.Rx !=0 || I2c[I2cDevPtr].Flag.Tx!=0
e se la routine a livello più basso è disponibile: I2cBusyFlag = 0
scambia i byte con il device attraverso la routine a livello più basso e alza I2cBusyFlag per impegnarla

-Strato I2cLowLevel:
E' eseguito se la InterruptServiceRoutine ha alzato I2cEventFlag
Esegue solo un'azione alla volta, imposta la prossima azione da eseguire ed esce in attesa del completamento dell'azione avviata.

-Strato fisico
Per lo strato a livello più basso, implementato in hardware nel PIC 18f452, rimando a:
l'ottima documentazione Microchip (Tutorials, ApplicationNotes, UserGuides)
le specifiche originali della Philips
l'enorme quantità di documenti sull'argomento presenti in Internet dei quali il seguente è solo un esempio: Using I2C bus

Nel ciclo Main sono controllati i flag a partire da quelli a livello più basso a salire.
L'intero ciclo è ripetuto per ogni device I2c scandendo il buffer .

# device descrizione bit fix bit free adr
0 24LC256 32KB eeprom 0 0 0 0 0 0 0 0x00
1 CMPS03 Compass 1 1 0 0 0 0 0 0xC0
2 MAX127 A/D expander 0 1 0 1 0 0 0 0x50
3 PCF8574 I/O expander 0 1 0 0 0 0 0 0x40
4 PCF8574 I/O expander 0 1 0 0 0 0 1 0x42
5 SRF08 Devantech US 1 1 1 0 0 0 0 0xE0

Indirizzi dei devices I2c usati ora o che ho intenzione di usare in futuro

aggiornato il 01 - 11 - 2005