Quais compensações devo considerar ao decidir usar uma interface SPI ou I2C?
Esta placa de aceleração / giroscópio está disponível em dois modelos, um para cada interface. Qualquer um deles seria mais fácil de integrar em um projeto do Arduino?
Quais compensações devo considerar ao decidir usar uma interface SPI ou I2C?
Esta placa de aceleração / giroscópio está disponível em dois modelos, um para cada interface. Qualquer um deles seria mais fácil de integrar em um projeto do Arduino?
Respostas:
Sumário
O I2C é um sistema de barramento com dados bidirecionais na linha SDA. O SPI é uma conexão ponto a ponto com entrada e saída de dados em linhas separadas (MOSI e MISO).
Essencialmente, o SPI consiste em um par de registradores de turno, nos quais você registra os dados em um registrador de turnos enquanto registra os dados no outro. Normalmente, os dados são gravados em bytes, tendo cada vez 8 pulsos de relógio em sucessão, mas isso não é um requisito SPI. Você também pode ter comprimentos de palavra de 16 bits ou até 13 bits, se desejar. Enquanto no I2C, a sincronização é feita pela sequência de inicialização no SPI, é feita pelo SS indo alto (o SS está ativo baixo). Você decide a si mesmo depois de quantos pulsos de relógio são. Se você usar palavras de 13 bits, o SS travará o último número cronometrado em bits após 13 pulsos de relógio.
Como os dados bidirecionais estão em duas linhas separadas, é fácil fazer a interface.
O SPI no modo padrão precisa de pelo menos quatro linhas: SCLK (relógio serial), MOSI (entrada principal escrava), MISO (entrada principal escrava) e SS (seleção escrava). No modo bidirecional, são necessárias pelo menos três linhas: SCLK (relógio serial), MIMO (Master In Master Out), que é uma das linhas MOSI ou MISO, e SS (Slave Select). Em sistemas com mais de um escravo, você precisa de uma linha SS para cada escravo, para que, para escravos, você tenha linhas no modo padrão e linhas no modo bidirecional. Se você não quer isso, no modo padrão, pode encadear os escravos em cadeia conectando o sinal MOSI de um escravo ao MISO do próximo. Isso diminuirá a comunicação, pois você precisará percorrer todos os dados dos escravos.N + 3 N + 2
Como tcrosley diz, o SPI pode operar com uma frequência muito maior que o I2C.
I2C é um pouco mais complexo. Como é um ônibus, você precisa de uma maneira de endereçar dispositivos. Sua comunicação começa com uma sequência de início exclusiva: a linha de dados (SDA) fica baixa enquanto o relógio (SCL) está alto, pois o restante dos dados de comunicação só pode mudar quando o relógio está baixo. Essa sequência inicial sincroniza cada comunicação.
Como a comunicação inclui o endereçamento, apenas duas linhas são necessárias para qualquer número de dispositivos (até 127).
editar
É óbvio que a linha de dados é bidirecional, mas vale a pena notar que isso também é válido para a linha do relógio. Os escravos podem esticar o relógio para controlar a velocidade do ônibus. Isso torna o I2C menos conveniente para troca de nível ou buffer. (As linhas SPI no modo padrão são todas unidirecionais.)
Após cada byte (endereço ou dados) ser enviado, o receptor deve confirmar o recebimento, colocando um pulso de reconhecimento no SDA. Se o seu microcontrolador tiver uma interface I2C, isso será resolvido automaticamente. Você ainda pode fazer um bit-bang se o seu microcontrolador não o suportar, mas será necessário alternar o pino de E / S da saída para a entrada para cada dado de reconhecimento ou leitura, a menos que você use um pino de E / S para leitura e um para escrever.
Em 400kHz, o padrão I2C é muito mais lento que o SPI. Existem dispositivos I2C de alta velocidade que operam a 1 MHz, ainda muito mais lento que o SPI de 20 MHz.
(editar: Para ficar claro, muitas das preocupações a seguir têm a ver com a integridade do sinal causada pelo uso placa-a-placa de dispositivos I2C / SPI, como Olin corretamente indica.)
A menos que você tenha restrições que o empurrem fortemente em direção a menos fios (tivemos um projeto com um conector hermeticamente fechado que cada contato adicional era bastante caro), evite o I2C sempre que possível e atenha-se ao SPI.
É fácil lidar com o SPI com base em hardware e software. No hardware, existem duas linhas de dados compartilhadas, Master In Slave Out (MISO ou SOMI) e Master Out Slave In (MOSI ou SIMO), um relógio compartilhado gerado pelo mestre e uma seleção de chip por dispositivo. A linha CS fica baixa, o relógio alterna e muda essencialmente nos bits de entrada e desloca os bits de saída, até a transação terminar, quando a linha CS fica alta. Quando a linha CS é alta, os dispositivos escravos não se comunicam: eles ignoram as linhas CLK e MOSI e colocam o pino MISO em um estado de alta impedância para permitir que outras pessoas o usem.
Se você possui um microcontrolador usando vários dispositivos SPI e ele possui um periférico SPI interno, envie a saída CS do microcontrolador para um desmultiplexador (por exemplo, 74HC138) e controle as linhas de endereço para selecionar o dispositivo entre as transações SPI; você escreve palavras em um registro para enfileirá-las para saída e as lê novamente depois que o pino CS é elevado.
Como os sinais SPI são todos unidirecionais, eles podem ser armazenados em buffer, usados através de uma barreira de isolamento com isoladores digitais e podem ser enviados de placa para placa usando drivers de linha como LVDS. Você só precisa se preocupar com o atraso na propagação de ida e volta, o que limitará sua frequência máxima.
I2C é uma história completamente diferente. Embora seja muito mais simples do ponto de vista da fiação, com apenas dois fios SCL e SDA, ambas as linhas são linhas bidirecionais compartilhadas que usam dispositivos de drenagem aberta com uma tração externa. Há um protocolo para I2C que começa transmitindo um endereço de dispositivo, para que vários dispositivos possam ser usados se cada um tiver seu próprio endereço.
Do ponto de vista do hardware, é muito difícil usar o I2C em sistemas com ruído significativo. Para armazenar em buffer ou isolar linhas I2C, você precisa recorrer a CIs exóticos - sim, eles existem, mas não existem muitos: usamos um em um projeto e percebemos que você poderia usar um isolador, mas não podia use dois em série - ele usou pequenas quedas de tensão para descobrir de que lado era o fim das coisas e duas quedas em série eram duas.
Os limites do nível lógico do I2C dependem do Vcc, portanto, você deve ter muito cuidado ao usar dispositivos de 3V / 3,3V e 5V no mesmo sistema.
Quaisquer sinais que usem um cabo de mais de um pé ou dois precisam se preocupar com a capacitância do cabo. A capacitância de 100pf / metro não é incomum para cabos multicondutores. Isso faz com que você tenha que desacelerar o barramento ou usar resistores de pullup inferiores, para poder lidar adequadamente com a capacitância extra e atender aos requisitos de tempo de subida.
Então, digamos que você tenha um sistema que tenha projetado bem e que possa lidar com a maioria dos problemas de integridade do sinal, e o ruído é raro (mas ainda presente). Com o que você precisa se preocupar?
Há várias condições de erro que você precisa estar preparado para lidar:
O dispositivo escravo não reconhece um byte específico. Você precisa detectar isso e parar e reiniciar a sequência de comunicações. (Com o SPI, você geralmente pode ler novamente os dados que enviar, se quiser ter certeza de que foram recebidos sem erros.)
Você está lendo um byte de dados de um dispositivo escravo, e o dispositivo é "hipnotizado" por causa do ruído na linha do relógio: você enviou os 8 relógios necessários para ler esse byte, mas por causa do ruído, o dispositivo escravo pensa que recebeu 7 relógios e ainda está transmitindo um 0 na linha de dados. Se o dispositivo tivesse recebido o oitavo relógio, teria liberado a linha de dados alta, para que o mestre pudesse aumentar ou diminuir a linha de dados para transmitir um bit ACK ou NACK, ou o mestre poderia transmitir uma condição de parada (P). Mas o escravo ainda mantém a linha de dados baixa, esperando em vão por outro relógio. Se um mestre não estiver preparado para experimentar relógios extras, o barramento I2C ficará preso em um impasse. Embora eu tenha usado vários microcontroladores que lidam com as condições normais do ACK / NACK,
O caso realmente terrível é quando um mestre está gravando dados em um dispositivo escravo, e outro escravo interpreta o endereço do dispositivo incorretamente e pensa que os dados transmitidos são para ele. Tivemos dispositivos I2C (expansores de E / S) que ocasionalmente têm registros configurados incorretamente por causa disso. É quase impossível detectar esse caso e, para ser robusto ao ruído, é necessário definir todos os registros periodicamente, para que, se você encontrar esse erro, pelo menos ele seja corrigido após um curto período de tempo. (A SPI nunca tem esse problema - se ocorrer uma falha na linha CS, ela nunca persistirá por muito tempo e você não obterá dados lidos acidentalmente pelo dispositivo escravo errado.)
Muitas dessas condições poderiam ser tratadas corretamente no protocolo se houvesse detecção de erro (códigos CRC), mas poucos dispositivos possuem isso.
Acho que tenho que criar um software complexo no meu dispositivo mestre I2C para lidar com essas condições. Na minha opinião, não vale a pena, a menos que as restrições na fiação nos forcem a usar o I2C e não o SPI.
A placa de interrupção para o dispositivo no SparkFun é realmente apenas para a versão I2C (MPU-6500). A versão MPU-6000 possui interfaces SPI e I2C no mesmo chip, e não vejo que o SparkFun tenha uma placa com esse chip. Portanto, acredito que você esteja limitado ao uso do I2C se desejar usar esse quadro específico. Mas eu recomendaria usar o I2C de qualquer maneira na sua situação pelos seguintes motivos.
Em geral, você encontrará que o barramento I2C é mais fácil de usar do ponto de vista do hardware do que o barramento SPI. I2C é um barramento de 2 fios (SCL / SDA):
SCL – Serial clock.
SDA – Serial data (bidirectional).
O SPI é um barramento de 4 fios (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.
Você pode ter vários dispositivos conectados a um barramento I2C. Cada dispositivo possui seu próprio conjunto de endereços embutidos no chip. O endereço é realmente transmitido pelo barramento como o primeiro byte de cada comando (junto com um bit de leitura / gravação). Isso, juntamente com outras sobrecargas, exige que mais bits sejam enviados por um barramento I2C versus SPI para a mesma funcionalidade.
Diferentes classes de dispositivos (memória, E / S, LCD etc.) possuem diferentes intervalos de endereços. Alguns dispositivos, comumente usados mais de uma vez em um sistema (como o expansor de E / S PCF8574), usam uma ou mais linhas de endereço (AD0-2 para o PCF8574) que podem ser vinculadas alta ou baixa para especificar os bits baixos do endereço. O MPU-6500 possui uma dessas linhas de endereço (AD0), portanto, duas delas podem ser usadas no mesmo sistema.
Você também pode ter vários dispositivos em um barramento SPI, mas cada dispositivo deve ter sua própria linha de seleção de chip (CS). Portanto, a descrição de 4 fios é um pouco inadequada - é realmente uma interface de três fios + um fio adicional por dispositivo. Não tenho experiência com a série de placas Arduino, mas acredito que isso dificultaria o uso do SPI no Arduino, pois se você precisasse de muitas linhas de seleção de chips, isso começaria a ficar complicado com as atribuições de pinos comuns usadas pelos vários escudos. .
Acredito que a maioria das placas Arduino roda em 5 volts, com algumas mais novas rodando em 3.3v. O MPU-6500 é executado em 3.3v. Se a tensão mínima de entrada "alta" para um barramento I2C em uma CPU de 5v for 3v ou menos, você poderá evitar problemas de conversão de nível fornecendo apenas resistores de pull-up de 10K a 3,3v nas linhas SCL e SDA, pois o barramento está aberto. colecionador. Verifique se todos os pullups internos de 5v em uma CPU estão desabilitados.
No entanto, verifiquei a folha de dados do ATmega2560 (usando o ADK 5v Arduino como exemplo) e sua tensão 'alta' mínima de entrada é 0,7 * Vcc ou 3,5v maior que 3,3v. Portanto, você precisa de algum tipo de nível ativo O TI PCA9306 , que requer resistores de pullups nos lados de 5v e 3,3v do chip, custa apenas 78 centavos em quantidades únicas.
Por que, então, escolher o SPI em vez do I2C? Principalmente porque o SPI pode ser executado muito, muito mais rapidamente - até muitos 10s de MHz em alguns casos. O I2C é geralmente limitado a 400 KHz. Mas isso não é realmente um problema para o acelerômetro MPU-6050/6000, já que ele roda a 400 KHz para I2C e apenas 1 MHz para SPI - não faz muita diferença.
Em geral, o SPI é um barramento mais rápido - a frequência do relógio pode estar na faixa de MHz. No entanto, o SPI requer pelo menos três linhas para comunicação bidirecional e uma seleção de escravo adicional para cada dispositivo no barramento.
O I2C requer apenas 2 linhas, independentemente de quantos dispositivos você possui (dentro dos limites, é claro). A velocidade, no entanto, está na faixa de kHz (100-400kHz é típico).
Atualmente, a maioria dos microcontroladores possui suporte de hardware para os dois barramentos, portanto, ambos são igualmente simples de usar.
I2C is designed for on-board applications.
- Aparentemente, os fabricantes de dispositivos I2C discordam de você. Pegue o TMP100 . A página do produto declara explicitamente: The TMP100 and TMP101 are ideal for extended temperature measurement in a variety of communication, computer, consumer, environmental, industrial, and instrumentation applications.
O mesmo vale para o TMP75
O SPI pode ser executado muito mais rápido que o I2C (alguns dispositivos SPI ultrapassam 60 MHz; não sei se a especificação "oficial" do I2C permite dispositivos acima de 1 MHz). A implementação de um dispositivo escravo usando qualquer um dos protocolos requer suporte de hardware, enquanto ambos permitem fácil implementação de mestres "software bit-bang". Com um hardware relativamente mínimo, é possível construir um escravo compatível com I2C, que funcionará corretamente, mesmo que o host decida arbitrariamente ignorar o barramento por até 500us por vez, sem a necessidade de cabos adicionais de handshake. A operação confiável do SPI, no entanto, mesmo com suporte de hardware , geralmente exige que se adicione um fio de handshake ou que o host "manualmente" adicione um atraso após cada byte igual ao pior tempo de resposta do escravo.
Se eu tivesse meus controladores, o suporte à SPI dos controladores conteria alguns recursos extras simples para fornecer transferências bidirecionais transparentes de 8 bits entre controladores com capacidade de handshake e wake-up, usando um total de três fios unidirecionais (Clock e MOSI [master saída do escravo do mestre; MISO [saída do escravo do mestre]. Em comparação, a comunicação eficiente e confiável entre microcontroladores com portas SPI "estocadas", quando ambos os processadores podem ser atrasados independentemente por períodos arbitrários de tempo, requer o uso de muito mais fios (Chip-Select, Clock, MISO e MOSI para iniciar Se algum escravo puder começar a receber dados de forma assíncrona (por exemplo, porque alguém apertou um botão), será necessário usar outro fio como uma "ativação"
O I2C não fornece todas as habilidades que meu SPI "aprimorado" teria, mas oferece habilidades de handshake embutidas que o SPI não possui e, em muitas implementações, pode ser julgado fornecer despertar também, mesmo se o mestre for um bit-bang de software. Para comunicação entre processadores, eu recomendaria fortemente o I2C sobre SPI, exceto quando forem necessárias velocidades mais altas do que o SPI pode fornecer e o uso de pinos extras for aceitável. Para comunicações entre processadores em que é necessária uma baixa contagem de pinos, os UARTs têm muito a recomendá-los.
Essa questão foi explorada minuciosamente nas excelentes respostas aqui, mas talvez haja mais um ponto de vista do I 2 C que eu poderia oferecer do ponto de vista de um fabricante de chips.
A interface elétrica do I 2 C é um coletor aberto . Agora respire e pense nas implicações. Usando I 2 C, posso projetar um chip totalmente independente da tensão de operação do barramento. Tudo o que eu preciso ser capaz de baixar é baixar a linha SDA, se assim o desejar, e comparar as tensões de SCL e SDA com alguma tensão de limite referenciada ao terra, que eu possa escolher. E se eu deixar de fora as estruturas normais de proteção lateral alta e substituí-las por outras estruturas, posso fazer um chip que possa viver totalmente sua própria vida, independente do resto do sistema - SCL, SDA nunca alimentará nenhuma corrente no meu chip e eu certamente não alimentará nenhuma corrente para esses pinos. É por isso que é um ônibus tão bom para relógios em tempo real e outras coisas de baixa potência como essa.
Uma coisa que não vi mencionada nas outras respostas é que o I2C suporta vários mestres no mesmo barramento. Se você precisar de comunicação bidirecional e não quiser usar um método baseado em pesquisa, o I2C fará o trabalho.
Em distâncias maiores, o CAN tem a mesma capacidade e é mais robusto. Mas o CAN é um protocolo assíncrono que requer suporte de hardware e um transceptor; portanto, pode não ser uma opção em um sistema de baixo custo.
Use o protocolo SPI e grave seus bits diretamente no dispositivo sempre que o relógio de sincronização estiver aumentando. O circuito lógico xnor pode ser usado para corresponder ao endereço "caseiro" de uma memória para selecionar o dispositivo desejado como se fosse um dispositivo i2c.
O i2c está integrando o circuito autoral dentro do formato do dispositivo, o padrão ... etc é complexo e diferente, com um spi você pode usar uma memória spi para exibir um vídeo na tela, mas não o i2c.