niedziela, 30 sierpnia 2020

Programowy scheduler z użyciem sprzętowego Timera w dsPIC33EP512GP506

 

 

Każdy programista prędzej czy później sięgnie po rozwiązanie, dające możliwość osiągnięcia teoretycznie nieograniczonej liczby Timerów programowych w swoim projekcie. 
Postaram się krok po kroku pokazać, w jaki sposób stworzyć samemu bardzo przydatny Timer programowy w środowisku MPLAB-X z wykorzystaniem mikrokontrollera 16-bit przedstawionego w tytule.

Otwieramy zatem środowisko MPLAB-X i wybieramy File i New Project a następnie przechodzimy do następnego okna wybierając Next> w polu Device wybieramy naszego bohatera dsPIC33EP512GP506 




Przechodzimy dalej wybierając programator i wersję kompilatora (ja obecnie używam v1.50) po czym nadajemy nazwę naszemu projektowi i kończymy przyciskiem Finish

Kolejnym krokiem jest konfiguracja sprzętowa naszego MCU z wykorzystaniem wtyczki MCC 


Danej przechodzimy do System Module i wybieramy taktowanie. Ja korzystam z kwarcu 8MHz i ustawień PLL jak poniżej:




Następnie z lewej strony w drzewku Device Resources rozwijamy Timer i klikamy dwukrotnie w Timer1, który to będzie nam służył za taktowanie timera programowego z podstawą co 10ms
należy pamiętać o zaznaczeniu włączenia przerwania:


Na koniec przygody z MCC w celu wizualizacji naszego efektu, dodajmy sobie dwie diody zmieniające swój stan podczas pracy timerów programowych. W tym celu przechodzimy w lewym górnym rogu do Pin Module i klikamy w GPIO kłódeczką w output na porcie, w którym mamy diodę LED (w moim przypadku jest to wyprowadzenie 55 i 45 w obudowie TQFP). Dodatkowo w tabeli u góry nazwałem odpowiednio port RC9 i RC10 jako Led1 i Led2 - tymi nazwami będziemy się posługiwać w programie.



Kończymy pracę klikając w przycisk Generate 

 i po chwili w oknie output zostaniemy poinformowani o 
ukończeniu operacji. 
 

Teraz możemy zamknąć konfigurator klikając w niebieski przycisk MCC.

Konfigurację sprzętową mamy już za sobą, przechodzimy zatem do Projects i rozwijamy w drzewku Source Files klikając na niego prawym klawiszem myszy, dodajemy nowy katalog logiczny jak poniżej:


Następnie dodajemy do swojego katalogu pliku .c i .h 



Po dodaniu plików usuwamy zawartość pliku c i h oraz dodajemy wpis jak na zdjęciu poniżej:



Kolejnym etapem jest dodanie funkcji timera programowego, którą przypiszemy jako argument funkcji obsługującej przerwanie przez wskaźnik, ale o tym później, na razie zajmiemy się funkcją TimeProg przedstawioną poniżej:


Należy zwrócić uwagę na modyfikator volatile przy  deklaracji zmiennej tmProg, oznacza on, że kompilator użyje tej samej przestrzeni adresowej zarówno w funkcji w przerwaniu jak i pętli głównej. Zawsze przy przekazywaniu wartości z przerwania do głównej funkcji Main należy stosować modyfikator volatile

Nadszedł czas na wykorzystanie timerów programowych, ale zanim to zrobimy należy niejako "podpiąć" naszą funkcję do obsługi przerwania. W celu dokładniejszego zrozumienia operacji, którą zaraz wykonamy otwórzmy plik tmr1.c z katalogu MCC Generated Files i spójrzmy na funkcję TMR1_SetInterruptHandler widać, że argumentem jest wskaźnik typu void tym samym umożliwia nam to przekazanie własnej funkcji, tak jakbyśmy umieścili ją w przerwaniu. Dalej wartość ta, jest przepisywana do zmiennej TMR1_InterruptHandler, która z kolei sprawdzana jest we właściwej funkcji przerwania void __attribute__ ( ( interrupt, no_auto_psv ) ) _T1Interrupt i jeśli nie jest FALSE czyli coś tam jest (nasza funkcja) to wykona się ona dokładnie w momencie przerwania Timera 1


Przechodzimy do pliku main.c i dokonujemy wpisu TMR1_SetInterruptHandler(TimerProg); należy zwrócić uwagę, że przy przekazywaniu funkcji przez wskaźnik nie wpisujemy nawiasów okrągłych, jak przy klasycznym wywoływaniu funkcji. 


Teraz możemy użyć swoim timerów programowych w pętli while, co prezentuje na poniższym zrzucie:



Dodałem dwa timery, każdy z nich pracuje niezależnie. W powyższym przykładzie podstawa 10ms pozwala nam na uzyskanie takiej rozdzielczości, co w zupełności wystarcza do migania diodą, jeżeli jednak potrzebujemy bardziej precyzyjny czas naszych timerów można ustawić taktowanie na 1ms w MCC albo nawet mniej i odpowiednio przemnożyć zadany czas, przypisując wartość do zmiennej tmProg pamiętając, że jest to typ uint16_t.

Zaprezentowany sposób użycia własnych timerów programowych można z powodzeniem wykorzystać na inny mikrokontroler i jest to sposób jeden z wielu (nie koniecznie najbardziej optymalny) ale na początek wystarczający :)

Link:

Brak komentarzy:

Prześlij komentarz