精华内容
下载资源
问答
  • stm32低功耗模式

    2019-12-30 14:19:11
    stm32低功耗模式 stm32f103系列有3种低功耗模式: 睡眠模式 停止模式 待机模式 从上往下功耗越低。 1. 睡眠模式 在睡眠模式中,仅关闭了内核时钟,内核停止运行,但其片上外设,CM3核心的外设全都还照常运行。...

    stm32低功耗模式

    stm32f103系列有3种低功耗模式:

    1. 睡眠模式
    2. 停止模式
    3. 待机模式

    从上往下功耗越低。

    1. 睡眠模式

    在睡眠模式中,仅关闭了内核时钟,内核停止运行,但其片上外设,CM3核心的外设全都还照常运行。有两种方式进入睡眠模式,它的进入方式决定了唤醒的方式,分别是:

    1. WFI(wait for interrupt),即等待中断唤醒
    2. WFE(wait for event),即等待事件唤醒

       

    直接调用函数void __WFI()void __WFE()即可进入睡眠模式

    2. 停止模式

    在停止模式中,进一步关闭了其他所有的时钟,所有的外设都停止工作,但保留了内核的寄存器、内存的信息,所以从停止模式唤醒,并重新开启时钟后,还可以从上次停止处继续执行代码。停止模式可以由任意一个外部中断(EXTI)唤醒,在停止模式中可以选择电压调节器为开模式或低功耗模式,低功耗模式下唤醒时间跟电压调节器为开模式比较时间较长

    直接调用函数void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)即可进入停止模式,调用这个函数需包含stm32f10x_pwr.h这个头文件。

    与睡眠模式不一样,系统从停止模式被唤醒时,时使用HSI作为系统时钟的,在stm32f103中,HSI时钟一般为8MHz,与我们常用的72MHz相差甚远,它会影响各种外设的工作 频率。所以在系统从停止模式唤醒后,若希望各种外设恢复正常的工作状态,就要恢复停止模式前使用的系统时钟,代码如下:

    static void SYSCLKConfig_STOP(void)
    {
        /* After wake-up from STOP reconfigure the system clock */
        /* 使能 HSE */
        RCC_HSEConfig(RCC_HSE_ON);
    
        /* 等待 HSE 准备就绪 */
        while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET)
        {
        }
    
        /* 使能 PLL */ 
        RCC_PLLCmd(ENABLE);
    
        /* 等待 PLL 准备就绪 */
        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
        {
        }
    
        /* 选择PLL作为系统时钟源 */
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    
        /* 等待PLL被选择为系统时钟源 */
        while (RCC_GetSYSCLKSource() != 0x08)
        {
        }
    }
    

    以下代码可以验证:

    RCC_ClocksTypeDef clock_status_wakeup,clock_status_config;
    uint8_t clock_source_wakeup,clock_source_config;
    
    PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);
            
    clock_source_wakeup = RCC_GetSYSCLKSource ();       
    RCC_GetClocksFreq(&clock_status_wakeup);
            
    /* 从新配置系统时钟 */
    SYSCLKConfig_STOP();
    clock_source_config = RCC_GetSYSCLKSource ();
    RCC_GetClocksFreq(&clock_status_config);
            
    printf("\r\n重新配置后的时钟状态:\r\n");
    printf(" SYSCLK频率:%d,\r\n HCLK频率:%d,\r\n PCLK1频率:%d,\r\n PCLK2频率:%d,\r\n 时钟源:%d (0表示HSI,8表示PLLCLK)\r\n", 
            clock_status_config.SYSCLK_Frequency, 
            clock_status_config.HCLK_Frequency, 
            clock_status_config.PCLK1_Frequency, 
            clock_status_config.PCLK2_Frequency, 
            clock_source_config);
                
    printf("\r\n刚唤醒的时钟状态:\r\n");    
    printf(" SYSCLK频率:%d,\r\n HCLK频率:%d,\r\n PCLK1频率:%d,\r\n PCLK2频率:%d,\r\n 时钟源:%d (0表示HSI,8表示PLLCLK)\r\n", 
            clock_status_wakeup.SYSCLK_Frequency, 
            clock_status_wakeup.HCLK_Frequency, 
            clock_status_wakeup.PCLK1_Frequency, 
            clock_status_wakeup.PCLK2_Frequency, 
            clock_source_wakeup);
    
    

    3. 待机模式

    从待机模式唤醒后,对芯片复位,重新检测boot条件,从头开始执行程序。它有4种唤醒方式:

    1. WKUP(PA0)引脚的上升沿
    2. RTC闹钟事件
    3. NRST引脚的复位
    4. IWDG(独立看门狗)复位

    以WKUP(PA0)引脚的上升沿唤醒为例:

    先调用库函数开启电源外设的时钟,即RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE);
    调用函数PWR_ClearFlag (PWR_FLAG_WU);清除标志位
    再调用函数PWR_WakeUpPinCmd (ENABLE);使能WKUP引脚的唤醒功能 ,使能PA0
    最后调用函数PWR_EnterSTANDBYMode();进入待机模式

    PWR_GetFlagStatus(PWR_FLAG_WU)可以检测复位类型,是上电复位还是待机复位。如果函数返回值是SET则表明是待机复位,否则是上电复位。


    几点说明:

    1. 待机模式下,PA0可以不用做任何配置。

    2. 处在低功耗模式下,程序无法下载。,想要下载:

      • 唤醒
      • 按复位键使芯片处于复位状态,然后点击下载按钮,再释放复位按键,即可下载
    3. 实测发现,在其他条件相同的情况下:

      • 运行模式下电流是30mA
      • 休眠模式下电流是11mA
      • 停止模式下电流是3mA
      • 待机模式下电流是2mA
    展开全文
  • STM32低功耗模式

    千次阅读 2020-04-17 15:04:24
    STM32低功耗模式有 3种: 1)睡眠模式(CM3内核停止,外设仍然运行) 2)停止模式(所有时钟都停止) 3)待机(standby)模式(1.8V内核电源关闭) 从待机模式唤醒后的代码执行等同于复位后的执行 进入Standby模式后...

    STM32 的低功耗模式有 3种: 1)睡眠模式(CM3内核停止,外设仍然运行) 2)停止模式(所有时钟都停止) 3)待机(standby)模式(1.8V内核电源关闭) 从待机模式唤醒后的代码执行等同于复位后的执行 进入Standby模式后,只能有Wake-up脚和RTC唤醒,特别是唤醒后,程序将从最开始运行,也就是相当于软件复位。不同系列的会略有不同,一般新出的芯片功能会增加一些。


    STM32L系列有五种低功耗模式,分别是standby,stop,sleep,low power sleep,low power run.
    standby模式下功耗最低,实测电流为1uA,此种模式下数据不保存。
    stop模式实测功耗为1.3uA,此种模式下数据保存。
    sleep模式下功耗为1mA左右,主要受频率,温度等影响,功耗发生变化。

    此代码使用RTC唤醒,使用其他方式唤醒方式相对简单,可以参考st官方例程。

    单片机源程序如下:

    
    /*
    *********************************************************
    ** Filename: stop_mode.c
    ** Abstract: 使用STM32L151C8T6MCU,使用RTC唤醒STOP和STANDBY模式下的低功耗,低功耗时长可以人为的进行设置
    **                                设置低功耗时长时请参考头文件中关于时长的宏定义
    ** 使用注意事项:使用CubeMX生成函数时,在main()函数后会自动生成SystemClock_Config()函数,此程序中调用了该函数。
    **                                如果该函数在其他文件中,请将该.h文件加入,以免发生错误;
    ** Date : 2018-01-04
    ** Author:王翔武
    *********************************************************
    */
    
    /* Includes ------------------------------------------------------------------*/
    #include "pwr_mode_rtc.h"
    #include "main.h"
    
    RTC_HandleTypeDef RTCHandle;        //RTC结构体变量       
    
    //进入STOP模式低功耗,使用RTC功能唤醒,其中stoptime单位为S,如设置1,低功耗1秒后唤醒
    void enter_stop_rtc(float stoptime)
    {
            uint32_t i;                //局部变量,用于计算低功耗时长
            system_power_config();
           
        /* Disable Wakeup Counter */
        HAL_RTCEx_DeactivateWakeUpTimer(&RTCHandle);
           
            /*To configure the wake up timer to 4s the WakeUpCounter is set to 0x242B:
            RTC_WAKEUPCLOCK_RTCCLK_DIV = RTCCLK_Div16 = 16
            Wakeup Time Base = 16 /(~37KHz) = ~0,432 ms
            Wakeup Time = ~5s = 0,432ms  * WakeUpCounter
            ==> WakeUpCounter = ~5s/0,432ms = 11562 */
            i = stoptime*2396;
        HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, i, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
       
        /* Enter Stop Mode */
        HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
            SystemClock_Config();
    }
    
    //进入STANDBY模式低功耗,使用RTC功能唤醒,其中standbytime单位为S,如设置1,低功耗1秒后唤醒
    void enter_standby_rtc(float standbytime)
    {
            uint32_t i;                //局部变量,用于计算低功耗时长
            system_power_config();
           
            if(__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET)
            {
                    /* Clear Standby flag */
                    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
            }
      
        /* Disable Wakeup Counter */
        HAL_RTCEx_DeactivateWakeUpTimer(&RTCHandle);
           
            /*To configure the wake up timer to 4s the WakeUpCounter is set to 0x242B:
            RTC_WAKEUPCLOCK_RTCCLK_DIV = RTCCLK_Div16 = 16
            Wakeup Time Base = 16 /(~37KHz) = ~0,432 ms
            Wakeup Time = ~5s = 0,432ms  * WakeUpCounter
            ==> WakeUpCounter = ~5s/0,432ms = 11562 */
            i = standbytime*2396;
        HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, i, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
       
            /* Clear all related wakeup flags */
            __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
    
             /* Enter the Standby mode */
            HAL_PWR_EnterSTANDBYMode();
    }
    
    //进入SLEEP模式低功耗,使用RTC功能唤醒,其中sleeptime单位为S,如设置1,低功耗1秒后唤醒
    void enter_sleep_rtc(float sleeptime)
    {
            uint32_t i;                //局部变量,用于计算低功耗时长
           
    
            system_power_config();
           
        /* Disable Wakeup Counter */
        HAL_RTCEx_DeactivateWakeUpTimer(&RTCHandle);
           
            /*To configure the wake up timer to 4s the WakeUpCounter is set to 0x242B:
            RTC_WAKEUPCLOCK_RTCCLK_DIV = RTCCLK_Div16 = 16
            Wakeup Time Base = 16 /(~37KHz) = ~0,432 ms
            Wakeup Time = ~5s = 0,432ms  * WakeUpCounter
            ==> WakeUpCounter = ~5s/0,432ms = 11562 */
            i = sleeptime*2396;
        HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, i, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
       
        /*Suspend Tick increment to prevent wakeup by Systick interrupt.
        Otherwise the Systick interrupt will wake up the device within 1ms (HAL time base)*/
        HAL_SuspendTick();
    
        /* Enter Sleep Mode , wake up is done once Key push button is pressed */
        HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
    
        /* Resume Tick interrupt if disabled prior to sleep mode entry*/
        HAL_ResumeTick();
    }
    
    //低功耗关闭项
    void system_power_config(void)
    {
            GPIO_InitTypeDef GPIO_InitStructure = {0};
    
            /* Enable Power Control clock */
            __HAL_RCC_PWR_CLK_ENABLE();
    
            /* Enable Ultra low power mode */
            HAL_PWREx_EnableUltraLowPower();
    
            /* Enable the fast wake up from Ultra low power mode */
            HAL_PWREx_EnableFastWakeUp();
    
            /* Enable GPIOs clock */
            __HAL_RCC_GPIOA_CLK_ENABLE();
            __HAL_RCC_GPIOB_CLK_ENABLE();
            __HAL_RCC_GPIOC_CLK_ENABLE();
            __HAL_RCC_GPIOD_CLK_ENABLE();
            __HAL_RCC_GPIOH_CLK_ENABLE();
            __HAL_RCC_GPIOE_CLK_ENABLE();
    
            /* Configure all GPIO port pins in Analog Input mode (floating input trigger OFF) */
            /* Note: Debug using ST-Link is not possible during the execution of this   */
            /*       example because communication between ST-link and the device       */
            /*       under test is done through UART. All GPIO pins are disabled (set   */
            /*       to analog input mode) including  UART I/O pins.           */
            GPIO_InitStructure.Pin = GPIO_PIN_All;
            GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
            GPIO_InitStructure.Pull = GPIO_NOPULL;
    
            HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
            HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
            HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
            HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
            HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);
            HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
    
            /* Disable GPIOs clock */
            __HAL_RCC_GPIOA_CLK_DISABLE();
            __HAL_RCC_GPIOB_CLK_DISABLE();
            __HAL_RCC_GPIOC_CLK_DISABLE();
            __HAL_RCC_GPIOD_CLK_DISABLE();
            __HAL_RCC_GPIOH_CLK_DISABLE();
            __HAL_RCC_GPIOE_CLK_DISABLE();
    
            /* Configure RTC */
            RTCHandle.Instance = RTC;
            /* Configure RTC prescaler and RTC data registers as follow:
            - Hour Format = Format 24
            - Asynch Prediv = Value according to source clock
            - Synch Prediv = Value according to source clock
            - OutPut = Output Disable
            - OutPutPolarity = High Polarity
            - OutPutType = Open Drain */
            RTCHandle.Init.HourFormat = RTC_HOURFORMAT_24;
            RTCHandle.Init.AsynchPrediv = 0x7C;
            RTCHandle.Init.SynchPrediv = 0x0127;
            RTCHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
            RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
            RTCHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
            if(HAL_RTC_Init(&RTCHandle) != HAL_OK)
            {
                    /* Initialization Error */
                    Error_Handler();
            }
    }
    
    
    /************************ Johnking *****END OF FILE****/

     用待机模式的理由及与停止模式的区别
    选用待机模式
    设备出厂,电池装在电路板上,封闭在模具当中,在到用户开始使用之前,必须保持最低功耗。停止模式下CPU电流消耗在20uA左右,而待机模式的电流消耗只有2uA。

    和停止模式的区别

    图

    因为SRAM和寄存器的内容会保存,即能PC指针能记录程序当前运行的位置,从停止模式唤醒时,能继续沿着到时进入停止模式处继续往下运行。(故运行时,设备检测到是电池供电时,选用停止模式:采集完数据进入停止模式,2小时后(根据需求自定义)定时唤醒采集,依此循环)

    图2
    SRAM和寄存器内容不会保存,即待机模式唤醒相当于系统复位,从头运行(设备测试完成,整机入库时,通过外部按键等方式触发进入待机模式)

    图3
    待机模式实现

    图4

    进入待机模式三个步骤说明:

    1.将系统控制寄存器第二位置1,当进入深度睡眠时,允许停止系统时钟(系统控制寄存器参考《Cortex-M3权威指南》)

    图5

    2.使能PWR_CR的PDDS位,使得深度休眠时进入待机模式
    3.清除WUF唤醒标志(WUF标志由硬件置位,当系统是WKUP唤醒复位而不是上电等复位时会置位。应用中可以用来读取PWR_CSR的WUF位是否为1来判断系统复位是不是待机唤醒)
    4.
    以上三个步骤由库函数PWR_EnterSTANDBYMode()实现

    图5
    进入待机模式
    void Standby_Entering(void)
    {
        RCC_APB2PeriphResetCmd(0x01fc, DISABLE);        //准备进入待机模式,复位所有IO,降低功耗(参照手册,根据需要复位对应IO)
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//需要配置电源控制寄存器,所以使能时钟,否则不能正常使用命令进入待机状态和唤醒
        PWR_WakeUpPinCmd(ENABLE);                    //使能WKUP引脚唤醒功能,否则WKUP引脚上升沿不能唤醒
        PWR_EnterSTANDBYMode();                    //进入待机模式
    }

    void Standby_Configure(void)
    {
        GPIO_InitTypeDef    GPIO_InitStructure;
        //EXTI_InitTypeDef  EXTI_InitStructure;
        //NVIC_InitTypeDef NVIC_InitStructure;
        
        GPIO_InitStructure.GPIO_Pin  =  GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IPD;
        GPIO_Init(WAKEUP_PORT, &GPIO_InitStructure);

    /*如果PA0只是用于唤醒,这部分可以不要,唤醒不是中断,中断控制器已经停止工作,如果正常模式下需要用到,可根据需要添加,这时候是中断事件
        GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
        EXTI_InitStructure.EXTI_Line = EXTI_Line0;
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
        EXTI_Init(&EXTI_InitStructure);
        
        NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;   
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    
        NVIC_Init(&NVIC_InitStructure); 
        */
    }
    中断处理(注:唤醒之后相当于复位,不会执行中断函数里的内容)
    void EXTI0_IRQHandler(void)
    {
        EXTI_ClearITPendingBit(EXTI_Line0);        //清除LINE0上的中断标志位
    }

    void main(void)
    {
        ...
        Standby_Configure();
        ...
        //读取PWR_CSR的WUF位检测复位来源,这也就是为什么在进入待机模式之前需要清除WUF唤醒标志,这样检测到唤醒标志就能确定发生了唤醒复位
        
        if(PWR_GetFlagStatus(PWR_FLAG_WU) == SET)//从待机唤醒后,除了电源控制/状态寄存器(PWR_CSR),所有寄存器被复位
        {
            //是待机唤醒复位,可帮助调试
        }
        else
        {
            //上电复位、软件复位等非唤醒复位
        }
        while(1)
        {
            if(外部按键标志)                //根据硬件和个人需求确定什么时候进入待机模式
            {
                Standby_Entering();
            }

            //数据采集、发送
            //进入停止模式
            //定时从停止模式唤醒    
        }
    }

    ————————————————
    版权声明:本文为CSDN博主「lmx11040101」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/lmx11040101/article/details/104496637


    这两天研究了STM32的低功耗知识,低功耗里主要研究的是STM32的待机模式和停机模式。让单片机进入的待机模式和停机模式比较容易,实验中通过设置中断口PA1来响应待机和停机模式。

    void EXTI1_IRQHandler(void)
    {
    if(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1))
    {
    delay_ms(10);
    while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1));
    if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1))
    {
    EXTI_ClearITPendingBit(EXTI_Line1);

    RTC_SetAlarm(RTC_GetCounter()+4);  //设置4S后闹钟唤醒
    RTC_ITConfig(RTC_IT_ALR, ENABLE);//使能闹钟中断. 
    RTC_WaitForLastTask();//等待上一次写RTC任务完成

    Standby();             //进入待机(停机)状态
    }
    }

    }


    void Standby()
    {
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE);//开电源管理时钟PWR_Regulator_LowPower

    PWR_WakeUpPinCmd(ENABLE);//使能唤醒引脚,默认PA0

             PWR_EnterSTANDBYMode();//进入待机
              //PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI|PWR_STOPEntry_WFE);//进入停机
    }


    进入的待机模式和停机模式很简单,基本一样。那么问题来了。

    主要问题有:

    1:如何对他们进行唤醒?

    2:唤醒的闹钟中断能否执行?

    2:唤醒后的程序入口在哪?

    通过各种实验和查资料,得到了如下结论:(本实验通过设定RTC_SetAlarm(RTC_GetCounter()+4); 为设置4S后进行闹钟唤醒,并开启闹钟中断,手册中可以查到闹钟中断能产生唤醒,故用闹钟中断进行实验)

    先研究待机模式下的唤醒,在闹钟中断函数如下:

    void RTCAlarm_IRQHandler(void)
    {
    if(RTC_GetFlagStatus(RTC_IT_ALR))
    {
      RTC_ClearITPendingBit(RTC_IT_ALR);
      RTC_WaitForLastTask(); 
    EXTI_ClearITPendingBit(EXTI_Line17);


            if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET)
            {
    PWR_ClearFlag(PWR_FLAG_WU);
            }
    GPIO_WriteBit(GPIOA, GPIO_Pin_5, 0);//LED指示

    }
    }

    实验结果:PA5的LED不指示,并且从其他LED灯的指示可以知道程序又重新开始运行。也就是被复位。

    因此待机模式下的唤醒结论如下:

    1:唤醒形式直接产生闹钟中断就能唤醒。

    2:唤醒后不会进入闹钟中断函数

    3:唤醒后程序复位,重新执行

     

    再研究停机模式下的唤醒,停机模式唤醒和待机唤醒差别很大,开始还以为两者相同,停机唤醒相对复杂些,中途调试了很长时间,才明白了停机唤醒的过程,贴上闹钟中断程序如下:

    char Wakeflag=0;

    void RTCAlarm_IRQHandler(void)
    {
    if(RTC_GetFlagStatus(RTC_IT_ALR))
    {
    EXTI_ClearITPendingBit(EXTI_Line17);
    RTC_ClearITPendingBit(RTC_IT_ALR);
    RTC_WaitForLastTask(); 
    EXTI_ClearITPendingBit(EXTI_Line7);
    EXTI_ClearITPendingBit(EXTI_Line1);//对于程序可能产生的标志位必须的清除干净,不清除会出现唤醒失灵现象!!

          if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET)
            {
    PWR_ClearFlag(PWR_FLAG_WU);//一般没用
            }
    SystemInit();//重要,由于停机下对所有时钟关闭,所以唤醒需要重新配置时钟!!

           Wakeflag=!Wakeflag;
    GPIO_WriteBit(GPIOA, GPIO_Pin_5, Wakeflag);//LED灯指示

    }
    }

    相比待机的闹钟中断是不复杂了很多,停机模式下的唤醒的中断函数需要注意这两点(能得到这两点,耗费了大量时间,终于还是搞定了,嗨皮!!):

    1:重要,对于程序可能产生的标志位必须的清除干净,不清除会出现唤醒失灵现象!!

    2:重要,由于停机下对所有时钟关闭,所以唤醒需要重新配置时钟!!

    实验现象:LED可以产生开通与关断的效果。并且从其他LED的指示可以看到程序没有被复位,而是继续原来运行。

    因此停机模式下的唤醒结论如下:

     

    1:唤醒形式产生闹钟中断不一定就唤醒,需要对任何可能的标志位清楚,并且时钟要重新配置。

    2:唤醒后进入闹钟中断函数

    3:唤醒后程序进入闹钟中断函数,然后再进入原来停机的位置继续运行。没有复位,单片机寄存器里的各种变量值仍然保留!!

     

    展开全文
  • stm32 低功耗模式

    2019-05-27 17:38:21
    https://www.cnblogs.com/firege/p/5806040.html
    展开全文
  • 本文主要解读STM32低功耗模式的机制,并不侧重STM32低功耗的程序实现,而且借助STM32固件库实现STM32低功耗会变的非常简单。 一、STM32芯片性能 使用芯片型号:stm32,CORTEX -M0.封装TSSOP20. 运行模式:...



    本文主要解读STM32低功耗模式的机制,并不侧重STM32低功耗的程序实现,而且借助STM32固件库实现STM32低功耗会变的非常简单。

    一、STM32芯片性能

    使用芯片型号:stm32,CORTEX -M0.封装TSSOP20.

    运行模式:内部时钟(HSI),系统时钟频率采用48MHZ

    工作电压:3.3V

    芯片具体参数如下:


    二、芯片功耗

    功耗:


    芯片工作模式:

    工作模式:外设正常运行,内核CPU及SRAM供电,未使用外设的时钟默认关闭。

    睡眠模式只有CPU停止工作,各个外设正常工作,依靠任何中断/事件唤醒。

    停机模式1.8V供电区域时钟被停止,内部HSI,PLL,外部时钟HSE均关闭,同时电压检测器也可进入低功耗模式,但SRAM和寄存器不断电,此时只能依靠外部中断(EXTI)RTC时钟才能唤醒。

    待机模式:1.8V供电区域被时钟停止,内部HSI,PLL,外部时钟HSE均关闭,同时电压检测器也可进入低功耗模式,SRAM和不属于待机电路的寄存器也被断电关闭,此时即使是外部中断(EXTI)也不能将其唤醒,只能通过复位(外部复位,看门狗复位)、唤醒引脚、RTC时钟来唤醒。

    注意:无论是在停止模式 还是待机模式下,RTCIWDG及其时钟源不会被关闭。

    各个模式功耗:

    功耗计算方式:功耗=工作电压*工作电流。




    I/O模块损耗:

    静态损耗:

    内部上下拉电阻损耗:这部分损耗主要取决于内部电阻的大小,一般为了降低内部电阻损耗常常需要降低电阻两端电压,若引脚为低电压则采用下拉电阻,若引脚为高电压则采用上拉电阻。

    I/O额外损耗:当引脚设为输入I/O时,用来区分电压高低的斯密特触发器电路会产生一部分消耗,为此可将引脚设为模拟输入模式。

    动态损耗:对于悬浮的引脚,由于其电压不稳定会产生外部电磁干扰和损耗,因此必须把悬浮引脚设为模拟模式或输出模式,引脚电压的切换会对外部和内部电容负载产生动态损耗,其损耗与电压切换频率和负载电容有关。具体损耗值如下:


    三、CORTEX-M0低功耗功能、指令、相关寄存器

    CORREX内核支持低功耗模式有2种:

    睡眠模式CPU时钟停止,对应stm32睡眠模式

    深度睡眠模式:系统时钟停止,PLL,FLASH 关闭,对应stm32停机模式。

    进入睡眠模式:

    CPU处理完中断后软件必须能使其进入睡眠模式,当CPU执行WFI指令,其将会立即进入睡眠模式,当异常产生或中断被挂起时,其立即被唤醒。

    CPU执行WFE指令时,它首先会检查对应的事件标志位,当事件标志寄存器为0时进入睡眠模式,否则将寄存器事件标志清0并继续执行程序。事件标志可由外部事件标志或SEV指令产生。

    返回方式:通过设置内核SCB寄存器的Sleep-on-exit位,可以选择系统被唤醒执行完中断服务程序后进入主线程模式后是否立即进入睡眠模式。

    从睡眠中唤醒:

    WFI唤醒或sleep-on-exit

    一般来说,使能的异常可以唤醒内核。对于一些系统,在唤醒后执行中断处理程序前需要先执行重新恢复的任务,则首先需要屏蔽所有中断(PRIMASK=1),中断发生后内核被唤醒但不执行中断处理,待执行完恢复任务后再将PRIMASK设为0,此后执行中断处理任务。

    WFE唤醒:

    使能异常可以唤醒内核。外部事件或SEV指令发送的事件也可唤醒内核。

    注意:当SCRSEVONPEND设置为1时,任何使能/非使能中断或事件都可唤醒内核。

    中断唤醒控制器(WIC):

    WIC只有在SCR寄存器DEEPSLEEP位设为1时才能使能,WIC不可编程也没有相关的控制寄存器,它仅与硬件信号有关,当进入深睡眠时内核大部分模块被关闭,系统计数器也被关闭,因此当内核被唤醒时需要较多的时间恢复到睡眠前的状态并处理中断。

    外部事件输入:可在WFE模式下唤醒内核。

    相关指令:

    WFE  等待事件,若无事件则睡眠,中断、事件唤醒

    WFI   等待中断,立即进入睡眠,中断唤醒

    SEV  软件发送一个事件,在核系统中可唤醒另一个内核。

    微控制器软件接口标准

    由指令对应的C语言接口:

    //core_cmInstr.h

    void __WFE(void) // Wait for Event

    void __WFI(void) // Wait for Interrupt

    void __SEV(void) // Send Event

    相关寄存器:

    SCR寄存器:


    SEVONPEND:

    0: 只有使能的中断或事件才能唤醒内核。

    1: 任何中断和事件都可以唤醒内核。

    SLEEPDEEP:

    0: 低功耗模式为睡眠模式。

    1: 进入低功耗时为深度睡眠模式。

    SLEEPONEXIT:

    0:  被唤醒进入线程模式后不再进入睡眠模式。

    1: 被唤醒后执行完相应的中断处理函数后进入睡眠模式。

    四、STM32时钟管理

    运行模式下可通过关闭和降低相关外设的时钟频率来减少功耗。

    APB 外设时钟和DMA时钟可用软件禁止。

    睡眠模式停止CPU时钟。在CPU睡眠中存储器接口时钟(FlashRAM接口)可被停止。当连接到APB所有外设的时钟禁止后,当进入睡眠期间AHB APB桥时钟由CPU的硬件关闭。

    CPU进入停止模式时停止V18域、PLLHSIHSI14HSE振荡器的时钟。

    HDMI CEC, USART1 I2C1 即使在MCU 进入停止模式下仍有能力打开HIS振荡器 (假如HIS被选为这些外设的时钟)

    LSE振荡器已使能的情况下,HDMI CEC 和 USART1 当在系统进入停止模式下也可由LSE振荡器驱动 (假如LSE被选为这些外设时钟)。但是这些外设没有打开LSE振荡器的能力。

    CPU进入待机模式时停止V18域、PLLHSIHSI14HSE振荡器的时钟。

    当设置DBGMCU_CR寄存器中的DBG_STOP DBG_STANDBY位,那么CPU在相应的深度睡眠模式下也可以具有调试功能。

    当系统由中断(停止模式)或复位(待机模式)唤醒后,HSI振荡器被选为系统时钟(不管进入停止模式或待机模式前选用的是何种时钟)

    假如当前正在进行闪存编程,只有在闪存编程全部完成之后才会进入深度睡眠模式(深度睡眠延后)。若当前正在使用APB域,那么只有全部完成APB域的操作后才进入深度睡眠模式。

    五、STM32低功耗设置


    STM32工作模式主要有运行、睡眠、停止、待机4种模式,前面已介绍过。详细见第二节。

    供电框图

      由上图可以看到整个stm32芯片的供电图,模拟电路部分采用VDDA独立供电,各个部分可以独立被关断或开启。备份电路部分由电池供电,主要有RTC时钟及相关的备份寄存器,VDD掉电后可由电池供电,对于没有VBAT引脚的芯片,其电源直接与VDD相连。核心部分分为1.8V工作域和VDD工作域,1.8V工作域主要有内核、存储、外设部分,VDD供电域主要有I/O、待机电路(唤醒电路,独立看门狗)、电压调节器(Voltage Regulator)

    电压调节器

    器件复位后电压调节器总是打开着的,其根据应用模式有三种不同的工作模式。

    运行模式:调节器以全功耗模式为域 (内核,内存和数字外设提供1.8V电源。

    停止模式:调节器以低功耗模式为保持寄存器及SRAM数据部分域提供1.8V的电源。

    待机模式:调节器断电,除了待机电路及备份域电路外,寄存器和SRAM的内容全部丢失。

    相关寄存器介绍:

    1cortex-mo中的SCR寄存器

    SEVONPEND:

    0: 只有使能的中断或事件才能唤醒内核。

    1: 任何中断和事件都可以唤醒内核。

    SLEEPDEEP:

    0: 低功耗模式为睡眠模式。

    1: 进入低功耗时为深度睡眠模式。

    SLEEPONEXIT:

    0:  被唤醒进入线程模式后不再进入睡眠模式。

    1: 被唤醒后执行完相应的中断处理函数后进入睡眠模式。

    2,电源控制寄存器PWR_CR


    其中与低功耗有关的控制位:

    CSBF: 清除待机标志,该位始终读出为0,写1清除待机标志。

    CWUF: 清除唤醒标志,该位始终读出为0。写1清除唤醒标志。

    PDDS: 掉电深睡眠

    0: CPU进入深睡眠时进入停机模式,调压器的状态由LPDS位控制。

    1: CPU进入深睡眠时进入待机模式。

    LPDS: 深睡眠下的低功耗

    0: 在停机模式下电压调节器开启

    1: 在停机模式下电压调节器处于低功耗模式

    3,电源控制/状态寄存器(PWR_CSR)


    EWUP2/EWUP1: 使能WKUP2EWUP1引脚。

    0: WKUP1/2 引脚作为通用IO口。WKUP1引脚上的事件不能将CPU从待机模式唤醒。

    1: WKUP1/2引脚用于将CPU从待机模式唤醒,WKUP1引脚被强置为输入下拉的配置(WKUP1引脚上的上升沿将系统从待机模式唤醒)

    SBF: 待机标志

    该位由硬件设置,只能设置电源控制寄存器PWR_CRCSBF位清除。

    0:系统不在待机模式

    1:系统进入待机模式

    WUF: 唤醒标志

    由硬件设置,只能设置电源控制寄存器PWR_CRCWUF位清除。

    0: 没有唤醒事件发生

    1: WKUPRTC闹钟产生一个唤醒事件

    注意:当WKUP引脚已经是高电平时,在(通过设置EWUP)使能WKUP引脚时,会检测到一个额外唤醒的事件。 

    低功耗模式的进入与退出问题

    1、睡眠模式

    进入睡眠模式:

    STM32在运行状态时,执行WFIWFE指令可进入睡眠模式。

    条件:SLEEPDEEP=0,设为睡眠模式。此时CPU时钟被停止。

    若令被唤醒的STM32执行完中断处理任务后进入睡眠模式,则可将SLEEPONEXIT设为1.

    退出睡眠模式:

    执行WFI指令进入睡眠,可通过使能中断唤醒。执行WFE指令进入睡眠可由事件唤醒,CPU时钟打开。产生事件的两种方式:

    配置一个外部或内部EXTI线做为事件模式。

    使能外设中断但不使能NVIC中断,同时将SEVONPEND设为1,此时任何中断和事件都可以唤醒内核,此时必须清除NVIC和外设的中断标志以免唤醒后出错。

    2、停止模式

    进入停止模式:

    进入停止模式后1.8电压区域时钟被停止,PLLHSIHSE被关闭,但SRAM和寄存器正常供电。进入停止模式方法:首先确定所有中断/事件标志被清除否则不会进入停止模式,关闭ADC\DAC电源,将SLEEPDEEP设为深睡眠模式,在深睡眠后选择进入停机模式(PDDS=0),可关闭或开启电压调节器(LPDS),执行WFIWFE指令进入停机模式。

    退出停止模式:

    一个使能的外部中断或外部事件可唤醒STM32SMT32被唤醒后系统时钟被设为HSI。因此在唤醒后还需软件恢复时钟设置,并清除相关的低功耗标志。

    3、待机模式

    进入待机模式:

    进入SRAM和寄存器内容丢失,进入条件:将SLEEPDEEP设为深睡眠模式,在深睡眠后选择进入待机模式(PDDS=1),关闭电压调节器(LPDS),执行WFIWFE指令进入待机模式。

    在待机模式下,除了复位引脚(始终有效)、当配置为防侵入或校准输出时的TAMPER 引脚、使能的唤醒(WKUP)引脚外,所有的I/O口线处于高阻态。因此进入待机模式前不需要再特意配置引脚的低功耗特性。

    退出待机模式:

    IWDG复位,WKUP引脚上的上升沿或RTC 闹钟事件可唤醒STM32,当退出待机模式时除了电源控制/状态寄存器(PWR_CSR)外所有寄存器复位,整个系统被复位。

    4、低功耗模式下的RTC自动唤醒

    RTC可以在不需要依赖外部中断的情况下唤醒低功耗模式下的微控制器(自动唤醒模式)RTC提供一个可编程的时间基数,用于周期性从停止或待机模式下唤醒。

    从停止模式下唤醒,必须进行如下操作:

    配置外部中断线17为上升沿触发。

    配置RTC使其可产生RTC闹钟事件。

    从待机模式中唤醒,不必配置外部中断线17

    5、调试模式

    默认情况下,如果在进行调试微处理器时,使微处理器进入停止或待机模式,将失去调试连接。这是因为Cortex-M0的内核失去了时钟。通过设置DBGMCU_CR寄存器中的某些配置位,可以在使用低功耗模式下调试软件。

    六、低功耗模式总结

    降低STM32功耗方法主要有:

    关闭不需要的外设、降低STM32的系统频率。

    合理设置I/O降低I/O静态和动态损耗。

    进入低功耗模式。

    恢复到正常运行状态:

    睡眠模式由中断或事件唤醒,唤醒后可清除唤醒标志。

    停止模式:唤醒后需恢复时钟设置,并将改动的I/O设置恢复。

    待机模式:唤醒后系统被恢复,随后系统被复位,可清除待机标志。

     

    七、固件库使用

    主要文件:

    stm32f0xx_rcc.cstm32f0xx_gpio.cstm32f0xx_pwr.c

     

    时钟及I/O设置相关函数(部分):

    void RCC_XXXPeriphClockCmd(X,X) ; //用于使能和关闭外设时钟

    void SystemInit (void)//系统初始化设置时钟

    GPIO_Init(GPIOX, &GPIO_InitStructure);//设置相关引脚

     

    低功耗函数(部分):

     

    //唤醒引脚配置

    void PWR_WakeUpPinCmd(uint32_t PWR_WakeUpPin, FunctionalState NewState);

    ///清除寄存器状态标识

    FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG);

    void PWR_ClearFlag(uint32_t PWR_FLAG);

    进入低功耗模式:

    void  PWR_EnterSleepMode(uint8_t PWR_SLEEPEntry);

    Void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry);

    void PWR_EnterSTANDBYMode(void);

     

    函数解析:

    下面是一个进入停机模式的函数,此函数功能和使用方法在注释部分已经非常明确。通过源代码可以看出SMT32在停机模式下寄存器的设置情况。调用此函数STM32可进入低功耗模式。


    void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)

    {

      uint32_t tmpreg = 0;

     

      /* Check the parameters */

      assert_param(IS_PWR_REGULATOR(PWR_Regulator));

      assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));

     

      /* Select the regulator state in STOP mode ---------------------------------*/

      tmpreg = PWR->CR;

      /* Clear PDDS and LPDSR bits */

      tmpreg &= CR_DS_MASK;

     

      /* Set LPDSR bit according to PWR_Regulator value */

      tmpreg |= PWR_Regulator;

     

      /* Store the new value */

      PWR->CR = tmpreg;

     

      /* Set SLEEPDEEP bit of Cortex-M0 System Control Register */

      SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

     

      /* Select STOP mode entry --------------------------------------------------*/

      if(PWR_STOPEntry == PWR_STOPEntry_WFI)

      {

        /* Request Wait For Interrupt */

        __WFI();

      }

      else

      {

        /* Request Wait For Event */

        __WFE();

      }

      /* Reset SLEEPDEEP bit of Cortex System Control Register */

      SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);  

    }

     博客地址:Beep  http://blog.csdn.net/beep_

    展开全文
  • STM32低功耗模式–停止模式 STM32F10xx低功耗模式 睡眠模式:Cortex™-M3内核停止,所有外设包括Cortex-M3核心的外设,如NVIC、系统时钟(SysTick)等仍在运行 停止模式:所有的时钟都已停止 待机模式:1.8V电源关闭 ...
  • STM32低功耗模式解读

    万次阅读 2015-08-25 12:26:23
    本文主要解读STM32低功耗模式的机制,并不侧重STM32低功耗的程序实现,而且借助STM32固件库实现STM32低功耗会变的非常简单。 一、STM32芯片性能 使用芯片型号:stm32f030f4,CORTEX -M0.封装TSSOP20. 运行模式:内部...
  • 1. STM32低功耗模式概述 2. 寄存器和库函数配置 3. HAL库配置PVD实例 1. STM32低功耗模式概述 系统或电源复位后,微控制器处于运行状态,HCLK位CPU提供时钟,内核执行代码。当CPU不需要继续运行时,乐意利用多种低...
  • STM32低功耗模式实践

    千次阅读 2016-01-28 09:28:31
    STM32低功耗模式实践 STM32一共有三种低功耗模式,睡眠模式、停止模式以及待机模式。 其中,睡眠模式时内核停止运行,但外设仍在工作,所有外设的时钟不会被关闭。 停止模式,除了Cortex-M3内核停止外,所有外设...
  • STM32低功耗模式笔记

    千次阅读 2018-11-25 23:27:41
    STM32低功耗模式   一、低功耗注意事项: 1、所有IO管脚,如果高阻状态端口是高电平,就设成上拉输入;如果高阻状态是低电平,设成下拉输入;如果高阻是中间状态,设成模拟输入。这个很多人都提到过,必须的。...
  • STM32低功耗模式下GPIO如何配置最节能,这里总结了一下四点,亲测有效(基于STM32L011芯片 LL库),可降低几百微安。 1、将未使用的GPIO 配置为模拟输入模式 GPIO始终有一个输入通道,可以是数字或模拟通道,如果...
  • STM32低功耗模式与烟雾报警器触发信号电路设计 https://www.cnblogs.com/kanite/p/5352642.html 1、STM32的3种低功耗模式 STM32有3种低功耗模式,分别是睡眠模式、停机模式和待机模式。 2、STM32在不同模式...
  • STM32低功耗模式测试

    2019-09-02 11:44:12
    stm32单片机低功耗模式共用3中,下来对3中低功耗进行分析测试。 先看手册上相关低功耗资料介绍: 先来分析睡眠模式: 进入睡眠模式比较简单,只需一条指令即可。唤醒睡眠模式,我们使用串口中断来唤醒,...
  • STM32支持3种低功耗模式: 1.第一种就是睡眠模式,这种模式,电压调节器开启,内核停止运行,外设保持运行状态。这种模式一般适用于等待外设的中断,或者是事件时降低系统的功耗。 2.第二种就是停止模式。这种模式,电压...
  • STM32低功耗模式之待机模式

    千次阅读 2019-04-29 17:24:52
    上周完成了一个小项目,项目涉及到stm32...先来看下低功耗模式下的情况(只看停止跟待机): 停止模式 停止模式在保留SRAM和寄存器内容的同时实现了非常低的功耗。 1.8V域中的所有时钟停止,PLL、HSI RC和禁用HS...
  • stm32低功耗模式

    2019-02-24 15:59:24
    这里对stm32的三种低功耗模式进行介绍,下图是参考手册的简介。 Standby待机模式 简述 该模式是三种低功耗模式中功耗最低的一种,最低2ua,类似于软件复位,每次唤醒后程序都要重头开始,保存的一些变量也会丢失。该...
  • 4.低功耗设计-stm32低功耗模式

    千次阅读 2019-09-19 10:07:57
    在之前的低功耗软件设计中也提到过一部分的stm32降功耗的方法,freeRtos系统帮我们写好的一个睡眠模式tickless,当我们的系统进入空闲任务后,就会自动睡眠,来达到降功耗的目的,打开方式也比较简单,在...
  • <p>stm32处于停机模式下,怎么保证定时器的PWM波继续输出,是把定时器的时钟源设置成外部的LSE吗还是 ,求解决,谢谢</p>
  • stm32低功耗模式总结

    千次阅读 2017-03-19 16:43:05
    只需要四条语句即可进入低功耗...感觉应该是,唤醒后系统会跑一遍主函数,所以,以后要想进入低功耗模式,可以在中断内设置,唤醒后不会再进入主函数(如果把进入低功耗模式放到主函数的话,会不断进入低功耗模式)。
  • STM32低功耗模式总结

    2020-08-12 10:43:22
    低功耗 具体要点为:1、所有IO管脚,如果高阻状态端口是高电平,就设成上拉输入,如果高阻状态是低电平,设成下拉输入,如果高阻是中间状态,设成模拟输入。这个很多人都提到过,必须的。作为输出口就免了,待机你想...
  • 低功耗模式 (1)睡眠SLEEP模式:CPU停,外设运行,唤醒源为所有中断(2)停机STOP模式:CPU停,时钟停,外设停,只有SRAM和寄存器还能保持原来的值,唤醒源是外部中断(3)待机SUSPEND模式:CPU停、外设停、时钟停、SRM...
  • 在嵌入式设备中,常涉及到低功耗...下文所涉及的低功耗模式都是指STM32的停机模式,在该模式下PLL停止工作,仅LSI和HSI继续运行(进休眠前已经打开的话),所有IO状态、内部RAM数据保持不变,所有外部IO中断、内部RTC...
  • 停止模式基于Cortex®-M3 deepsleep mode 结合外设时钟选通 停止模式: ... 选择进入低功耗睡眠模式的机制 (SLEEPONEXIT位),设置SLEEPDEEP位,清除PDDS位,清除WUF位, 设置LPSDSR(电压稳...
  • STM32低功耗模式---停机和待机模式

    千次阅读 2019-06-21 16:07:44
    进入低功耗模式先执行: RCC_APB2PeriphResetCmd(0X01FC,DISABLE);//复位所有IO口, 端口全设置为高阻态,最好外设时钟也关闭 停机模式: RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//使能PWR外设时钟 /...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 797
精华内容 318
关键字:

stm32低功耗模式