collapse

* Posts Recentes

Amplificador - Rockboard HA 1 In-Ear por almamater
[Ontem às 19:13]


O que é isto ? por KammutierSpule
[26 de Março de 2024, 19:35]


Bateria - Portátil por almamater
[25 de Março de 2024, 22:14]


Emulador NES em ESP32 por dropes
[13 de Março de 2024, 21:19]


Escolher Osciloscópio por jm_araujo
[06 de Fevereiro de 2024, 23:07]


TP4056 - Dúvida por dropes
[31 de Janeiro de 2024, 14:13]


Leitura de dados por Porta Serie por jm_araujo
[22 de Janeiro de 2024, 14:00]


Distancia Cabo por jm_araujo
[08 de Janeiro de 2024, 16:30]


Meu novo robô por josecarlos
[06 de Janeiro de 2024, 16:46]


Laser Engraver - Alguém tem? por almamater
[16 de Dezembro de 2023, 14:23]

Autor Tópico: Implementar I2C a partir de USI  (Lida 3262 vezes)

0 Membros e 1 Visitante estão a ver este tópico.

Offline Capeleiro

  • Mini Robot
  • *
  • Mensagens: 127
Implementar I2C a partir de USI
« em: 03 de Março de 2012, 20:18 »
Agradecia a ajuda de alguém que já tenha usado o USI de um ATtiny861 ou ATtiny85, ou qualquer coisa parecida.

Acontece que, sem muitas dificuldades, consegui pôr um ATtiny85 a comunicar por I2C, usando uma biblioteca conhecida, baseada nas AppNotes que a ATMEL criou.

http://code.google.com/p/attiny45-workshop/source/browse/twi_slave/firmware/?r=d8d7fc391a5414bfa09a5fed2630a4baf587818e

O problema é que não consigo de forma nenhuma fazer os outros ATtinys funcionarem. A biblioteca é exactamente a mesma, mas quando ligo o IC ao bus todos os outros slaves deixam de receber qualquer coisa, fica tudo parado.

Usando uma "espécie de osciloscópio" dá para perceber que quando ligo estes AVRs ao bus as duas linhas ficam a 0V, é esse o problema, mas não percebo o que pode estar a causar.

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.733
  • Helpdesk do sitio
Re: Implementar I2C a partir de USI
« Responder #1 em: 03 de Março de 2012, 21:30 »
Estás a usar esses micros como slaves?
Avr fanboy

Offline Capeleiro

  • Mini Robot
  • *
  • Mensagens: 127
Re: Implementar I2C a partir de USI
« Responder #2 em: 03 de Março de 2012, 21:33 »
Sim, estou.

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.733
  • Helpdesk do sitio
Re: Implementar I2C a partir de USI
« Responder #3 em: 03 de Março de 2012, 21:38 »
A app Note tem uns erros, á uma pessoa que corrigiu isso..
Vê este tópico todo, se não está lá o código corrigido está lá o link para a outro tópico com isso
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=51467
Avr fanboy

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: Implementar I2C a partir de USI
« Responder #4 em: 04 de Março de 2012, 00:45 »
Há de facto uns problemas com o código exemplo e também já esbarrei nisso. Na altura ainda fiz uma correcção e ficou a funcionar mas continuava a ter um problema no arranque. Depois descobri uma outra lib e roubei-lhe umas partes na inicialização e dei mais uns toques. Isto que aqui deixo funciona de certeza com ATtiny26 porque é onde o uso, num bus com 2 ATtiny26, 2 outros dispositivos e um SoC como master. Também já o usei num bus com os 2 ATtiny26 e uma "consola I2C" baseada em Arduino. Este código simula um dispositivo com 2 a 8 registos, em que uns podem ser read-only. O número de registos é definido pela macro I2C_REGISTER_FILE_SIZE (por omissão é 8, mas podes passar ao compilador uma flag de macro para o definir). Esboço de utilização:

// The registers we support. Can be read, some written, through I2C:
enum {
    eI2cReg_Command         = 0,    // R/W   command
    eI2cReg_Status          = 1,    //   R   status
    eI2cReg_Speed           = 2,    // R/W   speed
    eI2cReg_Acceleration    = 3,    // R/W   acceleration
    eI2cReg_Temperature     = 4,    //   R   temperature
    eI2cReg_MotorCurrent    = 5,    //   R   motor current
    eI2cReg_MotorVcc        = 6,    //   R   motor Vcc
    eI2cReg_SwRevision      = 7,    //   R   sw revision
};

byte volatile gI2C_RegFile[I2C_REGISTER_FILE_SIZE];

static void twi_init (void)
{
    byte  my_i2c_addr = PortRead(A, eI2CaddrSel)? 0x22 : 0x23;

    i2c_Set_Reg(eI2cReg_SwRevision, 0x02);      // 0 x <major> <minor>
    // By default all registers are read-only. Set the read-write ones here.
    i2c_Set_Reg_Access(eI2cReg_Command, eI2c_RW);
    i2c_Set_Reg_Access(eI2cReg_Speed, eI2c_RW);
    i2c_Set_Reg_Access(eI2cReg_Acceleration, eI2c_RW);

    i2c_Slave_Initialise(my_i2c_addr);
}

int __attribute__((noreturn)) main(void)
{
    // Init i2c slave interface (do it while interrupts are disabled)
    twi_init();
    ...
    // Enable interrupts
    sei();

    while(1)
    {
        // Handle I2C commands
        byte  chg_mask = i2c_Get_Changed_Mask();
        // If there are any changes in the I2C registers...
        if (chg_mask)
        {
            if (chg_mask & _BV(eI2cReg_Command))        // Command register changed
            {
                byte  cmdVal = 0;
                byte  cmd = i2c_Get_Reg(eI2cReg_Command);
            }
            else if (chg_mask & _BV(eI2cReg_Speed))        // Speed register changed
            {
                ...
            }
        }
        ...
    }
}


O array gI2C_RegFile é onde a lib I2C vai colocar os valores dos registos e tens que o declarar no teu código; quando um master escreve, os valores são lá alterados e a função i2c_Get_Changed_Mask() retorna uma bitmask em que cada bit corresponde a um registo e o bit vem a 1 para os registos que foram alterados. O que escreveres num registo é o que o master vai ler. Isto foi feito para simular que o AVR é um dispositivo I2C tipico com registos. O endereço I2C é decidido pelo estado dum pino, daí aquela 1ª linha da função de inicialização.

Nota1: A lib tem as macros LON e LOFF que escrevem para o pino PA7. Isto pode ser removido, eu tenho lá isto para fazer piscar um LED quando há actividade no I2C dirigida ao dispositivo (se o LED ficar constantemente aceso é porque alguém ficou a prender o bus).

Nota2: A escrita e leitura de registos faz "wrap-around".
« Última modificação: 04 de Março de 2012, 10:54 por Njay »

Offline Capeleiro

  • Mini Robot
  • *
  • Mensagens: 127
Re: Implementar I2C a partir de USI
« Responder #5 em: 04 de Março de 2012, 04:10 »
A app Note tem uns erros, á uma pessoa que corrigiu isso..
Vê este tópico todo, se não está lá o código corrigido está lá o link para a outro tópico com isso
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=51467
Pois, eu tinha ouvido falar destes erros, o que estava a fazer arrancar os cabelos era estar a usar precisamente este código corrigido... Mas depois de ver o código outra vez percebi o meu erro estúpido...

E muito obrigado, Njay, funcionou lindamente e é uma solução muito interessante, vai facilitar na hora de enviar e receber valores de diferentes sensores.

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.598
    • Tróniquices
Re: Implementar I2C a partir de USI
« Responder #6 em: 04 de Março de 2012, 10:53 »
Esqueci-me de avisar que a lib tem as macros LON e LOFF que escrevem para o pino PA7. Isto pode ser removido, eu tenho lá isto para fazer piscar um LED quando há actividade no I2C dirigida ao dispositivo (se o LED ficar constantemente aceso é porque alguém ficou a prender o bus).

A escrita e leitura de registos faz "wrap-around".