logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

komunikacja ATMEGA16 z eeprom po i2c

WielkiElektron 29 Gru 2010 22:54 1797 4
REKLAMA
  • #1 8932241
    WielkiElektron
    Poziom 10  
    Prosze o pomoc w wyjasnieniu gdzie jest pies pogrzebany.
    Napisałem prosty program w c do ATMEGA32, ktory powinien najpierw zapisac, a nastepnie odczytac wartosc 123 z adresu 2 w eeprom AT24C04 (po I2C) http://www.atmel.com/dyn/resources/prod_documents/doc0180.pdf. Niestety za kazdym razem wartosc odczytana wynosi 255, a zmienna status ma wartosc 32 (brak ACK). Wyprowadzenia A0, A1 i A2 sa podpiete do GND. Mikrokontroler jest taktowany 1Mhz (wewn. gen. RC). Rezystory podciagające linie SDA i SCL mają wartość 10k. Eeprom jest sprawny. Mikrokontroler zaprogramowałem programatorem USBasp z AVRdude.

    Kod:

    
    
    #define F_CPU 1000000UL  // 1 MHz
    #include <avr/io.h>
    #include <stdio.h>
    #include <util/delay.h>
    #include <string.h>
    #include <util/twi.h>
    
    // START
    void twistart(void)
    {
       TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
       while (!(TWCR & (1<<TWINT)));
    }
    
    // STOP
    void twistop(void)
    {
       TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
       while ((TWCR & (1<<TWSTO)));
    }
    
    // transmisja bajtu danych
    void twiwrite(unsigned char data)
    {
       TWDR = data;
       TWCR = (1<<TWINT) | (1<<TWEN);
       while (!(TWCR & (1<<TWINT)));
    }
    
    //odczyt bajtu danych
    int twiread(int ack)
    {
       TWCR = ack ?
       ((1 << TWINT) | (1 << TWEN) | (1 << TWEA))
       :
       ((1 << TWINT) | (1 << TWEN)) ;
       while (!(TWCR & (1<<TWINT)));
       return TWDR;
    }
    
    int main (void)
    {
    int j = 0;   
    TWBR = 255;
    
    //zapis do eeprom
    twistart();
    twiwrite(0b1010000);
    int status = (TWSR & 0xF8);
    twiwrite(2);      //adres     
    twiwrite(123);    //wartosc    
    twistop();      
    _delay_ms(200);
    
    //odczyt z eeprom uprzednio zapisanej wartosci
    twistart();
    twiwrite(0b10100000); 
    twiwrite(2);
    twistart();
    twiwrite(0b10100001); 
    j = twiread(0);      //O - NOACK
    twistop();
    
    //... dalej wyswietlam j na LCD 2x16
    
  • REKLAMA
  • REKLAMA
  • #3 8932952
    Circuit Chaos
    Poziom 13  
    W pierwszym twiwrite() (tym po którym sprawdzasz status) masz o jedno zero za mało. Takie błędy są najbardziej upierdliwe...

    BTW, w avr/io.h jest fajne makro - _BV(x), odpowiadające (1 << (x)). IMO ładniej wygląda :)
  • REKLAMA
  • #4 8933335
    Janadamis
    Poziom 14  
    Ja też dopiero zaczynam się uczyć programować pamięć eprom ale według mnie w tym kodzie jest błąd
    //odczyt z eeprom uprzednio zapisanej wartosci
    twistart();
    twiwrite(0b10100000);
    twiwrite(2);
    twistart();
    twiwrite(0b10100001);
    j = twiread(0);      //O - NOACK
    twistop();
    

    Tam gdzie masz podany adres pamięci czyli
    
    twiwrite(0b10100000);
    twiwrite(0b10100001);
    

    Powinno być to samo w obu przypadkach wiec np. w 1 zamień 0 na 1
    a po za tym to dodaj na początku kodu zapisu takie coś
    unsigned char tmp;
  • #5 8934255
    WielkiElektron
    Poziom 10  
    Tak jak napisał sp5gof, przyczyną był brak jednej cyfry w argumencie twiwrite, po ktorym sprawdzalem status. Zmienilem i dziala.
    Bede uzywal _BV.

    Odnosnie do odpowiedzi Janadamis: najmlodszy bit we wskazanym miejscu odpowiada za READ/~WRITE. Fajnie jest to rozrysowane w datasheetcie AT24C04.

    Dziękuję wszystkim za wskazówki i sugestie.
REKLAMA