(editar: Para ser claros, muchas de las siguientes preocupaciones tienen que ver con la integridad de la señal causada por el uso de dispositivos I2C / SPI de placa a placa, como señala correctamente Olin).
A menos que tenga restricciones que lo empujen fuertemente hacia menos cables (teníamos un proyecto con un conector sellado herméticamente en el que cada contacto adicional era bastante costoso), evite I2C cuando sea posible y siga con SPI.
SPI es bastante fácil de manejar por hardware y software. En hardware, hay dos líneas de datos compartidas, Master In Slave Out (MISO o SOMI) y Master Out Slave In (MOSI o SIMO), un reloj compartido generado por el maestro y una selección de chip por dispositivo. La línea CS baja, el reloj cambia y esencialmente cambia en bits de entrada y desplaza bits de salida, hasta que finaliza la transacción, momento en el que la línea CS sube. Cuando su línea CS es alta, los dispositivos esclavos no se comunican: ignoran las líneas CLK y MOSI, y ponen su pin MISO en un estado de alta impedancia para permitir que alguien más lo use.
Si tiene un microcontrolador que utiliza varios dispositivos SPI y tiene un periférico SPI incorporado, envíe la salida CS del microcontrolador a un demultiplexor (por ejemplo, 74HC138) y controle las líneas de dirección para seleccionar el dispositivo entre las transacciones SPI; usted escribe palabras en un registro para ponerlas en cola para la salida, y leerlas nuevamente después de que el pin CS se eleve alto.
Debido a que todas las señales SPI son unidireccionales, pueden almacenarse en búfer, usarse a través de una barrera de aislamiento con aisladores digitales, y pueden enviarse de placa a placa utilizando controladores de línea como LVDS. Lo único de lo que debe preocuparse es el retraso de propagación de ida y vuelta, que limitará su frecuencia máxima.
I2C es una historia completamente diferente. Si bien es mucho más simple desde el punto de vista del cableado, con solo dos cables SCL y SDA, ambas líneas son líneas bidireccionales compartidas que utilizan dispositivos de drenaje abierto con un pullup externo. Existe un protocolo para I2C que comienza transmitiendo la dirección de un dispositivo, de modo que se pueden usar varios dispositivos si cada uno tiene su propia dirección.
Desde el punto de vista del hardware, es muy difícil usar I2C en sistemas que tienen un ruido significativo. Para amortiguar o aislar las líneas I2C, debe recurrir a circuitos integrados exóticos; sí, existen, pero no hay muchos: utilizamos uno en un proyecto y nos dimos cuenta de que podía usar un aislador, pero no podía use dos en serie: usó pequeñas caídas de voltaje para determinar de qué lado era el extremo conductor de las cosas, y dos caídas en serie fueron dos mucho.
Los umbrales de nivel lógico de I2C dependen de Vcc, por lo que debe tener mucho cuidado si utiliza dispositivos de 3V / 3.3V y 5V en el mismo sistema.
Cualquier señal que use un cable de más de un pie o dos tiene que preocuparse por la capacitancia del cable. La capacidad de 100pf / metro no está fuera de lo común para el cable multiconductor. Esto hace que tenga que reducir la velocidad del bus, o usar resistencias pullup más bajas, para poder manejar la capacitancia adicional adecuadamente y cumplir con los requisitos de tiempo de subida.
Entonces, supongamos que tiene un sistema que cree que ha diseñado bien, y puede lidiar con la mayoría de los problemas de integridad de la señal, y el ruido es raro (pero aún está presente). ¿De qué tienes que preocuparte?
Hay un montón de condiciones de error que debes estar preparado para manejar:
El dispositivo esclavo no reconoce un byte particular. Debe detectar esto y detener y reiniciar la secuencia de comunicaciones. (Con SPI, generalmente puede volver a leer los datos que envía si desea asegurarse de que se recibieron sin error).
Está leyendo un byte de datos de un dispositivo esclavo, y el dispositivo está "hipnotizado" debido al ruido en la línea del reloj: ha enviado los 8 relojes necesarios para leer ese byte, pero debido al ruido, el dispositivo esclavo piensa que ha recibido 7 relojes y todavía está transmitiendo un 0 en la línea de datos. Si el dispositivo hubiera recibido el octavo reloj, habría liberado la línea de datos para que el maestro pudiera subir o bajar la línea de datos para transmitir un bit ACK o NACK, o el maestro podría transmitir una condición de parada (P). Pero el esclavo todavía mantiene la línea de datos baja, esperando en vano otro reloj. Si un maestro no está preparado para probar relojes adicionales, el bus I2C estará atascado en un punto muerto. Si bien he usado varios microcontroladores que manejan las condiciones normales de ACK / NACK,
El caso realmente horrible es cuando un maestro está escribiendo datos en un dispositivo esclavo, y otro esclavo interpreta la dirección del dispositivo incorrectamente y piensa que los datos transmitidos están destinados a ello. Hemos tenido dispositivos I2C (expansores de E / S) que ocasionalmente tienen registros configurados incorrectamente debido a esto. Es casi imposible detectar este caso, y para ser robusto al ruido, debe configurar periódicamente todos los registros, de modo que si se encuentra con este error, al menos se solucionará después de un corto período de tiempo. (SPI nunca tiene este problema: si tiene una falla en la línea CS, nunca persistirá por mucho tiempo y no obtendrá datos leídos accidentalmente por el dispositivo esclavo incorrecto).
Muchas de estas condiciones podrían manejarse adecuadamente en el protocolo si hubiera detección de errores (códigos CRC), pero pocos dispositivos tienen esto.
Me parece que tengo que construir un software complejo en mi dispositivo maestro I2C para manejar estas condiciones. En mi opinión, simplemente no vale la pena a menos que las restricciones en el cableado nos obliguen a usar I2C y no SPI.