KursyPoradnikiInspirujące DIYForum

Kurs STM32 F4 – #7 – Komunikacja przez UART

Kurs STM32 F4 – #7 – Komunikacja przez UART

Tworząc system, w którym mikrokontroler będzie współpracował z innymi urządzeniami, należy w jakiś sposób przesyłać między nimi dane.

Bardzo częstym rozwiązaniem, które implementują konstruktorzy jest UART. W tym odcinku skupimy się na opisie tego interfejsu od strony teoretycznej oraz praktycznej z użyciem kreatora Cube oraz bibliotek HAL.

Komunikacja przez USART / UART

USART / UART (ang. Universal Synchronous and Asynchronous Receiver and Transmitter) służy do przesyłania danych pomiędzy urządzeniami. Znaleźć można go na wyposażeniu praktycznie każdego mikrokontrolera.

Litera S oznacza możliwość zrealizowania komunikacji w trybie synchronicznym, a więc takim, w którym bity przesyłane są w takt zegara podawanego na dedykowanej do tego linii sygnałowej. USART pozwala więc na komunikację zarówno synchroniczną jak i asynchroniczną.

UART pozwala na komunikację typu Full-Duplex. Oznacza to, że dane mogą być jednocześnie nadawane i odbierane. Do komunikacji w takim trybie niezbędne są (co najmniej) trzy linie. Dwie linie transmisyjne - Tx, Rx oraz wspólna masa (GND).

Jak działa UART?

Żeby zrozumieć co ustawiamy w dalszej części konfiguracyjnej, powinniśmy poznać najpierw podstawy działania tego interfejsu. UART ma dwa wyprowadzenia odpowiadające za transmisję i odbieranie danych (Tx oraz Rx).

Wysyłając dane na linii transmisji (Tx) zaczną pojawiać się odpowiednio stany niskie i wysokie. Jakie, kiedy i dlaczego? Aby odpowiedzieć na te pytania, trzeba poznać budowę ramki!

Ramka danych UART

Ramka danych jest odgórnie ustaloną sekwencją znaków, które muszą się pojawić w określonej kolejności podczas komunikacji. Obie strony transmisji (urządzenie nadawcze i odbiorcze) muszą znać parametry tej ramki, aby komunikacja przebiegła pomyślnie.

Ramka UART.

Ramka UART.

  • Stan bezczynności (Idle) - oznacza, że aktualnie nie przebiega żadna transmisja. Komunikowany jest przez wymuszenie stanu wysokiego na linii danych.
  • Bit startu (St) - rozpoczyna każdą ramkę danych. W tym wypadku jest to wymuszenie stanu niskiego na linii danych. Bit startu jest obowiązkowym elementem każdej ramki.
  • Bity danych (0-8) - bity danych reprezentują aktualne informacje, które chcemy przesłać. Standardowo przesyła się ramki złożone z 8 bitów danych. W teorii może być ich od 5 do 9.
  • Bit parzystości (P) - służy jako podstawowa, niskopoziomowa forma sprawdzenia poprawności przesłanych danych. Jest on opcjonalny i jego obecność jest jednym z konfigurowalnych parametrów transmisji. Bit parzystości może działać w dwóch trybach:
    1.  Parzysty - celem jest uzyskanie parzystej sumy bitów danych i bitu parzystości. Jeżeli liczba "jedynek" w bitach danych była nieparzysta, bit przyjmie wartość 1. Jeżeli liczba ta była parzysta, bit parzystości przyjmie wartość 0.
    2.  Nieparzysty - analogicznie do trybu parzystego. Bit parzystości zawsze przyjmie taką wartość, aby sumarycznie liczba bitów w stanie wysokim była liczbą nieparzystą.
  • Bit stopu (Sp1, Sp2) - bit oznaczający zakończenie całej ramki danych. Komunikowany jest jako wymuszenie stanu wysokiego na linii danych. Liczba bitów stopu jest konfigurowalna i może wynosić 1 lub 2.

Mam nadzieję że przedstawiona tu teoria nie znudziła was do reszty. Jestem pewny, że dzięki tej odrobinie informacji dalsza część artykułu będzie bardziej zrozumiała.

Sprzęt potrzebny do realizacji zadań

Aby przetestować UART w praktyce będziemy potrzebować konwertera USB-UART, który możecie znaleźć na wyposażeniu zestawu przygotowanego specjalnie na potrzeby tego kursu.

Gotowe zestawy do kursów Forbota

 Komplet elementów  Gwarancja pomocy  Wysyłka w 24h

Zestaw elementów do przeprowadzenia wszystkich ćwiczeń z kursu STM32 F4 można nabyć u naszego dystrybutora! Zestaw zawiera m.in. płytkę Discovery, wyświetlacz OLED, joystick oraz enkoder.

Zamów w Botland.com.pl »

UART - konfiguracja dzięki CUBE

Przejdźmy w takim razie do rzeczy i użyjmy UARTa w praktyce!

Krok 1. Tworzymy nowy projekt i konfigurujemy zegar na maksymalną częstotliwość.

Krok 2. Włączamy peryferium USART 1 w trybie asynchronicznym.

Uruchomienie UARTa w odpowiednim trybie.

Uruchomienie UARTa w odpowiednim trybie.

Zauważ, że po włączeniu UARTA na podglądzie natychmiast pojawiły się wyprowadzenia TX oraz RX. Co, gdy nie podoba nam się ich umiejscowienie i chcielibyśmy wyprowadzić je gdzieś indziej?

Zmiana wyprowadzeń, czyli pin remapping w STM32 F4

Rodzina F4 umożliwia tzw. pin remapping, funkcja ta pozwala na wyprowadzenie peryferii w więcej niż jednym miejscu. Żeby sprawdzić gdzie jeszcze możemy wyprowadzić linie Tx oraz Rx, wystarczy wcisnąć i przytrzymać Ctrl, a następnie kliknąć lewym przyciskiem myszy na wyprowadzenie mikrokontrolera, które chcielibyśmy przenieść w inne miejsce.

KursF4_7_2

Zmiana wyprowadzeń obsługujących transmisję.

Czerwonym prostokątem zaznaczony jest kliknięty z klawiszem Ctrl pin PA10. Na niebiesko oznaczono wyprowadzenia PB3 i PB7, które zostały podświetlone podczas kliknięcia.

Spróbujmy w takim razie przenieść Rx oraz Tx na górną stronę mikrokontrolera. Dzięki poznanemu przed chwilą mechanizmowi wiemy, które wyprowadzenia udostępniają taką możliwość. Aby to zrobić, wystarczy kliknąć na któryś z dozwolonych pinów i wybrać odpowiednią funkcjonalność.

KursF4_7_4

Efekt finalny remappingu.

Wybrany tryb zostanie automatycznie wyłączony na poprzednim pinie i przeniesiony w nowe miejsce. To samo możemy zrobić z pinem Tx.

KursF4_7_3

Zmiana pinów dla komunikacji przez UART.

W efekcie dokonaliśmy remappingu pinów i przenieśliśmy UARTa na górną stronę mikrokontrolera.

Krok 3. Przechodzimy do panelu konfiguracyjnego UARTa.

KursF4_7_5

Panel konfiguracji UART.

  • Baud Rate - prędkość transmisji. Wartość domyślna, a więc 115200 będzie w zupełności wystarczająca dla wszystkich naszych wymagań (o ile urządzenie po drugiej stronie transmisji obsługuje taką wartość).
  • Word Length - ilość bitów danych wraz z bitem parzystości przesyłanych w ramce. Zostawiamy domyślną wartość 8, ponieważ nie zamierzamy używać bitu parzystości.
  • Parity - obecność bitu parzystości. Nie będziemy próbować obsługiwać błędów zakomunikowanych przez niezgodność bitu parzystości (jak 99% miejsc na świecie gdzie zastosowano UART, z którymi się spotkacie).
  • Stop Bits - standardową wartością używaną w popularnych zastosowaniach jest 1 stop bitu, dlatego tu również zostawiamy wartość domyślną.
  • Data Direction - jeżeli z jakiegoś powodu potrzebujemy jedynie możliwości nadawania lub odbierania, w tym miejscu możemy to skonfigurować. My będziemy korzystać z obydwu form, dlatego pozostawiamy domyślne Receive and Transmit.
  • Over Sampling - w celu redukcji błędów transmisji wynikających chociażby z zakłóceń, stan każdego bitu pobierany jest kilku lub kilkunastokrotnie. W naszym wypadku może to być 8 lub 16 razy. Oczywiście większa wartość gwarantuje większą pewność poprawnej transmisji, natomiast mniejsza pozwala osiągnąć wyższe prędkości transmisji.

Jak widać, konfiguracja UARTa wymaga od nas jedynie jego włączenia, ponieważ wszystkie domyślne wartości to standardowo używane w większości przypadków parametry transmisji.

Konfiguracja przerwań dla UART

Z UARTa można korzystać w 3 trybach. Blokującym, na przerwaniach oraz z wykorzystaniem DMA. Ze względu na to, że tryby wykorzystujące przerwania i DMA są o wiele wygodniejsze i łatwiejsze w użytkowaniu niż tryb blokujący, na nich skupię się w tym artykule.

Krok 4. Uruchamiamy przerwania dla UARTA.

KursF4_7_7

Uruchomienie przerwań dla UARTA.

Krok 5. Konfigurujemy odpowiednie wyjście GPIO, aby móc sygnalizować zdarzenia zapalaniem i gaszeniem wybranej diody LED. Jeżeli nie wiesz jak to zrobić, wróć do artykułu na temat GPIO.

Krok 6. Konfigurujemy licznik (timer) tak, aby generował przerwanie z częstotliwością 1Hz. Jeżeli nie wiesz jak zrealizować ten punkt, wróć do artykułu o licznikach.

Krok 5. Generujemy projekt pod nazwą 04_UART i importujemy go do IDE.

Uruchomienie UARTa w programie

Naszym pierwszym zadaniem będzie cykliczne przesyłanie wiadomości do komputera.

Krok 1. Załóżmy, że chcemy przesyłać do komputera wiadomości zawierające informację o swoim (kolejnym) numerze. Potrzebujemy więc tablicy przechowującej naszą wiadomość oraz zmienną będącą licznikiem.

Rozmiar tablicy do przechowywania danych musi być większy od długości wiadomości, które zamierzamy przesyłać. Należy go dobrać do własnych potrzeb.

Krok 2. Teraz musimy zawrzeć wysyłaną wiadomości w zmiennej data. Funkcja pozwalająca na takie działania to sprintf.

W linii 66 do zmiennej data wpisywana jest wiadomość "Liczba wyslanych wiadomosci: ", a następnie wpisana jest wartość zmiennej cnt. Funkcja sprintf zwraca ilość zapisanych znaków, stąd przypisanie do zmiennej size.

Co oznaczają znaki \n\r? Aby wiadomości wyświetlające się w terminalu były dla nas bardziej przejrzyste, musimy na nim wymusić zakończenie każdej wiadomości przejściem do nowej linii.

Krok 3. Na końcu pozostało nam wysłać stworzoną wiadomość i zakomunikować rozpoczęcie transmisji zmianą stanu diody świecącej (LED).

Pierwszym parametrem funkcji HAL_UART_Transmit_IT adres struktury konfiguracyjnej. Jako drugi podajemy adres tablicy, która zawiera wiadomość do przesłania. Ostatnim parametrem jest ilość znaków, jaką należy przesłać

Krok 4. Cały powyższy kod umieszczamy w funkcji obsługi przerwania cyklicznego od timera.

Krok 5. Pozostało nam już tylko uruchomić licznik tak, aby generował przerwania cykliczne.

Krok 6. Budujemy i wgrywamy program na płytkę. Po uruchomieniu, dioda powinna zmieniać swój stan (co sekundę).

Miganie wybranej diody - informacja o wysyłaniu danych.

Miganie wybranej diody - informacja o wysyłaniu danych (przykładowa animacja).

Podłączenie konwertera USB-UART

Krok 1. Łączymy linie Tx oraz Rx płytki z naszym konwerterem.

Połączenie zestawu Discovery z konwerterem UART.

Połączenie zestawu Discovery z konwerterem UART.

Schemat połączenia linii Tx oraz Rx.

Schemat połączenia linii Tx oraz Rx.

Wynika z tego, że przy obecnej konfiguracji podłączymy pin PB6 (Tx) mikrokontrolera z pinem Rx konwertera/modułu bluetooth. Linię PB7 (Rx) łączymy z wyprowadzeniem Tx konwertera.

Krok 2. Otwieramy menedżer urządzeń. Aby to zrobić klikamy prawym przyciskiem myszy na Mój komputer i wybieramy Zarządzanie komputerem. Otwieramy zakładkę:

Menedżer urządzeń > Porty (COM i LPT)

KursF4_7_7

Podgląd dostępny portów COM.

Krok 3. Podłączamy konwerter do portu USB w komputerze. Sprawdzamy nazwę i numer portu COM, który się pojawił po podłączeniu sprzętu.

KursF4_7_8

Pojawienie się nowego urządzenia.

W moim wypadku jest to Prolific USB-to-Serial Comm Port, któremu został przypisany numer portu COM7. Ta informacja przyda się zaraz przy konfiguracji oprogramowania.

Odbiór danych - niezbędne oprogramowanie

Aby sprawdzić co wysyła mikrokontroler, musimy zaopatrzyć się w oprogramowanie umożliwiające odbieranie i wysyłanie danych poprzez port szeregowy. Skorzystamy z programu RealTerm.

Krok 1. Pobieramy najnowszą wersję programu (w momencie pisania kursu jest to 2.0.0.70).
Krok 2. Instalujemy program.
Krok 3. Uruchamiamy RealTerma jako administrator.

Uruchamiamy program jako administrator.

Uruchamiamy program jako administrator.

Krok 4. Przechodzimy do zakładki Port i zmieniamy parametry transmisji na takie, które ustawiliśmy konfigurując UART w mikrokontrolerze.

Zmieniamy wartość Baud Rate na 115200. Port zmieniamy na ten, który został przypisany naszemu konwerterowi (sprawdzaliśmy to wcześniej w menadżerze urządzeń). Reszta ustawień domyślnie jest zgodna z tym co ustawiliśmy w Cube. Na końcu klikamy przycisk Change żeby nasze ustawienia zostały wdrożone do otwartego kanału komunikacyjnego.

Uruchomienie transmisji.

Uruchomienie transmisji.

W obszarze zaznaczonym na niebiesko przedstawione są obecne parametry transmisji. Skrót 8N1 oznacza 8 bitów danych, 0 bitów parzystości i 1 bit stopu.

Jeżeli wszystkie przedstawione dotąd instrukcje wykonaliśmy poprawnie, wraz z kliknięciem przycisku Change w terminalu powinny się zacząć pojawiać odbierane wiadomości.


Zauważmy, że po każdej z nich znaki nowej linii (LF - Line Feed) oraz powrotu kursora na początek linii (CR - Carriage Return) są widoczne. Aby takie znaki nie były wyświetlane, wystarczy zmienić tryb wyświetlania danych na ANSI.

Podgląd wyświetlanych danych.

Podgląd wyświetlanych danych.

Dodatkowo na powyższym obrazku zaznaczone są trzy przydatne sekcje. W zielonym prostokącie znajdują się parametry terminala wyświetlającego odebrane dane. Domyślnie jest to 16 linii o szerokości 80 znaków.

W obszarze zaznaczonym na niebiesko znajduje się pole oznaczające odbieranie danych. Zauważmy, że co sekundę rozświetla się ono na bardzo krótko. Taki sam rodzaj komunikowania stosowany jest w konwerterach UART - na naszym jest to czerwona dioda LED opisana jako RXD.

Bardzo prostą lecz przydatną funkcjonalność dostarcza oznaczony na fioletowo przycisk Clear. Pozwala on na wyczyszczenie aktualnej zawartości terminala.

Odbieranie danych przez UART na STM32 F4

Potrafimy już przesyłać dane z mikrokontrolera i wyświetlać je na komputerze. Teraz spróbujemy odebrać dane wysłane z komputera.

Krok 1. Pierwszą rzeczą jaką zrobimy będzie zadeklarowanie zmiennej do przechowywania odebranych danych.

Krok 2. Teraz musimy uruchomić nasłuchiwanie na kanale UART. Służy do tego funkcja Receive.

Pierwszym parametrem funkcji jest standardowo wskaźnik na strukturę konfiguracyjną. Drugim jest wskaźnik na obszar pamięci, do którego będą wpisywane dane. Trzeci parametr, to oczekiwany rozmiar wiadomości, innymi słowy - ilość odebranych znaków, po których zostanie wywołane przerwanie.

W tym miejscu mamy dwie możliwości.

  1. Jeżeli chcemy odbierać wiadomości, które składają się tylko z jednego znaku (np. proste komendy do Linefollowera typu 1-start i 0-stop) lub chcemy przetwarzać każdy znak odbieranej wiadomości po kolei, ilość odebranych danych należy ustawić na 1.
  2. Jeśli odbieramy dłuższe ciągi znaków i wiemy dokładnie ile znaków jest wysyłanych po stronie nadawczej, wygodniej jest ustawić ilość odebranych znaków na tę właśnie wartość.

Krok 3. Po odebraniu konkretnej liczby znaków (sprecyzowanej w parametrze wywołania funkcji Receive) wywołane zostaje przerwanie, które możemy obsłużyć funkcją:

Odbieranie wiadomości o rozmiarze "1"

W tym przykładzie będziemy wysyłać do mikrokontrolera bardzo proste instrukcje sterujące. Znak 0 oznaczać będzie wiadomość STOP, a 1 oznaczać będzie START. Zadaniem programu będzie sygnalizacja obecnego stanu diodą LED oraz odesłanie odebranej instrukcji z powrotem.

Obsługa przerwania dla tego zadania będzie wyglądać następująco.

Aby przetestować działanie powyższego mechanizmu, przechodzimy do zakładki Send w programie RealTerm. Wpisujemy wiadomość w pole zaznaczone na czerwono i wysyłamy przyciskiem Send ASCII.

KursF4_7_13

Wysyłanie wiadomości z komputera.

W terminalu możemy zaobserwować działanie naszego programu. Dodatkowo dioda LED na płytce Discovery sygnalizuje w jakim stanie (START/STOP) znajduje się aktualnie nasz program.


Jaki problem wynika z takiego podejścia? Jeżeli do mikrokontrolera zostanie wysłana wiadomość składająca się z większej ilość znaków, przerwanie zostanie wywołane wielokrotnie w bardzo krótkim czasie, co spowoduje błędy. Żeby to sprawdzić, wystarczy wysłać z RealTerma wiadomość składającą się z kilku znaków.

KursF4_7_14

Wysłanie zbyt długiej wiadomości.

Odbieranie wiadomości o rozmiarze większym od "1"

Aby zapobiec takiej sytuacji, wystarczy sprecyzować, że przerwanie ma się wywołać po odebraniu większej ilości znaków. W takiej sytuacji najpierw odbierana jest cała wiadomość, a dopiero po zakończeniu całego procesu zostaje wywołane przerwanie.

Czemu? Załóżmy, że uruchamiamy nasłuchiwanie i oczekujemy wiadomości o długości 10.

KursF4_7_15

Tablica odbieranych danych. Żadne dane nie zostały jeszcze odebrane (pusta tablica).

Wiadomość, która jest do nas wysłana ma tylko 7 znaków. W takiej sytuacji dane zostają odebrane i zapisane w tablicy, ale przerwanie informujące nas o zakończeniu transmisji nie zostanie wywołane.

KursF4_7_16

Tablica odbieranych danych. Odebrano wiadomość o długości 7. Brak przerwania.

Przypuśćmy, że zostanie do nas wysłana kolejna wiadomość. Tym razem składająca się z  2 znaków. W buforze mamy 7 znaków, więc teraz będzie ich 9. Ponieważ oczekujemy odebrania 10 znaków, przerwanie nadal się nie wywoła, chociaż mamy już dwie odebrane wiadomości w buforze.

KursF4_7_17

Tablica odbieranych danych. Odebrano drugą wiadomość o długości 2. Brak przerwania.

Kolejna wiadomość, która nadejdzie ma długość 4 znaków. Co się stanie w tym momencie? Po odebraniu pierwszego znaku nowej wiadomości w buforze będzie 10 znaków, a więc tyle ile oczekujemy. Zostaje wywołane przerwanie.

KursF4_7_18

Tablica odbieranych danych. Odebrano pierwszy znak trzeciej wiadomości. Przerwanie wywołane.

Tym samym bufor jest zerowany. W odbieranej wiadomości pozostały jednak jeszcze 3 znaki, które zostają wpisane do pustego bufora.

KursF4_7_19

Tablica odbieranych danych. Bufor został wyzerowany. Wpisano do niego pozostałe znaki trzeciej wiadomości. Brak przerwania.

Co z tego wynika?

Odebraliśmy 3 wiadomości, otrzymując powiadomienie w formie przerwania w środku ostatniej. Tym samym dostajemy bufor zawierający dwie pełne i kawałek trzeciej wiadomości. Jak to teraz obsłużyć? Cała sytuacja jest zupełnie bez sensu...

Zmusza nas to jednak do tworzenia ramek wiadomości o takiej samej długości, co wydaje się bardzo problematyczne. Istnieje jednak bardzo prosty mechanizm pozwalający na ominięcie tego problemu, który opisałem poniżej.

Lepsza wersja komunikacji

Spróbujmy więc przetestować przedstawione rozwiązanie w praktyce! Pierwszą zmianą jaką musimy dokonać jest przekształcenie zmiennej przechowującej odebrany znak w tablicę.

Następnie modyfikujemy zawartość przerwania tak, aby odebrana wiadomość była odsyłana z krótkim dopiskiem.

Ostatnia modyfikacja czeka nas w funkcji main, gdzie trzeba zaktualizować parametry wywołania funkcji rozpoczynającej nasłuchiwanie do naszych aktualnych wymagań.

Teraz możemy przetestować działanie nowo stworzonego mechanizmu wysyłając wiadomość o długości 10 znaków z RealTerm.

KursF4_7_20

Wysyłanie większej ilości znaków.

Wysyłanie wiadomości o stałej długości z mikrokontrolera

Zauważmy, że za każdym razem wysyłamy z mikrokontrolera dokładnie tyle znaków, z ilu składa się wiadomość. Możemy tak zrobić odczytując wartość zwracaną przez funkcję sprintf i podając ją następnie jako parametr funkcji transmitującej dane.

W celu wykonania pewnego testu, zmieńmy tryb wyświetlania danych z powrotem na ASCII.

KursF4_7_21

Zmiana trybu wyświetlania danych.

Dzięki temu będziemy widzieć wszystkie odbierane przez RealTerm znaki. W tym wypadku, poza znakami standardowej wiadomości będą to tylko znaki CR i LF, wyświetlane w terminalu przy ustawieniu ASCII. Dzięki temu widzimy, że wysyłamy dokładnie tyle znaków, ile mają wszystkie znaki użyteczne wiadomości plus dodane znaki nowej linii.

KursF4_7_22

Podgląd odebranych danych.

Ta informacja przyda nam się zaraz w porównaniu do innego przykładu. Jeżeli jednak chcielibyśmy komunikować się z innym mikrokontrolerem, który ma ustawione odbieranie na stałą wartość, za każdym razem musielibyśmy wysyłać wiadomości o tej właśnie stałej liczbie znaków.

Aby to zrobić, wystarczy ustawić trzeci parametr w funkcji HAL_UART_Transmit_IT na stałą szerokość wiadomości.

Zmienna size staje się w takim razie zbędna. Co się dzieje teraz z częścią wiadomości, w której nie ma żadnych informacji? Możemy to zaobserwować oglądając odbierane dane w trybie ASCII.

KursF4_7_23

Podgląd odebranych danych.

Wysłana wiadomość ma dokładnie 32 znaki (włącznie ze znakami LF oraz CR). Cała reszta zostaje zapełniona znakami zerowymi \0, które RealTerm wyświetla jako NULL. Widać, że jest ich dokładnie 8, a więc tyle, ile brakuje, aby cała wiadomość miała długość 40 znaków.


Teraz w urządzeniu odbiorczym, którym mógłby być inny mikrokontroler wystarczy ustawić odbieranie na długość 40 znaków. W ten sposób w urządzeniu odbiorczym przerwanie wywoła się zawsze w odpowiednim czasie, znaki zerowe na końcu nie będą w niczym przeszkadzać i tym samym transmisja zawsze będzie przebiegać poprawnie i efektywnie. W ten właśnie sposób można w praktyce rozwiązać problem wysyłania/odbierania długich wiadomości o różnej długości.

Obsługa UART z wykorzystaniem DMA

Spróbujmy teraz zaprząc do tego wszystkiego DMA. Dzięki temu odciążymy procesor w jeszcze większym stopniu. Jak zwykle z DMA, tak i teraz, cały proces jest bajecznie prosty.

Konfiguracja Cube

W zakładce DMA Settings panelu konfiguracyjnego UARTa dodajemy dwa kanały. Jeden dla transmisji, a drugi dla odbioru.

KursF4_7_24

Ponowna konfiguracja w Cube.

DMA ma przesyłać pojedyncze bajty w trybie normalnym, więc pozostawiamy ustawienia domyślne.

Obsługa DMA w programie

Aby uruchomić DMA w komunikacji UART, jedyne co musimy zrobić, to zamienić wywołania funkcji do obsługi UARTa na te korzystające z DMA. Nasz ostatni program po tej drobnej modyfikacji będzie w takim razie wyglądał następująco.

Rozpoczęcie nasłuchiwania w funkcji main też oczywiście musi zostać zamienione na funkcję wykorzystującą DMA.

Problem - zagadka

Po przerzuceniu poprzedniego kodu na korzystanie z DMA, na końcu transmitowanej wiadomości dodawany był jeden dodatkowy znak. Jedyne rozwiązanie tego problemu jakie znalazłem, to zmiana deklaracji zmiennej Data na zmienną globalną lub zmienną statyczną (jak w przykładzie powyżej).

Jeśli ktoś z Was znajdzie rozwiązanie tego problemu, koniecznie dajcie znać w komentarzach!

Podsumowanie

W tym odcinku nauczyliśmy się wysyłać i odbierać wiadomości za pomocą interfejsu UART. Wiemy już jak go skonfigurować tak, aby wykorzystywał w tym celu przerwania oraz DMA. Omówiliśmy także kilka problemów związanych z implementacją, które pojawiają się w praktyce.

W następnym artykule zajmiemy się bardziej zaawansowanymi możliwościami, jakie oferują nam licznik (timery) mikrokontrolerów STM32. Jak zwykle, jeśli macie jakiekolwiek problemy, pytania czy wątpliwości związane z UARTem, piszcie śmiało w komentarzach!

Autor kursu: Bartek (Popeye) Kurosz
Redakcja: Damian (Treker) Szymański

Nawigacja kursu

Załączniki

Projekty omówione w tym artykule (zip, 8 MB)

Archiwum zip ze wszystkimi projektami.

F4, komunikacja, kursSTM32F4, stm32, uart, USART

Trwa ładowanie komentarzy...