Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

eeprom wewnętrzny uC 89S52 i podobne

kubiaczek1982 07 Apr 2009 17:49 1488 12
  • #1
    kubiaczek1982
    Level 12  
    Witam.

    Poszukuje informacji na temat zapisywania i odczytu eepromu wewnętrznego uC w języku C. Konkretnie chodzi mi o funkcje np

    void zapis_eeprom(int adres, int dana)
    int dana odczyt_eeprom(int adres)

    Mogą być też w innych językach, ale najbardziej zależy mi na C
  • #2
    mirekk36
    Level 42  
    dla zwykłych avr-ków w GCC masz plik nagłówkowy <avr/eeprom.h> - wystarczy do niego zajrzeć i po zawodach (w nim masz właśnie gotowe do tego funkcje) - albo nawet w gogla wklepać i wyjdzie ze 100 podpowiedzi.

    Nie wiem jak dla twojego procka - ale na pewno zagoglować warto
  • #3
    kubiaczek1982
    Level 12  
    niestety ja mam 51 a nie avr, ale może i by pasowało gdybym miał ten pliczek. Mógłbyś go wrzucić??
  • #5
    kubiaczek1982
    Level 12  
    tak to jest jak sie coś wyczyta gdzieś i nie sprawdzi w nocie katalogowej. Dzięki za sprostowanie.

    A może by ktoś wiedział co poplątałem w kodzie I2C:
    Code:

    #define nop() B++

    void Delay1(void)
    {
       nop(); nop(); nop();
       nop(); nop(); nop();
       nop(); nop(); nop();
    }

    void i2c_start(void)
    {
       SDA = SCL = 1; Delay1();
       SDA = 0; Delay1();
       SCL = 0;
    }

    //I2C - stop
    void i2c_stop(void)
    {
       SDA = 0; Delay1();
       SCL = 1; Delay1();
       SDA = 1; Delay1();
    }

    int i2c_odczyt_int(void)
    {
       int i, tab[8], wynik;
       SDA = 1;
       Delay1();
       for(i=0; i<8; i++)
       {
          SCL = 0;
          Delay1();
          if(SDA==1)
          {
             tab[i] = 1;
          }else{
             tab[i] = 0;
          };
          SCL = 1;
          Delay1();
       };
       //potwierdzenie ACK
       SCL = 0;
       Delay1();
       SDA = 0;
       Delay1();
       SCL = 1;

       wynik = zamień(tab[])  <-- część nie istotna bo działa //zamienia tablice na 1 wartość

       retyrn wynik
    }

    //i2c - zapis bajtu
    void i2c_zapis_int(int x)
    {

       tab[] = zamien(x)  <-- część nie istotna bo dziala // zamienia wartość na tablice

       for(i=0; i<8; i++)
       {
          SCL = 0;
          Delay1();
          if(tab[i]==1)
          {
             SDA = 1;
          }else{
             SDA = 0;
          };
          Delay1();
          SCL = 1;
          Delay1();
       }
       SCL = 0;
       Delay1();
       //while(SDA==0);
       SCL = 1;
       Delay1();
    }
  • #6
    adamwesola
    Level 24  
    Istotnym parametrem jest czas cyklu zapisu, wg. not katalogowych różnych typów układów, wynosi on minimum 5ms (sprawdź u siebie). Wiec przy zapisie, po sekwencji STOP, odczekaj , no niech będzie 10ms, przed następna operacja.
    Nie znam C, ale nie widzę u Ciebie nigdzie podawanego adresu urządzenia i związanego z nim bitu odczyt/zapis. Jak mniemam dane do zapisu/odczytu są (?? napewno ?, gdzie ?) przekazywane jako parametry procedur.
    No i tak ładniej, klarowniej napisz procedurkę START, tak jak wzorowo wygląda Twój STOP.
  • #7
    kubiaczek1982
    Level 12  
    A więc na przykładzie zapisu:

    Code:


    i2c_start();                  // i2c  start
    i2c_zapis_int(162);       // adres urządzenia (dobrze obliczony)
    i2c_zapis_int(0);          // zapis pod adres 0
    i2c_zapis_int(dana);     // zapis danej z przedziału 0 - 255 (czyli 1 bit)
    i2c_stop();                  // i2c  stop



    przy odczycie 4 linia wygląda:

    Code:


    dana = i2c_odczyt_int();



    ale problem leży gdzie indziej ponieważ dostawiłem wyświetlanie wartości przekazywanej (x) w pętli for przy zapisie i wyświetla mi 1 przy przekazywaniu liczby 162 do funkcji
  • #8
    bolek
    Level 35  
    A zrób tak, nie pamiętam dlaczego tak robie, ale działa to od lat :)

    Code:

    CALL I2C_START
    MOV A, #160 ; adres układu
    CALL I2C_WRITE
    MOV A, #2FH ; adres komorki
    CALL I2C_WRITE
    MOV A, dana ;dana do zapisu
    CALL I2C_WRITE
    CALL I2C_STOP
    CALL I2C_15MS


    odczyt:

    Code:

    CALL I2C_START
    MOV A, #160 ;ADRES PAMIECI
    CALL I2C_WRITE
    MOV A, #2FH ;ADRES KOMORKI
    CALL I2C_WRITE
    CALL I2C_START
    MOV A, #161 ;ADRES PAMIECI DO ODCZYTU
    CALL I2C_WRITE
    CLR C ;NACK
    CALL I2C_READ
    MOV dana, A
  • #9
    kubiaczek1982
    Level 12  
    Może i by działało, ale na razie mam problem z przekazaniem wartości do pamięci, pozatym funkcja I2C_WRITE i I2C_READ musi być jakoś zbudowana.

    W tej chwili wygląda to tak:

    Code:
    dana wysyłana             dana odbierana
    
       do funkcji               w funkcji

         162                       1
         0                         0
         <255                      1 lub 0
  • #10
    Zaquadnik
    Level 27  
    Ku pamięci, procedury obsługi EEPROMu w AT89S8252/53:

    1. "Aktywacja" EEPROMu:

    Code:

    EECON = EECON | 0x08;



    2. Zapis:

    Code:

    void EEPROMwrite(int adres,char dana)
    {   
       adres;
       dana;
       EECON = EECON | 0x10;
       _asm
       movx @DPTR,A
       _endasm;
       while (!(EECON & 0x02)){}   
       EECON = EECON & 0xEF;
    }


    3. Odczyt:

    Code:

    char EEPROMread(int adres)
    {   
       adres;
       _asm
       movx A,@DPTR
       _endasm;
       return ACC;
    }


    Kompilator: SDCC
  • #11
    bolek
    Level 35  
    -> Kubiaczek. Wkleiłem to żebyś widział schemat zapisu/odczytu. Skąt wiesz że nie działa ci zapis? może odczyt jest do kitu?.

    Jeśli twoja "dana odebrana w funkcji" to ACK, i nie odpowiada na sam adres to może masz zły adres?
  • #12
    kubiaczek1982
    Level 12  
    Faktycznie ACK nie chce wracać (miałem zrobione pominięcie). Może ktoś mi pomoże ustalić jaki powinien być adres. EEprom to 24C02WP, linie adresowe - A0 +5V, A1, A2 GND, wejście WC - GND. Specyfikacja kości. Moim zdaniem zapis to 162 a odczyt 163, ale mylić się mogę więc proszę o sprostowanie. chyba że błędnie rozszyfrowałem czy pin 7 to MODE czy WC.

    --

    Chcąc przetestować jaki adres ma eeprom stworzyłem programik testujący adres od 160 bo (1010xxxx). Wygląda to tak:

    Code:
    void main(void)
    
    {
        for(i=160; i<175; i++)
        {
            lcd_ustaw(0, 1);
            LCD(i);
            I2C_start();
            I2C_zapisz(i);
            I2C_stop();
        }
    }


    dodatkowo w funkcji samego zapisu zamiast zwykłego odbioru ACK zrobiłem:

    Code:
    if(ACK==0)
    
    {
        lcd_ustaw(1,1);
        LCD(i);
    }


    czyli w pierwszej linii wyświetla testowany adres, a w drugiej ten sam adres jeśli nadejdzie potwierdzenie. Potwierdzenia nie dostałem tylko przy adresie 161

    zmieniłem sprawdzanie ACK
    Code:

    SDA = 1;
    if(ACK==0)
    {
        lcd_ustaw(1,1);
        LCD(i);
    }

    i wykryło mi adresy 162 i 163 i takie też mam w programie. Została kwestia który to zapis (ja podejżewam 162 zapis a 163 odczyt) oraz wyjście 7 pamięczy czy powinno być do GND czy +5

    ------

    Dziwna rzecz sie dzieje. Programik sie wiesza po podaniu adresu urządzenia i adresu komórki, ale przy zapisie gdy pin 7 jest podpięty do plusa i przy odczycie gdy podpięty do minusa (albo odwrotnie - zdążyłem sie pogubić). Czy to jest normalne i pin ten powinien być sterowany przez uC:?:
  • #13
    kubiaczek1982
    Level 12  
    Witam ponownie. Już mi wszystko działa. Błąd był w procedurze stopu. Obecnie wygląda ona tak:
    Code:
    void I2c_stop(void)
    
    {
       int a;
       SDA = 0; Delay1();
       SCL = 1; Delay1();
       SDA = 1; Delay1();
       a = SDA;
    }


    brakowało odczytu linii SDA.

    Nie wiem dlaczego, ale musiałem zrezygnować z potwierdzenia ACK przy zapisie na szynę I2C mimo że czyta wszystko jak należy. W tym przypadku mi to nie przeszkadza, ponieważ spowolniłem trochę przesył danych i wszystko śmiga (chyba jest teraz około 50k, ale prawie tego nie widać, a i tak przy potwierdzeniu musze przystopować żeby napis było widać na LCD). Nie wiem czy jest sens zamieszczać cały listing procedur I2C w tym miejscu. jeśli tak proszę napisać to zamieszczę.