17: 低消費電力モード(PWR)---HALライブラリ

1: PWRモジュール概要

### PWRの役割 PWR(Power Control)はSTM32マイクロコントローラの電源管理を担当し、可変電圧監視機能と低消費電力モードを実現します。可変電圧監視器(PVD)はVDD電源電圧を監視し、電圧がしきい値を超える/下回った際に中断を発生させ、緊急停止処理を実行します。 低消費電力モードには以下の3種類があります: - 睡眠モード(Sleep) - 停止モード(Stop) - 待機モード(Standby) これらはシステムが空閑時に消費電力を削減し、デバイスの運用時間を延長するための機能です。

2: 電源構成図

VDDは電圧レギュレータを通じて1.8Vに降圧され、1.8V領域への電源供給を行います。

3: 低消費電力モードの選択

  • HSL/HSE: 内部高速クロック(HSI)と外部高速クロック(HSE)
  • 時鐘停止: 計算処理は一時停止しますが、レジスタ値は保持されます。
  • 電源停止: 回路が完全に電源オフになり、データも失われます。
  • 電圧レギュレータ: 1.8V領域への電源供給を担当し、停止させるとその領域が使用不可になります。

4: 睡眠モードの特徴

  • WFI: 任意のNVIC応答割り込みで覚醒可能
  • WFE: イベントまたは割り込みで覚醒可能(割り込みの優先度が高い)
  • 1.8V領域のCPUクロックのみ停止

5: 停止モードの特徴

  • PLL、HSI、HSEが無効化される
  • SRAMとレジスタ値は保持される
  • 外部割り込みでしか覚醒できない(内部割り込みは不可)
  • 覚醒後はHSE再起動が必要

6: 待機モードの特徴

  • 1.8V領域が電源オフになる
  • SRAMとレジスタ値が消失
  • WKUPピンやRTCアラームでしか覚醒できない
  • LSI/LSEはRTCとIWDGの維持のために動作継続

7: レジスタ操作

電源管理レジスタの設定例を示します。

2: STM32F407の実装

STM32F407のコード構造はSTM32F103と同様の設計原則を採用しています。

3: 実装例

A: 睡眠モード(WFI)

外部割り込みで覚醒する例:


#include "stm32f1xx_hal.h"
#include "rcc.h"
#include "UART.h"
#include "delay.h"
#include "key.h"

int main(void)
{
    HAL_Init();
    sys_stm32_clock_init(RCC_PLL_MUL9);
    delay_init(72);
    Uart_Init(115200);
    KEY_Init();

    while(1)
    {
        printf("5\n");
        HAL_Delay(1000);
        printf("4\n");
        HAL_Delay(1000);
        printf("3\n");
        HAL_Delay(1000);

        HAL_PWR_DisableSleepOnExit();
        SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
        HAL_PWR_EnterSLEEPMode(0, PWR_SLEEPENTRY_WFI);

        printf("2\n");
        HAL_Delay(1000);
        printf("1\n");
        HAL_Delay(1000);
    }
}

B: 内部割り込みによる覚醒

タイマ割り込みで睡眠モードを覚醒させる例:


#include "stm32f1xx_hal.h"
#include "rcc.h"
#include "UART.h"
#include "delay.h"
#include "key.h"
#include "IC_encoder.h"

int main(void)
{
    HAL_Init();
    sys_stm32_clock_init(RCC_PLL_MUL9);
    delay_init(72);
    Uart_Init(115200);
    KEY_Init();
    IC_encoder_Init(20000-1, 7200);

    while(1)
    {
        printf("5\n");
        HAL_Delay(1000);
        printf("4\n");
        HAL_Delay(1000);
        printf("3\n");
        HAL_Delay(1000);

        HAL_PWR_DisableSleepOnExit();
        SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
        HAL_PWR_EnterSLEEPMode(0, PWR_SLEEPENTRY_WFI);

        printf("2\n");
        HAL_Delay(1000);
        printf("1\n");
        HAL_Delay(1000);
    }
}

C: イベントによる覚醒

外部イベントで睡眠モードを覚醒させる例:


#include "stm32f1xx_hal.h"
#include "rcc.h"
#include "UART.h"
#include "delay.h"
#include "key.h"

int main(void)
{
    HAL_Init();
    sys_stm32_clock_init(RCC_PLL_MUL9);
    delay_init(72);
    Uart_Init(115200);
    KEY_Init();

    while(1)
    {
        printf("5\n");
        HAL_Delay(1000);
        printf("4\n");
        HAL_Delay(1000);
        printf("3\n");
        HAL_Delay(1000);

        HAL_PWR_DisableSleepOnExit();
        SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
        HAL_PWR_EnterSLEEPMode(0, PWR_SLEEPENTRY_WFE);
        SysTick->CTRL |= (SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);

        printf("2\n");
        HAL_Delay(1000);
        printf("1\n");
        HAL_Delay(1000);
    }
}

D: 内部イベントによる覚醒

内部イベントで睡眠モードを覚醒させる例:


#include "stm32f1xx_hal.h"
#include "rcc.h"
#include "UART.h"
#include "delay.h"
#include "key.h"
#include "IC_encoder.h"

int main(void)
{
    HAL_Init();
    sys_stm32_clock_init(RCC_PLL_MUL9);
    delay_init(72);
    Uart_Init(115200);
    KEY_Init();
    IC_encoder_Init(20000-1, 7200);

    while(1)
    {
        printf("5\n");
        HAL_Delay(1000);
        printf("4\n");
        HAL_Delay(1000);
        printf("3\n");
        HAL_Delay(1000);

        HAL_PWR_EnableSEVOnPend();
        HAL_PWR_DisableSleepOnExit();
        SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
        HAL_PWR_EnterSLEEPMode(0, PWR_SLEEPENTRY_WFE);
        SysTick->CTRL |= (SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);

        __HAL_TIM_CLEAR_FLAG(&PA0TIM2CH1Handleinit, TIM_FLAG_UPDATE);
        NVIC_ClearPendingIRQ(TIM2_IRQn);
        HAL_TIM_Base_Stop_IT(&PA0TIM2CH1Handleinit);

        printf("2\n");
        HAL_Delay(1000);
        printf("1\n");
        HAL_Delay(1000);
    }
}

E: SLEEP-ON-EXITモード

すべての処理を割り込みで実行する例:


#include "stm32f1xx_hal.h"
#include "rcc.h"
#include "UART.h"
#include "delay.h"
#include "key.h"
#include "IC_encoder.h"

int main(void)
{
    HAL_Init();
    sys_stm32_clock_init(RCC_PLL_MUL9);
    Uart_Init(115200);
    KEY_Init();
    HAL_PWR_EnableSleepOnExit();
    IC_encoder_Init(20000-1, 7200);

    while(1)
    {
        // 主ループは空にして割り込み処理に依存
    }
}

F: 停止モード(WFI)

外部割り込みで覚醒する例:


#include "stm32f1xx_hal.h"
#include "rcc.h"
#include "UART.h"
#include "key.h"

int main(void)
{
    HAL_Init();
    sys_stm32_clock_init(RCC_PLL_MUL9);
    Uart_Init(115200);
    KEY_Init();

    while(1)
    {
        printf("5\n");
        HAL_Delay(1000);
        printf("4\n");
        HAL_Delay(1000);
        printf("3\n");
        HAL_Delay(1000);

        SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
        HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);

        printf("2\n");
        HAL_Delay(1000);
        printf("1\n");
        HAL_Delay(1000);
    }
}

G: 停止モード(WFE)

外部イベントで覚醒する例:


#include "stm32f1xx_hal.h"
#include "rcc.h"
#include "UART.h"
#include "key.h"

int main(void)
{
    HAL_Init();
    sys_stm32_clock_init(RCC_PLL_MUL9);
    Uart_Init(115200);
    KEY_Init();

    while(1)
    {
        printf("5\n");
        HAL_Delay(1000);
        printf("4\n");
        HAL_Delay(1000);
        printf("3\n");
        HAL_Delay(1000);

        SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
        HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFE);
        SysTick->CTRL |= (SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
        sys_stm32_clock_init(RCC_PLL_MUL9);

        printf("2\n");
        HAL_Delay(1000);
        printf("1\n");
        HAL_Delay(1000);
    }
}

H: 待機モード

WKUPピンで覚醒する例:


#include "stm32f1xx_hal.h"
#include "rcc.h"
#include "UART.h"
#include "key.h"

int main(void)
{
    HAL_Init();
    sys_stm32_clock_init(RCC_PLL_MUL9);
    Uart_Init(115200);
    KEY_Init();
    __HAL_RCC_PWR_CLK_ENABLE();

    if(__HAL_PWR_GET_FLAG(PWR_FLAG_SB))
    {
        printf("待機モード中\n");
        __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
    }
    else
    {
        printf("待機モード外\n");
    }

    while(1)
    {
        printf("5\n");
        HAL_Delay(1000);
        printf("4\n");
        HAL_Delay(1000);
        printf("3\n");
        HAL_Delay(1000);

        HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
        __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
        HAL_PWR_EnterSTANDBYMode();

        printf("2\n");
        HAL_Delay(1000);
        printf("1\n");
        HAL_Delay(1000);
    }
}

RTCアラームで覚醒する例については、別のセクションで詳細に説明します。

タグ: STM32 HALライブラリ 低消費電力モード PWR STM32F103

7月28日 04:55 投稿