Do wyboru są następujące rodzaje trybów oszczędzania energii w STM32:
- Tryb uśpienia (Sleep Mode)
- Tryb zatrzymania (Stop Mode)
- Tryb czuwania (Standby Mode)
- Tryb Vbat (Vbat Mode)
Rys. 1. Pobór prądu dla mikrokontrolerów [datasheet]
Poniżej przedstawię jakie elementy układu działają dla poszczególnych trybów pracy:
W trybie uśpienia wyłączeniu ulega rdzeń mikrokontrolera, natomiast bloki peryferyjne oraz źródła sygnałów zegarowych są pozostawione jako aktywne. Z tego powodu powrót układu do normalnej pracy jest najszybszy z pozostałych układów. W związku z tym, że zegary są włączone to pobór prądu w tym trybie oraz w przypadku standardowej pracy zależy od częstotliwości taktowania. Jak można zaobserwować na rysunku 1, dla stm32f407 wartość prądu przy maksymalnej częstotliwości wynosi 40mA.
Kolejnym trybem jest tryb zatrzymania. W tym przypadku dane w SRAM oraz rejestrach zostają zachowane. Zegary PLL, HSI oraz HSE zostają zatrzymane, LSE, LSI oraz zegary czasu rzeczywistego, jeśli nie zostały wcześniej wyłączone, pracują nadal. Regulatory napięcia pracują w trybie normalnym albo z obniżonym poborem prądu. Natomiast pamięć flash może zostać skonfigurowana do pracy w trybie zatrzymania albo głębokiego uśpienia. Regulator napięci 1,2V można wprowadzić w tryb obniżonego poboru mocy. Spowoduje to natomiast dłuższy czas wybudzania układu. Dodatkowo układ niezależnego watchdoga może pracować w normalnym trybie.
Tryb czuwania jest najbardziej ekonomiczny, cechuje się najniższą wartością poboru prądu. W tym trybie zegary oraz rdzeń zostały wyłączone. Regulator napięcia oraz domeny 1.2V także są ustawione jako wyłączone. Dane przechowywane w rejestrach zostają utracone, z wyjątkiem danych wprowadzonych do tzw. Backup domain czyli do rejestrów chronionych. Zasilanie Vbat musi być doprowadzone do układu. Układ wraca do normalnej pracy, w przypadku wystąpienia sygnału reset, po przepełnieniu niezależnego watchdoga, w przypadku wystąpienia alarmu na RTC bądź gdy pojawi się sygnał na linii Wakeup.
Ostatni z trybów tzn. Vbat mode może być używane tylko w przypadku wyłączenia głównego zasilania Vdd.
Programowanie:
Do obsługi trybów uśpienia służą rozkazy asemblerowe __WFI() (wait for interrup) lub __WFE() (wait for event). Oraz biblioteki stm32f4xx_pwr. Zawiera ona wszystkie funkcje umożliwiające wprowadzanie układów tryby oszczędzania energii.
__WFI() wchodzi w tryb uśpienia wtedy gdy zakończyć wykonywanie wszystkich przerwań. Z trybu uśpienia może go wybudzić wywołanie przerwania.
Wybudzenie będzie szybsze w przypadku zastosowania instrukcji __WFE(), która nie potrzebuje dodatkowo wykonywania obsługi przerwania.
Pierwsza funkcja pozwala na wprowadzenie układu w stan uśpienia, aż do momentu wystąpienia określonego zdarzenia.
__WFI() wchodzi w tryb uśpienia wtedy gdy zakończyć wykonywanie wszystkich przerwań. Z trybu uśpienia może go wybudzić wywołanie przerwania.
Wybudzenie będzie szybsze w przypadku zastosowania instrukcji __WFE(), która nie potrzebuje dodatkowo wykonywania obsługi przerwania.
Pierwsza funkcja pozwala na wprowadzenie układu w stan uśpienia, aż do momentu wystąpienia określonego zdarzenia.
- void LOWPOWER_GO_SLEEP_INTERRUPT(uint8_t parameter_off_timer)
- {
- //parameter_delay_timer, gdy jeden to wylacza timery
- //gdy zero to zostawia je wlaczone
- //Wylaczenie timerow oraz systicka
- if (parameter_off_timer == 1)
- {
- #if defined(TIMER_DELAY)
- //Wylaczenie zdefiniowanego timer dla opoznien
- TIM_Cmd(TM_DELAY_TIM, DISABLE);
- #else
- //Wylaczenie systicka jeśli on służy do opóźnień zamiast zwykłego timera
- SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
- #endif
- }
- __WFI(); //Czekanie na przerwanie
- //Mikrokontroler w trybie sleep mode, oczekiwanie na przerwanie
- //Wlaczenie timerow
- if (parameter_off_timer == 1)
- {
- #if defined(TIMER_DELAY)
- //Wlaczenie timera
- TIM_Cmd(TM_DELAY_TIM, ENABLE);
- #else
- //Wlaczenie systicka
- SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
- #endif
- }
- }
Wprowadzenie układu w tryb uśpienia z oczekiwaniem na zdarzenie realizuje się poprzez wywołanie odpowiedniego makra. Nie trzeba w tym przypadku wyłączać systicka i timerów, ponieważ nie mogą one wywołać zdarzenia.
- void LOWPOWER_GO_SLEEP_EVENT(void)
- {
- //Oczekiwanie na zdarzenie
- __WFE();
- }
Następna opcja umożliwia wprowadzenie układu w tryb czuwania tzw. stand by. W tym przypadku należy wyczyścić flagi, standby oraz wakeup, po czym przejść do funkcji PWR_EnterSTANDBYMode(), która jest zdefiniowana w bibliotekach API. Wprowadza ona układ w omawiany tryb.
- void LOWPOWER_GO_STANDBY_MODE(void)
- {
- //Czyszczenie flag
- //PWR_CSR_SBF oraz PWR_CSR_WUF
- PWR_ClearFlag(PWR_FLAG_SB | PWR_FLAG_WU);
- //Przejście w tryb StandBy
- PWR_EnterSTANDBYMode();
- }
- uint8_t LOWPOWER_STANDBY_MODE_RESET(void)
- {
- //sprawdzenie flagi
- if (PWR_GetFlagStatus(PWR_FLAG_SB) != RESET)
- {
- //Wyczysc flagi
- PWR_ClearFlag(PWR_FLAG_SB | PWR_FLAG_WU);
- }
- return 0;
- }
Następnym trybem jest STOP mode. Jego wywołanie wygląda następująco:
- void LOWPOWER_GO_STOP_INTERRUPT(void)
- {
- //Przejście w tryb zatrzymania
- PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
- //Ponowne włączenie wszystkich zegarów
- SystemInit();
- }
W odpowiedni tryb wchodzi się poprzez podanie funkcji z biblioteki PWR. Po wyjściu z trybu zatrzymania należy ponownie włączyć wszystkie zegary.
Tryb zatrzymania do momentu wystąpienia zdarzenia:
- void LOWPOWER_GO_STOP_EVENT(void)
- {
- //Wejscie w tryb stop
- PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);
- //Wlaczenie zegarow
- SystemInit();
- }
Jeśli chodzi o ograniczenie poboru prądu przez cały układ z mikrokontrolerem, to można tu uzyskać poprzez wykonywanie następujących elementów:
- ograniczenie częstotliwości taktowania do wartości najmniejszej zadowalającej, czyli takiej która nie wpłynie negatywnie na procesy transmisji danych pomiędzy układami;
- stosowanie układów z niższym zapotrzebowaniem energetycznym bądź takich które można wprowadzać w odpowiednie stany ograniczające pobór mocy.
- wyłączenie nie potrzebnych linii zegarowych oraz peryferiów,
- dodatkowo jeśli urządzenie działa cyklicznie to po dokonaniu pomiarów można wyłączyć wszystkie peryferia (czasami jest to wykonywane samoistnie w trybach uśpienia, w niektórych mikrokontrolerach należy to robić ręcznie) na czas oczekiwania przed dokonaniem kolejnego pomiaru.
Przy projektowaniu systemu wymagającego obniżony pobór mocy należy pamięć o:
- przeprowadzeniu dokładnych obliczeń poboru prądu, oraz długości życia baterii,
- dokładnego zbadania możliwości obcięcia poboru energii dla wybranego mikrokontrolera,
- na jaki okres czasu przy budowanym systemie poszczególne bloki mogą zostać pozbawione zasilania,
- jak szybko możliwe jest przejście do trybu aktywnego i w jaki sposób to wykonać, tzn. jakie elementy muszą zostać włączone, przy wystąpieniu jakiej sytuacji mikrokontroler się obudzi itp.
Dokumentacja:
[1] Using STM32F4 MCU power modes with best dynamic efficiency