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

Pamięć EEPROM 24C16 zapis/odczyt

.3lite 01 Maj 2011 18:46 8281 17
REKLAMA
  • #1 9458467
    .3lite
    Poziom 17  
    Witam,

    od razu zaznaczam, że dopiero zaczynam przygodę z programowaniem mikroprocesorów (niedawno zakładałem temat z problemem uruchomienia programatora stk500v2) no i tutaj napotykam większy problem:

    Ostatnio znalazłem pamięć EEPROM typu 24C16, która służyła do zapisu ustawień przedwzmacniacza audio (nie mój projekt) no i jako, że sam układ przestał dawno temu działać to zabrałem pamięć próbując coś zapisać na niej - tutaj już nie jestem pewien czy wykonuje COKOLWIEK dobrze, sam kod piszę na bazie tego pdf'a:
    http://www.datasheetcatalog.org/datasheets/208/160469_DS.pdf

    Na razie to co wyskrobałem wygląda tak:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Mógłby mnie ktoś chociaż naprowadzić czy to dobrze robię?
  • REKLAMA
  • #2 9459421
    skalsky5000
    Poziom 21  
    Jaki to procesor ? Nie lepiej wykorzystać sprzętową obsługę I2C?
  • REKLAMA
  • #3 9459432
    .3lite
    Poziom 17  
    Jest to Atmega8, zapewne lepiej ale sensowniej jest się czegoś nauczyć przy tym.
  • #4 9459462
    skalsky5000
    Poziom 21  
    Miedzy zapisami daj jakieś opóźnienie bo pamięć potrzebuje czasu na zapis danej .Sprawdzasz jakoś dane jakie zapisałeś ?
  • #5 9459468
    .3lite
    Poziom 17  
    Jeszcze właśnie nie napisałem funkcji do czytania danych, jak na razie chciałem tylko spytać czy w ogóle dobrą droga idę czytając tego pdf'a i pisząc ten kod.
  • #6 9459623
    acid12
    Poziom 21  
    dobrze robisz czytajac note, odnośnie adresu:
    str 7 pierwszy akapit. pisze tam poco są 3 linie adresowe (u ciebie zwarte na stałe z masa) i jak ich uzyc
    Cytat:

    The most significant bit must
    be a one followed by the A2, A1 and A0 device select bits
    (the A1 bit must be the compliment of the A1 input pin signal). The next 3 bits are used for memory block addressing
    and select one of the eight 256 x 8 memory blocks. These
    bits should be considered the three most significant bits of
    the data word address. The eighth bit of the device address
    is the read/write select bit. A read operation is selected if
    this bit is high or a write operation is selected if this bit is
    low.


    poczytaj o I2C (albo TWI - jeden kit tylko inna nazwa), jak sie adresuje urządzenia.
    powodzenia w dalszej pracy :)
  • #7 9467599
    .3lite
    Poziom 17  
    Okej, z tego co zrozumiałem skoro mam podpięte do GND adres to normalnie 0xA0, no to wyskrobałem ile wlezie tego kodu ale dalej nie rozumiem o co chodzi z tym potwierdzeniem (ACK), mógłby ktoś wyjaśnić? Tutaj to co do tej pory napisałem (nie działa jeszcze):
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Prosiłbym aby ktoś chociaż powiedział gdzie robię błąd w kodzie i czy w ogóle dobrze się za to biorę (czytając o magistrali I2C tak to rozumiem).
  • REKLAMA
  • #8 9467791
    krru
    Poziom 33  
    Standardowa 24C16 nie ma żadnych linii adresowych. Ma na sztywno A0.
    Do zapisu i odczytu używa się innych adresów - tj do zapisu adres jest parzysty a do odczytu nieparzysty, o 1 większy - tutaj A1
    Funkcja eeprom_rbyte nie zwraca wartości.
  • #9 9467957
    acid12
    Poziom 21  
    adres urzadzenia tj:

    1 A2 ~A1 A0 X X X W/R

    gdzie X - adres bloku danych
    A2, A0 - stan na liniach adresowych
    ~A1 - odwrotny stan niż na liniii adresowej
    W/R - ustawiasz bit lub nie zaleznie czy piszesz lub czytasz

    jezeli masz A2-A0 -> GND to u Ciebie powinno to byc

    1010 X X X W/R,

    chyba że tak jak krru pisze podesłałeś DS do innego układu :)
  • #10 9468229
    krru
    Poziom 33  
    Jest taka wersja 24C16, która ma adresy na starszych bitach - produkuje to chyba Atmel i ma oznaczenie AT24C16.
    Standardowa wersja nie ma żadnych linii adresowych, te piny są NC.
    Ale to chyba nie ważne. Jeśli wszystkie te piny połączy się na GND to adresy będą A0-A8.
    Pozostaje problem nie zwracania wartości przez eeprom_rbyte(). Brakuje return temp; na koncu.
  • REKLAMA
  • #11 9468421
    piotrva
    VIP Zasłużony dla elektroda
    no niestety znaleziony przez mnie datasheet tych pamięci (at24cxx, w tym at24c16) mówi co innego:
    http://dhost.info/ky3orr/funkcje/download.php?dzial=pliki&link=dokumentacje/at24cxx.pdf
    proszę spojrzeć na stronę 8 - wyraźnie przy wersji 16 piny są NC a 3 najmłodsze bity adresu to adres strony (pomijając bit R/W)
    zaś kolega znalazł datasheet kości z taką samą pamięcią, ale to jest model at24c164 i w nim rzeczywiście da się za pomocom tych pinów adresować układ.
    Więc pozostaje pytanie, jaką pamięć w rzeczywistości kolega ma at24c16 czy at24c164 :D
  • #12 9468434
    .3lite
    Poziom 17  
    Pamięć EEPROM 24C16 zapis/odczyt

    Jeszcze dzisiaj wszystko sprawdzę co koledzy napisali, mam nadzieję, że coś wreszcie ruszy.
  • #13 9468578
    piotrva
    VIP Zasłużony dla elektroda
    no to jest ewidentnie 24c16!
    więc korzystaj z tego datasheetu:
    http://dhost.info/ky3orr/funkcje/download.php?dzial=pliki&link=dokumentacje/at24cxx.pdf
    czyli innymi słowy mówiąc masz pamięć o adresie
    0b1010PPPW, gdzie PPP to 3-bitowy adres strony w pamięci, a W to bit R/W
    co też jednoznacznie oznacza, że w układzie nie możesz mieć m. in. zegarów typu pcf8583/8563, bo będzie konflikt adresów. To mówię tak przyszłościowo, bo wiele osób ma z tym problemy
  • #14 9468778
    .3lite
    Poziom 17  
    piotrva napisał:
    no to jest ewidentnie 24c16!
    więc korzystaj z tego datasheetu:
    http://dhost.info/ky3orr/funkcje/download.php?dzial=pliki&link=dokumentacje/at24cxx.pdf
    czyli innymi słowy mówiąc masz pamięć o adresie
    0b1010PPPW, gdzie PPP to 3-bitowy adres strony w pamięci, a W to bit R/W
    co też jednoznacznie oznacza, że w układzie nie możesz mieć m. in. zegarów typu pcf8583/8563, bo będzie konflikt adresów. To mówię tak przyszłościowo, bo wiele osób ma z tym problemy


    OK, czyli wszystkie dobrze bo 10100000 (2) = 160 (10) = 0xA0 (16)

    PPP zostawiamy na 0 na razie bo w tej chwili mało nas to interesuje, R/W podczas write jest zero, a podczas odczytu jest 1:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Coś niestety dalej mojej głowie umyka ponieważ nic nie czyta z układu, dioda świeci.
  • #15 9469944
    Andrzej__S
    Poziom 28  
    Skoro już koniecznie chcesz to zrobić programowo, to proponuję na początek zmianę podejścia. Magistrala I2C jest magistralą typu wired-and. Oznacza to, że stan wysoki wymuszają rezystory podciągające, a tylko stan niski jest wymuszany przez tranzystor na wyjściu mikrokontrolera. Zastanów się, co będzie w sytuacji, gdy pamięć chce wysłać bit potwierdzenia (oznacza to zwarcie linii SDA do masy w 9 takcie zegara) w momencie, gdy wyjście mikrokontrolera wymusza stan wysoki.
    Dla ułatwienia pisania programu proponowałbym zastosować zewnętrzne rezystory podciągające do Vcc na liniach SDA i SCL (wykorzystanie wewnętrznych pull-up'ów nieco skomplikuje sprawę). Jeśli ustawisz odpowiedni bit rejestru PORTB jako 0, to później manipulujesz tylko rejestrem DDRB. Gdy ustawisz za pomocą rejestru DDRB ten pin jako wejście, na odpowiedniej linii magistrali otrzymasz stan wysoki (poprzez rezystor), jak ustawisz jako wyjście - uzyskasz stan niski. W momencie wysyłania przez układ slave bitu potwierdzenia, powinieneś właśnie pozostawić pin odpowiadający linii SDA w stanie wysokiej impedancji (skonfigurowany jako wejście), aby układ slave mógł tę linię zewrzeć do masy.
    Widzę, że coś tam próbowałeś zrobić (makra DATA_IN i DATA_OUT, chociaż obecnie masz je zakomentowane przy odczycie bitu potwierdzenia), ale chyba jednak nie tędy droga. Zwróć uwagę na taki fragment specyfikacji:
    Cytat:

    If a slave can’t receive or transmit another complete byte of data until it has performed some other function, for example servicing an internal interrupt, it can hold the clock line SCL LOW to force the master into a wait state.

    W Twoim przypadku to bez znaczenia, ale podobnie jest z linią SDA w systemach multi-master. Z tego wniosek, że generalnie bezpieczniej nie używać pinów sterujących liniami SDA i SCL jako wyjścia w stanie wysokim.

    Druga sprawa - popracuj jeszcze nad tym kodem. Nie analizowałem wszystkiego dokładnie, ale weźmy przykładowo funkcję eeprom_sbyte():
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Iterator b pętli for będzie miał w pierwszym przebiegu pętli wartość 16-bitową (w systemie dwójkowym) 0000 0001 0000 0000. Jak myślisz, co się stanie gdy wykonasz funkcję AND ze zmienną 8-bitową byte?

    Dlaczego przykładowo jedno opóźnienie jest uzależnione od warunku if(byte & b)? Czy w przypadku, gdy dany bit jest zerem, to opóźnienia być nie musi? Być może przy zegarze 1MHz ten numer przejdzie (1 takt = 1us), ale jak zmienisz częstotliwość taktowania procesora, to raczej ten kod przestanie działać.

    Więcej już nie sprawdzałem. Proponuję jeszcze raz poczytać specyfikację magistrali, i krok po kroku przeanalizować program zwracając uwagę na opóźnienia w odpowiednich miejscach (rysunek 31 na stronie 33 i tabela 5 na stronie 32). Chyba, że ten kod ma być tylko dla treningu i będzie działał tylko przy częstotliwości taktowania 1MHz, wtedy jest szansa, że niektóre potrzebne opóźnienia "zrobią się same" pod wpływem wykonywanego programu. Przykładowo takie konstrukcje CLK_OFF; i DATA_OFF; następujące zaraz po sobie przy taktowaniu 16MHz to już raczej nie przejdą.
  • #16 9470563
    .3lite
    Poziom 17  
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Poprawka na 1 << 7, plus dodatkowo kilka opóźnień i chyba dostaje teraz potwierdzenie (dioda zostaje włączona), wcześniej przy złym przesunięciu bitowym jak wyżej kolega wspomniał dioda nie włączała się (DATA w stanie wysokim była).

    Jeszcze tylko teraz read trzeba poprawić, niestety tu już coś innego jest źle ale chyba idziemy w dobrym kierunku :)
  • #17 9470841
    Andrzej__S
    Poziom 28  
    Odnoszę wrażenie, że zignorowałeś początkowy fragment mojej odpowiedzi, a to jednak bardzo istotne. Spójrz na stronę 10, rysunek 6 i zwróć uwagę na takie miejsce oznaczone "clock line held low while interrupts are serviced", pomyśl dobrze, to na pewno zrozumiesz, dlaczego robisz źle ustawiając piny sterujące magistralą (SDA i SCL) jako wyjścia w stanie wysokim. Mam nadzieję, że rozumiesz, na czym polega wired-and. Jest to też pokazane na rysunku 3 (strona 8) specyfikacji magistrali.
  • #18 10779075
    .3lite
    Poziom 17  
    Rozwiązanie tak jak napisałem + uwaga kolegi Andrzej__S czyli zmiana stanu wysoki/niski mając rezystory podciągające.
REKLAMA