[3] STM32CUBE w przykładach (USART)

Sterowanie kolorem diody RGB z komputera

Uruchamiamy CubeMX i otwieramy w nim nasz projekt. Zgodnie z instrukcją z poprzedniej części, ustawiamy piny diody RGB jako wyjściowe piny generatora PWM, konfigurujemy licznik oraz generujemy projekt z wprowadzonymi zmianami. Jeśli stosowaliśmy się do sekcji „USER CODE”, nie powinniśmy teraz utracić naszego kodu. Ponownie uruchamiamy System Workbench lub odświeżamy listę plików (polecenie Refresh w Project Explorer). W sekcji „USER CODE 0” wpisujemy poniższy fragment kodu, obsługujący korekcję gamma. Funkcji z poprzedniego etapu możemy się już pozbyć (wrócimy do nich w kolejnej części cyklu).

Do sekcji „USER CODE 2” wpisujemy poniższy kod – powodujący uruchomienie generatora PWM na pinach.

W sekcji „USER CODE 3” umieszczamy poniższy:

W pierwszej linii powyższego kodu (w sekcji „USER CODE 3”), tworzymy bufor o rozmiarze jednego znaku. Następnie odbieramy ten znak od użytkownika do buforu, korzystając z funkcji HAL_UART_Receive() – jej kolejnymi parametrami są: wskaźnik na strukturę konfiguracyjną interfejsu, wskaźnik na bufor, długość bufora oraz timeout – czas, po jakim funkcja ma się poddać i zwrócić informację o niepowodzeniu, jeśli nie otrzyma żadnych danych. Dalej sprawdzamy, czy funkcja zwróciła informację o odebraniu danych i na podstawie odebranego znaku decydujemy, jasność, jakiej barwy zwiększamy lub zmniejszamy. Jeśli wychodzimy przy tym poza skalę – od 0 do 1, w kolejnych liniach kodu, powracamy do właściwego zakresu. Na koniec, korzystając z omówionej, w poprzedniej części kursu funkcji set_led_brightness(), ustawiamy jasność poszczególnych kanałów diody RGB.

Kompilujemy oraz uruchamiamy program na mikrokontrolerze. Jeśli środowisko nadal nie widzi części plików lub zmiennych, możemy zmusić je do przeindeksowania zawartości projektu – wybieramy w tym celu z menu, w górnej części okna, polecenie: „Project” -> „C/C++ Index” -> „Freshen All Files”. Należy też pamiętać o błędzie związanym z biblioteką „m”. Sposób jego rozwiązania został podany w poprzedniej części – w ustawieniach linkera musimy odznaczyć opcję dołączania biblioteki „m” oraz dodać ją ręcznie na liście dołączanych bibliotek.

Od teraz, po wciśnięciu w programie PuTTY klawiszy „q”, „w” i „e”, zwiększymy jasność świecenia poszczególnych kolorów składowych diody RGB – odpowiednio: czerwonego, zielonego i niebieskiego. Klawiszami „a”, „s” i „d”, analogicznie zmniejszymy ich jasność.

 

Przerwania

W tej chwili, przez większość czasu swojej pracy, nasz procesor oczekuje na odebranie od użytkownika danych. Po ich odebraniu, interpretuje je, wykonuje stosowną akcje i powraca do oczekiwania. To rozwiązanie sprawdza się w przypadku prostych ćwiczeń. Co jednak w sytuacji, gdy chcielibyśmy w międzyczasie wykonywać jakieś inne operacje? Przykładowo: obsłużyć połączenia TCP/IP, przerysowywać zawartość wyświetlacza czy zmierzyć odległość od przeszkody, do której zbliża się nasz robot…

Z pomocą przychodzą nam przerwania. Możemy ustawić interfejs UART tak, aby w momencie otrzymania od urządzenia po drugiej stronie danych, kazał procesorowi przerwać wykonywanie obecnej operacji i przetworzył przychodzące dane. Procesor zrzuca wtedy na swój stos zawartość rejestrów (kontekst) oraz przeskakuje pod odpowiedni adres w pamięci kodu, w którym to umieścimy naszą funkcję obsługującą przerwanie. Po jej wykonaniu, procesor przywróci zawartość rejestrów i powróci do normalnej pracy.

Przerwania mogą oczywiście generować również inne interfejsy i peryferiale. Mogą one także być wywoływane z zewnątrz – po zmianie stanu wybranego pinu. Możemy ustawić dowolny licznik, tak, aby wywoływał w ustalonych odstępach czasu przerwania (najczęściej w momencie resetu wartości licznika). Przerwaniom możemy również przypisywać priorytety – te o niższym priorytecie nie mogą przerywać tych o wyższym. Procesor, pomiędzy wykonywaniem rozkazów sprawdza wektor przerwań – jeśli jakieś przerwanie wymaga obsłużenia, w wektorze tym znajdzie się odpowiednio ustawiona flaga – w ten sposób, przerwania o różnych priorytetach mogą być kolejkowanie.

Aby uruchomić generowanie przerwań przez interfejs UART, wracamy do programu STM32CubeMX i wczytujemy w nim nasz projekt. Następnie przechodzimy do zakładki „Configuration” i wybieramy interfejs USART z sekcji „Connectivity”. W nowootwartym oknie przechodzimy do zakładki „NVIC Settings” i zaznaczamy jedynego checkboxa na liście (w polu „Enable”). Alternatywnie, w zakładce „Configuration”, moglibyśmy wybrać opcje „NVIC” – wtedy wyświetli nam się lista wszystkich możliwych do uruchomienia w danym projekcie przerwań. Możemy tam także ustawiać ich priorytety.

Rys. 7. Włączanie obsługi przerwań w ustawieniach interfejsu w programie STM32CubeMX
Rys. 8. Ustawienia kontrolera przerwań w programie STM32CubeMX

Teraz możemy już wygenerować projekt i dokonać kilku zmian w kodzie programu, w środowisku System Workbench. Do sekcji „USER CODE 0” dopisujemy poniższą funkcję. Funkcja ta będzie wywoływana za każdym razem, gdy interfejs UART odbierze dane i wywoła przerwanie. Jej zawartość jest podobna do poprzedniego kodu wywoływanego w pętli.

Zawartość sekcji „USER CODE 2” zmieniamy na poniższą – dodajemy tutaj instrukcję włączającą obsługę przerwania.

Do sekcji „USER CODE PV” dopisujemy poniższy kod – przenosimy zmienne do sekcji globalnej, tak, aby były dostępne zarówno z poziomu funkcji obsługującej przerwanie, jak również z funkcji main().

Sekcję „USER CODE 3” natomiast czyścimy – nie potrzebujemy w tej chwili aby jakikolwiek kod wykonywał się w pętli.

Po uruchomieniu mikrokontrolera, wykonany zostanie kod z sekcji „USER CODE 2”. W ostatniej linii tego kodu, korzystając z funkcji HAL_UART_Receive_IT(), włączamy przerwanie interfejsu UART. Składnia tej funkcji jest niemal identyczna jak składnia funkcji odbierającej dane do bufora. Tutaj również wskazujemy, gdzie zapisany ma zostać odebrany ciąg oraz jak długi jest bufor. Przed przeskoczeniem do wykonania funkcji przerwania, do wskazanego bufora zapisane zostaną odebrane dane. Żeby bufor był dostępny z zarówno z poziomu funkcji main(), jak i funkcji obsługującej przerwanie, deklarujemy go jako zmienną globalną w sekcji „USER CODE PV”. Na końcu funkcji obsługującej przerwanie, ponawiamy wywołanie funkcji uruchamiającej przerwanie – włącza ona obsługę przerwania, aż do jego następnego wywołania.

Kody źródłowe przykładów oraz projektu programu STM32CubeMX poszczególnych przykładów, dostępne są na serwerze FTP.

Następną część kursu poświęcimy układowi ESP8266. Dodamy dzięki niemu do naszego mikrokontrolera obsługę sieci Wi-Fi oraz stosu TCP/IP. Utworzymy także prostą stronę WWW przy pomocy, której będziemy sterować naszą diodą RGB.

Aleksander Kurczyk

Do pobrania

Autor: