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

Xmega ATXmega128A3U - problem z komunikacją TWI z RTC DS3231

Ty-grysek 26 Lut 2016 14:35 3030 29
  • #1 15472996
    Ty-grysek
    Poziom 12  
    Witam,

    Mam problem z komunikacją ATXmega128A3U z RTC DS3231 (w sumie typ RTC chyba nie mam tu nic do rzeczy) po TWI i właśnie w obsłudze TWI (chyba) jest problem.

    Do rzeczy:
    Przy wykonywaniu odczytu program zatrzymuje się w oczekiwaniu na status TWI_MASTER_RIF_bm. Przetestowałem kilka źródeł znalezionych w necie i zawsze to samo, ale mimo pewnego doświadczenia w ATMegach, w Xmega jestem bardzo początkujący.

    Stan fizyczny:
    - używam portu TWIE: PE0 podłączony do SDA, PE1 do SCL
    - rezystory pull-up 4,7k do Vcc
    - GCC C, Atmel Studio 6.2

    Załączony poniżej program ma odczytać z RTC liczbę sekund (pierwszy rejestr DS3231) i błysnąć diodą odpowiednią liczbę razy. Program zatrzymuje się we wskazanym miejscu funkcji uint8_t twi_read_rtc:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #2 15473245
    Konto nie istnieje
    Konto nie istnieje  
  • #4 15473417
    Konto nie istnieje
    Konto nie istnieje  
  • #5 15473630
    Ty-grysek
    Poziom 12  
    :-) Więc tak

    1. Wg dokumentacji xmega sama wysyła START:
    "When the address (ADDR) register is written with a slave address and the R/W bit while the bus is idle, a START condition is issued and the 7-bit slave address and the R/W bit are transmitted on the bus".

    2. Taki schemat, jak w załączonym listingu, pojawia się na wielu stronach internetowych - jako rzekomo działający!

    3. Moja wiedza i doświadczenie są za małe, żeby przetłumaczyć przedstawione etapy 1 - 17 (za które bardzo dziękuję) na odpowiednie wpisy do rejestrów. Dlatego, po przeczesaniu internetu, szukam wsparcia na forum.

    Pozdrawiam
  • #6 15474006
    Konto nie istnieje
    Konto nie istnieje  
  • #7 15475160
    Ty-grysek
    Poziom 12  
    No dobra, zaopatrzyłem się w analizator stanów logicznych, zczytałem rejestr STATUS po kolejnych liniach kodu i oto co mi wyszło:

    RIF - zawsze 0
    BUSERR - zawsze 0
    RXACK - zawsze 0
    ARBLOST - zawsze 0

    przebieg procedury odczytu danych TWI:

    (inicjalizacja TWI)

    status: 00000001 (Bus state = IDLE)
    SCL: ...HHHH...
    SDA: ...HHHH...


    uint8_t address = RTC_SLAVE_ADDRESS;
    address |= 0x01;
    twiname->MASTER.ADDR = RTC_SLAVE_ADDRESS;


    status: 01110010 (Write interrupt flag = 1 / Clok hold = 1 / Received Acknowledge = 1 / Bus state = OWNER)
    SCL: ...HHHHHHLHLHLHLHLHLHLHLHLHLLLLL...
    SDA: ...HLLLLLLLHHHHLLHHLLLLLLHHHHHHH...


    while(!(twiname->MASTER.STATUS & TWI_MASTER_WIF_bm));

    status: 01110010 (j.w.)
    SCL: ...L...
    SDA: ...H...


    twiname->MASTER.DATA = 0x00; // write word addrpointer first

    status: 01110010 (j.w.)
    SCL: ...LLLLLHLHLHLHLHLHLHLHLHLLLL...
    SDA: ...HHHHLLLLLLLLLLLLLLLLHHHHHH...

    twiname->MASTER.ADDR = address; // send read command

    status: 01110010 (j.w.)
    SCL: ...LLLHHHHHHHHHHLHLHLHLHLHLHLHLHLHLLL...
    SDA: ...HHHHHHHHLLLLLLLHHHHLLHHLLLLHHHHHHH...


    while(!(twiname->MASTER.STATUS & TWI_MASTER_RIF_bm)); //<------ tu się zatrzymuje --------

    Czy coś z tego wynika?
    Z góry dziękuję za każdą uwagę :-)
  • #8 15475254
    Konto nie istnieje
    Konto nie istnieje  
  • #9 15475306
    Ty-grysek
    Poziom 12  
    Teraz zatrzymał się na tym nowym while. Wcześniej (po wysłaniu adresu a przed nowym while) mamy:

    status: 01110010 (bez zmian)
    SCL: ...LLLLLHLHLHLHLHLHLHLHLHLLLL...
    SDA: ...HHHHLLLLLLLLLLLLLLLLHHHHHH...
  • #10 15475377
    Konto nie istnieje
    Konto nie istnieje  
  • #11 15475430
    Ty-grysek
    Poziom 12  
    No ok, teraz przeszło dalej.
    Po nowym while statusy i przebiegi jak pisałem.
    Zatrzymuje się tam gdzie kiedyś.

    Dodatkowo co zinterpertował analizator:
    - Setup write to [h (0x68)] + NAK
    - '0' (0x00) + NAK
    - Setup Readed to [i (0x69)] + NAK
  • #12 15475480
    Konto nie istnieje
    Konto nie istnieje  
  • #14 15475549
    Konto nie istnieje
    Konto nie istnieje  
  • #15 15475557
    Ty-grysek
    Poziom 12  
    Całkiem możliwe RTC jest padnięty - z fizycznie wyjętym układem całość reaguje dokładnie tak samo :-) - takie same pzrebiegi. Sprawdzę to dokładnie i dam znać.
  • #16 15475561
    Konto nie istnieje
    Konto nie istnieje  
  • #18 15475648
    Ty-grysek
    Poziom 12  
    Tak, na pewno 32MHz.
    Analizator pokazuje częstotliwość sygnału 100kHz - tak jak chciałem. DS3231 pracuje do 400kHz

    DS3231 na pewno działa - sparwdziłem na Arduino (5V!).
    Swoją drogą - 5 minut i uruchomione :-) (oczywiście tutaj korzystam z bibliotek).
  • #19 15475698
    Konto nie istnieje
    Konto nie istnieje  
  • #20 15475789
    Ty-grysek
    Poziom 12  
    JarekC - to jest to! Dziękuję.
    Adres urządzenia to 0x68, więc mamy do komunikacji D0 i D1

    Chyba jesteśmy blisko - mam już pierwszy odczyt z DS3231 !
    Przy kolejnym odczycie staje tam gdzie zawsze...

    Dodano po 29 [minuty]:

    Mam teraz taką sytuację:

    (inicjalizacja)

    PIERWSZY PRZEBIEG:

    status: 00000001 (Bus state = IDLE)
    uint8_t address = RTC_SLAVE_ADDRESS;
    address |= 0x01;
    twiname->MASTER.ADDR = RTC_SLAVE_ADDRESS;

    status: 01100010 (Write Interrupt Flag, Clock Hold, Owner bus state)
    while(!(twiname->MASTER.STATUS & TWI_MASTER_WIF_bm));
    status: 01100010 (Write Interrupt Flag, Clock Hold, Owner bus state)
    twiname->MASTER.DATA = 0x00; // write word addrpointer first
    status: 01100010 (Write Interrupt Flag, Clock Hold, Owner bus state)
    while(!(twiname->MASTER.STATUS & TWI_MASTER_WIF_bm));
    status: 01100010 (Write Interrupt Flag, Clock Hold, Owner bus state)
    twiname->MASTER.ADDR = address; // send read command
    status: 10100010 (Read Interrupt Flag, Clock Hold, Owner bus state)
    while(!(twiname->MASTER.STATUS & TWI_MASTER_RIF_bm));
    status: 10100010 (Read Interrupt Flag, Clock Hold, Owner bus state)
    return twiname->MASTER.DATA;

    i jest OK.

    DRUGI PRZEBIEG:

    status: 10100010 (Read Interrupt Flag, Clock Hold, Owner bus state)
    uint8_t address = RTC_SLAVE_ADDRESS;
    address |= 0x01;
    twiname->MASTER.ADDR = RTC_SLAVE_ADDRESS;

    status: 01001011 (Write Interrupt Flag, Arbitration Lost, Busy bus state)
    while(!(twiname->MASTER.STATUS & TWI_MASTER_WIF_bm));
    status: 01001011 (Write Interrupt Flag, Arbitration Lost, Busy bus state)
    twiname->MASTER.DATA = 0x00; // write word addrpointer first
    status: 01001011 (Write Interrupt Flag, Arbitration Lost, Busy bus state)
    while(!(twiname->MASTER.STATUS & TWI_MASTER_WIF_bm));
    status: 01001011 (Write Interrupt Flag, Arbitration Lost, Busy bus state)
    twiname->MASTER.ADDR = address; // send read command
    status: 00000011 (Busy bus state)
    while(!(twiname->MASTER.STATUS & TWI_MASTER_RIF_bm));

    i tu się zatrzymuje...

    ARM? Kurcze, dopiero co przeszedłem z ATMega na ATXMega...
    Obiecuję - zainteresuję się :-)
  • #21 15475903
    Konto nie istnieje
    Konto nie istnieje  
  • Pomocny post
    #22 15475937
    grko
    Poziom 33  
    @Ty-grysek
    Obadaj sobie datasheet DS3221 str 17

    Cytat:

    Figure 5. Data Write/Read (Write Pointer, Then Read) Slave Receive and Transmit


    Teraz weź zobacz co Twoja funkcja robi. Moim zdaniem powinno to mniej więcej wyglądać tak:

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


    Pomijam tutaj obsługę błędów. Coś bardziej zaawansowanego znajdziesz tutaj:
    https://github.com/mojo-chan/xmega_twi/blob/master/xmega_twi/twi.c
  • #23 15478585
    Ty-grysek
    Poziom 12  
    Panie Grzegorzu,

    Mam wrażenie że kierując mnie do dokumentacji RTC ma Pan zastrzeżenia do sposobu adresowania. W moim kodzie może nie jest to tak czytelne jak u Pana, ale też jest rozwiązane poprawnie: adres DS3231 0x68 jest przesuwany o 1 bit w lewo i uzupełniany w najmłodszym bicie 1 lub 0 - w zależności od kierunku transmisji.

    chcę zwrócić uwagę że mam już pierwszy odczyt i jet poprawny. Problem mam teraz z kolejnym odczytem, gdyż zatrzymuje się pod koniec - podczas czekaniu na status:
    while(!(twiname->MASTER.STATUS & TWI_MASTER_RIF_bm));
    nawet po dodaniu:
    twiname->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;
    czego u mnie brakowało. I wygląda na to że to RTC blokuje transmisję, bo reset Xmegi nie pomaga (po resecie nie mam nawet pierwszego odczytu), muszę zresetować RTC i znowu mam pierwszy odczyt a na drugim się zatrzymuje. Wydaje mi się że chodzi o status Arbitration Lost.

    Co do załączonego linku - na tym kodzie nie udało mi się uzyskać transmisji. Wprawdzie program już się nie zatrzymuje (wszak taką ma konstrukcję), ale nie uzyskuję żadnych odczytów. Za głęboka woda dla mnie jak na początek...[/spoiler]
  • #25 15479216
    Konto nie istnieje
    Konto nie istnieje  
  • #26 15492074
    Ty-grysek
    Poziom 12  
    Udało mi się stworzyć działający kod, głównie dzięki linkowi podanemu przez GrzegorzKostka - bardzo dziękuję.

    Mimo że odczytuję i zapisuję dane, to jednak nadal jest coś nie tak: funkcja odczytu TWI_read jest poprawnie wykonywana dokładnie co drugi raz - szczegóły w komentarzu funkcji. Nie mam pomysłu co może być nie tak. Procedura zapisu działa OK.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #27 15492870
    Konto nie istnieje
    Konto nie istnieje  
  • Pomocny post
    #29 15493076
    Konto nie istnieje
    Konto nie istnieje  
  • #30 15494642
    Ty-grysek
    Poziom 12  
    Fakt, wygląda na to, że TWI nie był w trybie smart. Poprawiłem inicjalizację i wygląda na to że wszystko działa jak należy. Poniżej cały, sprawdzony i działający kod. Dziękuję wszystkim za konstruktywną pomoc :-)

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