Generatory PWM – obsługa programowa

Często mikrokontrolery sterują układami peryferyjnymi za pomocą sygnału zegarowego lub sygnałów PWM. W przykładzie pokażemy działanie i praktyczne wykorzystanie licznika TIM1 oraz możliwość jego współpracy z innymi blokami mikrokontrolera.

Dioda LED2 na płytce STM32Butterfly jest włączona na stałe, natomiast dioda LED1 jest sterowana za pomocą licznika TIM1. Program można wgrać do pamięci RAM.
Sterowanie odbywa się przy wykorzystaniu joysticka, przełączenie go w odpowiednią pozycję powoduje następującą reakcję:

  • wciśnięcie – wyłączenie licznika oraz włączenie na stałe diody LED1,
  • w prawo – generowanie sygnału PWM, ustawienie jasności świecenia diody,
  • w lewo – generowanie sygnału zegarowego o małej częstotliwości, miganie diody LED1,
  • w górę – jeśli generowany jest sygnał PWM to zwiększenie wartości współczynnika wypełnienia (LED1 będzie świeciła jaśniej), jeśli generowany jest sygnał zegarowy to nastąpi zwiększenie częstotliwości sygnału,
  • w dół – jeśli generowany jest sygnał PWM to zmniejszenie wartości współczynnika wypełnienia (LED1 będzie świeciła słabiej), jeśli generowany jest sygnał zegarowy to nastąpi zmniejszenie częstotliwości sygnału.

Należy pamiętać, że w zestawie STM32Butterfly diody LED1 i LED2 zapala się poprzez ustawienie stanu niskiego na wyjściu. Wykrywanie zmiany położenia joysticka zostało zrealizowane przy wykorzystaniu przerwań.
W programie wykorzystywane są następujące zmienne:

Modułami wykorzystywanymi w projekcie są AFIO, GPIOE oraz TIM1, należy pamiętać o doprowadzeniu sygnału zegarowego do tych modułów poprzez polecenie:

Konfiguracja pinów sterujących diodami jest następująca:

Następnie jest przeprowadzana konfiguracja sygnałów generujących przerwania poprzez ustawienie wykorzystywanych pinów. Bardzo ważnym poleceniem jest NVIC_SetVectorTable biblioteki Standard Peripherals Library, informującym gdzie znajduje się tablica NVIC. Ma to znaczenie dla programu wgrywanego do pamięci RAM mikrokontrolera, gdyż domyślnie tablica jest w pamięci Flash, a dla programu wgrywanego do pamięci RAM program szukałby tablicy właśnie w pamięci RAM. Następnie przeprowadzana jest konfiguracja kanałów przerwań EXTI9_5_IRQn i EXTI10_15_IRQn wraz z ustawieniem linii jako generującej przerwanie oraz zdefiniowania sposobu generowania przerwania.

Na samym końcu głównego programu włączany jest remaping, wymagane jest to ze względu iż standardowym wyjściem kanału czwartego licznika TIM1 (wykorzystywanego do sterowania diodą w projekcie) jest PA11 natomiast przy włączeniu pełnego remapingu dla timera TIM1 uzyskamy dla kanału czwartego wyjście PE14, do którego jest podłączona dioda LED1. Włączenie remapingu jest realizowane w następujący sposób:

Powyższy opis dotyczył wstępnej konfiguracji wykorzystywanych funkcji mikrokontrolera, pomijając konfigurację timera, która ma miejsce w obsłudze przerwań ze względu na rozróżnienie czy ma być generowany sygnał zegarowy czy sygnał PWM. Cała obsługa działania jest realizowana poprzez funkcje:
EXTI9_5_IRQHandler(void)
oraz
EXTI15_10_IRQHandler(void)
Należy pamiętać, że te funkcje grupują przerwania, w związku z czym w samej funkcji naeży rozpoznać źródło przerwania realizuje się to poprzez warunki EXTI_GetITStatus(EXTI_Line8) != RESET i analogicznie dla pozostałych linii. Należy także pamiętać o wyczyszczeniu flagi przerwania przy pomocy polecenia EXTI_ClearITPendingBit(EXTI_Line8), analogicznie wykonywanego dla pozostałych linii.
Konfiguracja licznika jako generatora sygnału zegarowego o małej częstotliwości została przypisana do pozycji joysticka w prawo, a jest realizowana następująco:

W celu uzyskania sygnału wolnozmiennego zmienne struktury TIM_Prescaler oraz TIM_ClockDivision ustawiono na najwyższe wartości, uzyskując w ten sposób częstotliwość 274 Hz (dla częstotliwości APB2 wynoszącej 72 MHz), częstotliwość jest ustawiana poprzez zdefiniowanie wartości zmiennej TIM_Period. Zmienna TIM_Pulse definiuje w, którym momencie nastąpi zmiana stanów. W przypadku konfiguracji licznika TIM1 , jako bardziej rozbudowanego, w celu włączenia wyjść należy dodać polecenie TIM_CtrlPWMOutputs(TIM1, ENABLE).
W przypadku generowania sygnału PWM konfiguracja jest identyczna, z tą różnicą iż wypełnienie steruje się poprzez wartość zmiennej TIM_Pulse struktury opisującej kanał licznika. Konfiguracja następuje przez wygenerowanie przerwania przez pozycję josticka w lewo. Cała konfiguracja prezentuje się następująco:

W przypadku opisu kanału wartość TIM_OCMode zmienia się z wartości TIM_OCMode_Toggle (dla sygnału zegarowego) na wartość TIM_OCMode_PWM1. Wartość TIM_Pulse, opisująca wypełnienie sygnału PWM, odczytywana jest z tablicy.
Projekt umożliwia konfigurowanie parametrów sygnału zegarowego i sygnału PWM, jest to realizowane poprzez następujące operacje:

Aktualizacja parametrów odbywa się bezpośrednio do rejestrów w przypadku sygnału PWM jest to aktualizacja rejestru CCR4 licznika TIM1, natomiast dla sygnału zegarowego aktualizowany jest rejestr ARR licznika oraz zerowanie rejestru CNT, zerowanie jest realizowane w celu uniknięcia sytuaji gdy rejestr CNT będzie posiadał większą wartość od ARR.
W przypadku wciśniecia joysticka (pozycja OK) następuje wyłączenie licznika, jest ono realizowane następująco:

Funkcje obsługi przerwań odwołują się do zmiennych zadeklarowanych w pliku main.c, aby umożliwić odwoływania się do tych zmiennych w funkcji obsługi przerwania należy przeprowadzić ich inicjalizacje jest to realizowane poprzez:

Mariusz Dziębowski
m.dziebowski@interia.pl