Codificação compatível com Arduino 18: Comunicação serial síncrona usando o barramento I2C

Nos tutoriais anteriores, cobrimos serial comunicação usando o UART e série de software em Arduino. O receptor/transmissor assíncrono universal (UART), I2C e SPI são as interfaces seriais mais comumente usadas em sistemas embarcados.

UART é útil para comunicação serial full-duplex com um único dispositivo em dois fios. A interface I2C ou interface de dois fios (TWI) é usada para comunicação serial síncrona half-duplex com vários dispositivos no modo mestre-escravo. O barramento SPI é usado para comunicação serial síncrona full-duplex com vários dispositivos.

Agora, neste tutorial, aprenderemos sobre comunicação serial síncrona no Arduino usando o barramento de circuito interintegrado (I2C).

O barramento I2C
O I2C, ou TWI, é um protocolo de comunicação serial síncrona mestre-escravo originalmente desenvolvido pela Philips Semiconductors (que agora é NXP). O barramento I2C possui apenas dois fios: um é uma linha de dados (SDA) e o outro é uma linha de clock (SCL).

Em um barramento de dois fios, centenas de dispositivos mestres e escravos podem comunicar dados seriais usando o protocolo I2C.

O I2C é um barramento do tipo mestre-escravo e deve haver pelo menos um dispositivo mestre para controlar o barramento de dois fios.

O dispositivo mestre é responsável por sincronizar as transferências de dados:

  • Gerando o sinal do relógio
  • Selecionando um dispositivo escravo para comunicação
  • Controlando as operações de leitura/gravação no barramento

Como existe apenas uma linha de dados, apenas a comunicação half-duplex com um único dispositivo escravo é possível por vez. Isto significa que qualquer número de dispositivos mestres pode ser conectado ao barramento I2C, mas apenas um mestre pode controlar o barramento ao mesmo tempo.

Os fios são puxados para ALTO por padrão, usando os resistores pull-up e os drivers I2C são dreno aberto (ou seja, eles só podem puxar a linha para BAIXO). Isso evita com êxito qualquer contenção de barramento.

Cada escravo I2C conectado a um barramento deve ter um endereço único. O dispositivo mestre utiliza endereçamento em banda para acessar a comunicação com os dispositivos escravos. Os endereços I2C dos vários dispositivos escravos são decididos pela NXP.

Muitos dispositivos escravos possuem um endereço I2C configurável. O endereçamento em banda pode ser de 7 ou 10 bits. No endereçamento de 7 bits, 112 dispositivos escravos podem ser conectados ao barramento. No endereçamento de 10 bits, 1.008 dispositivos escravos podem ser conectados ao barramento. Além disso, o mestre I2C pode usar endereços de 7 e 10 bits no mesmo barramento.

Além disso, existem algumas placas breakout que permitem a comunicação com vários dispositivos escravos usando um endereço comum. Nestas placas, os dispositivos escravos são multiplexados através de um controlador integrado.

A implementação do protocolo I2C requer simplesmente dois canais de drenagem abertos em um dispositivo. Na maioria dos controladores/computadores, existe hardware dedicado para gerenciar o protocolo I2C.

A taxa de transferência de dados no I2C depende da frequência do clock gerada pelo mestre I2C.

Existem velocidades de clock I2C padrão, que incluem:

  • 100 a 400 kHz (padrão I2C)
  • 1 MHz (I2C de modo rápido)
  • 3,4 MHz (I2C de alta velocidade)
  • 5 MHz (I2C de modo ultra rápido).

Normalmente, o barramento I2C usa níveis lógicos TTL de 5V ou 3V3. É recomendado conectar os dispositivos compatíveis com tensão através do barramento I2C, caso contrário, o dispositivo de baixa tensão corre o risco de danificar seus canais I2C ao receber dados. Se dois dispositivos tiverem níveis de tensão TTL diferentes, um deslocador de tensão adequado deverá ser usado entre os dispositivos e conectado através do barramento de dois fios.

O protocolo I2C
A comunicação de dados é sempre iniciada por um dispositivo mestre no barramento TWI. Um dispositivo mestre gera uma condição inicial para acesso ao barramento. Ao gerar a condição de início, é decidido qual mestre acessará o barramento se dois ou mais tentarem fazê-lo ao mesmo tempo.

Depois de fazer isso com sucesso, o mestre transmite um endereço em banda na forma de um quadro de endereço para selecionar um dispositivo escravo para comunicação. O mestre deve ler ou gravar dados no dispositivo escravo selecionado, que é indicado no quadro de endereço.

Depois de selecionar um dispositivo escravo, o mestre pode ler ou escrever dados na forma de pacotes de dados de 8 bits. Após a troca de cada pacote de dados, o dispositivo receptor envia um bit de confirmação ao remetente para indicar que o byte foi comunicado com sucesso.

Depois de obter acesso ao barramento I2C, um mestre pode gerar múltiplas condições de inicialização para conversar várias vezes com um dispositivo escravo – ou para conversar com vários dispositivos escravos, um após o outro.

Para liberar o barramento para outros mestres, porém, o mestre precisa gerar uma condição de parada. Os dispositivos escravos nunca podem iniciar a comunicação por conta própria ou controlar o barramento, mas podem reter temporariamente o pulso do relógio (após uma condição de parada) para fazer os mestres esperarem para acessar o barramento. Isso é chamado de alongamento do relógio. (Saiba mais sobre o protocolo I2C aqui).

Aplicações do barramento I2C
Como vários dispositivos podem comunicar dados em apenas dois fios usando o protocolo I2C, a interface I2C/TWI é amplamente utilizada por sensores e módulos incorporados. Alguns exemplos de sensores que utilizam o barramento I2C para comunicação de dados são o acelerômetro ADXL345, o giroscópio L3G4200D, o magnetômetro MC5883L, o sensor de pressão BMP180, o DS1307 RTC e outros.

Usando I2C em placas Arduino
A maioria das placas Arduino possui pelo menos um módulo I2C. O módulo I2C pode ser acessível através de uma ou mais portas da placa.

Os pinos I2C não são puxados internamente para cima, portanto, pode ser necessário puxá-los para ALTO usando resistores externos, dependendo do dispositivo I2C ao qual estão conectados.

Os pinos I2C em um Arduino UNO são mostrados aqui:

Esta tabela resume a localização dos pinos I2C em várias placas Arduino…

A biblioteca de fios
É mais fácil conversar com dispositivos I2C/TWI usando Arduino, em parte porque esta plataforma fornece uma biblioteca: Um fio para gerenciar a comunicação de placas Arduino em um barramento I2C.

As placas Arduino podem ser configuradas como mestre I2C e como escravo I2C. A biblioteca wire usa um buffer de 32 bytes, portanto, qualquer transferência de dados I2C deve estar dentro desse limite. Se mais bytes forem comunicados em uma transmissão, os bytes excedentes serão deixados de fora.

A biblioteca de fios pode ser importada em um esboço do Arduino usando esta instrução:

#include

A biblioteca wire possui estes métodos:

fio.begin usado para ingressar no barramento I2C como mestre ou escravo. Isto tem esta sintaxe:

Wire.begin
ou
Wire.begin(endereço)

Se o Arduino ingressar no barramento I2C como mestre, o método deverá ser chamado sem argumentos. Se o Arduino ingressar no barramento I2C como escravo, um endereço arbitrário de 7 bits deverá ser passado como argumento. Asa escravo, pode ter um endereço entre 8 e 127. Os endereços de 0 a 7 são reservados, porém, e não utilizados pelo Arduino.

Aqui estão exemplos válidos deste método:

Wire.begin //Arduino como mestre I2C
Wire.begin(8) // Arduino como escravo I2C

Wire.setClock usado pelo Arduino e configurado como mestre I2C. Este método é usado para alterar a frequência do clock do barramento I2C. Os escravos I2C não possuem frequência mínima, embora 100 kHz seja a linha de base. Este método tem esta sintaxe:

Wire.setClock(clockFrequency)

Toma a frequência do clock em Hertz como argumento. Aqui está um exemplo válido:

Wire.setClock(3200)

Wire.beginTransmission (endereço)usado pelo Arduino e configurado como mestre I2C. Este método é usado para iniciar a transmissão para um escravo I2C. O endereço do escravo I2C selecionado é passado como argumento na função. Tem esta sintaxe:

Wire.beginTransmission(endereço)

E aqui está um exemplo válido:

Wire.beginTransmissão(8)

Wire.write usado para gravar dados no barramento I2C. Ele pode ser usado pelo Arduino como mestre I2C e escravo I2C. Como mestre, este método deve ser usado entre chamadas aos métodos beginTransmission e endTransmission .

Como escravo, este método pode ser usado em resposta a uma solicitação de um dispositivo mestre. Pode ser usado para transmitir um valor, uma string ou uma matriz de bytes. Tem esta sintaxe:

Wire.write(valor)
ou
Wire.write(string)
ou
Wire.write(dados, comprimento)

Aqui estão exemplos válidos:

Wire.write(7)
Wire.write(“Olá”)
Wire.write(arraybytes, 5) //arraybytes é uma matriz de valores de 5 bytes
matriz de valores de 5 bytes

Wire.onReceive(manipulador) usado pelo Arduino e configurado como escravo. Ele atribui uma função manipuladora a ser chamada em resposta quando os dados são recebidos do mestre I2C. A função manipuladora definida pelo usuário deve usar o número de bytes lidos do mestre como argumento, se necessário. A função também deve ser do tipo void e não retornar nada. Tem esta sintaxe:

Wire.onReceive(manipulador)

Aqui está um exemplo válido:

Wire.onReceive(receiveEvent);
void receberEvento
{
Serial.print(“dados recebidos do mestre I2C);
}

Wire.requestFrom usado pelo Arduino e configurado como mestre I2C. Este método é usado para solicitar dados do escravo I2C. Os dados solicitados são então recuperados pelo Arduino mestre usando os métodos Wire.available e Wire.read . Tem esta sintaxe:

Wire.requestFrom(endereço, quantidade)
Wire.requestFrom(endereço, quantidade, parada)

O método leva dois argumentos – o endereço I2C do dispositivo escravo e o número de bytes solicitados. Possui um argumento booleano opcional – stop que pode ser 'True' ou 'False'.

A parada é por padrão True. Quando for True, uma condição de parada é gerada após a requisição, liberando o barramento. Quando for False, uma condição de reinicialização é gerada após a solicitação, permitindo que o Arduino mestre continue utilizando o barramento. O método retorna o número de bytes recebidos do dispositivo escravo. Aqui está um exemplo válido:

Wire.requestFrom(8, 6, verdadeiro)

Wire.onRequest(manipulador) usado pelo Arduino configurado como escravo. Ele atribui uma função manipuladora a ser chamada em resposta quando o mestre I2C solicitar dados deste escravo. A função manipuladora definida pelo usuário não aceita argumentos e não retorna nada. Este método tem esta sintaxe:

Wire.onRequest(manipulador)

E aqui está um exemplo válido:

Wire.onRequest(requestEvent);
void requestEvent
{
Wire.write(“Mestre, obtenha esses dados”);
}

Fio.disponível usado como Arduino é configurado como mestre ou escravo. Retorna o número de bytes disponíveis para recuperação do barramento I2C. Ele deve ser chamado pelo Arduino mestre após uma chamada para requestFrom e pelo Arduino escravo dentro do manipulador onReceive . Tem esta sintaxe:

Fio.disponível

O método não aceita argumentos. Este é um exemplo válido:

enquanto (Wire.available )
{
char c = Wire.read ;
}

Wire.read – lê um byte transmitido de um dispositivo escravo para um mestre após uma chamada para requestFrom ou se transmitido de um mestre para um escravo. Tem esta sintaxe:

Fio.ler

O método não aceita argumentos. Este é um exemplo válido:

Wire.requestFrom(2, 6);
enquanto(Wire.disponível )
{
char c = Wire.read ;
}

Wire.endTransmission usado por um Arduino e configurado como mestre I2C. Este método é usado para finalizar a transmissão para o escravo I2C e transmitir bytes enfileirados usando o método write . Portanto, ele deve ser chamado após uma chamada ao método write . Tem esta sintaxe:

Wire.endTransmission
Wire.endTransmission(parar)

O método recebe um argumento opcional – stop. É um valor booleano, que se definido como True gera uma condição de parada, liberando o barramento. Se definido como False, gera uma condição de reinicialização, permitindo que o Arduino mestre continue acessando o barramento.

Este método retorna um byte de status, que pode ser 0, 1, 2, 3 ou 4.

  • Se o byte de status for 0, a transmissão foi finalizada com sucesso.
  • Se for 1, os dados eram muito longos para caber no buffer de 32 bytes
  • Se for 2, NACK foi recebido no endereço de transmissão
  • Se for 3, NACK foi recebido na transmissão de dados
  • Se for 4, ocorreu um erro.

Aqui está um exemplo válido deste método:

Wire.beginTransmission(8);
Wire.write(“Olá, sou I2C Master”);
Wire.endTransmission ;

Arduino como mestre I2C
O Arduino pode ser configurado como um mestre I2C chamando Wire.begin sem nenhum argumento. O Arduino mestre pode definir a frequência do clock I2C usando o método Wire.setClock se a velocidade do clock precisar ser modificada.

Ele pode transmitir dados para um escravo chamando os métodos Wire.beginTransmission , Wire.write e Wire.endTransmission . Ele também pode solicitar dados de um escravo usando o método requestFrom e recuperar os dados solicitados usando os métodos Wire.available e Wire.read .

Arduino como escravo I2C
O Arduino pode ingressar no barramento I2C como escravo chamando o método Wire.begin com seu endereço passado como argumento. Ele pode executar um bloco de código em resposta aos dados recebidos do mestre usando o método Wire.onReceive(handler).

Na função manipuladora, os bytes recebidos podem ser lidos usando os métodos Wire.available e Wire.read . Ele também pode executar um bloco de código em resposta a uma solicitação do mestre I2C usando o método Wire.onRequest(handler).

Na função manipuladora, os dados solicitados podem ser enviados usando o método Wire.write .

No próximo tutorial, abordaremos como fazer a interface de um sensor acelerômetro ADXL345 com Arduino usando a interface I2C.

(tagsParaTraduzir)Arduino

Conteúdo Relacionado

Voltar para o blog

Deixe um comentário

Os comentários precisam ser aprovados antes da publicação.