Vous êtes sur la page 1sur 11

I2C – Protocolo de ComunicaçãoI2C – Protocolo de Comunicação

Até este momento vimos alguns protocolos de comunicação que o Arduino suporta, como SPI, One-Wire, e mesmo a interface serial é um protocolo de comunicação bem definido. O I2C trabalha no modelo master-slave, com pelo menos um dispositivo atuando como master, e os demais dispositivos atuando como slave. A função do master é coordenar a comunicação, sendo que é ele quem envia informações a determinado slave ou consulta informações. Não vi nenhum setup, ou tutorial, onde o dispositivo slave inicia a comunicação, sempre é o master quem faz esse papel. Podemos ter mais de um master numa conexão I2C, e até 112 dispositivos slaves. Alguns materiais pela Internet, incluindo

o site do Arduino, falam que é possível termos 127 dispositivos num setup I2C, mas eu

acredito que esse número seja teórico, e que 112 dispositivos é um número mais realista.

Nesta página você encontra um excelente material sobre I2C.

Conexão utilizando I2C

I2C é um protocolo de barramento(ou bus), ou seja, com os mesmo fios conectamos todos os dispositivos do nosso setup. Essa característica, barramento, é um dos grandes atrativos do I2C, pois reduzimos em muito a necessidade de pinos de conexão no Arduino, pois usaremos sempre os mesmo fios para a conexão, não importa se estamos utilizando 1 ou 127 dispositivos.

não importa se estamos utilizando 1 ou 127 dispositivos. Um dispositivo conectado ao barramento, atuando como

Um dispositivo conectado ao barramento, atuando como Master, e 3 dispositivos atuando como Slave,

também conectados ao barramento

O Arduino vem com pinos próprios para a conexão I2C, no caso do Uno e derivados os pinos são sempre o 4 (SDA) e 5(SCL). No caso do Arduino Mega, os pinos utilizados são

o 20 (SDA) e 21 (SCL).

SDA significa Serial Data e SCL significa Serial Clock. SDA é o pino que efetivamente transfere os dados, e SCL serve para temporização entre os dispositivos, de modo que a comunicação pela SDApossa ter confiabilidade. Como podem observar, tanto o envio quanto a recepção de dados é realizada utilizando a linha SDA, ou seja, é uma linha bi- direcional de comunicação, ora estamos enviando dados por este pino, ora estamos recebendo dados.

Pinos utilizados para a comunicação I2C Existem uma variedade enorme de dispositivos que utilizam o

Pinos utilizados para a comunicação I2C

Existem uma variedade enorme de dispositivos que utilizam o protocolo I2C, como o próprio Arduino, Raspberry, memórias externas (EEPROM), I/O expanders, RTC (Real Time Clock), Visor (LCD, TFT, etc), sensores diversos(temperatura, acelerômetro, etc). Portanto, uma hora ou outra você certamente vai se deparar com um dispositivo I2C, e saber trabalhar com o protocolo vai ser muito útil. Vários dispositivos oferecem várias interfaces de conexão, ou seja, podemos conectá-lo ao Arduino usando I2C, ou serial, ou SPI, e, depois que aprender I2C, é bem provável que esta seja sua escolha.

Além do SDA e SCL, os dispositivos utilizam o terra (GND) e o Vcc para alimentação. Abaixo um exemplo de ligação mais real:

alimentação. Abaixo um exemplo de ligação mais real: Arduino e outros dispositivos atuando como Slave de

Arduino e outros dispositivos atuando como Slave de um Raspberry Master.

Reparem na imagem acima o uso de resistores pull-up para as linhas SDA e SCL. Estes resistores normalmente são utilizados quando há mais de um slave no barramento, e o valor do resistor é dependente dos dispositivos. Normalmente dispositivos I2C possuem um datasheet, e nele podemos encontrar o valor adequado dos resistores pull-up. Se estiver utilizando apenas um dispositivo slave conectado ao Arduino, não se preocupe, o Arduino já vem com resistores pull-up internos especializados para a comunicação I2C.

Ainda com relação a imagem acima, a ordem que conectamos os dispositivos não importa. Podemos ligar os dispositivos como quizermos, respeitando a pinagem certa, que o resultado final será o mesmo.

A distância normal de trabalho no barramento I2C é de aproximadamente 1 metro.Alem disso podemos ter problemas de impedância, mas ai já não posso ajudar muito, se

de impedância, mas ai já não posso ajudar muito, se lembrem que sou um Zé Mané

lembrem que sou um Zé Mané em eletrônica

estender esta distância de trabalho até aproximadamente 50 metros, e talvez eu faça um

post sobre esses dispositivos futuramente.

. Existem dispositivos que podem

Bem, já sabemos como conectar os dispositivos no barramento, sabemos que podemos ter teoricamente 127 dispositivos, mas… Como saber com qual dispositivos estou falando?

I2C Endereçamento de dispositivos

Dispositivos I2C possuem um endereço que os identifica. Esse endereço é composto normalmente por 7 bits. Se lembram do limite teórico de 127 dispositivos, pois então, com

do limite teórico de 127 dispositivos, pois então, com 7 bits podemos ter 127 valores diferentes

7 bits podemos ter 127 valores diferentes

pois alem dos 7 bits que definem o endereçamento, temos ainda um ultimo bit, totalizando

8 bits, que indicam se é uma operação de leitura ou escrita (read/write). Normalmente os

dispositivos vem indicando o seu endereço no formato hexadecimal, considerando 7 bits. Neste caso o Arduino, atuando como master, insere estes 7 bits no início da transmissão, ajusta adequadamente o oitavo bit, e tudo funciona muito bem.

. Aqui temos um pouco de confusão,

tudo funciona muito bem. . Aqui temos um pouco de confusão, Em alguns casos, o fabricante

Em alguns casos, o fabricante do dispositivo especifica o endereço do dispositivo utilizando o oitavo bit. Nestes casos é comum o datasheet especificar um endereço para escrita e outra para leitura. Nesta situação temos que calcular o endereço correto (7 bits), ou dar um shift em nosso sketch de modo a desconsiderar o oitavo bit.

shift em nosso sketch de modo a desconsiderar o oitavo bit. Como podem ver no exemplo

Como podem ver no exemplo acima, o dispositivo X possui dois endereços( 0x92 e 0x93), sendo que o valor que realmente nos interessa é o 0x49, que é obtido desconsiderando o ultimo bit de qualquer um dos endereços anteriores.

Caso não fique claro pelo datasheet se o seu dispositivo usa 7 ou 8 bits no endereçamento, outra forma é verificar se o endereço esta na faixa de endereços I2C válidos.

Como podem ver, a faixa disponível vai de 0x08 a 0x77. Não se esqueça que

Como podem ver, a faixa disponível vai de 0x08 a 0x77. Não se esqueça que é em hexadecimal, e fazendo as conversões para decimal podemos concluir que o número de

dispositivos possíveis na prática é 112

que o número de dispositivos possíveis na prática é 112 Bem, já sabemos como conectar os

Bem, já sabemos como conectar os dispositivos e como nos direcionar a ele. Vamos começar a brincadeira?

I2C Escritas e Leituras.

Todo o trabalho com dispositivos I2C se resume a uma operação de leitura ou uma operação de escrita. Em nossos sketches, independente do dispositivo, estaremos lendo alguma informação ou escrevendo alguma informação em um dispositivo especifico. Será comum encontrarmos dispositivos com alguma particularidade nas operações de escrita/leitura, mas em geral o datasheet do dispositivo fornece esses detalhes. Vamos ver como funciona a escrita e a leitura de dispositivos I2c.

Uma observação importante para trabalharmos com I2C no Arduino; temos que dar um include na biblioteca Wire. No início de qualquer sketch inclua a linha #include <Wire.h> . Após incluirmos a biblioteca, é necessário inicializá-la dentro de setup() com Wire.begin().

I2C Escrita

A escrita em dispositivos I2C é relativamente simples. O trecho de código abaixo mostra como funciona esse processo:

Wire.beginTransmission(endereço);

Wire.write(memória);

Wire.write(valor);

Wire.endTransmission();

Wire.beginTransmission(endereço); envia o endereço do dispositivo pela linha SDA, sinalizando o dispositivo correspondente que haverá uma comunicação. Todos os dispositivos “escutam” essa informação, mas apenas o dispositivo que possui o endereço informado estará apto a se comunicar. Wire.write(memória); A maioria possui diversos registradores que podem ser gravados, e precisamos informar em qual registrador queremos informação. Wire.write(valor); envia o valor (sempre 1 byte) pela SDA para o dispositivo informado anteriormente. O dispositivo possui um registrador (ou memória) aguardando pela informação, e os outros dispositivos ignoram esta comunicação. O comum é enviarmos uma informação (um byte) em cada operação.

Wire.endTransmission(); Após enviarmos a informação, devemos finalizar a operação com essa linha, liberando o dispositivo e o barramento I2C para novas operações. Não sei se notaram, mas utilizamos o mesmo comando tanto para informar ONDE queremos gravar e O QUE queremos gravar. Essa é uma fonte de confusão inicialmente, mas é relativamente simples. Tudo dependo do datasheet do dispositivo, onde, no caso acima, teríamos a instrução de que, numa operação de escrita, o primeiro byte indica a posição de memória, e o segundo byte indica o valor a ser gravado. Poderíamos muito bem ter um dispositivo com apenas um registrador para gravação, e portanto não seria necessário informar em qual posição é para o valor ser gravado

I2C Leitura.

O processo de leitura envolve mais comandos. Normalmente o dispositivo possui diversos registradores (ou posições de memória) para armazenar diferentes informações, então temos que informar de qual registrador queremos ler informação. Ainda, lembrando que cada registrador armazena um byte, podemos especificar o número de bytes que queremos ler. Vamor ver um trecho de código:

Wire.beginTransmission(endereço);

Wire.write(memoria);

Wire.endTransmission();

Wire.requestFrom(endereço, 1);

byte valor;

if (Wire.available()){

valor=Wire.read();

}

Wire.endTransmission();

As três primeiras linhas foram explicadas anteriormente e, basicamente, posicionam o registrador do dispositivo na posição que queremos fazer a leitura. Na sequência temos:

Wire.requestFrom(endereço, 1); Este comando informa o dispositivo identificado por endereço que queremos ler uma posição de memória(ou byte, ou registrador), a partir da posição de memória especificada anteriormente. Esta informação é posta imediatamente na linha SDA, e o dispositivo então responde informando também na SDA o valor contido no registrador. Neste exemplo estamos pedindo apenas o valor de um registrador, mas poderíamos pedir tantos quanto forem necessários. Neste caso o dispositivo iria informar sequencialmente, a partir da posição informada pelo write anterior. Wire.available(); Este comando verifica se há informação disponível para leitura. O hardware do Arduino armazena em buffer as informações recebidas, e atualmente este buffer tem o tamanho de 32 bytes. com isso podemos fazer tranquilamente a leitura de 32 bytes sequenciais.

Wire.read(); Esta é bem simples, similar ao Serial.read. Basicamente este comando lê um byte de cada vez.

Chega por hoje né?

Bem pessoal, vou ficando por aqui. Espero ter ajudado um pouco. Creio que I2C é uma daqueles casos em que a melhor teoria é a prática, então no próximo post vamos continuar vendo I2C, desta vez aplicando o que vimos aqui no módulo AT24C256.

Abs e até a próxima.

Referências

Blog TronixStuff Endereçamento PDF sobre o protocolo I2C I2C é a sigla de Inter-Integrated Circuit, e basicamente é um protocolo de comunicação entre dispositivos que “falam” I2C.

Até este momento vimos alguns protocolos de comunicação que o Arduino suporta, como SPI, One-Wire, e mesmo a interface serial é um protocolo de comunicação bem definido. O I2C trabalha no modelo master-slave, com pelo menos um dispositivo atuando como master, e os demais dispositivos atuando como slave. A função do master é coordenar a comunicação, sendo que é ele quem envia informações a determinado slave ou consulta informações. Não vi nenhum setup, ou tutorial, onde o dispositivo slave inicia a comunicação, sempre é o master quem faz esse papel. Podemos ter mais de um master numa conexão I2C, e até 112 dispositivos slaves. Alguns materiais pela Internet, incluindo o site do Arduino, falam que é possível termos 127 dispositivos num setup I2C, mas eu acredito que esse número seja teórico, e que 112 dispositivos é um número mais realista. Nesta página você encontra um excelente material sobre I2C.

Conexão utilizando I2C

I2C é um protocolo de barramento(ou bus), ou seja, com os mesmo fios conectamos todos os dispositivos do nosso setup. Essa característica, barramento, é um dos grandes atrativos do I2C, pois reduzimos em muito a necessidade de pinos de conexão no Arduino, pois usaremos sempre os mesmo fios para a conexão, não importa se estamos utilizando 1 ou 127 dispositivos.

não importa se estamos utilizando 1 ou 127 dispositivos. Um dispositivo conectado ao barramento, atuando como

Um dispositivo conectado ao barramento, atuando como Master, e 3 dispositivos atuando como Slave,

também conectados ao barramento

O Arduino vem com pinos próprios para a conexão I2C, no caso do Uno e derivados os pinos são sempre o 4 (SDA) e 5(SCL). No caso do Arduino Mega, os pinos utilizados são o 20 (SDA) e 21 (SCL). SDA significa Serial Data e SCL significa Serial Clock. SDA é o pino que efetivamente transfere os dados, e SCL serve para temporização entre os dispositivos, de modo que a comunicação pela SDApossa ter confiabilidade. Como podem observar, tanto o envio quanto a recepção de dados é realizada utilizando a linha SDA, ou seja, é uma linha bi- direcional de comunicação, ora estamos enviando dados por este pino, ora estamos recebendo dados.

enviando dados por este pino, ora estamos recebendo dados. Pinos utilizados para a comunicação I2C Existem

Pinos utilizados para a comunicação I2C

Existem uma variedade enorme de dispositivos que utilizam o protocolo I2C, como o próprio Arduino, Raspberry, memórias externas (EEPROM), I/O expanders, RTC (Real Time Clock), Visor(LCD, TFT, etc), sensores diversos(temperatura, acelerometro, etc). Portanto, um hora ou outra você certamente vai se deparar com um dispositivo I2C, e saber trabalhar com o protocolo vai ser muito útil. Vários dispositivos oferecem várias interfaces de conexão, ou seja, podemos conectá-lo ao Arduino usando I2C, ou serial, ou SPI, e, depois que aprender I2C, é bem provável que esta seja sua escolha.

Alem do SDA e SCL, os dispositivos utilizam o terra(GND) e o Vcc para alimentação. Abaixo um exemplo de ligação mais real:

Arduino e outros dispositivos atuando como Slave de um Raspberry Master. Reparem na imagem acima

Arduino e outros dispositivos atuando como Slave de um Raspberry Master.

Reparem na imagem acima o uso de resistores pull-up para as linhas SDA e SCL. Estes resistores normalmente são utilizados quando há mais de um slave no barramento, e o valor do resistor é dependente dos dispositivos. Normalmente dispositivos I2C possuem um datasheet, e nele podemos encontrar o valor adequado dos resistores pull-up. Se estiver utilizando apenas um dispositivo slave conectado ao Arduino, não se preocupe, o Arduino já vem com resistores pull-up internos especializados para a comunicação I2C.

Ainda com relação a imagem acima, a ordem que conectamos os dispositivos não importa. Podemos ligar os dispositivos como quizermos, respeitando a pinagem certa, que o resultado final será o mesmo.

A distância normal de trabalho no barramento I2C é de aproximadamente 1 metro.Alem disso podemos ter problemas de impedância, mas ai já não posso ajudar muito, se

de impedância, mas ai já não posso ajudar muito, se lembrem que sou um Zé Mané

lembrem que sou um Zé Mané em eletrônica

estender esta distância de trabalho até aproximadamente 50 metros, e talvez eu faça um post sobre esses dispositivos futuramente.

. Existem dispositivos que podem

Bem, já sabemos como conectar os dispositivos no barramento, sabemos que podemos ter teoricamente 127 dispositivos, mas… Como saber com qual dispositivos estou falando?

I2C Endereçamento de dispositivos

Dispositivos I2C possuem um endereço que os identifica. Esse endereço é composto normalmente por 7 bits. Se lembram do limite teórico de 127 dispositivos, pois então, com

do limite teórico de 127 dispositivos, pois então, com 7 bits podemos ter 127 valores diferentes

7 bits podemos ter 127 valores diferentes

pois alem dos 7 bits que definem o endereçamento, temos ainda um ultimo bit, totalizando

8 bits, que indicam se é uma operação de leitura ou escrita (read/write). Normalmente os

dispositivos vem indicando o seu endereço no formato hexadecimal, considerando 7 bits. Neste caso o Arduino, atuando como master, insere estes 7 bits no início da transmissão, ajusta adequadamente o oitavo bit, e tudo funciona muito bem.

. Aqui temos um pouco de confusão,

tudo funciona muito bem. . Aqui temos um pouco de confusão, Em alguns casos, o fabricante

Em alguns casos, o fabricante do dispositivo especifica o endereço do dispositivo utilizando o oitavo bit. Nestes casos é comum o datasheet especificar um endereço para escrita e outra para leitura. Nesta situação temos que calcular o endereço correto (7 bits), ou dar um shift em nosso sketch de modo a desconsiderar o oitavo bit.

shift em nosso sketch de modo a desconsiderar o oitavo bit. Como podem ver no exemplo

Como podem ver no exemplo acima, o dispositivo X possui dois endereços( 0x92 e 0x93), sendo que o valor que realmente nos interessa é o 0x49, que é obtido desconsiderando o ultimo bit de qualquer um dos endereços anteriores.

Caso não fique claro pelo datasheet se o seu dispositivo usa 7 ou 8 bits no endereçamento, outra forma é verificar se o endereço esta na faixa de endereços I2C válidos.

se o endereço esta na faixa de endereços I2C válidos. Como podem ver, a faixa disponível

Como podem ver, a faixa disponível vai de 0x08 a 0x77. Não se esqueça que é em hexadecimal, e fazendo as conversões para decimal podemos concluir que o número de

dispositivos possíveis na prática é 112

e fazendo as conversões para decimal podemos concluir que o número de dispositivos possíveis na prática

Bem, já sabemos como conectar os dispositivos e como nos direcionar a ele. Vamos começar a brincadeira?

I2C Escritas e Leituras.

Todo o trabalho com dispositivos I2C se resume a uma operação de leitura ou uma operação de escrita. Em nossos sketches, independente do dispositivo, estaremos lendo alguma informação ou escrevendo alguma informação em um dispositivo especifico. Será comum encontrarmos dispositivos com alguma particularidade nas operações de escrita/leitura, mas em geral o datasheet do dispositivo fornece esses detalhes. Vamos ver como funciona a escrita e a leitura de dispositivos I2c.

Uma observação importante para trabalharmos com I2C no Arduino; temos que dar um include na biblioteca Wire. No início de qualquer sketch inclua a linha #include <Wire.h> . Após incluirmos a biblioteca, é necessário inicializá-la dentro de setup() com Wire.begin().

I2C Escrita

A escrita em dispositivos I2C é relativamente simples. O trecho de código abaixo mostra

como funciona esse processo:

Wire.beginTransmission(endereço);

Wire.write(memória);

Wire.write(valor);

Wire.endTransmission();

Wire.beginTransmission(endereço); envia o endereço do dispositivo pela linha SDA, sinalizando o dispositivo correspondente que haverá uma comunicação. Todos os dispositivos “escutam” essa informação, mas apenas o dispositivo que possui o endereço informado estará apto a se comunicar. Wire.write(memória); A maioria possui diversos registradores que podem ser gravados, e precisamos informar em qual registrador queremos informação. Wire.write(valor); envia o valor (sempre 1 byte) pela SDA para o dispositivo informado anteriormente. O dispositivo possui um registrador (ou memória) aguardando pela informação, e os outros dispositivos ignoram esta comunicação. O comum é enviarmos uma informação (um byte) em cada operação. Wire.endTransmission(); Após enviarmos a informação, devemos finalizar a operação com essa linha, liberando o dispositivo e o barramento I2C para novas operações. Não sei se notaram, mas utilizamos o mesmo comando tanto para informar ONDE queremos gravar e O QUE queremos gravar. Essa é uma fonte de confusão inicialmente, mas é relativamente simples. Tudo dependo do datasheet do

dispositivo, onde, no caso acima, teríamos a instrução de que, numa operação de escrita,

o primeiro byte indica a posição de memória, e o segundo byte indica o valor a ser gravado. Poderíamos muito bem ter um dispositivo com apenas um registrador para

gravação, e portanto não seria necessário informar em qual posição é para o valor ser

gravado

I2C Leitura.

O processo de leitura envolve mais comandos. Normalmente o dispositivo possui diversos

registradores (ou posições de memória) para armazenar diferentes informações, então temos que informar de qual registrador queremos ler informação. Ainda, lembrando que

cada registrador armazena um byte, podemos especificar o número de bytes que queremos ler. Vamor ver um trecho de código:

Wire.beginTransmission(endereço);

Wire.write(memoria);

Wire.endTransmission();

Wire.requestFrom(endereço, 1);

byte valor;

if (Wire.available()){

valor=Wire.read();

}

Wire.endTransmission();

As três primeiras linhas foram explicadas anteriormente e, basicamente, posicionam o registrador do dispositivo na posição que queremos fazer a leitura. Na sequência temos:

Wire.requestFrom(endereço, 1); Este comando informa o dispositivo identificado por endereço que queremos ler uma posição de memória(ou byte, ou registrador), a partir da posição de memória especificada anteriormente. Esta informação é posta imediatamente na linha SDA, e o dispositivo então responde informando também na SDA o valor contido no registrador. Neste exemplo estamos pedindo apenas o valor de um registrador, mas poderíamos pedir tantos quanto forem necessários. Neste caso o dispositivo iria informar sequencialmente, a partir da posição informada pelo write anterior. Wire.available(); Este comando verifica se há informação disponível para leitura. O hardware do Arduino armazena em buffer as informações recebidas, e atualmente este buffer tem o tamanho de 32 bytes. com isso podemos fazer tranquilamente a leitura de 32 bytes sequenciais. Wire.read(); Esta é bem simples, similar ao Serial.read. Basicamente este comando lê um byte de cada vez.

Chega por hoje né?

Bem pessoal, vou ficando por aqui. Espero ter ajudado um pouco. Creio que I2C é uma daqueles casos em que a melhor teoria é a prática, então no próximo post vamos continuar vendo I2C, desta vez aplicando o que vimos aqui no módulo AT24C256.

Abs e até a próxima.