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

[Atmega16][C] Obsługa pamięci 24LC16

maciej_333 17 Gru 2011 01:43 1796 8
REKLAMA
MediaMarkt Black Week
  • #1 10269186
    maciej_333
    Poziom 38  
    Odczyt pojedynczych bajtów zwykle się udaje. Problem z odczytem bajtów kolejno po sobie. Poniżej kod:

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


    Zwykle udaje się odczytać klika bajtów, potem program zapętla się przy wysyłaniu warunków startu (procedura I2C_start()) dla kolejnego bajtu. Wygląda to tak, jakby szyna I2C była zajęta. Na linii SCL jest wówczas +5V, na SDA 0V. Mam zastosowane rezystory podciągające, WP dla 24LC16 dołączone do masy. Linie A1...A0 dołączone do masy, choć to nie istotne.

    24LC16 odczytuję sekwencyjnie, odczyt wierszy jest mniej wygodny. Zapis jest raczej poprawny. Próbowałem też z kilkoma 24C08, ale jest identycznie.

    Najciekawszym zjawiskiem jest jakieś dziwne powiązanie USART'u z TWI. Jeżeli odczytanych bajtów z 24LC16 nie wysyłam poprzez USART wszystko pracuje poprawnie. Przy stosowaniu USART jest jak wyżej. Jak to rozumieć ?

    Żeby tak prosta sprawa sprawiała tyle problemu :cry: ...
  • REKLAMA
    MediaMarkt Black Week
  • #2 10269761
    daniel6662
    Poziom 21  
    Nie wiem jak to u ciebie wygląda w pętli głównej, ale po każdym zapisie do pamięci musisz odczekać chwile zanim cokolwiek wyślesz na i2c, wg. Datasheet układu 24lc16 maksymalny czas zapisu to 10ms więc po każdym zapisie tyle trzeba czekać. Co do zakłucania się uatru z twi, spróbuj zastosować buforowanie danych z eepromu tzn. odczytywane dane zapisz w sobie w tablicy i dopiero po skończeniu odczytu wyślij przez uart.
    Pozdrawiam
  • #3 10270126
    maciej_333
    Poziom 38  
    daniel6662 napisał:
    Nie wiem jak to u ciebie wygląda w pętli głównej, ale po każdym zapisie do pamięci musisz odczekać chwile zanim cokolwiek wyślesz na i2c, wg. Datasheet układu 24lc16 maksymalny czas zapisu to 10ms więc po każdym zapisie tyle trzeba czekać. Co do zakłucania się uatru z twi, spróbuj zastosować buforowanie danych z eepromu tzn. odczytywane dane zapisz w sobie w tablicy i dopiero po skończeniu odczytu wyślij przez uart.
    Pozdrawiam


    Zgodnie z datasheet nie muszę czekać 10ms. Mogę równie dobrze czekać na ACK. Z tego co napisali w datasheet dla 24LC16 kostka wystawia NACK dopóki nie wykona wewnętrznego zapisu. To powinno wychodzić na to samo. Jednak zapis mnie teraz mniej martwi.

    W funkcji main mam coś takiego:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Obsługa USARTU wygląda tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
    MediaMarkt Black Week
  • #4 10271366
    daniel6662
    Poziom 21  
    Masz mały konflikt typów, mianowicie "I2C_wyslij" może przyjąć u char a ty próbujesz w nią wcisnąć zmienną "adres" która jest typu u int. Więc teoretycznie przy twoim kodzie możesz zaadresować tylko 256 bajtów pamięci 24LC16 znajdujących się w bloku nr 6.

    A co do UART-a zakłucającego twi spróbuj takiego rozwiązania:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    W załączniku wysyłam sprawdzone procedury do obsługi twi, coprawda nie testowałem na pamięciach ale skoro z rtc i ekspanderami io dały sobie rade to z pamięcią też powinny;)
    Załączniki:
  • #5 10272632
    maciej_333
    Poziom 38  
    "I2C_wyslij" przyjmuje u char, ale co z tego ? Po I2C i tak można jednorazowo wysłać tylko 8 bitów. Stąd u char. 24LC16 zajmuje osiem adresów na szynie I2C dla wysyłki i tyle samo do odczytu (na każdy blok). Do pracy z tą pamięcią potrzeba 11 bitów. Trzy starsze bity idą razem z adresem kostki. Osiem młodszych bitów idzie zaraz potem. Adres jest odpowiednio "krojony". No chyba, że to źle rozumiem.

    Proponowanej sztuczki już próbowałem. Nie da się pracować naprzemiennie z TWI i USART. Trzeba buforować dane w ramie z dużym buforem.

    Kiedyś uruchomiłem TWI w asemblerze bez trudu, a tu takie schody. Jednak tam pracowałem z syntezami PLL, może dlatego.
  • Pomocny post
    #6 10272888
    daniel6662
    Poziom 21  
    A spróbuj w miejsce I2C_odbierz podstawić:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    I w funkcji main:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #7 10272973
    maciej_333
    Poziom 38  
    Spróbuje z tym też. Jednak wyszukałem jeszcze jedną kostkę 24C08 (Siemens). Trzeba przyznać, że ten scalak zachowuje się 100 razy lepiej. Dziwna sprawa, ale ACK przy odczycie w tym scalaku wystawiane jest sporo szybciej, niż w 24LC16 (Microchip). Chyba powinienem kupić nową kostkę. W telewizorach często takie pamięci padały. Ja zaś stosuję w swoim układzie pamięci z odzysku.

    [edit]Zaproponowany kod działa. Jednak dlaczego nie działa tak, jak miałem to zrobione ?
  • #8 10273880
    daniel6662
    Poziom 21  
    Ponieważ twoja procedura odczytu:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Po odebraniu bajtu wystawia ack, a dla 24lc16 oznacza to tyle że master chce następny bajt, i zaczyna go wysyłać, z tym że ty kończysz wtedy transmisje wysyłając stop czego nie jest wstanie wychwycić eeprom i I2C jest wtedy zawieszone. Z procedury I2C_odbierz usuń "(1<<TWEA) |" jeżeli TWEA=1 wtedy twi po odebraniu bajtu wysyła ack.
REKLAMA