¿Qué compensaciones debo considerar al decidir usar una interfaz SPI o I2C?
Esta placa de arranque de acelerómetro / giroscopio está disponible en dos modelos, uno para cada interfaz. ¿Sería más fácil integrarlo en un proyecto Arduino?
¿Qué compensaciones debo considerar al decidir usar una interfaz SPI o I2C?
Esta placa de arranque de acelerómetro / giroscopio está disponible en dos modelos, uno para cada interfaz. ¿Sería más fácil integrarlo en un proyecto Arduino?
Respuestas:
Resumen
I2C es un sistema de bus con datos bidireccionales en la línea SDA. SPI es una conexión punto a punto con datos de entrada y salida de datos en líneas separadas (MOSI y MISO).
Esencialmente, el SPI consiste en un par de registros de desplazamiento, donde registra los datos en un registro de desplazamiento mientras registra los datos del otro. Por lo general, los datos se escriben en bytes teniendo 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 con SS en alta (SS está activo en baja). Tú decides después de cuántos pulsos de reloj es esto. Si usa palabras de 13 bits, el SS bloqueará el último reloj en bits 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 serie), MOSI (Master Out Slave In), MISO (Master In Slave Out) y SS (Slave Select). En modo bideroctional 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 esclavos tenga líneas en modo estándar y líneas en modo bidireccional. Si no quiere eso, en 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 debe recorrer todos los datos de esclavos.N + 3 N + 2
Como dice tcrosley, SPI puede operar a una frecuencia mucho más alta que I2C.
I2C es un poco más complejo. Como se trata de un autobús, necesita una forma de abordar 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 acusar recibo colocando un pulso de confirmación en SDA. Si su microcontrolador tiene una interfaz I2C, esto se solucionará automáticamente. Aún puede usar bit-bang si su microcontrolador no lo admite, pero tendrá que cambiar el pin de E / S de la salida a la entrada para cada reconocimiento o lectura de datos, a menos que use un pin de E / S para leer y uno para escribir.
A 400kHz, I2C estándar es mucho más lento que SPI. Hay dispositivos I2C de alta velocidad que funcionan a 1MHz, aún mucho más lentos que 20MHz SPI.
(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.
La placa de conexión para el dispositivo 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. Entonces, creo que está limitado a usar I2C si desea 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 se transmite en 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 vs SPI para la misma funcionalidad.
Las diferentes clases de dispositivos (memoria, E / S, LCD, etc.) tienen diferentes rangos de direcciones. Algunos dispositivos, que se usan comúnmente 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 PCF8574) que pueden vincularse alto o bajo para especificar los bits bajos de la direccion. El MPU-6500 tiene una de esas líneas de dirección (AD0), por lo que dos de ellas se pueden usar en el mismo sistema.
También puede tener múltiples 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 inapropiado: en realidad es una interfaz de tres cables + un cable adicional por dispositivo. No tengo experiencia con la serie de tableros Arduino, pero creo que esto haría que el uso de SPI sea más difícil en el Arduino, ya que si necesitara muchas líneas de selección de chips, esto comenzaría a ser engorroso con las asignaciones de pin comunes utilizadas 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 de entrada "alto" mínimo para un bus I2C en una CPU de 5v es de 3v o inferior, 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 pullup interno de 5v en una CPU esté deshabilitado.
Sin embargo, verifiqué la hoja de datos del ATmega2560 (usando el ADK 5v Arduino como ejemplo), y su voltaje de entrada "alto" mínimo es 0.7 * Vcc, o 3.5v, que es mayor que 3.3v. Por lo tanto, necesita algún tipo de nivel activo conversión. La TI PCA9306 , que requiere resistencias pullups en ambos lados de 5v y 3.3v del chip, cuesta solo 78 centavos en cantidades individuales.
¿Por qué entonces elegir SPI sobre I2C? Principalmente porque SPI se puede ejecutar mucho más rápido, hasta muchos 10's 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, lo que no es una gran diferencia.
En general, SPI es un bus más rápido: la frecuencia de reloj puede estar en un rango de MHz. Sin embargo, SPI requiere al menos 3 líneas para la 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.
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 dice 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
SPI se puede ejecutar mucho más rápido que I2C (algunos dispositivos SPI superan los 60MHz; no sé si la especificación "oficial" I2C permite dispositivos superiores a 1MHz). La implementación de un dispositivo esclavo usando cualquiera de los protocolos requiere soporte de hardware, mientras que ambos permiten la implementación sencilla de maestros de "explosión de bit de software". 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 por hasta 500us a la vez, sin necesidad de cables adicionales de comunicación. Sin embargo, una operación SPI confiable, incluso con soporte de hardware , generalmente requiere que uno agregue un cable de protocolo de enlace o que el host agregue "manualmente" un retraso después de cada byte igual al peor tiempo de respuesta del esclavo.
Si tuviera mis druthers, el soporte 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 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 "estándar", cuando ambos procesadores pueden retrasarse independientemente por períodos arbitrarios de tiempo, requiere el uso de muchos más cables (Chip-Select, Clock, MISO y MOSI para comenzar con, además de algún tipo de cable de reconocimiento del esclavo. Si el esclavo podría comenzar a tener datos para enviar de forma asincrónica (por ejemplo, porque alguien presionó un botón), entonces uno debe usar otro cable como "activación"
I2C no proporciona todas las habilidades que tendría mi SPI "mejorado", pero sí ofrece capacidades de apretón de manos incorporadas que SPI carece, y en muchas implementaciones puede ser eludido para proporcionar también la activación, incluso si el maestro es un software bit-bang. Por lo tanto, para la comunicación entre procesadores, recomendaría encarecidamente I2C sobre SPI, excepto cuando se necesitan velocidades más altas que las que SPI puede suministrar, y el uso de pines adicionales es aceptable. Para las comunicaciones entre procesadores donde se necesita un recuento bajo de pines, los UART tienen mucho que recomendar.
Esta pregunta ha sido explorada a fondo en las excelentes respuestas aquí, pero tal vez hay 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 de la tensión de funcionamiento del bus. Todo lo que necesito poder hacer es bajar la línea SDA si me place, 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 del lado alto y las reemplazo con otras estructuras, puedo hacer un chip que pueda vivir totalmente su propia vida independiente del resto del sistema: SCL, SDA nunca alimentan ninguna corriente a mi chip y yo ciertamente no alimentará ninguna corriente a esos pines. Es por eso que es un autobús tan agradable para relojes en tiempo real y otras cosas de baja potencia como esa.
Una cosa que no he visto mencionada en las otras respuestas es que I2C admite múltiples maestros en el mismo bus. Si necesita comunicación bidireccional y no desea utilizar un método basado en encuestas, I2C hará el trabajo.
En distancias más largas, CAN tiene la misma capacidad y es más robusto. Pero CAN es un protocolo asincrónico que requiere soporte de hardware y un transceptor, por lo que puede no ser una opción en un sistema de bajo costo.
Use el protocolo SPI y escriba sus bits directamente en el dispositivo cada vez que el reloj de sincronización esté subiendo. El circuito lógico xnor puede usarse 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 de autor dentro del formato del dispositivo, los estándares ... etc. son complejos y diferentes, con un spi puede usar una memoria spi para mostrar un video en pantalla, pero no i2c.