(modifica: per essere chiari, molte delle seguenti preoccupazioni hanno a che fare con l'integrità del segnale causata dall'uso scheda-scheda dei dispositivi I2C / SPI, come sottolinea correttamente Olin.)
A meno che tu non abbia vincoli che ti spingano fortemente verso un minor numero di fili (avevamo un progetto con un connettore sigillato ermeticamente che ogni contatto aggiuntivo era piuttosto costoso), evita I2C quando possibile e attacca con SPI.
SPI è abbastanza facile da gestire su base hardware e software. Nell'hardware esistono due linee dati condivise, Master In Slave Out (MISO o SOMI) e Master Out Slave In (MOSI o SIMO), un clock condiviso generato dal master e una selezione di chip per dispositivo. La linea CS si abbassa, il clock scorre e si sposta essenzialmente nei bit di input e sposta i bit di output, fino al termine della transazione, a quel punto la linea CS diventa alta. Quando la loro linea CS è alta, i dispositivi slave non comunicano: ignorano le linee CLK e MOSI e mettono il loro pin MISO in uno stato ad alta impedenza per consentire a qualcun altro di usarlo.
Se si dispone di un microcontrollore che utilizza diversi dispositivi SPI e ha una periferica SPI integrata, inviare l'output CS del microcontrollore a un demultiplexer (ad esempio 74HC138) e controllare le linee degli indirizzi per selezionare il dispositivo tra le transazioni SPI; scrivi le parole in un registro per metterle in coda per l'output e le rileggi dopo che il pin CS è alzato in alto.
Poiché i segnali SPI sono tutti unidirezionali, possono essere bufferizzati, utilizzati attraverso una barriera di isolamento con isolatori digitali e possono essere inviati da scheda a scheda utilizzando driver di linea come LVDS. L'unica cosa di cui devi preoccuparti è il ritardo di propagazione di andata e ritorno, che limiterà la frequenza massima.
I2C è una storia completamente diversa. Sebbene sia molto più semplice dal punto di vista del cablaggio, con solo due fili SCL e SDA, entrambe queste linee sono linee bidirezionali condivise che utilizzano dispositivi a drenaggio aperto con un pullup esterno. Esiste un protocollo per I2C che inizia trasmettendo un indirizzo di dispositivo, in modo che possano essere utilizzati più dispositivi se ognuno ha il proprio indirizzo.
Dal punto di vista hardware, è molto difficile utilizzare I2C in sistemi che presentano rumori significativi. Per bufferizzare o isolare le linee I2C, devi ricorrere a circuiti integrati esotici - sì, esistono, ma non ce ne sono molti: ne abbiamo usato uno su un progetto e ci siamo resi conto che potresti usare un isolatore, ma non puoi usane due in serie - ha usato piccole cadute di tensione per capire da che parte era la parte trainante delle cose, e due cadute in serie erano due.
Le soglie del livello logico di I2C dipendono da Vcc, quindi è necessario fare molta attenzione se si utilizzano dispositivi 3V / 3.3V e 5V nello stesso sistema.
Qualsiasi segnale che utilizza un cavo di più di un piede o due deve preoccuparsi della capacità del cavo. La capacità di 100pf / metro non è fuori dall'ordinario per il cavo multiconduttore. Ciò comporta la necessità di rallentare il bus o utilizzare resistenze di pullup inferiori per essere in grado di gestire correttamente la capacità aggiuntiva e soddisfare i requisiti di tempo di salita.
Supponiamo quindi che tu abbia un sistema che ritieni di aver progettato bene e che tu possa affrontare la maggior parte dei problemi di integrità del segnale e che il rumore sia raro (ma ancora presente). Di cosa ti devi preoccupare?
Ci sono un sacco di condizioni di errore che devi essere preparato per gestire:
Il dispositivo slave non riconosce un byte particolare. È necessario rilevare questo, arrestare e riavviare la sequenza di comunicazioni. (Con SPI, di solito è possibile rileggere i dati inviati se si desidera assicurarsi che siano stati ricevuti senza errori.)
Stai leggendo un byte di dati da un dispositivo slave e il dispositivo è "ipnotizzato" a causa del rumore sulla linea dell'orologio: hai inviato gli 8 orologi necessari per leggere quel byte, ma a causa del rumore il dispositivo slave lo pensa ha ricevuto 7 orologi e sta ancora trasmettendo uno 0 sulla linea dati. Se il dispositivo avesse ricevuto l'ottavo clock, avrebbe liberato la linea di dati in modo che il master potesse alzare o abbassare la linea di dati per trasmettere un bit ACK o NACK, oppure il master poteva trasmettere una condizione di arresto (P). Ma lo slave mantiene ancora bassa la linea dati, aspettando invano un altro orologio. Se un master non è disposto a provare altri clock, il bus I2C sarà bloccato in deadlock. Mentre ho usato diversi microcontrollori che gestiscono le normali condizioni ACK / NACK,
Il caso davvero terribile è quando un master sta scrivendo dati su un dispositivo slave e un altro slave interpreta in modo errato l'indirizzo del dispositivo e pensa che i dati trasmessi siano destinati a questo. Abbiamo avuto dispositivi I2C (espansori I / O) che a volte hanno registri impostati in modo errato a causa di ciò. È quasi impossibile rilevare questo caso ed essere robusto al rumore, è necessario impostare periodicamente tutti i registri, in modo che se si verifica questo errore, almeno verrà risolto dopo un breve periodo di tempo. (SPI non ha mai questo problema - se ti capita di avere un problema tecnico sulla linea CS, non persisterà mai a lungo e non otterrai i dati accidentalmente letti dal dispositivo slave sbagliato.)
Molte di queste condizioni potrebbero essere gestite correttamente nel protocollo in caso di rilevamento di errori (codici CRC), ma pochi dispositivi dispongono di questo.
Trovo che devo creare software complessi nel mio dispositivo master I2C per gestire queste condizioni. A mio avviso, non ne vale la pena a meno che i vincoli sul cablaggio non ci costringano a utilizzare I2C e non SPI.