Fork me on GitHub

Microcontrolandos

O Blog está passando por uma fase de mudanças. Todos os posts estão sendo atualizados, códigos, links e imagens estão sendo arrumados. Conteúdos novos ainda estão por vir.

Tutorial 6: Biblioteca MikroC: I2C

Share:

Biblioteca MikroC PRO for PIC: I2C




BIBLIOTECA I2C

MikroC PRO for PIC oferece a biblioteca que suporta o modo master I2C.

Alguns MCUs ter vários módulos I2C. A fim de utilizar o desejadorotina da biblioteca, basta alterar o número 1 no protótipo com o número do módulo adequado.

Rotinas

I2C1_Init(const unsigned long clock) - Inicializa o módulo I2C com o clock desejado
 
clock- Clock em Hertz;

I2C1_Start() - Determina o barramento como livre, e envia um sinal de START;

I2C1_Repeated_Start() - Repete o sinal de START;

I2C1_Is_Idle() - Retorna 1 se o barramento estiver livre caso contrário 0;

I2C1_Rd(unsigned short ack) - Lê um byte do escravo e não envia um sinal de
 reconhecimento se ack for 0, ou seja, termina a leitura, caso contrário ele envia
 um sinal acknowledge e prepara para fazer a próxima leitura.
 
ack- sinal de reconhecimento (acknowledge);

I2C1_Wr(unsigned short data) - Envia um byte para o escravo.
data- byte a ser enviado ao escravo; I2C1_Stop() - Envia um sinal de STOP.
EXEMPLO:
void main(){
  ANSEL  = 0;                // Configure AN pins as digital I/O
  ANSELH = 0;
  PORTB = 0;
  TRISB = 0;                 // Configure PORTB as output

  I2C1_Init(100000);         // initialize I2C communication
  I2C1_Start();              // issue I2C start signal
  I2C1_Wr(0xA2);             // send byte via I2C  (device address + W)
  I2C1_Wr(2);                // send byte (address of EEPROM location)
  I2C1_Wr(0xAA);             // send data (data to be written)
  I2C1_Stop();               // issue I2C stop signal

  Delay_100ms();

  I2C1_Start();              // issue I2C start signal
  I2C1_Wr(0xA2);             // send byte via I2C  (device address + W)
  I2C1_Wr(2);                // send byte (data address)
  I2C1_Repeated_Start();     // issue I2C signal repeated start
  I2C1_Wr(0xA3);             // send byte (device address + R)
  PORTB = I2C1_Rd(0u);       // Read the data (NO acknowledge)
  I2C1_Stop();               // issue I2C stop signal
}

11 comentários:

  1. caro colega voce pode escrever um codigo utilizando memeoria E2prom 25AA320, essa memoria utiliza o protocolo SPI.

    ResponderExcluir
  2. Estou tendo alguns problemas para comunicar o PIC 18f4550 com um módulo I2C (PCF8574AT) e um LCD 16x2. Consegui utilizar o Arduino Mega e a biblioteca LiquidCrystal I2C, mas no MikroC e Proteus não funciona seu eu coloco o endereço do Ci do módulo (0x3f). No datasheet mostra que esse endereço ignora o último bit do byte, justamente o que define se será leitura ou escrita (R/W). Se eu utilizo outro endereço a simulação funciona, mas na prática não. Com Arduino da certo, mas no PIC não. Estou utilizando uma biblioteca que baixei do canal Vitor Santos do Youtube, onde ele mostra uma aplicação com esse CI e um PIC16. Será que alguém poderia me ajudar?

    ResponderExcluir
    Respostas
    1. Conseguiu resolver o problema ? estou tendo o mesmo problema que vc.
      att

      Excluir
    2. Cara, eu resolvi, mas faz muito tempo já. Nem lembro como fiz. O que recomendo é que vc use Arduino para descobrir o endereço do PCF8574 e olhar no datasheet qual configuracao para esse endereço.

      Excluir
  3. Amigo bom dia. Como eu faria para enviar um hexa do tipo 0x1C2A? Eu tento enviar mas só vai os últimos 2 dígitos...

    ResponderExcluir
  4. Amigo bom dia. Como eu faria para enviar um hexa do tipo 0x1C2A? Eu tento enviar mas só vai os últimos 2 dígitos...

    ResponderExcluir
    Respostas
    1. Tiago obrigado pela pronta resposta. Realmente funciona, entretanto eu recebo um numero de 16 bits que gera um hexa com 2 nibbles, exemplo: 0x1234 como separo os nibbles antes de enviar via I2C ? Obrigado!

      Excluir
    2. unsigned int valor = 0x1234; //valor inteiro de 16bits
      I2C1_Wr( valor & 0x0F ); //4, nibble menos significativo
      I2C1_Wr( (valor >> 4) & 0x0F ); //3
      I2C1_Wr( (valor >> 8) & 0x0F ); //2
      I2C1_Wr( (valor >> 12) & 0x0F ); //1, nibble mais significativo

      Excluir
  5. Tiago bom dia!! Muito obrigado pela resposta consegui resolver usando sua ideia, mas com a seguinte modificação:
    I2C1_Wr( valor & 0xFF ); //4, nibble menos significativo
    I2C1_Wr( (valor >> 8) & 0xFF ); //2 nibble mais significativo

    Aproveitando, eu agora estou com dificuldade na leitura....

    Só estou conseguindo ler 1 nibble....


    unsigned int retornomem;
    I2C1_Start();
    I2C1_Wr(0xA0 | (DEVICE << 1));
    I2C1_Wr(((char *)&address)[1]);
    I2C1_Wr(((char *)&address)[0]);
    I2C1_Repeated_Start();
    I2C1_Wr(0xA1 | (DEVICE << 1));//Envia o endereço, device e comando de leitura
    retornomem = I2C1_Rd(0);
    I2C1_Stop();
    delay_ms(15);


    Gostaria de ler novamente o valor inteiro.... ex: 0xABCD

    ResponderExcluir