Sterownik PWM: Definicja timerów w STM32 do programowych PWM oraz odczyt ADC STM32
W ostatnim czasie Mateusz Pluta pracuje zarówno nad hardwarem jaki i softwarem projektu sterownika, którego wyjścia sterowane są za pomocą PWM. Na pokładzie sterownika będzie maksymalnie 30 wyjść, stąd niezbędna jest taka sama liczba PWM. W procesorze, na którym Mateusz pisze program, czyli STM32F4, istnieje możliwość wygenerowania tylko 16 sprzętowych PWM. Po odrzuceniu opcji wykorzystania sprzętowych PWM chciał wykorzystać układ scalony PCA9635, lecz nie ma w nim możliwości obniżenia częstotliwości generowanego sygnału. Drugi minus to cena. Ostatnim pomysłem, który wykorzystał, jest generowanie programowych PWM. Tym razem Mateusz opisze sposób, w jaki generuje programowe PWM z wykorzystaniem timerów. Zaprezentuje też implementację timera do wyzwalania pomiaru ADC. Program, nad którym pracuje, opiera się na bibliotece StdPeriph.
Więcej artykułów o projektach na blogu: InThou
Konfiguracja timerów:
W projekcie wykorzystałem 3 timery. Timer 2 do wyzwalania pomiaru ADC. Timer 3 do ustalenia stałej częstotliwości generowanego sygnału PWM oraz wypełnienia. Timer 4 do odliczania czasu załączenia danego wyjścia.
Timer 3 oraz 4 zostały skonfigurowane tak samo. W obu timerach skorzystałem z funkcji TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE) dzięki, której otrzymuję flagę o doliczeniu timera do ustalonej wartości.
Wszystkie użyte przeze mnie timery są podpięte do linii APB1. Zegar systemowy odlicza z częstotliwością 84MHz. Do wyznaczenia interesującej nas wartości częstotliwości np. 10kHz użyjemy następującego wzoru:
Timer 2 użyłem do innego celu, służy on do wyzwalania pomiaru ADC. Podczas konfiguracji użyłem funkcji TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update). Wykorzystywana jest ona jako zewnętrzny trigger do pomiaru ADC. Poniższa konfiguracja timera pozwala odczytywać wartość ADC co 200Hz.
Implementacja funkcji TIM_IT_Update:
Wykorzystanie wspomnianej flagi można zaimplementować do programu w następujący sposób:
W powyższej części programu dekrementuję zmienną period co każde wystawienie flagi przez funkcję, czyli doliczenie timera do zdefiniowanej wartości. Na podstawie zmiennej period ustalam częstotliwość pracy wyjść PWM.
Mierzone wartości ADC w projekcie:
Pomiary ADC są wykorzystywane w projekcie do odczytu wartości prądu oraz napięcia na danym wyjściu. Odczyt prądu wykonywany jest metodą low-side, który wybrałem z powodu tańszej implementacji niż high-side. Pomiar low-side nie zabezpiecza przed zewnętrznym zwarciem wyjścia do masy. Dlatego niezbędne jest zastosowanie jakiegoś dodatkowego rozwiązania, aby zwarcie nie spowodowało spalenia urządzenia. Do rozwiązania wspomnianego problemu wybrałem pomiar napięcia każdego wyjścia względem masy. Jeśli wartość napięcia będzie niższa niż ustawiony poziom przy jednocześnie włączonym wyjściu to nastąpi detekcja zwarcia i wyjście zostanie wyłączone. Jak wspomniałem poprzednio w projekcie będzie około 30 wyjść, dlatego niezbędne będą multipleksery.
Synchronizacja PWM z pomiarem:
PWM generowany w sposób programowy ma wiele ograniczeń, jednym z nich jest metoda synchronizacji pomiaru z przebiegiem PWM. W projekcie wykorzystałem wyzwalanie pomiaru ADC za pomocą timera. Do wyzwalanie ADC za pomocą timera służy funkcja TRGO. Podczas konfiguracji timera należy aktywować następującą funkcję: TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update). Konfiguracja timera:
Poniżej zamieszczam część konfiguracji przetwornika ADC, do użycia wyzwalania pomiaru za pomocą timera:
Pomiar ADC można wyzwalać używając także innych timerów, poniżej przedstawiam tabelę z Reference Manual [1], w której zawarte są informację na temat innych zdarzeń mogących wyzwalać pomiar.
Moment pomiaru:
Jak wspomniałem powyżej, pomiar ADC jest zsynchronizowany z przebiegiem PWM, tak aby był realizowany tylko i wyłącznie podczas stanu wysokiego. W momencie generowania stanu wysokiego wyzwalany jest timer związany z pomiarem ADC, zaś w stanie niskim timer jest dezaktywowany.
W programie zawarłem zabezpieczenie od chwilowej niesynchronicznej pracy PWM (np. podczas małego wypełnienia), które ma wpływ na pomiar ADC. Zabezpieczenie jest zrealizowane w postaci programowego filtru dolnoprzepustowego, pojedyncze niezsynchronizowane próbki nie będą wpływały na wynik pomiaru.
DMA (Direct Memory Access):
W projekcie do obsługi przetwornika ADC użyłem DMA, aby nie obciążać procesora, a po drugie ze względów edukacyjnych:).
Informację o tym, którego użyć strumienia DMA, oraz kanału także znajdziesz w Reference Manual [1]:
Do przeczytania komentarza do artykułu Mateusz zaprasza na swój blog: Odczyt ADC STM32