LinkedIn YouTube Facebook
Szukaj

Wstecz
Artykuły

Oszczędzanie energii w mikrokontrolerach STM32

Zmniejszenie poboru energii przez mikrokontroler można osiągnąć poprzez zmniejszenie częstotliwości jego taktowania (co wiąże się ze spowolnieniem działania) lub przez selektywne wyłączanie układy peryferyjnych wbudowanych w jego strukturę. Ten drugi mechanizm doskonale sprawdza się w mikrokontrolerach STM32, które są konstrukcyjnie przystosowane do selektywnego włączania i wyłączania większości wbudowanych bloków peryferyjnych.

 

 

Zaczniemy od omówienia dostępnych trybów oszczędnościowych, których działanie przetestowano na zestawie STM3210B–EVAL/A.

Sleep mode

Ten tryb oszczędzania energii jest integralną częścią rdzenia Cortex-M3, dlatego informacji na jego temat należy szukać nie w dokumentacji przygotowanej przez producenta mikrokontrolerów STM32, ale w opisie rdzenia przygotowanej przez firmę ARM.
W trybie sleep mode wyłączany jest rdzeń, natomiast wszystkie bloki peryferyjne i źródła sygnałów zegarowych są aktywne. Czas wyjścia z trybu uśpienia i powrót do normalnej pracy mikrokontrolera jest najkrótszy ze wszystkich dostępnych pośród trybów obniżonego poboru mocy. Natężenie prądu pobieranego ze źródła zasilania zależy przede wszystkim od częstotliwości pracy generatorów przebiegów taktujących i aktywnych bloków peryferyjnych. W skrajnym przypadku, gdy mikrokontroler pracuje z zegarem 72 MHz (włączone HSE i PLL) i są włączone wszystkie peryferia, mikrokontroler może pobierać blisko 15 mA. Drugim skrajnym przypadkiem jest praca rdzenia z taktowaniem 125 kHz przy wykorzystaniu wewnętrznego oscylatora HSI i po wyłączeniu wszystkich peryferiów. W takich warunkach mikrokontroler pobiera prąd o natężeniu nie przekraczającym 0,5 mA.
Zależnie od zastosowanych mechanizmów „usypiania” i „wybudzania” rozróżniane jest kilka rodzajów trybów pracy. Za sterowanie tymi trybami odpowiadają dwie instrukcje: WFI (Wait For Interrupt) oraz WFE (Wait For Event). Są to rozkazy asemblerowe, ich użycie w programie napisanym w C wymaga zastosowania podwójnego podkreślenia w roli przedrostka. Przykładowo: żeby wywołać instrukcję WFI należy zastosować zapis:
__WFI();

Sleep-on-exit

Wykorzystanie instrukcji WFI umożliwia między innymi wprowadzenie rdzenia w stan sleep-on-exit. Rdzeń w takim przypadku jest wprowadzany w tryb uśpienia dopiero po zakończeniu obsługi wszystkich przerwań. Wyjście z trybu jest wówczas, gdy w systemie zostanie wykryte żądanie obsługi przerwania. Fragment programu, który działa w opisany sposób przedstawiono na list. 1. Nadzór nad trybami uśpienia sprawowany jest przez NVIC, dlatego wykorzystano funkcje sterujące jego pracą.

List. 1. Fragment programu ilustrującego tryb oszczędzania energii sleep-on-exit

int main(void)
{
    EXTI_InitTypeDef EXTI_InitStructure;

      RCC_Conf();
      NVIC_Conf();
      GPIO_Conf();

      // Poinformowanie uC o zrodle przerwania
      GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource0);

      // Bedzie generowane przerwanie na zboczu opadajacym na EXTI_Line0
      EXTI_InitStructure.EXTI_Line = EXTI_Line0;
      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
      EXTI_Init(&EXTI_InitStructure);    

    // Po obsluzeniu przerwania ponownie bedzie wprowadzony tryb uspienia
      NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE);

      while (1);
}

Przerwanie od wyprowadzenia PD0 mikrokontrolera, do którego podłączono przycisk, skonfigurowano do reakcji na zbocze opadające. Po jego pojawieniu rdzeń wyjdzie z trybu uśpienia i nastąpi wywołanie funkcji obsługi przerwania.
Funkcja obsługi przerwania wygląda następująco:

void EXTI9_5_IRQHandler(void)
{
  EXTI_ClearITPendingBit(EXTI_Line9);
  GPIO_SetBits(GPIOC, GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9);
  delay_ms(2000);
  GPIO_ResetBits(GPIOC, GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9);
}

Rdzeń wybudza się na czas około 2 sekund zaświecając cztery diody LED, gasi je i ponownie „usypia”.
Uruchomienie opisanego trybu w trakcie debugowania spowoduje przerwanie pracy debugera. Rdzeń nie pracuje, więc nie ma potrzeby poszukiwania błędów. Istnieje jednak możliwość takiej konfiguracji mikrokontrolera, że nawet w trybach obniżonego poboru mocy, połączenie debugera i mikrokontrolera nie zostanie zerwane. Do tego celu służy funkcja DBGMCU_Config().Przykładowo, jeśli wykorzystywany jest tryb uśpienia, to należy umieścić w programie linijkę:

DBGMCU_Config(DBGMCU_SLEEP, ENABLE);