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

[Attiny2313][AVRStudio] Komunikacja USI/SPI + żyroskop ADIS16100

m1ly 10 Cze 2011 02:24 4142 15
  • #1 9595559
    m1ly
    Poziom 10  
    Witam,

    Mam problem z nawiązaniem komunikacji za pomocą SPI z żyroskopem.
    Korzystam z płytki testowej ZL11AVR oraz żyroskopu ADIS16100.
    Chcę odczytać dwa bajty z żyroskopu(SLAVE) i wysłać je przez USART na komputer.
    Jednak cały czas w otrzymuje znak 0xFF
    Nie mam pojęcia dlaczego komunikacja SPI mi nie działa.

    Piny podłączone mam następująco:
    SCLK <-> CLK
    MISO(PB6) <-> DO
    MOSI(PB5) <-> DI
    SS(PB4) <-> CS

    Wyjście MISO sprawdzałem na oscyloskopie i widać było, że bajty są przesyłane. Niestety mam do niego dostęp tylko podczas zajęć.
    Również zwierając MISO z MOSI otrzymuję bajt 0x10.

    Oto kod programu:

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


    Będę wdzięczny za wszelkie sugestie.
  • Pomocny post
    #2 9597072
    paw789
    Poziom 18  
    Popełniasz kilka poważnych błędów w inicjacji USI. Poczytaj uważnie dokumentację, m.in. fragment inicjacji "SPI Master Operation Example" na str 140.
    W programie który umieściłeś pownieneś wykorzstywac fakt że funkcja spi() zwraca wartośc, zamiast przekazywać wartość za pomocą rejestru USIDR.
  • #3 9605318
    m1ly
    Poziom 10  
    Dzięki za odpowiedź. Znalazłem ciekawy poradnik odnośnie konfiguracji SPI na Attiny. Link
    Odkryłem również, że miałem odwrotnie podłączone MISO i MOSI.

    Uwaga dla osób które mają podobny problem z SPI na Attiny.
    W nocie katalogowej podpisy "MISO" i "MOSI" dotyczą ISP, a nie SPI.

    Bazując na poradniku i poradach paw789 obecnie mam taki kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Nadal mam ten sam problem czyli na cały czas otrzymuje 0xFF
  • Pomocny post
    #4 9605739
    Andrzej__S
    Poziom 28  
    Chyba nie doczytałeś jeszcze dokładnie dokumentacji od ADIS16100. Na stronie 5 wyraźnie wynika, że linia SCLK powinna być wstępnie w stanie wysokim, a samplowanie odbywa się przy zboczu opadającym (USICS0 powinno być 1).
  • #5 9605903
    m1ly
    Poziom 10  
    Dziękuje za uwagę. Poprawiłem rejestr i usawiłem wg. zaleceń:
    USICR = (1<<USIWM0)|(1<<USICS0)|(1<<USICS1)|(1<USICLK)|(1<<USITC);

    Nadal mam niestety ten sam problem.
  • Pomocny post
    #6 9606239
    Andrzej__S
    Poziom 28  
    m1ly napisał:
    Dziękuje za uwagę. Poprawiłem rejestr i usawiłem wg. zaleceń:
    USICR = (1<<USIWM0)|(1<<USICS0)|(1<<USICS1)|(1<USICLK)|(1<<USITC);

    Nadal mam niestety ten sam problem.

    To nie wszystko. Nie napisałeś, czy ustawiłeś również pin 7 portu B (USCK) w stan wysoki podczas inicjalizacji SPI.

    m1ly napisał:

    Piny podłączone mam następująco:
    SCLK <-> CLK
    MISO(PB6) <-> DO
    MOSI(PB5) <-> DI
    SS(PB4) <-> CS

    .....

    Odkryłem również, że miałem odwrotnie podłączone MISO i MOSI.

    Trochę to niejasne co piszesz. Dla ścisłości:
    
    __________________________________
    |   ATtiny2313   |   ADIS16100   |
    ----------------------------------
    | USCK (PB7)      |  SCLK        |
    ----------------------------------
    | DO (PB6)        |  DIN         |
    ----------------------------------
    | DI (PB5)        |  DOUT        |
    ----------------------------------
    | SS (PB4)        |  CS          |
    ----------------------------------
    
  • #7 9607414
    m1ly
    Poziom 10  
    Znaczy się w SPIInit() dodać PORTB |= _BV(PB7)?
    Po tej zmianie nadal jest to samo. Może źle bajty konfiguracyjne wysyłam?
  • Pomocny post
    #8 9608279
    Andrzej__S
    Poziom 28  
    m1ly napisał:

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


    Tutaj popełniasz dosyć poważny błąd. Po odebraniu pierwszego bajtu zatrzymujesz transmisję na SPI na stosunkowo długi czas potrzebny na przesłanie tego bajtu poprzez USART.
    Nie to jednak jest najgorsze. Po dokładniejszym przeanalizowaniu noty ADIS16100 zauważyłem dwa dosyć ważne problemy.
    Pierwszy to taki, że stosunek czasu trwania stanu wysokiego do czasu trwania stanu niskiego na linii SCLK może się wahać od 40/60 do 60/40, więc nawet czas potrzebny na skopiowanie pierwszego odebranego bajtu do jakiejś zmiennej tymczasowej może zakłócić transmisję (USIDR nie jest buforowany). Należałoby chyba wprowadzić jakieś opóźnienia podczas transmisji, aby zrównać czasy impulsów zegarowych podczas transmisji i kopiowania USIDR do zmiennej po odebraniu pierwszego bajtu, albo użyć innego źródła sygnału zegarowego, np. Timer/Counter0 overflow.
    Drugi to taki, że ADIS16100 używa innych ustawień polaryzacji i fazy zegara dla nadawania i odbioru. Nie znam zbyt dobrze USI w ATtiny2313, ale zastanawiam się, czy w ogóle uda się to rozwiązać za pomocą interfejsu sprzętowego, czy trzeba będzie napisać obsługę programową z dosyć dokładnym timingiem (czyli najlepiej w ASM).
  • #9 9609495
    m1ly
    Poziom 10  
    Dzisiaj miałem okazje popracować na oscyloskopie z analizatorem stanów logicznych.
    Po paru przeróbkach kodu udało mi się ustawić wszystkie wejścia (CS, DI, SCLK) tak jak jest w dokumentacji żyroskopu. Jedyną niepokojącą sprawą jest mały odstęp czasowy (około dwa bity) między przesyłem pierwszego i drugiego bajtu na wyjściach SCLK i DI. Nie wiem czy to ma wpływ na działanie programu ale przy ciągłym stanie niskim CS myślę, że powinno wszystko działać. Niestety nie ma żadnych rezultatów. Cały czas otrzymuję stan 0xFF. Wydaje mi się, że układ ADIS może być niesprawny. Pod koniec tygodnia będę mieć możliwość sprawdzenia programu na innej sztuce.

    Poniżej zamieszczam obecny kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #10 9697702
    m1ly
    Poziom 10  
    Żyroskop był jednak niesprawny. Po podłączeniu innego egzemplarza układ zaczął odpowiadać. Po poprawieniu kilku drobnych błędów w kodzie udało mi się otrzymać w miarę logiczne dane. Niestety nie odpowiadają one do końca wzorcom z datasheetu. Przede wszystkim wydaje mi się że starszy bajt lub całość jest o jedno zero przesunięta w lewo.

    W załączniku przesyłam wyniki pomiarów dla różnych dostępnych urządzeń (termometr, żyroskop, wyjście Analogowe 1) oraz kod programu.
  • #11 10526180
    Aimeiz
    Poziom 16  
    Mam kłopot ze sterowaniem wyświetlacza od Nokia 6100 przez USI w attiny 85

    Działa bez problemów, tylko jest wolne takie programowe przesyłanie:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    A nie chce działać gdy zastąpię ten kawałek sprzętowym przesyłaniem poprzez USK w trybie SPI Master:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Natomiast na atmega8 działa idealnie i szybciutko poprzez SPI:
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Wyświetlacz jest tak podłączony:
    Connections Attiny85
    LCD_CS PORTB3
    LCD_CLK PORTB2 (USCK)
    LCD_DATA IN PORTB1 (DO)
    LCD_RESET PORTB4
    LCD_BACKLIGHT +5V

    Miałby ktoś pomysł w czym leży przyczyna?
  • #13 10537572
    Aimeiz
    Poziom 16  
    Po żmudnych badaniach znalazłem powód niedziałania poprzez USI, ale niestety niestety wszelkie próby obejścia problemu nie powiodły się.

    Przyczyną jest odwrotny / przesunięty w fazie sygnał CLK.
    Widać to na przebiegach oscyloskopu.

    Ten z działającej prawidłowo procedurki z pętlą for(.....
    [Attiny2313][AVRStudio] Komunikacja USI/SPI + żyroskop ADIS16100

    A ten z wykorzystaniem USI jako SPI Master
    [Attiny2313][AVRStudio] Komunikacja USI/SPI + żyroskop ADIS16100


    W opisie USI nie doszukałem się możliwości zanegowania wyjścia CLK.
    Aby przyspieszyć transmisję, pozostaje napisać procedurkę w assemblerze, lub chyba lepiej zastosować procesor z SPI choćby atmega_8.

    Z drugiej strony, w dokumentacji attiny 85 są pokazane takie przebiegi:
    [Attiny2313][AVRStudio] Komunikacja USI/SPI + żyroskop ADIS16100

    Powinno działać. Może kostka walnięta i wprowadza jakieśprzesunięcie? Mało prawdopodobne.
  • #14 10547272
    Aimeiz
    Poziom 16  
    Próbuję napisać wstawkę assmblerową, która zastąpi kod C:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    To moja pierwsza próba z wstawką assemblerową.
    Czytam opisy w instrukcji do niestety mam trudności ze zrozumieniem w jaki sposób określa się dane wejścia i wyjścia i rejestry jakie ma przydzielić kompilator.
    To jest niestety jak dla mnie dosyć mętnie wytłumaczone w literaturze.
    Napisałem poniższy kod, bazując na przykładach, ale nawet nie daje się skompilować:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Może ktoś z kolegów wie jak się przydziela te zmienne we wstawkach assemblerowych i pomoże mi poprawić kod.
  • #15 10549901
    Aimeiz
    Poziom 16  
    Trochę metodą prób i błądów udało mi się zrobić działający kod.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jest kilkukrotnie szybszy niż pętla for w C. Zbliżony do sprzętowego SPI. Zaczynam już nieco rozumieć pewne niuanse.
    Narazie mało elegancki, bo adres portu B jest wstawiony na sztywno, również wstawiłem na sztywno rejestr 24 zamiast jego wybór powierzyć kompilatorowi.
    Nie umiem też wstawiać komentarzy do linii assemblera.
  • #16 10552230
    Aimeiz
    Poziom 16  
    W końcu załapałem jak się to robi.
    Kod działa, uwzględnia również zdefiniowane wyrażenia

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