Programowanie ARM, nauka, środowiska programistyczne IDE
Koleżankom i Kolegom Radioamatorom, Krótkofalowcom,
Konstruktorom i Waszym Rodzinom –
w tych trudnych czasach –
po dotkliwej awarii naszego forum
Pogodnego czasu po Bożym Narodzeniu,
Dosiego Nowego Roku
oraz Radosnych Trzech Króli
Życzy Zespół Home Made
Ankieta: Jaki system operacyjnym preferujesz Nie posiadasz uprawnień, aby oddać głos w tej ankiecie.
Podstawowym celem zadania nr. 1 było nauczenie się podstaw konfiguracji pinów portów GPIO. Poznaliśmy kod do ustawienia pinów jako wyścia do sterowania LED-ów oraz jako wejście do odczytu stanu klawisza BUTTON.
Zadanie nr.3 obsługa encodera
Kolejnym etapem poznawania konfiguracji pinów będzie poznanie sposobu odczytu stanu encodera. Piny do których podłączony jest nasz enkoder (PG2, PG3) są domyślnie ustawione w tryb INPUT, należy dodatkowo włączyć rezystory podciągające do plusa zasilania (PUPD_UP). Aby obsługa ekcodera była szybka, prosta i abyśmy nie gubili impulsów zrobimy to z wykorzystaniem systemu przerwań. Każdy pin może generować zewnętrzne przerwania sprzętowe EXTIx, np. pin encodera GPIO_G2 będzie generował przerwanie EXTI2. Rozpoznanie kierunku obrotu encodera jest zrobione w kodzie obsługi przerwania. Zmienna [ int8_t encoder_counter ] zawiera ilość odczytanych impulsów, wartość dodatnia to obrót w prawo, wartość ujemna obrót w lewo.
Na podstawie obrotu enkodera jest modyfikowany okresu przełączania zielonej diody w przedziale 20...2000ms. Obracając encoder w lewo zielona dioda mruga coraz szybciej a w prawo coraz wolniej. Jeśli mamy odwrotnie należy zamienić wejścia A, B encodera. Wciśnięcie niebieskiego klawisza przywraca okres diody do wartości początkowej 500ms.
W zadaniu mamy wydzielone pliki z funkcjami do konfiguracji pinów ( f4_cmsis_gpio.h, f4_cmsis_gpio.c ), trzy funkcje do ustawiania pojedynczy pinów oraz trzy do jednoczesnej konfiguracji wielu pinów na tym samym porcie. Takie podejście jest moim zdaniem najbardziej uniwersalne.
W załączniku paczka z plikami do zadania nr. 3
Na zdjęciu podłączenie encodera do modułu DiskoveryF429 (GND-czarny, PG2-żółty, PG3-zielony). Bezpośrednio do wejść encodera a masą przylutowane są dwa kondensatory ceramiczne po 10nF do tłumienia drgań styków.
Trochę się pogubiłem w temacie utworzonych MACR dla LEDów. Prosiłbym o przybliżenie tematu, zarówno do Z003, jak i wcześniejszego Z001v3, gdzie macra były zastosowane po raz pierwszy.
Rysio!
Jeśli w dużym programie trafisz na taką linię kodu to bez schematu nie wiesz praktycznie nic.
Kod:
GPIOG->BSRRL = GPIO_Pin_14;
Wiadomo, że zmieniasz stan na nodze procesora i tyle, nawet nie wiesz czy taki rozkaz włącza urządzenie czy wyłącza bo dioda może być podwieszona do zasilania lub do masy. Aby kod był bardziej czytelny należy posługiwać się własnymi nazwami opisującymi sterowane elementy systemu, w tym przypadku LED_RED.
Kod:
#define LED_RED_GPIO GPIOG
#define LED_RED_RCC RCC_AHB1Periph_GPIOG
#define LED_RED_PIN GPIO_Pin_14
#define LED_RED_OFF LED_RED_GPIO->BSRRH = LED_RED_PIN //niski stan na pinie
#define LED_RED_ON LED_RED_GPIO->BSRRL = LED_RED_PIN //wysoki stan na pinie
Dla naszej diody definiujemy port, zegar taktujący dla portu, maskę pinu oraz makra ON/OFF. W definicji makra jest również zawarta informacja o sposobie włączania diody (zerem czy jedynką). Teraz w programie jak chcesz zapalić LED_RED to nie musisz pamiętać na jakim porcie i pinie masz tą diodę ani tego, że włączanie jest jedynką, po prostu piszesz:
Każdy kto widzi taki rozkaz (makro) od razu wie co on robi, kod jest czytelny a program krótszy i łatwiejszy w pisaniu. Dodatkową zaletą stosowania makr jest bardzo łatwa zmiana konfiguracji sterowania. Jeśli musimy zmienić pin diody z pin_14 na pin_12 to poprawiamy tylko definicję jednego makra bez konieczności szukania w całym kodzie programu.
Makra mogą być również bardziej rozbudowane np. z parametrami.
Kod:
#define _gpio_mode_set(gpio,pin_maska) gpio->MODER |= pin_maska //ustawia tryb pracy pinow na porcie
Mamy zdefiniowane makro do konfiguracji pinów portu. nasz pin_14 dla diody LED_RED może pracować w czterech trybach:
Kod:
//domyślny po resecie INPUT oraz
#define GPIO_14_MODE_OUT ((uint32_t)0x10000000)
#define GPIO_14_MODE_AF ((uint32_t)0x20000000)
#define GPIO_14_MODE_ANL ((uint32_t)0x30000000)
Aby skonfigurować nasz pin dla diody jako wyjście wpisujemy:
Kod:
_gpio_mode_set(GPIOG, GPIO_14_MODE_OUT); //na rejestrach lub
_gpio_mode_set(LED_RED_GPIO, LED_RED_MODE); //nazwy symboliczne
Ważne jest aby na początku nie mylić numeru pinu, numeru trybu z maską pinu, maską trybu bo to zupełnie co innego.
26-07-2016, 9:48 (Ten post był ostatnio modyfikowany: 26-07-2016, 9:48 przez QRP73.)
Te makra w programie dla procesara nic nie zmieniaja, funkcje zawsze sa takie same. Znienia sie tylko zapis programu. Obsluga enkodera jest niepokojaco krotka w porownaniu do przykadow z internetu. Zastanawia mnie czy bedzie to poprawnie pracowalo z roznymi enkoderami. Chwilowo nie mam jak testowac, urlop poza domem.
Przepraszam za brak polskich liter (telefon).
(26-07-2016, 9:48)QRP73 napisał(a): Obsluga enkodera jest niepokojaco krotka w porownaniu do przykadow z internetu.
Długi kod to źle bo trudno go zrozumieć, za krótki też niedobrze bo to niemożliwe żeby te kilka linijek mogły robić to samo co rozbudowane funkcje. Wychowałem się na małych procesorach i generalnie jestem zwolennikiem prostych i szybkich aplikacji, lubię rejestry i przerwania. Obsługę encodera można zrobić na kilka sposobów, ten jest najprostszy i u mnie działa poprawnie. Nic nie stoi na przeszkodzie aby zaprezentować własne rozwiązanie tego zadania.
Po pierwszych postach w tym wątku widziałem duży potencjał grupy i spodziewałem się prezentacji wielu własnych programów oraz ciekawej dyskusji. Niestety na tą chwilę tylko Paweł i ja zamieszczamy działające przykłady. Zachęcam wszystkich, bez tego nie będzie postępów ani w kursie ani nauce.
(26-07-2016, 15:20)SP5FCS napisał(a): Długi kod to źle bo trudno go zrozumieć, za krótki też niedobrze bo to niemożliwe żeby te kilka linijek mogły robić to samo co rozbudowane funkcje. Wychowałem się na małych procesorach i generalnie jestem zwolennikiem prostych i szybkich aplikacji, lubię rejestry i przerwania. Obsługę encodera można zrobić na kilka sposobów, ten jest najprostszy i u mnie działa poprawnie.
(26-07-2016, 15:20)SP5FCS napisał(a): Po pierwszych postach w tym wątku widziałem duży potencjał grupy i spodziewałem się prezentacji wielu własnych programów oraz ciekawej dyskusji. Niestety na tą chwilę tylko Paweł i ja zamieszczamy działające przykłady. Zachęcam wszystkich, bez tego nie będzie postępów ani w kursie ani nauce.
Proszę mnie nie martwić, gdzie ja będę szukał wzorów do naśladowania, już się czegoś nauczyłem, mam dalej szperać po internecie? Na chwilę obecną nie czuję się na siłach pisać swoich programików.
Rysio!
Zapewne po to aby zrobić kiedyś jakiś fajny przyrząd lub sterownik do radia. Procesor ma bardzo rozbudowane układy peryferyjne, do tego dochodzi wyświetlacz TFT, panel dotykowy, CAT, USB, generator Si5351 lub jakiś DDS, jakieś rejestry do sterowania pasmami, przetworniki ADC do S-metra i SWR-a nie wspominając o kodeku i DSP. Jeśli chcemy zbudować jakiś sterownik radia to jest do opanowania ogromny materiał i trzeba napisać setki funkcji. Jeden człowiek sam tego szybko nie zrobi, a nawet gdyby się uparł i zrobił to niekoniecznie podzieli się kodem.
Jakie więc mamy wyjście ? Jeśli chcemy czegoś się nauczyć i zrobić coś praktycznie to większa grupa uczestników kursu powinna się przyłożyć i coś napisać, potestować, poszperać w dokumentacji czy necie za ciekawymi przykładami. Samo się nie zrobi.
Jak pracuje zwykły enkoder mechaniczny możemy sprawdzić na prostym teście wyświetlacza TFT. Enkoder podłączony tak jak w zadaniu nr. 3.
Enkoderem możemy zmieniać nastawę częstotliwości, krok 10Hz.
Zdjęcie i plik HEX w załączniku.
27-07-2016, 15:31 (Ten post był ostatnio modyfikowany: 27-07-2016, 15:32 przez SP9IT.)
Witajcie.
Co do makr by wniósł dwie rzeczy.
Po pierwsze, i to jest ważne, w "prawej" części czyli zawartości makra, ujmowanie w nawiasy czegokolwiek bardziej złożonego. Można sobie zrobić kuku, jak kiedyś użyje się makra w kontekście złożonym, np wyrażenia. Są różne szkoły, i święte wojny jak te nawiasy zrobić, ale lepsze (prawie) dowolne, niż żadne.
Po drugie, ja jestem z tych, co makra "akcyjne (przeciwieństwo do "wartości" zwykle stałej w wyrażeniu) markuje nawiasem jak funkcja bezargumentowa
lub żeby nie wywołać polemiki super-hackerów C, jedna z ambitnych notacji
Kod:
#define LED_RED_ON() do { LED_RED_GPIO->BSRRL = LED_RED_PIN; } while(0)
W ogóle jestem zwolennikiem odchodzenia od makr najbardziej jak się da, nowoczesne dialekty C (o C++ nie wspominam) mają funkcje inline, które mają wszystkie zalety makr (generowanie kodu maszynowego w miejscu, bez wywołania call, stosu itd) a nie mają wad i ryzyka.
Aha, makro bezargumentowe nie może koło tych nawiasów mieć spacji