¿Compensaciones al considerar SPI o I2C?

¿Qué compensaciones debo considerar al decidir usar una interfaz SPI o I2C?

Esta placa de acelerómetro/giroscopio está disponible en dos modelos, uno para cada interfaz. ¿Alguno de los dos sería más fácil de integrar en un proyecto Arduino?

http://www.sparkfun.com/products/11028

ingrese la descripción de la imagen aquí

I2C y SPI tienen sus puntos fuertes. I2C es más complejo de configurar, una vez estable, puede extenderse fácilmente (siempre que el cableado de su bus no sea demasiado largo o grande). SPI es fácil de configurar... puede bitbangearlo muy fácilmente si es necesario. La expansión consume E/S con todas las selecciones de chips. Si tengo el lujo de E/S y espacio de conector y no necesito buses, siempre optaría por SPI.
¿Cómo es I2C más complejo? He usado ambos buses en diferentes micros (PIC pequeños y ARM de tamaño decente) y en todos los casos la configuración de I2C fue más simple (es decir, menos registros para escribir). En todo caso, SPI es más complejo debido a la polaridad del reloj y las opciones de muestreo de datos.
@Armandas -- ¡de ninguna manera! SPI tiene 4 modos posibles para polaridad de reloj/datos, y dos de ellos dominan: casi todos los dispositivos SPI actualizan su salida MISO en el flanco descendente de un reloj y leen su entrada MOSI en el flanco ascendente de un reloj. Puede averiguar cuál en unos minutos mirando la hoja de datos, y luego ya está. Si elige el modo incorrecto por error, lo descubrirá rápidamente una vez que observe las trazas del osciloscopio. Los errores de datos de SPI son raros y no lo dejan atascado en estados extraños como lo hace I2C.
Digo que I2c es mucho más complejo porque una vez tuve que escribir un controlador I2C en un procesador ARM. Seguí la máquina de estado de los documentos NXP, y tenía unos 20 estados de largo. Me tomó un tiempo decente averiguar el reconocimiento, cuándo se lee/escribe el último byte, etc. Nunca he tenido ninguno de estos problemas con SPI, solo tengo que alinear el reloj y los datos.
Lea las respuestas aquí antes de elegir una respuesta: electronics.stackexchange.com/questions/13987/… Ambos tienen sus aplicaciones.
@JonL, francamente, soy el único que ha proporcionado una respuesta completa hasta ahora, ya que soy el único que discute el tema de la placa de conexión en particular que el OP quiere usar y señala que no está disponible en tanto SPI como I2C, pero solo I2C, por lo que tiene que usar I2C si quiere usar esta placa en particular. Los otros solo se ocuparon de qué interfaz (SPI o I2C) es más fácil de interactuar, que también cubrí.
@Hans: La implementación de I2C documentada por NXP incluye disposiciones para cosas como el arbitraje multimaestro que no son necesarias en una aplicación típica, y también está diseñado en torno a un enfoque basado en el estado. El código para un maestro I2C basado en procedimientos es mucho más simple de lo que sugeriría dicha documentación.

Respuestas (9)

Resumen

  • SPI es más rápido.
  • I2C es más complejo y no tan fácil de usar si su microcontrolador no tiene un controlador I2C.
  • I2C solo requiere 2 líneas.

I2C es un sistema de bus con datos bidireccionales en la línea SDA. SPI es una conexión punto a punto con entrada y salida de datos en líneas separadas (MOSI y MISO).

Esencialmente , SPI consiste en un par de registros de desplazamiento, en los que ingresa datos en un registro de desplazamiento mientras registra datos en el otro. Por lo general, los datos se escriben en bytes al tener cada vez 8 pulsos de reloj en sucesión, pero eso no es un requisito de SPI. También puede tener longitudes de palabra de 16 bits o incluso 13 bits, si lo desea. Mientras que en I2C la sincronización se realiza mediante la secuencia de inicio en SPI, se realiza mediante SS yendo alto (SS está activo bajo). Tú mismo decides después de cuántos pulsos de reloj son. Si usa palabras de 13 bits, el SS bloqueará los últimos bits cronometrados después de 13 pulsos de reloj.
Dado que los datos bidireccionales están en dos líneas separadas, es fácil interactuar.

SPI en modo estándar necesita al menos cuatro líneas: SCLK (reloj en serie), MOSI (Master Out Slave In), MISO (Master In Slave Out) y SS (Slave Select). En modo bidireccional necesita al menos tres líneas: SCLK (reloj serial), MIMO (Master In Master Out) que es una de las líneas MOSI o MISO y SS (Slave Select). En sistemas con más de un esclavo, necesita una línea SS para cada esclavo, de modo que para norte esclavos que tienes norte + 3 líneas en modo estándar y norte + 2 líneas en modo bidireccional. Si no desea eso, en el modo estándar puede conectar en cadena los esclavos conectando la señal MOSI de un esclavo al MISO del siguiente. Esto ralentizará la comunicación ya que tiene que pasar por todos los datos de los esclavos.

Como dice tcrosley, SPI puede operar a una frecuencia mucho más alta que I2C.

I2C es un poco más complejo. Dado que es un bus, necesita una forma de direccionar los dispositivos. Su comunicación comienza con una secuencia de inicio única: la línea de datos (SDA) se baja mientras el reloj (SCL) está alto, ya que el resto de los datos de comunicación solo pueden cambiar cuando el reloj está bajo. Esta secuencia de inicio sincroniza cada comunicación.
Dado que la comunicación incluye el direccionamiento, solo se requieren dos líneas para cualquier número de dispositivos (hasta 127).

editar
Es obvio que la línea de datos es bidireccional, pero vale la pena señalar que esto también es cierto para la línea del reloj. Los esclavos pueden estirar el reloj para controlar la velocidad del autobús. Esto hace que I2C sea menos conveniente para el cambio de nivel o el almacenamiento en búfer. (Las líneas SPI en modo estándar son todas unidireccionales).

Después de enviar cada byte (dirección o datos), el receptor debe confirmar el recibo colocando un pulso de reconocimiento en SDA. Si su microcontrolador tiene una interfaz I2C, esto se solucionará automáticamente. Todavía puede hacer un bit-bang si su microcontrolador no lo admite, pero tendrá que cambiar el pin de E/S de salida a entrada para cada reconocimiento o lectura de datos, a menos que use un pin de E/S para leer y uno para escribir.

A 400 kHz, I2C estándar es mucho más lento que SPI. Hay dispositivos I2C de alta velocidad que funcionan a 1 MHz, aún mucho más lentos que los 20 MHz SPI.

Todavía no he conocido un microcontrolador que maneje todos los casos de esquina de la necesidad de I2C para manejar la detección y recuperación de errores adecuada de una manera que sea utilizable sin tener que ser un experto en I2C. Siempre he tenido que volver a bajar de un periférico I2C "inteligente" a bitbanging temporalmente para manejar el caso de reloj perdido cuando SDA se mantiene bajo, lo cual es un dolor total./
(pero +1 ya que estoy de acuerdo con el resto de tu respuesta)
Incluso hay dispositivos I2C que funcionan a 3,4 MHz, pero no estoy seguro de que se puedan combinar con dispositivos más lentos (ya que todos los dispositivos deben poder seguir el direccionamiento del bus). También creo que los tiempos de 3.4MHz I2C son un poco diferentes.
@Hans: HS I2C parece ser compatible hacia abajo con los dispositivos de 400kbit más comunes. Francamente, (sin una investigación exhaustiva) nunca he visto un microcontrolador que admita HS (todavía), es por eso que no quería mencionarlo.
@stevenvh: las implementaciones de dos cables de algunos controladores (por ejemplo, Cypress PSOC) requieren que SCK esté bajo durante al menos uno o dos ciclos de un reloj interno antes de que se enganche y funcione mal, no es así. No sé por qué no pueden detectar y extender el reloj de una condición de inicio I2C sin un pulso de reloj del sistema, pero tales comportamientos significan que cuando un chip de este tipo se ejecuta a una velocidad de reloj del sistema baja, todas las transacciones I2C en el bus deben correr lentamente). Incluso la operación de 400Khz es demasiado rápida para un PSOC que funciona a 3MHz.
Debe tenerse en cuenta que muchos dispositivos SPI requieren que SS se use de manera adecuada, incluso si son el único dispositivo en el bus. SS no solo habilita un solo esclavo, sino que también proporciona sincronización. El borde de ataque de SS se usa a menudo para indicar el comienzo de un nuevo mensaje, con la resincronización asociada por parte de la lógica del dispositivo esclavo.
@stevenvh: ¿Pero las SS no solo inhiben el reloj? No, y ese es el punto. Muchos dispositivos usan el borde de ataque de SS para indicar un nuevo mensaje. Por ejemplo, una EEPROM podría tomar los dos primeros bytes después de SS como dirección y luego los bytes subsiguientes como datos. Es muy común con los A/D que los bits significativos se transmitan en una posición fija en relación con el SS, y luego siga enviando 0 o bits indefinidos. Eso permite una compatibilidad más sencilla con el hardware que solo puede hacer múltiplos fijos de bits, como 8 o 16. Para algunos dispositivos, el primer byte es un código de operación, el resto depende de ese código de operación.
@stevenvh: La gran mayoría de los dispositivos SPI usan SS para la sincronización y requieren que siga siendo válido a través de una transacción. Algunos dispositivos tienen un cable de habilitación de reloj separado , lo que hará que ignoren los pulsos de reloj durante una transacción. Esto puede ser útil si una rutina de servicio de interrupción necesita acceder a un dispositivo en un bus SPI mientras el "código de línea principal" accede a otros dispositivos (como un chip de memoria flash).
@Olin, supergato: anoche en la cama me di cuenta de que mi comentario sobre la sincronización SPI es completamente incorrecto. Equivocado. No sé lo que había estado fumando. Lo eliminaré y editaré mi respuesta.
@stevenvh: SPI bidireccional requiere cuatro líneas; muchos dispositivos SPI solo usan transferencia unidireccional y requieren tres. Aunque los registros de desplazamiento se usan comúnmente en un bus SPI y permiten la conexión en cadena, y algunos periféricos más complejos también lo hacen, estos dispositivos son la excepción y no la regla.
@stevenh La serie LPC1300/1700/1800/4300 afirma admitir operaciones de 1 Mbit/s. ¡Lo que no he visto es un periférico para conectarlo!
@OlinLathrop: un diseño de interfaz de ADC que me gustó generaría 16 bits en orden big-endian (que el procesador podría comenzar a registrar incluso mientras la conversión estaba en proceso, siempre que no registrara ningún bit en particular hasta que estuviera disponible ) seguido de esos mismos 16 bits en orden little-endian. Esto significaba que incluso si una plataforma de hardware solo tuviera un puerto serie síncrono little-endian, podría leer una conversión en su orden de bits nativo simplemente omitiendo los dos primeros bytes y leyendo los dos siguientes.

(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 quédese con SPI.

SPI es bastante fácil de manejar sobre una base de hardware y software. En el 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 cicla y esencialmente cambia los bits de entrada y los bits de salida, hasta que finaliza la transacción, momento en el que la línea CS pasa a nivel alto. 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 otra persona lo use.

Si tiene un microcontrolador que utiliza varios dispositivos SPI y tiene un periférico SPI integrado, envíe la salida CS del microcontrolador a un demultiplexor (p. ej., 74HC138) y controle las líneas de dirección para seleccionar el dispositivo entre las transacciones SPI; escribe palabras en un registro para ponerlas en cola para la salida, y las vuelve a leer después de que el pin CS se eleva 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 usan dispositivos de drenaje abierto con un pullup externo. Hay un protocolo para I2C que comienza transmitiendo una dirección de 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 líneas I2C, debe recurrir a circuitos integrados exóticos; sí, existen, pero no hay muchos: usamos un proyecto uno a uno 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 qué lado era el extremo impulsor de las cosas, y dos caídas en serie eran dos.

Los umbrales de nivel lógico de I2C dependen de Vcc, por lo que debe tener mucho cuidado si usa 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 debe preocuparse por la capacitancia del cable. La capacitancia de 100 pf/metro no está fuera de lo común para un cable multiconductor. Esto hace que tenga que reducir la velocidad del bus o usar resistencias pull-up más bajas para poder manejar la capacitancia adicional correctamente y cumplir con los requisitos de tiempo de subida.

Entonces, digamos que tiene un sistema que cree que ha diseñado bien, y puede manejar 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 debe estar preparado para manejar:

  • El dispositivo esclavo no reconoce un byte en particular. Tienes que 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 errores).

  • Estás leyendo un byte de datos de un dispositivo esclavo y el dispositivo está "hipnotizado" debido al ruido en la línea del reloj: has enviado los 8 relojes necesarios para leer ese byte, pero debido al ruido, el dispositivo esclavo lo piensa. 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 alta 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 aún mantiene baja la línea de datos, esperando en vano otro reloj. Si un maestro no está preparado para probar relojes adicionales, el bus I2C quedará bloqueado. Si bien he usado varios microcontroladores que manejan las condiciones normales de ACK/NACK,

  • El caso realmente terrible 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 son para él. 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 resistente 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 breve 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 correctamente en el protocolo si hubiera detección de errores (códigos CRC), pero pocos dispositivos tienen esto.


Encuentro 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 limitaciones del cableado nos obliguen a usar I2C y no SPI.

Su disgusto religioso por IIC no tiene cabida aquí. Tanto IIC como SPI son buenos en lo que hacen y cada uno tiene su lugar. La mayoría de sus objeciones a la IIC provienen del uso inapropiado de la misma. IIC debe considerarse solo a bordo, aunque se usa de forma rutinaria en la industria de suministro de energía para controlar suministros inteligentes. Si se encuentra deseando buffers IIC, entonces es una fuerte indicación de que IIC no es la solución adecuada. Sin embargo, IIC funciona muy bien para dispositivos de baja velocidad en la misma placa.
Los umbrales de nivel lógico de I2C dependen de Vcc, por lo que debe tener mucho cuidado si usa dispositivos de 3V/3.3V y 5V en el mismo sistema . No, esto está mal. Los umbrales lógicos de IIC están en voltajes fijos. Puede mezclar trivialmente sistemas de 5 V y 3,3 V elevando las líneas a solo 3,3 V.
Olin: ¿puede señalar los umbrales de voltaje fijo en una especificación? Tenía la impresión de que también estaban arreglados (los umbrales de SMBus son fijos), pero busqué en el Manual del usuario de NXP I2C (UM10204) y citan los umbrales como 0.3VDD y 0.7VDD.
No es una aversión religiosa de I2C, es una aversión práctica de I2C. Tienes razón en que es mucho más fácil con los sistemas integrados; Lo usaré cuando tenga sentido, pero agrega costo de software, y demasiados ingenieros de hardware simplemente colocan un dispositivo I2C en una placa sin discutir las compensaciones que causan más dolores de cabeza de software.
No recuerdo exactamente dónde lo vi, y buscando un poco parece haber cierta confusión y diferentes opciones, pero estoy bastante seguro de que recuerdo 1.5V como el umbral bajo lógico máximo, por ejemplo.
IIC es un poco más fácil de implementar eléctricamente y SPI quizás un poco más fácil en el firmware. Sin embargo, ambos son bastante fáciles y sencillos en ambos aspectos.
I2C está diseñado para su uso en entornos eléctricamente limpios y no se puede "fortificar" fácilmente para su uso en entornos más hostiles. Habiendo dicho eso, I2C puede ser mucho más conveniente que SPI para las comunicaciones entre procesadores en entornos eléctricamente limpios. Los UART pueden ser aún mejores, pero los procesadores nunca parecen tener suficiente, y la forma en que los UART de muchos controladores están integrados con sus sistemas de reloj hace que sea difícil cambiar la velocidad del reloj sin corromper los datos que el otro extremo podría haber decidido enviar de forma asíncrona.
@Olin: el umbral fijo de 1,5 V parece usarse en el pasado, pero según la última versión de los umbrales de especificaciones, de hecho, son 0,3 Vcc y 0,7 Vcc. Esta cita de la especificación menciona los 1,5 V para dispositivos heredados.
@JasonS Así que han pasado 6 años y ha habido muchas discusiones útiles en los comentarios. ¿Es posible que podamos tener una lista de casos, confiabilidad I2C y modos de error en cada uno? Por ejemplo, al escribir en un solo dispositivo, parece 100% correcto. Al escribir en varios dispositivos, algunos pueden malinterpretar los datos. Al leer desde un solo dispositivo, es posible que deba hacer un bit-bang y reiniciar. Al leer desde varios dispositivos, ¿se puede requerir un ciclo de energía completo para salir de un punto muerto?

La placa de conexión para dispositivos en SparkFun es en realidad solo para la versión I2C (MPU-6500). La versión MPU-6000 tiene interfaces SPI e I2C en el mismo chip, y no veo que SparkFun tenga una placa con ese chip. Así que creo que está limitado a usar I2C si quiere usar esa placa en particular. Pero iba a recomendar usar I2C de todos modos en su situación por las siguientes razones.

En general, encontrará que el bus I2C es más fácil de usar desde el punto de vista del hardware que el bus SPI. I2C es un bus de 2 hilos (SCL/SDA):

SCL – Serial clock.
SDA – Serial data (bidirectional).

SPI es un bus de 4 hilos (SCLK/MOSI/MISO/CS):

SCLK– Serial clock.
MOSI – Master-out, Slave-in. Data from the CPU to the peripheral.
MISO – Master-in, Slave out. Data from the peripheral back to the CPU.
CS – Chip select.

Puede tener varios dispositivos conectados a un bus I2C. Cada dispositivo tiene su propio conjunto de direcciones integradas en el chip. La dirección en realidad se transmite por el bus como el primer byte de cada comando (junto con un bit de lectura/escritura). Esto, junto con algunos otros gastos generales, requiere que se envíen más bits a través de un bus I2C frente a SPI para la misma funcionalidad.

Las diferentes clases de dispositivos (memoria, E/S, LCD, etc.) tienen diferentes rangos de direcciones. Algunos dispositivos, que comúnmente se usan más de una vez en un sistema (como el expansor de E/S PCF8574), usan una o más líneas de dirección (AD0-2 para el PCF8574) que se pueden vincular alto o bajo para especificar los bits bajos. de la dirección El MPU-6500 tiene una de esas líneas de dirección (AD0), por lo que se pueden usar dos en el mismo sistema.

También puede tener varios dispositivos en un bus SPI, pero cada dispositivo debe tener su propia línea de selección de chip (CS). Por lo tanto, la descripción de 4 cables es un poco inapropiada: en realidad es una interfaz de tres cables + un cable adicional por dispositivo. No tengo experiencia con la serie de placas Arduino, pero creo que esto dificultaría el uso de SPI en Arduino, ya que si necesita muchas líneas de selección de chips, esto comenzaría a ser engorroso con las asignaciones de pines comunes utilizados por los diversos escudos. .

Creo que la mayoría de las placas Arduino funcionan a 5 voltios, y algunas más nuevas funcionan a 3.3v. El MPU-6500 funciona a 3,3v. Si el voltaje "alto" de entrada mínimo para un bus I2C en una CPU de 5v es de 3v o menos, puede evitar problemas de conversión de nivel simplemente proporcionando resistencias pullup de 10K a 3.3v en las líneas SCL y SDA, ya que el bus está abierto. coleccionista. Asegúrese de que cualquier extracción interna de 5v en una CPU esté deshabilitada.

Sin embargo, verifiqué la hoja de datos del ATmega2560 (usando el ADK 5v Arduino como ejemplo), y su voltaje mínimo de entrada "alto" es 0.7 * Vcc, o 3.5v, que es mayor que 3.3v. Entonces, necesita algún tipo de nivel activo conversión El TI PCA9306 , que requiere resistencias pull-ups en ambos lados del chip de 5v y 3.3v, cuesta solo 78 centavos en cantidades individuales.

Entonces, ¿por qué elegir SPI sobre I2C? Principalmente porque SPI se puede ejecutar mucho más rápido, hasta muchas decenas de MHz en algunos casos. I2C generalmente está limitado a 400 KHz. Pero esto no es realmente un problema para el acelerómetro MPU-6050/6000, ya que funciona a 400 KHz para I2C y solo 1 MHz para SPI, no hay mucha diferencia.

Otra razón para elegir SPI sobre I2C: todas las líneas son unidireccionales, lo que facilita un poco las cosas como los cambios de nivel.
@markrages, revisé la hoja de datos de una CPU Arduino de 5v y descubrí que mi solución pullup simple no funciona ya que la entrada mínima para el I2C es 0.7*Vcc, o 3.5v. Por lo tanto, se necesitaría un cambiador de nivel. Modifiqué mi respuesta para indicar esto y recomiendo usar un chip. Estoy de acuerdo en que el cambio de nivel para SPI es más simple, ya que solo tiene que lidiar con una línea de entrada de CPU (MISO): las salidas se pueden manejar con divisores de voltaje.
¿I2C es más fácil que SPI? Lo único sobre I2C que es más fácil es la conectividad si puede conectar todo junto. De lo contrario, la integridad de la señal es más difícil en I2C, y la implementación robusta de software es mucho más difícil en I2C.
@JasonS, he completado docenas de proyectos de software integrado usando I2C y nunca me he encontrado con los problemas de bloqueo que mencionas en tu publicación. Puedo entender que no te guste debido a tus malas experiencias. Actualmente tengo un producto en el mercado que usa un DAC I2C para emitir audio, mientras leo simultáneamente el siguiente búfer de datos de una tarjeta SD a través de SPI. Funciona genial. No podía usar SPI tanto para el DAC como para la tarjeta SD porque estaba teniendo problemas con el bus y el audio se interrumpía. El micro (uno de gama baja) solo tiene un puerto SPI y uno I2C.
¡Estoy impresionado de que pueda enviar audio a un DAC I2C! (¿Cuál es la velocidad máxima del reloj?) Si está utilizando circuitos integrados integrados con carreras cortas, la probabilidad de que se bloquee es extremadamente pequeña, pero aún existe. (Además, nunca lo encontraría si solo está escribiendo datos en I2C. Requiere que lea desde un dispositivo que está dispuesto a esperar para siempre por lo que cree que es un reloj faltante / adicional).
@JasonS, el audio es solo calidad de voz, 8 KHz. Estoy usando una interrupción de 128 us para generar cada muestra de 16 bits. El I2C también se ejecuta en su propia interrupción. El tiempo libre se utiliza para leer datos de la tarjeta SD. Buen punto sobre el bloqueo que nunca ocurre al escribir. A excepción de los ADC, generalmente he usado I2C para dispositivos de salida. Sin embargo, ¿sabías que la interfaz de solo lectura (2 botones, acelerómetro y joystick) entre el control remoto de Wii y el Wii Nunchuck (que se encuentra a través de un cable de 3 pies) es I2C a 400 KHz? Hay mucha información en la web sobre la piratería de la interfaz de este dispositivo.
@JasonS: Para la comunicación entre dos microcontroladores, la falta de protocolo de enlace en SPI es un verdadero dolor.
Disculpas por mi voto negativo; si realiza una edición de token (agrega espacios en blanco o lo que sea), eliminaré el voto negativo.
JasonS, edité mi respuesta para aclarar que quería decir que el bus I2C es generalmente más fácil de usar desde el punto de vista del hardware (a pesar de los problemas de transición de nivel).
-1 --------> +1

En general, SPI es un bus más rápido: la frecuencia del reloj puede estar en un rango de MHz. Sin embargo, SPI requiere al menos 3 líneas para comunicación bidireccional y una selección de esclavo adicional para cada dispositivo en el bus.

I2C solo requiere 2 líneas, independientemente de cuántos dispositivos tenga (dentro de los límites, por supuesto). La velocidad, sin embargo, está en el rango de kHz (100-400kHz es típico).

La mayoría de los microcontroladores, hoy en día, tienen soporte de hardware para ambos buses, por lo que ambos son igualmente fáciles de usar.

-1: Ambos no son igualmente fáciles de usar. I2C tiene una gran cantidad de manejo y recuperación de errores complejos que no suelen ser manejados por periféricos de microcontrolador (ciertamente no en PIC18, PIC30 o TI C28xx DSP; obtiene un periférico que manejará la mayoría de I2C pero fallará en manejar todos los casos .)
@Jason: Parece que tienes algún prejuicio contra IIC, pero es injusto criticar a otras personas por eso. Tanto IIC como SPI son "fáciles", y cada uno tiene sus propias arrugas. SPI necesita líneas adicionales, lo que puede no ser fácil. IIC es un poco más complicado, pero aún es fácil hacer todas las implementaciones de firmware, lo que he hecho muchas veces. No se necesita tanto código. Ambos tienen su lugar y ambos son lo suficientemente fáciles como para que eso no sea un factor para cualquiera que sepa lo que está haciendo.
No injusto. Estoy feliz de votar cuando la declaración de "igualmente simple de usar" se corrige o al menos se aclara. Desafío a cualquiera a escribir software en un microprocesador con periféricos inteligentes I2C y SPI para interactuar con una serie de IC que tiene variantes I2C y SPI, y mostrarme la complejidad del software a través de cualquier medida objetiva (líneas de código, número de estados, complejidad ciclomática , etc.) para demostrar que son igualmente fáciles de usar. Ejemplos: Microchip 24LC256/25LC256 EEPROM, MCP23017/23S17 Expansor de E/S.
@Jason: Acabo de verificar, y mi código IIC genérico para la implementación de firmware de IIC en PIC de 8 bits tiene solo 311 líneas, y probablemente más de la mitad son comentarios. Eso te da una interfaz de procedimiento para el bus IIC al nivel de las rutinas para iniciar, poner, obtener, detener, etc. Gran cosa. Un módulo que llama a eso para controlar una EEPROM simple tiene 272 líneas, nuevamente 1/2 comentarios probablemente, y eso incluye una gestión de alto nivel como datos predeterminados, interfaz de depuración UART, etc. Todo esto es tan trivial que discutir si toma 10 instrucciones menos que SPI no tiene sentido.
@JasonS: El hecho de que no encuentre que I2C sea fácil de usar no lo hace difícil para todos. He diseñado muchos equipos industriales usando I2C y nunca me he encontrado con los problemas que describe en su respuesta. Creo que Olin tiene razón: ha aplicado incorrectamente I2C y ha desarrollado una aversión muy fuerte por él. Una opinión no tiene nada de malo, y tienes algunos buenos puntos, pero criticarla en casi todas las respuestas aquí y continuar defendiendo tu postura... eso no es una aversión práctica; eso es fanatismo religioso. Tu respuesta fue muy buena. No hay necesidad de comentar sobre los demás también.
@AndrewKohlsmith: Para ser justos con Jason, hay algunos trucos con bit-bang I2C que pueden facilitar mucho las cosas, pero la documentación del dispositivo no suele presentarlos y muchas implementaciones de hardware no los admiten. A menudo es más fácil, por ejemplo, tener una rutina de lectura de bytes que envíe un ACK antes de leer cada byte después del primero y llamar a una rutina NAK después de leer el último byte, que tener una rutina de lectura de bytes que use un parámetro para especificar ya sea para ACK o NAK, ya que es posible que uno no sepa hasta después de haber leído un byte si querrá otro.
Ok, me gustaría disculparme por tomar un tono enojado tanto en mis comentarios a otras publicaciones como en mi propia respuesta. Lo que admitiré es que hay formas de escribir software I2C usando periféricos en chip que son relativamente fáciles, ignorando ciertas condiciones de error raras. Habiendo dicho eso, sigo pensando que decir que I2C es fácil es engañoso. Y no creo que haya aplicado mal I2C. Mire el TMP75, un sensor de temperatura I2C. Puedes poner hasta 27 de ellos en el autobús. (Tenemos un sistema con 8.) ¿Alguien los pondría todos en un solo tablero? La hoja de datos no le advierte sobre problemas externos.
Olin: solo curiosidad: ¿su implementación es bloqueante o no bloqueante (por ejemplo, impulsada por el estado)? Puedo ver que una implementación de bloqueo podría manejar condiciones de error sin demasiados problemas. Tengo un sistema que tiene requisitos estrictos en tiempo real y tengo que dividir mi procesamiento I2C en una máquina de estado debido a todos los diferentes casos de error, mientras que el procesamiento SPI es pan comido; simplemente cambiamos nuestra dirección de CS, bajamos la línea de habilitación de CS, colocamos datos de transmisión en la cola, esperamos unos microsegundos, elevamos la línea de habilitación de CS y leemos los datos recibidos.
Andrew: "nunca se encuentre con los problemas que describe en su respuesta". Claro, especialmente si el bus I2C está a bordo con trazas relativamente cortas. Menos ruido = la probabilidad de que se pierda un reloj I2C se reduce a una cantidad muy pequeña. Disponemos de 8 sensores TMP75 en un sistema ruidoso industrial. (En retrospectiva, desearía que nuestro diseñador hubiera usado sensores de temperatura analógicos). Si se tratara de errores de datos ocasionales (que recibimos), no sería tan malo. Pero el problema es que puede entrar en un punto muerto, e incluso si la probabilidad de error es remota, una vez que esté allí, su probabilidad de escapar es 0 sin el manejo correcto de errores.
@Armandas: Disculpas por mi voto negativo; si realiza una edición de token (agrega espacios en blanco o lo que sea), eliminaré el voto negativo.
@JasonS ese es mi punto: I2C está diseñado para aplicaciones integradas. Se puede estirar para transmitirse por cables, pero esa no es su aplicación prevista, y debe diseñarse para la complejidad adicional. En lo que respecta a los dispositivos zombis: ningún esclavo I2C en su sano juicio estiraría el reloj indefinidamente, y si tiene control sobre el reloj, puede abortar la transferencia I2C y restablecer el bus. No es el sistema loco y difícil que pareces hacer que sea.
@Andrew Kohlsmith - I2C is designed for on-board applications.- Aparentemente, los fabricantes de dispositivos I2C no están de acuerdo con usted. Tome el TMP100 . La página del producto establece explícitamente: The TMP100 and TMP101 are ideal for extended temperature measurement in a variety of communication, computer, consumer, environmental, industrial, and instrumentation applications.Lo mismo es cierto para el TMP75
Por lo que vale, he ejecutado 8 TMP100 en un bus I2C que tenía ~ 15 'de largo, pero el entorno tenía poco ruido. Toda la interfaz I2C para ese proyecto fue un poco rota, y fue un dolor en el culo.
Creo que todo este argumento se reduce a que las personas tienen diferentes perspectivas. Tienes a Jason S, que parece estar diseñando sistemas de control industrial en tiempo real de una fiabilidad extremadamente alta, y Andrew Kohlsmith y Olin Lathrop, que diseñan dispositivos más orientados al consumidor (?). Es posible que I2C no sea viable en un entorno en el que esa tasa de error del 0,001 % sea un problema significativo y grave (especialmente si no puede esperar ~1 segundo para que se agote el tiempo de espera). Sin embargo, en muchas situaciones, tal error es lo suficientemente improbable como para no causar problemas, o el retraso que introduciría no es problemático.
Personalmente, elegiría SPI sobre I2C, pero eso es más porque soy bastante malo programando y encuentro que la complejidad de un cable conductor adicional es trivial. YMMV.
@JasonS No se preocupe, es una respuesta simple y, en términos puntuales, está donde debería estar.
@FakeName, el TMP100 no indica en ninguna parte que esté destinado a la detección de temperatura externa. Su cotización simplemente indica que es ideal en ciertas aplicaciones. Puede detectar la temperatura con el dispositivo en esas aplicaciones. Pelusa de marketing estándar, eso es todo. Maxim es particularmente malo para enumerar miles de aplicaciones para cualquier dispositivo.
@FakeName Cuando construí un anemómetro de alambre caliente, usé dispositivos de transistor dual que se conectaron a través de pares trenzados a un controlador de temperatura/ventilador SMBus estándar. SMBus es I2C mejorado, como sabe, pero el chip estaba integrado y nunca tuvo problemas de comunicación. Creo que aplicaste mal el sensor de temperatura.
@FakeName Estás equivocado; Pasé 13 años haciendo electrónica de potencia industrial. (iniciar y monitorear motores trifásicos GRANDES es un entorno MUY ruidoso) No se trata de que SPI sea más confiable, se trata de diseñar el sistema con todos los modos de falla planificados y considerados, y tener opciones de recuperación integradas en el sistema donde sea necesario. Nunca, nunca tuve un pico de ruido que matara mis comunicaciones I2C (o SPI para el caso), pero tampoco confié exclusivamente en el controlador I2C para hacer todo por mí. Es una cuestión de planificación y diseño, no de que un autobús sea mejor.
"pero tampoco confié exclusivamente en el controlador I2C para hacer todo por mí"; eso no es fácil, ese era mi punto.
@akohlsmith: I2C de un solo maestro y un solo esclavo debe ser robusto con un maestro "bit-bang". Si hay varios esclavos y dos se "confunden" simultáneamente de diferentes maneras, el bus podría bloquearse de manera irrecuperable (por ejemplo, si dos o más chips de memoria que están llenos de ceros piensan que el maestro está tratando de leerlos, pero sus contadores de bits no están sincronizados, entonces cada uno solo liberará SDA durante los momentos en que el otro lo afirma, y ​​nada que el maestro pueda hacer liberará el bus a menos que pueda conducir un "alto" lo suficientemente potente como para sobrecargar a todos los esclavos.

SPI se puede ejecutar mucho más rápido que I2C (algunos dispositivos SPI superan los 60MHz; no sé si la especificación I2C "oficial" permite dispositivos de más de 1MHz). La implementación de un dispositivo esclavo usando cualquiera de los protocolos requiere soporte de hardware, mientras que ambos permiten una fácil implementación de maestros de "software bit-bang". Con un hardware relativamente mínimo, se puede construir un esclavo compatible con I2C que funcionará correctamente incluso si el host puede decidir arbitrariamente ignorar el bus hasta 500us a la vez, sin necesidad de cables de enlace adicionales. Sin embargo, la operación confiable de SPI, incluso con soporte de hardware , generalmente requiere que se agregue un cable de protocolo de enlace o que el host agregue "manualmente" un retraso después de cada byte igual al tiempo de respuesta del esclavo en el peor de los casos.

Si tuviera mis preferencias, la compatibilidad con SPI de los controladores contendría algunas características adicionales simples para proporcionar transferencias de datos bidireccionales transparentes de 8 bits entre controladores con capacidades de establecimiento de comunicación y activación, utilizando un total de tres cables unidireccionales (Reloj y MOSI [maestro -out-slave-in] del maestro; MISO [master-in-slave-out] del esclavo). En comparación, la comunicación eficiente y confiable entre microcontroladores con puertos SPI "de stock", cuando ambos procesadores pueden retrasarse de forma independiente por períodos de tiempo arbitrarios, requiere el uso de muchos más cables (Chip-Select, Clock, MISO y MOSI para iniciar con, además de algún tipo de cable de reconocimiento del esclavo.Si el esclavo pudiera comenzar a tener datos para enviar de forma asíncrona (por ejemplo, porque alguien presionó un botón), entonces uno debe usar otro cable más como "despertador"

I2C no proporciona todas las capacidades que tendría mi SPI "mejorado", pero sí ofrece capacidades de protocolo de enlace integradas de las que carece SPI, y en muchas implementaciones también se puede modificar para proporcionar activación, incluso si el maestro es un software bit-bang. Para la comunicación entre procesadores, recomendaría enfáticamente I2C sobre SPI, excepto cuando se necesiten velocidades más altas que las que puede suministrar SPI, y el uso de pines adicionales sea aceptable. Para las comunicaciones entre procesadores donde se necesita un número bajo de pines, los UART tienen mucho que recomendar.

Hay una versión de alta velocidad de I2C que permite 1 MHz; I2C normal es 400kHz.
@TheResistance: sé que el I2C normal era de 400 kHz, pero las versiones se especificaron hasta 1MHz. Lo que no sé es si se han especificado versiones más rápidas.
De acuerdo con la especificación, 400 kbps (no kHz, utilicé las unidades incorrectas allí) es el modo rápido, 1 Mbps es el modo rápido Plus y hay un modo de alta velocidad de hasta 3,4 Mbps. Ultrarrápida sube hasta 5 Mbps, pero es unidireccional.
@TheResistance: Gracias. No había oído hablar de esas versiones posteriores. ¿Qué quiere decir exactamente con 'unidireccional'? Sé que la velocidad de la comunicación SPI de esclavo a maestro puede ser más rápida que la de maestro a esclavo porque se garantiza que el esclavo obtendrá su reloj después del maestro, pero no estoy seguro de un concepto equivalente para I2C. ¿Tienes un enlace?
Encuentre la especificación aquí . En la página 23 dice que Ultra-fast se puede usar para dispositivos que no devuelven datos (solo escritura), ni siquiera ACK.
@TheResistance: El formato ultrarrápido parece un poco curioso. Cuando necesito comunicación push-pull para hablar con un CPLD con cables mínimos, utilicé SPI pero reinicié la interfaz de comunicaciones si recibía dos o más flancos ascendentes en MOSI mientras el reloj estaba bajo (generado al cambiar MOSI a propósito general E/S). Tal enfoque permitió el uso de casi cualquier hardware maestro SPI de controlador (muchas implementaciones de I2C no se pueden configurar como push-pull) y no requirió un reloj adicional después de cada byte.

Esta pregunta se ha explorado a fondo en las excelentes respuestas aquí, pero tal vez haya un punto de vista más para I 2 C que podría ofrecer desde el punto de vista de un fabricante de chips.

La interfaz eléctrica del I 2 C es un colector abierto . Ahora respira y piensa en las implicaciones. Usando I 2 C, puedo diseñar un chip que sea totalmente independiente del voltaje operativo del bus. Todo lo que necesito poder hacer es bajar la línea SDA si me complace hacerlo, y comparar los voltajes de SCL y SDA con algún voltaje de umbral con referencia a tierra, que puedo elegir. Y si dejo de lado las estructuras normales de protección lateral alta y las reemplazo con otras estructuras, puedo hacer un chip que puede vivir su propia vida totalmente independientemente del resto del sistema: SCL, SDA nunca alimentan mi chip con corriente y yo ciertamente no alimentará ninguna corriente a esos pines. Es por eso que es un buen bus para relojes en tiempo real y otras cosas de bajo consumo como ese.

Una cosa que no he visto mencionada en las otras respuestas es que I2C admite múltiples maestros en el mismo bus. Si necesita una comunicación bidireccional y no desea utilizar un método basado en sondeos, I2C hará el trabajo.

En distancias más largas, CAN tiene la misma capacidad y es más robusto. Pero CAN es un protocolo asíncrono que requiere soporte de hardware y un transceptor, por lo que puede no ser una opción en un sistema de bajo costo.

Buen punto (en multimaestro), también he visto dispositivos SPI con pines de interrupción, mientras que un dispositivo sigue siendo el maestro, ambos pueden instanciar la comunicación (bidireccional). Para dispositivos remotos hay, por supuesto, opciones más sólidas y mejores (como CAN).

Utilice el protocolo SPI y escriba sus bits directamente en el dispositivo siempre que el reloj de sincronización aumente. El circuito lógico xnor se puede usar para hacer coincidir la dirección "casera" de una memoria para seleccionar el dispositivo deseado como si fuera un dispositivo i2c.

El i2c está integrando el circuito autoral dentro del formato del dispositivo, estándar... etc. son complejos y diferentes, con un spi puedes usar una memoria spi para mostrar un video en pantalla, pero i2c no.

I2C es un bus con direcciones de datos. SPI es un bus con direcciones físicas.

I2C, como se mencionó anteriormente, no es fácil ni simple sin un controlador de hardware.

De hecho, SPI tampoco es simple sin un controlador de hardware en el contexto de esta discusión. Principalmente porque el tiempo es tan rápido que puede ser difícil de anticipar y cada dispositivo tiene su propio protocolo y anomalías.

Mi sugerencia es tomar esta decisión en función del ancho de banda.

Si su aplicación se beneficia de precisión de tiempo y tasa de datos. Especialmente si I2C no proporciona SPI de uso de ancho de banda completo.

Es probable que exista una biblioteca de interfaz para ambos o lo hará en breve. Si no, personalmente disfruto resolviendo problemas de SPI más que problemas de I2C.

Si ninguno de estos temas te preocupa. Use I2C simplemente porque es más probable que tenga un código existente y hay menos conexiones para hacer.