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

[STM32] Komunikacja SPI z ADS7843 , STM32 nie wysyła komend

^Rachel 24 Maj 2012 17:05 10256 49
Najlepsze odpowiedzi

Dlaczego STM32F4 nie wysyła poprawnie komend SPI do ADS7843 i jak to skonfigurować, żeby transmisja działała?

STM32 nie wysyłał komend, bo piny SPI były źle skonfigurowane, a transmisja była obsługiwana w złej kolejności: dla SPI trzeba wybrać właściwą funkcję alternatywną, w tym przypadku AF6, a nie przypadkowe wartości, oraz poprawnie ustawić rejestry GPIO/AFR [#10930328] [#10932638] Nie podnoś CS w trakcie nadawania; trzymaj go w stanie niskim przez całą ramkę i dopiero po zakończeniu transmisji czekaj na BSY=0, zanim przełączysz CS na wysoki [#10931601] [#10931396] W prostym nadawaniu wystarczy poczekać na TXE, zapisać do DR i przy odbiorze używać RXNE; samo odczytywanie DR nie inicjuje nowej transmisji [#10931396] [#10933050] Dla ADS7843 trzeba wysłać 3-bajtową ramkę: pierwszy bajt to komenda, a dwa kolejne zawierają wynik, więc układ może wymagać 16 taktów albo odczytu dwóch bajtów z odrzuceniem ostatnich 4 bitów [#10933050] [#10933600] Jeśli na analizatorze nie było widać przebiegów, sprawdź też częstotliwość próbkowania — zbyt niska może ukryć sygnały SPI [#10932921]
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA
  • #1 10930252
    ^Rachel
    Poziom 21  
    Posty: 570
    Pomógł: 15
    Ocena: 149
    Witam !

    Tak jak w temacie, STM nie wysyła w ogóle komendy WriteSPI.

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


    Prosty programik testujący tylko WriteSPI, badałem go na analizatorze logicznym.
    STM tylko poprawnie zeruje i ustawia bit CS podczas komendy WriteSPI, lecz nie wysyła sygnałów CLK DOUT i DIN ( linie te są w stanie 0 ).

    Proszę o pomoc.
  • REKLAMA
  • Pomocny post
    #2 10930328
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Po pierwsze - nie wybrałeś która niby funkcja alternatywna ma być na pinie.
    Po drugie - pętle oczekujące w funkcji WriteSPI masz całkowicie źle.
    Po trzecie - czemu mamy się domyślać, że chodzi Ci o STM32F4?

    4\/3!!
  • Pomocny post
    #3 10930459
    gaskoin
    Poziom 38  
    Posty: 4159
    Pomógł: 436
    Ocena: 102
    Włączanie samego SPI też bym wyniósł poza wszelkie konfiguracje. Czasami prowadzi to do problemów - wpisanie konfiguracji z jednoczesnym włączeniem. No i czy Twoje SPI Ma mieć 164,0625 kHz ? Jeśli tak, to polling nie jest najszczęśliwszym pomysłem :)
  • #4 10930535
    ^Rachel
    Poziom 21  
    Posty: 570
    Pomógł: 15
    Ocena: 149
    Dzięki , dopiero od tygodnia bawię się tym STM32F4. Więc też jest dużo błędów.
    Cytat:
    Po pierwsze - nie wybrałeś która niby funkcja alternatywna ma być na pinie.


    To się tak robi ? :
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    bo wywaliło błąd w tej linijce :
    main.c(22): warning:  #175-D: subscript out of range


    gaskoin napisał:
    No i czy Twoje SPI Ma mieć 164,0625 kHz ? Jeśli tak, to polling nie jest najszczęśliwszym pomysłem :)


    polling ? a co to takiego ? a te 164 kHz to jest najmniejsza wartość prędkości wybrana na preskalerze, dobrze by było mieć te 80kHz , bo błąd wtedy by był najmniejszy ( http://www.mikrokontroler.pl/sites/default/files/ADS7843.pdf strona 5 ostatni wykres )
  • Pomocny post
    #5 10930592
    gaskoin
    Poziom 38  
    Posty: 4159
    Pomógł: 436
    Ocena: 102
    Polling w tym przypadku oznacza mniej więcej przesył manualny :D

    Procesor ma 168MHz, a czekając na paczki, które idą z prędkością 160kHz to równie dobrze mógłbyś go zwolnić do 1MHz. W przypadku tak wolnych transferów DMA jest idealne. Jeśli chcesz mieć większą kontrolę nad transferem to przerwania.

    Jeżeli nie przeszkodzi Ci to w dalszym postępie projektu to możesz zwolnić magistralę APB1 jeśli chcesz mieć wolniejsze SPI. Aczkolwiek sama prędkość przesyłu raczej nie ma znaczenia. Bardziej to, jak często będziesz odpytywał układ. Transmisja może mieć 100GHz a odpytywać możesz urządzenie raz w roku.

    To nie tak z tym AF. GPIO ma dwa rejestry AFRL i AFRH, które ST wymyśliło sobie zrobić w dwuelementowej tablicy (AFR[0] i AFR[1], notabene jest więcej takich dziwnych niuansów, nie wiadomo czym podyktowanych :P).

    Zajrzyj do RM0090 do sekcji GPIO jak wyglądają opcje tych rejestrów (AFRL i AFRH) to się stanie wszystko jasne. Natomiast w Datasheecie procesora jest napisane jaką wartość ustawić dla poszczególnych pinów.
  • REKLAMA
  • Pomocny post
    #6 10930672
    Jado_one
    Poziom 22  
    Posty: 650
    Pomógł: 43
    Ocena: 12
    gaskoin napisał:

    To nie tak z tym AF. GPIO ma dwa rejestry AFRL i AFRH, które ST wymyśliło sobie zrobić w dwuelementowej tablicy (AFR[0] i AFR[1], notabene jest więcej takich dziwnych niuansów, nie wiadomo czym podyktowanych :P).

    Warto też zaglądać do pliku stm32f4xx.h, żeby dokładnie zobaczyć jak oni to podefiniowali - bo czasami manual swoje, a tam swoje :-)
  • Pomocny post
    #7 10930760
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    ^Rachel napisał:
    To się tak robi ? :

    Pobierz z mojej strony przykładowy projekt dla STM32F4 i tam masz funkcję do konfiguracji portów, która zajmuje się za Ciebie takimi detalami.

    http://www.freddiechopin.info/pl/download/category/6-przyklady

    4\/3!!
  • #8 10931128
    ^Rachel
    Poziom 21  
    Posty: 570
    Pomógł: 15
    Ocena: 149
    Wolę ręcznie poustawiać wszystko, bo tak szczerze to trochę mnie to śmieszy , żeby były biblioteki do ustawiania I/O gdzie to powinno być najprostsze ?

    W stm32f4xx.h jest tylko taka informacja :
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Zakładając że AFR[2] to starsza część rejestru , konfiguracja pinów alternatywnych będzie wyglądać tak ? :
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    [/code]
  • Pomocny post
    #9 10931147
    gaskoin
    Poziom 38  
    Posty: 4159
    Pomógł: 436
    Ocena: 102
    ^Rachel napisał:

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


    Zakładając że AFR[2] to starsza część rejestru , konfiguracja pinów alternatywnych będzie wyglądać tak ? :
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    [/code]


    Rachel załamujesz mnie :D
    __IO uint32_t AFR[2] to deklaracja tablicy dwuelementowej a w C indeksuje się je od 0 :)
  • #10 10931192
    ^Rachel
    Poziom 21  
    Posty: 570
    Pomógł: 15
    Ocena: 149
    GPIOC->AFR[1] |= (0x06<<10)|(0x06<<11)|(0x06<<12);

    tak powinno być , bo wcześniej bład wywalało

    AFR[1] starsza część, AFR[0] młodsza

    Dodano po 4 [minuty]:

    To teraz funkcja WriteSPI narazie bez DMA.

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


    TXE: Transmit buffer empty
    0: Tx buffer not empty
    1: Tx buffer empty

    RXNE: Receive buffer not empty
    0: Rx buffer empty
    1: Rx buffer not empty

    Czyli się zgadza, ale nie działa ;)
  • Pomocny post
    #11 10931396
    gaskoin
    Poziom 38  
    Posty: 4159
    Pomógł: 436
    Ocena: 102
    Wykrzyknik masz w nie tym miejscu co trzeba no i bez sensu sprawdzasz RXNE skoro nic przecież nie odbierasz. Powinieneś tylko poczekać na opróżnienie bufora nadawania. Zmień położenie wykrzyknika i powinno ruszyć.
    BTW najpierw powinieneś coś wysłać a potem czekać na opróżnienie bufora - nie na odwrót jak u Ciebie.

    Acha i jeszcze jedna rzecz. To cały kod ? Bo jeśli tak to Twój kontroler działa na 16MHz. APB1 tak samo na 16MHz, a Twój SPI na 62.5 kHz.
  • REKLAMA
  • #12 10931501
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    gaskoin napisał:
    BTW najpierw powinieneś coś wysłać a potem czekać na opróżnienie bufora - nie na odwrót jak u Ciebie.

    Nieprawda - właśnie lepiej czekać PRZED, bo po wysłaniu wcale nie musisz - możesz w tym czasie robić coś innego. Jest to rozwiązanie o wiele bardziej optymalne - czekając PO czekasz ZAWSZE (nawet jak za chwilę nic nie będziesz wysyłał. Czekając PRZED czekasz tylko jak jest potrzeba. A z ustawieniem CS i tak trzeba czekać na inny bit, bo TXE ani RXNE niekoniecznie znaczą, że transmisja się skończyła... Do tego celu jest bit BSY.

    ^Rachel napisał:
    Wolę ręcznie poustawiać wszystko, bo tak szczerze to trochę mnie to śmieszy , żeby były biblioteki do ustawiania I/O gdzie to powinno być najprostsze ?

    Po pierwsze nie mówimy o "ustawianiu" (zero/jeden) pinów, tylko o ich konfiguracji.
    Po drugie to się robi zwykle raz na początku i koniec.
    Po trzecie nawet jak chcesz przestawić na coś innego, to bez funkcji jest to jeszcze bardziej bolesne, bo trzeba zerować części rejestrów.
    Po czwarte zaś - jak będziesz miał do skonfigurowania 50 różych pinów w 15 różnych plikach, to też będziesz wolał robić wszystko ręcznie zamiast np tak:
    gpio_pin_cfg(LED_GPIO, LED_pin, GPIO_OUT_PP_25MHz);
    ?
    Po ostatnie - z takiej funkcji od razu widać co ustawiasz, z Twoich liczb - nikt nic nie skuma.

    4\/3!!
  • #13 10931574
    ^Rachel
    Poziom 21  
    Posty: 570
    Pomógł: 15
    Ocena: 149
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Zmieniłem troche kod, nie działa. Co zauważyłem jeszcze, że nic nie zapisuję do bufora DR, sprawdziłem to tym kodem :
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    na wyswietlaczu wyswietla sie 0 ..
  • Pomocny post
    #14 10931601
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Nie działa bo podnosisz CS w trakcie wysyłania. Przeczytaj to co napisałem w poprzednim poście.

    Kod na który to zmieniłeś jest już zupełnie bezsensu, a wnioski które wyciągnąłeś całkowicie błędne.

    4\/3!!
  • #15 10931669
    ^Rachel
    Poziom 21  
    Posty: 570
    Pomógł: 15
    Ocena: 149
    Siedząc nad jednym problemem cały dzień już przestaję myśleć i robię wszystko zgadując :(

    Biorąc pod uwagę poprzednie posty wydaje mi się że powinno to tak wyglądać :
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Bit 7 BSY: Busy flag
    0: SPI (or I2S)not busy
    1: SPI (or I2S)is busy in communication or Tx buffer is not empty
    This flag is set and cleared by hardware.
  • #17 10931743
    ^Rachel
    Poziom 21  
    Posty: 570
    Pomógł: 15
    Ocena: 149
    Pomiar analizatorem logicznym :
    [STM32] Komunikacja SPI z ADS7843 , STM32 nie wysyła komend

    SCK = 1
    MOSI = 0
    MISO = 1
    CS = dziala poprawnie

    Dodano po 57 [minuty]:

    Sprawdzałem w debugu, nic nie mogę wpisać do rejestru DR
  • #18 10932015
    Mechanik PSC
    Poziom 12  
    Posty: 29
    Pomógł: 7
    Ja zrobię mały OT i na dodatek komuś podpadnę mocno, ale mam to w d ... Jak ktoś zaczyna to prościej napisać te 5 linijek za pomocą standardowych bibliotek STM niż się zastanawiać, czy dobrze ustawiłem 13 bit w rejestrze którymśtam. Funkcja inicjalizacji SPI, konfiguracja pinów dla funkcji alternatywnych to kilka linijek standardowej biblioteki i po sprawie. Jak ktoś potem chce dociekać dlaczego własnie tak, a nie inaczej to jest na to zawsze odpowiedni czas. Ale w życiu nie siedziałbym tygodnia nad niedziałającą transmisją SPI skoro do jego uruchomienia są gotowce. Wszelkie inicjalizacje w przeważającej większości przypadków robi się raz jeden na początku aplikacji. I moim zdaniem czy funkcja konfiguracji zajmie 100 baajtów, czy 160 nie ma w tym przypadku żadnego znaczenia. Dziękuję za uwagę i przepraszam za OT.
  • Pomocny post
    #19 10932276
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Mechanik PSC napisał:
    Jak ktoś zaczyna to prościej napisać te 5 linijek za pomocą standardowych bibliotek STM niż się zastanawiać, czy dobrze ustawiłem 13 bit w rejestrze którymśtam.

    OK, masz pięć (słownie: 5) linijek - zmieść w nich inicjalizację SPI z konfiguracją pinów - sam to napisałeś. Czekam. Chyba że chodziło Ci o 50 linijek, to co innego...

    Mechanik PSC napisał:
    Wszelkie inicjalizacje w przeważającej większości przypadków robi się raz jeden na początku aplikacji.

    Czyli do wysyłania danych (wpisy do DR, oczekiwanie na flagi w SR, ...) już byś nie korzystał z SPL, czy może tam - z rozpędu - również?

    Mechanik PSC napisał:
    I moim zdaniem czy funkcja konfiguracji zajmie 100 baajtów, czy 160 nie ma w tym przypadku żadnego znaczenia.

    A jak będziesz miał różnicę typu 20bajtów vs 1kB to też bez znaczenia? Bo inicjalizacja SPI na rejestrach to generalnie są dwie linijki (nie liczę RCC i GPIO) i to dwie linijki z przypisaniem do rejestru, a nie dwa wywołania funkcji z milionem ifów każda...

    Co do problemu głównego:
    Wrzuć CAŁY swój kod, żebyśmy zobaczyli w jakiej jest postaci dokładnie teraz. Naprawdę proponuję skorzystać (choćby chwilowo) z funkcji, która ustawi konfigurację pinów, bo wbrew pozorom jest to dosyć skomplikowane w STM32, a w STM32F4 jeszcze bardziej skomplikowane...

    I nie sugeruj się komentarzami jak powyżej - bardzo dobrze że nie korzystasz z tej bzdurnej biblioteczki zwanej SPL (;

    4\/3!!
  • Pomocny post
    #20 10932474
    Jado_one
    Poziom 22  
    Posty: 650
    Pomógł: 43
    Ocena: 12
    Ja od siebie dodam, że czasami problemem jest nie tyle błąd procedury konfigurujacej piny, co właściwy dobór opcji konfiguracyjnych do danego peryferium.
    Czasami trzeba to robić "na czuja", na doświadczenie albo metodą prób i błedów.
    Mam na myśli tutaj właściwy wybór wyjścia typu PP vs OD, uwzględnienie Pull Up/Down'ów, itp....
  • #21 10932485
    ^Rachel
    Poziom 21  
    Posty: 570
    Pomógł: 15
    Ocena: 149
    Oto cały program :
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Ok spróbuję z tą biblioteką konfiguracji pinów.

    Dodano po 20 [minuty]:

    Mam rozumieć, że z biblioteką program ma wyglądać tak ? :
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Dodano po 4 [minuty]:

    Jeśli tak to nie działa, wszystkie piny = 0
  • #22 10932638
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    ^Rachel napisał:
    GPIOC->AFR[1] |= (0x06<<10)|(0x06<<11)|(0x06<<12); //0x00066600;

    To jest źle - popatrz na swój komentarz i zastanów się jakim cudem coś takiego miałoby wyjść.

    ^Rachel napisał:
    Mam rozumieć, że z biblioteką program ma wyglądać tak ? :

    Nie tak. Wybrałeś funkcje alternatywne 10, 11 i 12. Powinno być w każdym pinie od SPI ..._AF6_...

    4\/3!!
  • #23 10932699
    ^Rachel
    Poziom 21  
    Posty: 570
    Pomógł: 15
    Ocena: 149
    Ok zmieniłem na GPIOC->AFR[1] |= 0x00066600;
    i w debugerze niby działa , tzn laduje wartość do rejestru DR. Ale nic nie wystawia na piny.

    [STM32] Komunikacja SPI z ADS7843 , STM32 nie wysyła komend

    Dodano po 2 [minuty]:

    Dziwny przebieg na analizatorze :
    [STM32] Komunikacja SPI z ADS7843 , STM32 nie wysyła komend
  • Pomocny post
    #24 10932707
    Jado_one
    Poziom 22  
    Posty: 650
    Pomógł: 43
    Ocena: 12
    Ja u siebie konfigurację PIN'ow rozwiązałem stosując makro (jeszcze jedna alternatywa dla konfiguracji I/O).
    Przykładowe definicje dla portów SPI (ale SPI1, więc będą trochę inne od SPI3) pokazują, które rejestry/opcje trzeba uwzględnić podczas konfiguracji pinów:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #25 10932710
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Naprawdę przestałbym odczytywać na Twoim miejscu rejestr DR, bo on pełni dwie funkcje w zależności od tego czy odczytujesz czy zapisujesz... Bo jak odczytujesz, to wcale nie widzisz tego co przed chwilą zapisałeś, tylko to co ODEBRAŁEŚ poprzednio. Nie ma możliwości odczytania tego co zapisałeś.

    4\/3!!
  • #26 10932740
    ^Rachel
    Poziom 21  
    Posty: 570
    Pomógł: 15
    Ocena: 149
    Spróbowałem Pull Up i nic nie pomogło. Już nie mam sił do tego...

    Spróbowałem także odpalić SPI 2 w ten sam sposób i też nie działa :(

    Dodano po 34 [minuty]:

    Już bym to dawno zrobił programowo i w przerwaniu na timerku co 80kHz... ale jest SPI to wstyd nie wykorzystac
  • REKLAMA
  • #27 10932879
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    A nie jest przypadkiem tak, że sygnały są zbyt szybkie dla analizatora? W końcu cała transmisja odbywa się niby w momencie gdy CS jest w stanie niskim. Jak długo trwają te momenty?

    4\/3!!
  • #28 10932921
    ^Rachel
    Poziom 21  
    Posty: 570
    Pomógł: 15
    Ocena: 149
    Freddie Chopin napisał:
    A nie jest przypadkiem tak, że sygnały są zbyt szybkie dla analizatora? W końcu cała transmisja odbywa się niby w momencie gdy CS jest w stanie niskim. Jak długo trwają te momenty?

    4\/3!!


    Nie wierze ! :D rzeczywiście , po ustawieniu Sampling Rate na 1MHz widać jak ładnie idą sobie dane :
    [STM32] Komunikacja SPI z ADS7843 , STM32 nie wysyła komend

    Dodano po 47 [sekundy]:

    Wykres powyżej dla 0xA3

    Dodano po 7 [minuty]:

    To teraz jak to jest z tym odczytem danych ? Po wysłaniu komendy , układ odpowiada daną 12-bitową
  • #29 10933050
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    No i tu będzie problem... Jeśli do układu możesz wysłać 16-taktów zegara zamiast 12, to po prostu odbierasz dwa bajty, a ostatnie 4 bity ignorujesz (pamiętaj o dobrym poskładaniu tak odebranych danych). Jeśli taktów ma być właśnie 12, to zostaje Ci tylko SPI programowe );

    P.S. Może być też takie wymaganie, że przez całą transmisję (rozkaz, odpowiedź) CS ma być w stanie niskim, więc będziesz to musiał może zmienić w swoich funkcjach.

    4\/3!!
  • Pomocny post
    #30 10933600
    Piotr Piechota
    Poziom 22  
    Posty: 519
    Pomógł: 55
    Ocena: 85
    ADS7843 do komunikacji używa 3 bajtowej ramki. W pierwszym bajcie wysyłasz polecenie a w dwu ostatnich dostajesz wynik (które bity wykorzystać masz w dokumentacji).

    PS tak jak pisał Freddie musisz zmienić sterowanie CS.
    PS2 widzę, że układ ma też inne możliwości komunikacji np. tryb 8-bitowy

Podsumowanie tematu

✨ W dyskusji poruszono problem komunikacji SPI między mikrokontrolerem STM32F4 a układem ADS7843, w którym STM32 nie wysyłał komend. Użytkownicy wskazali na błędy w konfiguracji pinów oraz w logice funkcji WriteSPI. Zasugerowano poprawki dotyczące ustawienia funkcji alternatywnych dla pinów, a także optymalizację kodu, aby poprawić działanie SPI. Wskazano na znaczenie odpowiedniego ustawienia flag SPI oraz na konieczność utrzymania stanu CS w niskim poziomie przez cały czas trwania transmisji. Użytkownicy podzielili się również doświadczeniami związanymi z używaniem analizatorów logicznych do monitorowania sygnałów SPI oraz z problemami związanymi z odczytem danych.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA