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

Jak skonfigurować STM32 do transmisji USART3 z DMA po zdarzeniu TXE?

francuz8912 27 Lis 2011 13:51 4918 28
REKLAMA
  • #1 10188472
    francuz8912
    Poziom 10  
    Posty: 11
    Witam kolegów, mam problem z transmisją szeregową z wykorzystaniem DMA. Chciałbym osiągnąć następujący wynik, po każdym zdarzeniu TXE wysyłana będzie ramka poprzez USART3. Poniżej zamieszczam kod:
    Ustawienie USART3:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    Ustawienie DMA:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    Pętla główna main:
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Po włączeniu STM'a ramka wysyła się raz, po czym milczy. Chciałbym aby po każdym zdarzeniu TXE ramka się wysyłała. Wydaje mi się że źle wywołuje zdarzenie lub coś innego źle robię. Proszę szanownych kolegów o pomoc.
  • REKLAMA
  • #2 10188586
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Zamień te cyferki na odpowiednie makra z nagłówków, bo nie sądzę aby komukolwiek chciało się bawić w sprawdzanie który bit od czego jest.

    Kanały DMA trzeba włączyć bitem EN, a jak licznik zjedzie do zera, to one się wyłączają.

    Poniżej przykładowy konfig dla SPI i działania z przerwaniami:
    Kod: text
    Zaloguj się, aby zobaczyć kod


    No i jaki ma sens wysyłanie przez DMA JEDNEGO znaku?

    4\/3!!
  • REKLAMA
  • #3 10189068
    francuz8912
    Poziom 10  
    Posty: 11
    Dzięki Freddie Chopin za szybką odpowiedz. Sprawdziłem w debagerze czy po zejściu licznika (wartość CNDTR) do zera wyłącza się kanał DMA. Okazuj się iż jest nadal włączony. Twój kod zbyt wiele mi nie pomógł, wcześniej tez go spotkałem w innym temacie na forum. Na początku chcę przesyłać jeden bajt cyklicznie(czyli po każdym wywołaniu zdarzenia TXE), i chciałbym żeby przynajmniej to mi zadziałało. Jeżeli to już będzie działało to rozwinę to na całą transmisje.
    Tak jak wspomniałeś zamieniłem cyferki na makra. Poniżej kod:
    USART3:

    Kod: text
    Zaloguj się, aby zobaczyć kod

    DMA:
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Pętla główna:
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Kolejną kwestia: czy jak przesyłam dane przez DMA po każdym zdarzeniu TEX(jeżeli dobrze to zdarzenie wywołuje?) to powinienem używać trybu normalnego jak do tej pory czy trybu kołowego?
  • #4 10189282
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Wpisując w licznik wartość JEDEN zostanie wysłany JEDEN element, po czym DMA się wyłączy. To co widzisz w debuggerze nie ma tu znaczenia, może bit faktycznie wciąż jest ustawiony - nieistotne, DMA nie działa po wysłaniu zadanej ilości danych.

    Nie wiem też absolutnie jakim cudem chcesz "ustawiać flagę nadawania" w rejestrze CR1, skoro ta flaga jest generowana automatycznie jeśli nie ma niczego do nadania, czyli generalnie po włączeniu UARTa jest ona ustawiona natychmiast, po wpisaniu danej do rejestru na chwilę się zeruje, aby ponownie ustawić się gdy UART przechwyci wartość rejestru... "Zdarzenia TXE" nie da się "wywołać" ręcznie. Przypuszczam że ustawiasz jeden na bicie odpowiedzialnym za przerwanie od TXE, którego nie masz (funkcji przerwania), a więc następuje natychmiastowy zwis układu.

    4\/3!!
  • #5 10190406
    francuz8912
    Poziom 10  
    Posty: 11
    W sumie to co napisałeś Freddie Chopin dużo wyjaśnia to co się działo z STM. Musisz mieć rację. Napisz mi tylko jeszcze czy jest możliwe zrobić czegoś takiego:
    W USAR'cie gdy chciałem wysłać 1 bajt np. co 1sek to wówczas ustawiałem flagę nadawania program przechodził do procedury obsługi przerwania i kopiował zawartość zmienne do rejestru nadawczego i tak co 1sek gdy została ustawiona flaga nadawania.
    A teraz chciałem uzyskać podobny efekt tylko bez obsługi przerwań.Czyli gdy chce wysłać ramkę ustawiam flagę, wówczas DMA jest wyzwalane i przesyła zawartość zmiennej do rejestru nadawczego a USART wysyła i kończy pracę aż do momentu gdy procedura się nie powtórzy(czyli ustawię flagę). W trybie kołowym ramka przez cały czas jest wysyłana:/ a nie tylko raz co jakiś okres czasu(a to mnie nie urządza).

    Czy jest coś takiego w ogóle możliwe wykorzystując DMA? Bo z tego co zrozumiałem nie:/
  • #6 10190705
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Po pierwsze, to co robiłeś wcześniej to nie było "ustawianie flagi nadawania" tylko włączenie przerwania od pustego bufora nadawczego. No i skoro chciałeś wysyłać coś co 1s, to nie prościej było po prostu... wysyłać to co 1s wpisując owe "coś" do rejestru danych, zamiast korzystać z przerwania?

    No ale nieistotne. Wysyłanie przez DMA jednego bajtu jest nieporozumieniem. No ale to powiedzmy, że też nieistotne. Jeśli chcesz ponownie wyzwolić DMA, to w ogóle nie musisz ruszać UARTu (jego konfiguracji), a jedynie ponownie ustawić bit EN w rejestrze konfiguracyjnym DMA - wyzwoli to kolejny transfer. Ewentualnie możesz najpierw wyzerować całkowicie ten rejestr, a potem wpisać ponownie to co trzeba (włącznie z bitem EN).

    Tylko wciąż nie wiem jaki masz zysk z wysyłania jednego bajtu przez UART co 1s - obawiam się że żaden, ale może to część jakiegoś większego planu.

    4\/3!!
  • #7 10190988
    francuz8912
    Poziom 10  
    Posty: 11
    Tak wiem to wygląda trochę głupio gość piszę że chce wysyłać co 1 sek jeden bajt. Czy nie mógł by po prostu wpisać jej do rejestru nadawczego co 1 sek? A pewnie że by mógł. Tyle że ja ostateczne będę chciał przesyłać 20 elementów tablicy, czyli zapoczątkuje jedno wysyłanie a DMA samo przejedzie po wszystkich elementach tablicy aż licznik zejdzie do 0.
    To co napisałeś jak najbardziej działa i dziękuje ci szczerze za pomoc oraz poświęcony czas. Tego mi właśnie brakowało:) A teraz się tak zastanawiam czy nie ma łatwiejszego sposobu niż wyłącznie kanału DMA i ustawianie go od nowa.
  • #8 10191021
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    No ale nie musisz go ustawiać od nowa (po zakończeniu transferu wszystkie parametry są przecież niezmienione, nawet licznik powraca chyba do starej wartości) - chodzi tylko o ponowne ustawienie bitu EN, a jeśli samo wpisanie tam jedynki nic nie daje, to wyzeruj tylko ten jeden rejestr i następnie ustaw w nim potrzebne bity - to są max 2 linijki, a raczej tylko jedna starczy.

    4\/3!!
  • #9 10191148
    francuz8912
    Poziom 10  
    Posty: 11
    Niestety licznik też trzeba nadpisywać ale i tak jest to wielka oszczędność czasu pisząc 3 linijki a nie robić całą procedurę przerwań dla 20 elementów.
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Jeszcze raz dziękuje za pomoc! Jest rozwiązanie więc myślę że na tym można już zakończyć temat.
  • #10 10406572
    nasiono
    Poziom 17  
    Posty: 355
    Pomógł: 1
    Ocena: 4
    Witam.
    Mam problem z uruchomieniem USARTA1 wykorzystującego DMA do nadawania.
    W trybie "kołowym" wszystko działa .
    Teraz chciałbym uruchomić tryb pojedynczej transmisji staram sie wykonywać wszystko tak jak zaleca datasheet w szczególności str.765 i 783 gdzie przedstawiona jest kolejność działań.
    Zauważyłem w debugerze brak jakiejkolwiek reakcji rejestru CNDTR na próby nad pisania cały czas widnieje 0.

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


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #12 10406674
    nasiono
    Poziom 17  
    Posty: 355
    Pomógł: 1
    Ocena: 4
    Witam.
    Dodałem funkcje DMA1_Channel4->CCR = 0; choć wcześniej było DMA1_Channel4->CCR = DMA_CCR4_DIR ; więc teoretycznie to samo. Tak czy inaczej skutek taki sam niestety bez zmian.
  • #14 10406698
    nasiono
    Poziom 17  
    Posty: 355
    Pomógł: 1
    Ocena: 4
    Teraz część DMA wygląda tak
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Niestety bez zmian.
    Nic z tego nie rozumiem czego się wartości nie nad pisują w rejestrze CNDTR
  • #15 10406728
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Odczyt za pomocą debuggera traktuj jako nie do końca wiarygodny - sam rejestr może przy odczycie nie zwracać faktycznych wartości.

    Tak przy okazji, to proponowałbym ustawiać adresy przy każdym wyzwoleniu - może w tym problem?

    4\/3!!
  • #16 10406774
    nasiono
    Poziom 17  
    Posty: 355
    Pomógł: 1
    Ocena: 4
    Główna pętla przybrała taki kształt

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




    nadal nic.
    Wcześniej nie napisałem, że program zaraz po uruchomieniu wysyła prawidłowo jedną ramkę a potem zapętla się w miejscu " while(!(USART1->SR & USART_SR_TC)); "
  • #17 10406979
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Ten bit (TC) może być ustawiany/kasowany w jakiś sposób przez DMA, ale to raczej mało prawdopodobne. W manualu piszą też, ze ręczne zerowanie bitu TC nie jest polecane dla "normalnych" zastosowań - pozbyłbym się więc tego ręcznego kasowania.

    4\/3!!
  • #18 10407021
    nasiono
    Poziom 17  
    Posty: 355
    Pomógł: 1
    Ocena: 4
    Próbowałem tego niestety choć program nie zatrzymuje się już na pętli to nic poza jednorazowym wyświetleniem ramki się nie dzieje.
    Sam miałem wątpliwości co do kasowania tego bitu na stronie 783 jest takie zalecenie "6. Clear the TC bit in the SR register by writing 0 to it.". Ale tak jak pisze próbowałem i bez tej operacji - bez zmian.

    W trybie Circual wszytko działa , bez DMA niema problemu.
  • #19 10407087
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Ustaw więc to zerowanie CCR ale zrób to w końcu P-R-Z-E-D konfiguracją. "Przed" czyli przed ustawianiem adresów i rozmiaru, bo to też konfiguracja.

    Sprawdź profilaktycznie, czy bit TXC w UART jest ustawiony - bez tego nie będzie nowych żądań transferu przez DMA. Poprzeglądaj rejestry statusowe w poszukiwaniu zapalonych flag błędów (zarówno DMA jak i UART).

    4\/3!!
  • #20 10407212
    nasiono
    Poziom 17  
    Posty: 355
    Pomógł: 1
    Ocena: 4
    Dziękuje zerowanie CCR na samym początku odniosło pożądany skutek. Nie wiem wprawdzie dla czego ale ważne, że działa.
    Kolejny raz DZIĘKI !

    Program ostatecznie wygląda tak.

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



    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #21 10407226
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Opis rejestru CNDTR

    Cytat:
    This register can only be written when the
    channel is disabled. Once the channel is enabled, this register is read-only, indicating the
    remaining bytes to be transmitted.


    4\/3!!
  • #22 10430845
    grzegorzn
    Poziom 13  
    Posty: 128
    Pomógł: 3
    Ocena: 5
    Wydaje mi się, że nie ma sensu zaczynać nowego wątku, więc pozwalam sobie doczepić się tutaj.

    Skonfigurowałem DMA żeby przerzucało wartość z USART1->DR do TIM2->CCR1. W ten sposób steruję wypełnieniem PWM przez seriala. Wszystko działa i w ogóle jest super, ale pod warunkiem, że rozmiar danych jest skonfigurowany jako half word. Wydaje mi się, że powinno też działać z wielkością ustawioną na bajt, bo i tak przesyłane są tylko pojedyncze bajty. Niestety wtedy następuje dziwne zjawisko, wartość się jakby kopiuje na starszy bajt w docelowym rejestrze. Czyli jak w USART1->DR jest 0x00000045 to w TIM2->CCR1 jest 0x00004545. Następuje to przy przesłaniu pojedynczego bajtu, nie ma inkrementacji adresów.
  • #23 10431555
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Przejrzyj w manualu rozdział "13.3.4 Programmable data width, data alignment and endians", ze szczególnym uwzględnieniem akapitu "Addressing an AHB peripheral that does not support byte or halfword write operations".

    Potem patrzysz na początek opisu rejestrów timera i wyczytujesz tam:
    "The peripheral registers can be accessed by half-words (16-bit) or words (32-bit).".

    4\/3!!
  • REKLAMA
  • #24 10432958
    grzegorzn
    Poziom 13  
    Posty: 128
    Pomógł: 3
    Ocena: 5
    Teraz wszystko jasne, dzięki!
  • #25 10984148
    nasiono
    Poziom 17  
    Posty: 355
    Pomógł: 1
    Ocena: 4
    Witam ponownie.
    Uruchomiłem USART na stm32f4 chodzi pięknie . Teraz testowo chce wysłać ciąg 1,2,3 z wykorzystaniem DMA i niestety pomimo moich starań ramka przesyłana jest tylko raz.
    W czym leży problem.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    main
    while:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #26 10987239
    Krauser
    Poziom 26  
    Posty: 508
    Pomógł: 124
    Ocena: 12
    Jak robisz rekonfigurację to wyzeruj DMA_LISR i DMA_HISR używając DMA_LIFCR i DMA_HIFCR.

    PS.
    A w pętli nie wystarczy tylko linia DMA1_Stream6->CR|=DMA_SxCR_EN;
  • #27 10989104
    nasiono
    Poziom 17  
    Posty: 355
    Pomógł: 1
    Ocena: 4
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Rzeczywiście przy kasowaniu flagi od DMA wszystko działa. Nie znalazłem jednak w dokumentacji żadnej informacji na ten temat.
    Dziwne jest jeszcze to, że transfer działa bez zakłócania i przerywania pomimo iż nie sprawdzam żadnej flagi końca. Czy to jest normalne?

    Pozdrawiam i dziękuje.
  • #28 10989705
    Krauser
    Poziom 26  
    Posty: 508
    Pomógł: 124
    Ocena: 12
    Poczytaj RM0090 na stronie 179.
    Nie podoba mi się twój kod. Działa ponieważ DMA1_Stream6->CR |=DMA_SxCR_EN; nie przerywa transmisji, ale również nie zaczyna jej od nowa. Raz trafi i włączy, a innym razem nic nie zaszkodzi. W normalnych warunkach trzeba czekać na zakończenie transmisji. Chodziło mi o to, że po co powtarzać całą konfigurację skoro wszystko jest tak samo.
    Jeśli chcesz wysyłać ciągle to samo to równie dobrze możesz ustawić bit CIRC.
  • #29 10989726
    nasiono
    Poziom 17  
    Posty: 355
    Pomógł: 1
    Ocena: 4
    Na razie eksperymentuje może jak obmyślę szybką sprawną komunikacje może docelowo zastosuje tryb ciągły. Flagę zakończenia docelowo oczywiście będę sprawdzał. Wydaje się że to było by na tyle problem zażegnany. Dzięki.

Podsumowanie tematu

✨ W dyskusji poruszono problem konfiguracji STM32 do transmisji USART3 z wykorzystaniem DMA po zdarzeniu TXE. Użytkownik starał się przesyłać dane cyklicznie po każdym wywołaniu zdarzenia TXE, jednak napotkał trudności z poprawnym działaniem DMA. Uczestnicy forum sugerowali zamianę wartości na makra, włączenie kanałów DMA oraz poprawne ustawienie rejestrów. Wskazano, że DMA nie działa po wysłaniu zadanej ilości danych, a także omówiono kwestie związane z ręcznym kasowaniem bitów w rejestrach. Użytkownik ostatecznie uzyskał działające rozwiązanie, które polegało na ponownym ustawieniu bitu EN w rejestrze DMA po zakończeniu transferu. W dalszej części dyskusji poruszono również problemy z USART1 oraz DMA, a także kwestie związane z przesyłaniem danych do rejestrów peryferyjnych.
Wygenerowane przez model językowy.
REKLAMA