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

ATxmega TWI - nie umiem obsłużyć tej magistrali po przesiadce z Mega

Paros 13 Lut 2014 11:37 2499 10
  • #1 13296252
    Paros
    Poziom 11  
    Witam.
    Proszę o podpowiedź, gdzie szukać problemu.

    Na Atmega32 pracującej jako Slave I2C mam wyświetlacz GLCD. Fragment kodu :
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Tutaj raczej nie szukałbym problemu, ponieważ kiedy steruję to z innej Atmegi (8, 128) układ działa bardzo dobrze.

    Fragment kodu nadajnika na Amega (uproszczony, przykładowy):
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Licznik kręci się z zawrotną prędkością, ograniczoną chyba tylko instrukcjami "I2C_WaitTillStopWasSent();"

    Teraz przesiadka na Atxmega (128, 256). TWI i tzw. "drivery" Atmela.
    Funkcja wysyłająca coś po magistrali TWI:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Instrukcja, którą wysyłam dane:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Wszystko niby działa (namęczyłem się sporo zanim zaczęło), ale tylko przy zastosowaniu opóźnień pomiędzy instrukcjami. Jeśli opóźnienia są mniejsze niż dwadzieścia kilka milisekund, program przeskakuje dalej nie wykonując instrukcji. Przykładowo, jeśli pominąłbym opóźnienie tylko po instrukcji czyszczenia ekranu, ekran nie zostanie wyczyszczony, ale pozostałe napisy się wyświetlą.
    Xmega pracuje na domyślnym zegarze 2MHz. Gdzie szukać przyczyny?
  • #3 13299698
    Paros
    Poziom 11  
    Dziękuję za załączniki. Akurat znam je, bo na ich podstawie robię próby opisane w tym wątku. Wciąż nie wiem, dlaczego program nie chce wysyłać kolejnych instrukcji bez (znacznych) opóźnień między nimi. Myślałem nawet, że to Slave nie wyrabia z wykonaniem funkcji, ale jak pisałem "zwykła" Atmega wysyła te dane bez problemu, wystarczą jej opóźnienia "...I2C_WaitTillStopWasSent...". Tak po omacku próbowałem manewrować zegarami zarówno Slave jak i Master - nie pomaga. Próbowałem zmieniać priorytety przerwań TWI. Powyłączałem wszystkie inne części programu używające przerwań. Zrobiłem nawet tak, że w gołym projekcie zaincludowałem tylko dwa pliki (oprócz tych "systemowych") - te od TWI i program miał za zadanie tylko wysłanie kilku danych po I2C. To samo.

    Dodano po 4 [godziny] 4 [minuty]:

    Robię kolejne testy. Wygląda na to, że magistrala TWI jako taka działa dobrze, a problemy są tylko z komunikacją z modułem GLCD.

    Mam też moduł wyświetlacza LED na I2C. Aby wyświetlić cyfry, wymaga on instrukcji: "2, pierwsza cyfra, druga cyfra, trzecia cyfra, czwarta cyfra". Jeśli wpinam ją na magistralę a w pętli głównej wpisuję coś takiego:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    licznik "kręci się jak zwariowany", czyli magistrala działa (oczywiście na ten czas wyłączyłem moduł z GLCD, z którym mam problemy . Jednocześnie pracuje ADC, obsługa IR, USART a wszystko ładnie działa bez konieczności żadnych opóźnień.
  • #4 13302201
    Paros
    Poziom 11  
    Podpiąłem analizator stanów na magistralę. Łapałem przebieg do kodu poniżej:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Obrazki "delay" oznaczają przebieg z odkomentowanymi liniami "delay" - w tym przypadku wszystko działa dobrze, ale ja nie chcę takich opóźnień.
    Obrazki "no_delay" powstały po zakomentowaniu opóźnień .

    Czy ktoś z Was mógłby się temu przyjrzeć - może uda się wywnioskować, gdzie tkwi problem?
  • #5 13302667
    JarekC
    Poziom 32  
    Witam,

    Nie pokazałeś jak zorganizowany jest odbiór w SLAVE.
    Kiedy ustawiany jest znacznik BUF_status.st_ready i co robi funkcja BUFEmpty?
    Czy odbiór I2C masz zorganizowany na przerwaniach?

    Pamiętaj że musisz uwzględnić czas wykonania rozkazów GLCD, chyba że masz podwójny bufor.

    Pozdrawiam
    JarekC
  • #6 13303698
    Paros
    Poziom 11  
    Program na GLCD skleiłem z dwóch bibliotek - I2C Slave TMF (pierwsza książka)
    oraz obsługa wyświetlacza autorstwa "SunRivera" udostępnionej przez niego na Dropie.

    Podejrzewam, że mogłem coś namieszać w I2C - biblioteka była pisana na Atmega 88, ja skompilowałem ją na Atmega32. Kompilator protestował przeciwko obecności rejestru "TWAMR", którego 32 nie posiada. Po zakomentowaniu tego, program skompilował się bez błędów. Jak już pisałem, układ dobrze współpracuje z "tradycyjnymi" Atmegami. Obsługę I2C Master na Atmega pisał również TMF.

    I2C Slave na Atmega32 wygląda tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Zastanawia mnie symbol NAK z rejestratora na obrazkach "no_delay". Czy to może być NACK tylko źle opisany przez analizator? Gdyby tak, to kto nadaje ten sygnał? Jeśli Slave, to zgodnie z opisem TMF'a bitów stanu związanych z odbiorem w trybie slave, odbiornik miałby status "TW_SR_DATA_NACK" (0x88)? Czyli "Odebrano bajt danych, wysłano NACK (koniec transmisji)" ? Czyli po pierwszym odebraniu adresu i literki 'c' odbiornik odbiera już tylko adresy potwierdzając to sygnałem NACK (robi to w przerwaniach, a sam realizuje np. czyszczenie ekranu)? Czy myślę w "dobrym kierunku"?
  • #7 13304132
    JarekC
    Poziom 32  
    Wszystko się zgadza.
    Masz taka sytuację:

    MASTER wysyła ramkę.

    SLAVE odbiera ramkę i blokuje TWI.(!!!)

    SLAVE analizuje ramkę i wykonuje jedną z funkcji GLCD. Zajmuje mu to xx [ms]

    SLAVE odblokowuje TWI (funkcja BUF_Empty).

    Teraz jeżeli MASTER wyśle następną ramkę zanim SLAVE wykona rozkaz (zajmuje mu to xx[ms]), to SLAVE będzie odpowiadał NAK na wszystkie transmisje bo TWI jest wyłączony.

    Czasy wykonania rozkazów GLCD mogą być różne i są zależne od tego jak została napisana biblioteka LCD.

    MASTER musi poczekać okrećlony czas przed transmisja następnej ramki
    albo transmitować ramki aż otrzyma ACK.

    Pozdrawiam
    JarekC
  • #8 13304206
    Paros
    Poziom 11  
    Dzięki, tak intuicyjnie wyczuwałem. Czy byłbyś jeszcze uprzejmy spojrzeć na kody dla Mega, które przesyłają te dane bez oczekiwań, a nic się nie dzieje? W którym miejscu tych funkcji jest oczekiwanie na gotowość Slave i jak to przełożyć na funkję nadającą w Xmega?
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Dotychczas sądziłem, że funkcja " I2C_WaitTillStopWasSent();" od TMF'a jest równoważna z "while (twiMaster.status != TWIM_STATUS_READY);" od Atmela dla Xmega...

    A gdyby tak po stronie Slave, w pętli głównej przed " BUFEmpty(); " wstawić jakieś oczekiwanie na zakończenie poszczególnych funkcji... Może na koniec każdej z tych funkcji ustawianie/zerowanie jakiejś flagi?
    Czy to możliwe, żeby wykonanie funkcji obsługi GLCD trwało aż tak długo? Kiedy zmniejszałem opóźnienia poniżej 25ms układ wariował...

    Dodano po 1 [godziny] 19 [minuty]:

    Chyba wreszcie zbliżam się do jakiegoś finału. Podłączyłem analizator na magistralę, gdzie GLCD sterowane jest z Atmegi8 z funkcjami TMF. Na obrazku widać, że pomimo braku "_delay_ms()" w kodzie, transmisja danych i tak zaczyna się dopiero w okolicach 23ms. Wcześniej są tylko sekwencje "Start .. NACK". Czyli obsługa wyświetlacza faktycznie trwa tak długo (czy to normalne?)...
  • #9 13305443
    JarekC
    Poziom 32  
    Czas obsługi wyświetlacza zależy od tego jak została napisana biblioteka.

    Jeżeli jest to standardowy wyświetlacz zgodny z HD4470 to czas wykonania
    komendy to około 40us a dla komendy ClearDisplay około 2ms.

    W przypadku gdy biblioteka jest pisana dla konfiguracji bez odczytu bitu
    zajętości (linia R/W na stałe podłączona do masy) wielu autorów idzie na łatwiznę
    i nie rozróżnia jaki rozkaz jest wykonywany i wstawia opóźnienie większe niż 2ms.
    Co powoduje że wykonanie każdego rozkazu trwa tyle, pomimo że wyświetlacz
    był gotowy już znacznie wcześniej.

    Sprawdź jak jest w twojej bibliotece do obsługi wyświetlacza.

    Pozdrawiam
    JarekC
  • #10 13305648
    Paros
    Poziom 11  
    to jest wyświetlacz GLCD na sterowniku KS108....
REKLAMA