当前位置:   article > 正文

STM32F4_待机唤醒详解_stm32 sleepmode 唤醒

stm32 sleepmode 唤醒

目录

1. 低功耗模式

1.1 降低系统时钟速度

1.2 外设时钟门控

2. 睡眠模式

2.1 进入睡眠模式

2.2 退出休眠模式

3. 停止模式

3.1 进入停止模式

3.2 退出停止模式

4. 待机模式

4.1 进入待机模式

4.2 退出待机模式

4.3 电源控制寄存器:PWR_CR

4.4 电源控制/状态寄存器:PWR_CSR

5. 库函数配置进入待机模式

6. 实验程序


        在学习STM32待机唤醒功能之前,我们首先来系统的学习32单片机的低功耗模式,这将对于我们理解睡眠/停止/待机模式有很大的帮助。

1. 低功耗模式

        默认情况下,系统复位或者上电复位后,MCU微控制器进入运行模式。在运行模式下,CPU通过HCLK提供时钟,并且执行程序代码。系统提供了多个低功耗模式,可在CPU不需要运行时(例如等待外部事件时)节省功耗。由用户根据应用选择具体的低功耗模式,以在低功耗、短启动时间和可用唤醒源之间寻求最佳平衡。

STM32有三种低功耗模式

  • 睡眠模式(Cortex -M4F内核停止,外设保持运行)
  • 停止模式(所有时钟都停止)
  • 待机模式(1.2V域断电)

此外,还可以通过其他方式降低功耗:

        1. 降低系统时钟速度

        2. 不使用APBx和AHBx外设时,将对应的外设时钟关闭

其中:嵌入式线性调压器为备份域和待机电路以外的所有数字电路供电。调压器输出电压约为1.2V。

1.1 降低系统时钟速度

        在运行模式下,可以通过对预分频寄存器编程来降低系统时钟(SYSCLK、HCLK、PCLK1和PCLK2)速度。进入睡眠模式之前,也可以使用这些预分频器降低外设速度。

1.2 外设时钟门控

        在运行模式下,可以随时的停止各个外设和存储器的HCLKx和PCLKx以降低功耗。要进一步的降低睡眠模式的功耗,可在执行WFI或者WFE指令之前禁止外设时钟。

        外设时钟门控由AHB1外设时钟使能寄存器RCC_AHB1ENR、AHB2外设时钟使能寄存器RCC_AHB2ENR和AHB3外设时钟使能寄存器RCC_AHB3ENR进行控制。

        在睡眠模式下,复位RCC_AHBxLPENR和RCC_APBxLPENR寄存器中的对应位可以自动禁止外设时钟。

2. 睡眠模式

2.1 进入睡眠模式

        执行WFI(等待中断)或者WFE(等待事件)指令即可进入睡眠模式。根据M4F内核系统控制寄存器中的SLEEPONEXIT位的设置,可以通过两种方案选择睡眠模式进入机制。

立即休眠:如果SLEEPONEXIT位清零,MCU将在执行WFI和WFE指令时立即进入睡眠模式。

退出时休眠:如果SLEEPONEXIT位置1,MCU将在退出优先级最低的ISR时立即进入睡眠模式。(ISR的全称是Interrupt Service Routines,也就是中断服务,中断是有NVIC中断优先级的,这里的意思就是当执行完中断中优先级最低的中断以后进入休眠)

2.2 退出休眠模式

因为进入睡眠模式是由指令WFI和指令WFE控制的。所以退出休眠模式也应该从这两方面入手。

如果使用WFI指令进入睡眠模式,则通过中断控制器NVIC确认的任意外设中断都会将器件从睡眠模式唤醒。

如果使用WFE指令进入睡眠模式,MCU将在有事件发生时立即退出睡眠模式。

唤醒事件可以通过以下方式产生:

        在外设的控制寄存器使能一个中断,但不在NVIC中使能,同时使能M4F内核系统控制寄存器中的SEVONPEND位。当MCU从WFE恢复时,需要清除相应外设的中断挂起位和外设NVIC中断通道挂起位(在NVIC中断清除挂起寄存器中)。

        配置一个外部或者内部EXTI线为事件模式。当CPU从WFE恢复时,因为对应事件线的挂起位没有被置位,不必清除相应外设的中断挂起位或NVIC中断通道挂起位。

3. 停止模式

        停止模式基于M4内核深度睡眠模式与外设时钟门控。调压器既可以配置为正常模式,也可以配置为低功耗模式。在停止模式下,1.2V域中的所有时钟都会停止,PLL、HSI和HSE RC振荡器也会被禁止。内部SRAM和寄存器内容将会被保留。

        将PWR_CR电源控制寄存器中的FPDS位置1后,Flash闪存还会在器件进入停止模式时进入掉电状态。Flash处于掉电模式时,将器件从停止模式唤醒将需要额外的启动延时。

3.1 进入停止模式

要进一步降低停止模式的功耗,可将内部调压器设置为低功耗模式。通过对STM32F4的PWR电源控制寄存器(PWR_CR)的LPDS位进行配置

如果正在进行Flash编程,停止模式的进入将延迟到存储器访问结束后执行。

如果正在访问APB域,停止模式的进入则延迟到APB访问结束后执行。

在停止模式下,可以通过对各个控制位进行编程来选择以下功能:

        独立看门狗IWDG:IWDG通过写入其密钥寄存器或使用硬件选项来启动。而且一旦启动便无法停止,除非复位。

        实时时钟RTC:通过RCC备份域控制寄存器RCC_BDCR中的RTCEN位进行配置。

        内部RC振荡器(LSI RC):通过RCC时钟控制和状态寄存器(RCC_CSR)中的LSION位进行配置。

        外部32.768KHz振荡器(LSE OSC):通过RCC备份域控制寄存器RCC_BDCR中的LSEON位进行配置。

在停止模式下,ADC和DAC也会产生功耗,除非在进入停止模式前将其禁止。要禁用这些转换器,必须将ADC_CR2寄存器的ADON位和DAC_CR寄存器中的ENx位都清零。

3.2 退出停止模式

通过发出中断或者唤醒事件退出停止模式时,将选择HSI RC振荡器作为系统时钟。

4. 待机模式

        待机模式下可达到最低功耗。待机模式基于M4内核深度睡眠模式,该模式在深度睡眠模式时关闭电压调节器。因此1.2V域断电。PLL、HSI振荡器也将关闭。除备份域(RTC寄存器、RTC备份寄存器和备份SRAM)和待机电路中的寄存器外,SRAM和寄存器内容都将丢失。

4.1 进入待机模式

在待机模式下,可以通过对各控制位进行编程来选择以下功能:

●独立的看门狗 (IWDG):IWDG 通过写入其密钥寄存器或使用硬件选项来启动。而且一 旦启动便无法停止,除非复位。

●实时时钟 (RTC):通过备份域控制寄存器 (RCC_BDCR) 中的 RTCEN 位进行配置。

●内部 RC 振荡器 (LSI RC):通过控制/状态寄存器 (RCC_CSR) 中的 LSION 位进行配置。

●外部 32.768 kHz 振荡器 (LSE OSC):通过备份域控制寄存器 (RCC_BDCR) 中的 LSEON 位进行配置。

4.2 退出待机模式

        检测到外部复位(NRST引脚)、IWDG引脚、WKUP引脚上升沿、RTC闹钟、入侵事件或时间戳事件时,微控制器退出待机模式。从待机模式唤醒后,除PWR电源控制/状态寄存器PWR_CSR外,所有寄存器都将复位。

        从待机模式唤醒后,程序将按照复位(启动引脚采样、复位向量已获取等)后的方式重新执行。PWR电源控制/状态寄存器PWR_CSR中的SBF状态标志指示MCU已处于待机模式。

        从待机模式唤醒后的代码执行等同于复位后的执行(采样启动模式引脚,读取复位向量等)。电源控制/状态寄存器PER_CSR将会指示内核由待机状态退出。意思就是说从待机模式退出后等同于按下开发板上的复位键,执行相对于的代码。

        在进入待机模式后,除了复位引脚、RTC_AF1引脚(PC13)(如果针对入侵、时间戳、RTC闹钟输出或RTC时钟校准输出进行了配置)和WK_UP(PA0)(如果使能了)等引脚外,其他所有IO引脚都将处于高阻态。

        总结:在这三种低功耗模式中,最低功耗的是待机模式,在此模式下,最低只需要2.2uA左右的电流。停机模式是次低功耗的,其典型的电流消耗在350uA左右。最后就是睡眠模式了。

4.3 电源控制寄存器:PWR_CR

通过对进入待机模式的学习,我们已经清楚了需要将电源控制寄存器PWR_CR的 位1 和 位2 置1,使器件在CPU进入深度睡眠时进入待机模式,并且将WUF唤醒标志清零。

4.4 电源控制/状态寄存器:PWR_CSR

这里我们需要 位8 置1,从待机模式中唤醒器件;也可以通过位0来检测是否收到了唤醒标志。

5. 库函数配置进入待机模式

首先注意:对于已经使能了RTC中断或者RTC唤醒中断的情况,必须先禁止中断,清除相关中断标志位,清除唤醒中断WK_UP,等一切都完成以后,再次使能中断,进入低功耗模式。具体如下:

1. 禁止RTC中断(ALRAIE、ALRBIE闹钟A和B、WUTIE、TAMPIE和TSIE等)

2. 清零对应中断标志位

3. 清除PWR唤醒(WUF)标志(通过设置PWR_CR的CWUF位实现)

4. 重新使能RTC对应中断

5. 进入低功耗模式

1. 使能电源时钟

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);     //使能PWR外设时钟

2. 设置WK_UP(也就是PA0引脚,KEY_UP按键)引脚作为唤醒源

PWR_WakeUpPinCmd(ENABLE);            //使能KEY_UP按键唤醒功能 ,用KEY_UP将CPU从待机模式唤醒

3. 设置SLEERDEEP(深度睡眠)位,设置PDDS位,执行WFI指令,进入待机模式

进入待机模式,首先设置SLEEPDEEP位,接着通过PWR_CR设置PDDS位,使得CPU进入深度睡眠时进入待机模式,最后执行WFI指令开始进入待机模式,并等待WK_UP(KEY_UP)中断的到来;

void PWR_EnterSTANDBYMode(void); //进入待机模式

4. 编写WK_UP中断函数

通过WK_UP中断(PA0中断)来唤醒CPU,同时通过该函数进入待机模式。

6. 实验程序

        该实验程序实现功能:长按3秒KEY_UP按键开机,通过LED0指示灯指示程序开始运行,再次长按按键,进入待机模式,LED0关闭,程序停止运行。类似于手机开关机。

6.1 main.c

  1. #include "stm32f4xx.h"
  2. #include "delay.h"
  3. #include "usart.h"
  4. #include "LED.h"
  5. #include "lcd.h"
  6. #include "usmart.h"
  7. #include "Key.h"
  8. #include "WKUP.h"
  9. //LCD状态设置函数
  10. void led_set(u8 sta)//只要工程目录下有usmart调试函数,主函数就必须调用这两个函数
  11. {
  12. LED1=sta;
  13. }
  14. //函数参数调用测试函数
  15. void test_fun(void(*ledset)(u8),u8 sta)
  16. {
  17. led_set(sta);
  18. }
  19. int main(void)
  20. {
  21. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统分组中断优先级2
  22. delay_init(168);
  23. uart_init(115200);//这里切记先初始化串口,否则无法显示实验现象
  24. LED_Init();
  25. LCD_Init();
  26. WKUP_Init();
  27. POINT_COLOR=RED;
  28. LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
  29. LCD_ShowString(30,70,200,16,16,"WKUP Test");
  30. LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
  31. LCD_ShowString(30,110,200,16,16,"2023/20/23");
  32. LCD_ShowString(30,130,200,16,16,"WK_UP:Standby/WK_UP");
  33. while(1)
  34. {
  35. LED0=!LED0;
  36. delay_ms(250);
  37. }
  38. }

6.2 WKUP.c

  1. #include "stm32f4xx.h"
  2. #include "WKUP.h"
  3. #include "Key.h"
  4. #include "LED.h"
  5. #include "delay.h"
  6. //系统进入待机模式
  7. void Sys_Enter_Standby(void)
  8. {
  9. while(WKUP_KD);//while循环内设置为空,等待KEY_UP按键松开,跳过while循环
  10. RCC_AHB1PeriphResetCmd(0x04FF,ENABLE);//复位所有IO口
  11. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//使能PWR电源时钟
  12. PWR_BackupAccessCmd(ENABLE);//使能后备域寄存器,RTC实时时钟中介绍过该寄存器
  13. RTC_ITConfig(RTC_IT_ALRB|RTC_IT_ALRA|RTC_IT_TS|RTC_IT_WUT,DISABLE);//禁止RTC相关中断,这些中断可能在RTC实验中开启了
  14. RTC_ClearITPendingBit(RTC_IT_ALRB|RTC_IT_ALRA|RTC_IT_TS|RTC_IT_WUT);//清除相关中断标志位
  15. PWR_ClearFlag(PWR_FLAG_WU);//清除Wake_up唤醒标志
  16. PWR_WakeUpPinCmd(ENABLE);//使能KEY_UP按键唤醒功能 ,用KEY_UP将CPU从待机模式唤醒
  17. PWR_EnterSTANDBYMode();//进入待机模式
  18. }
  19. //检测WKUP脚的信号
  20. //返回值1:连续按下3s以上
  21. // 0:错误的触发
  22. u8 Check_WKUP(void)
  23. {
  24. u8 t=0;//记录时间
  25. u8 tx=0;//记录松开的次数
  26. LED0=0;//LED0点亮
  27. while(1)
  28. {
  29. if(WKUP_KD)//KEY_UP按键按下
  30. {
  31. t++; //记录KEY_UP按键按下的时间,需要去判断这个时间的长短,就跟我们的手机关机一样,不会只是按一下电源键就关机了,需要按下保持一段时间
  32. tx=0; //只要进入if循环语句,那么按键就一直被按下,所以松开次数始终都是零
  33. }
  34. else //松开KEY_UP
  35. {
  36. tx++;//松开的次数++
  37. if(tx>3)//如果松开的次数大于3,超过90s内没有WKUP信号
  38. {
  39. LED0=1; //LED0熄灭
  40. return 0;//错误按键,返回
  41. //这里的错误的意思是:还是我们手机关机的例子,假设需要长按电源键5秒关机,如果我们在5秒内频繁的松开按键,就一定不会关机了;直接一点,松开一次按键就不会关机了
  42. //也就表示用户取消了关机,return 0
  43. }
  44. }
  45. delay_ms(30);
  46. if(t>=100)//按下超过3秒钟 表示按键超过了预设的时间,那么进入待机模式
  47. {
  48. LED0=0;
  49. return 1;//按键3s以上了,进入待机模式
  50. }
  51. }
  52. }
  53. //中断,检测到PA0脚上的一个上升沿
  54. //中断线0上的中断检测
  55. void EXTI0_IRQHandler(void)
  56. {
  57. EXTI_ClearITPendingBit(EXTI_Line0);//清除LINE0上的中断标志位
  58. if(Check_WKUP())//表示检测3秒以上的函数返回值为1
  59. {
  60. Sys_Enter_Standby();//进入待机模式
  61. }
  62. }
  63. //PA0 KEY_UP 唤醒中断初始化
  64. void WKUP_Init(void)
  65. {
  66. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//使能GPIOA时钟
  67. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);//使能SYSCFG时钟
  68. GPIO_InitTypeDef GPIO_InitStructure;
  69. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;//按键的模式是输入
  70. GPIO_InitStructure.GPIO_OType=GPIO_OType_OD;
  71. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
  72. GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;//按键KEY_UP下拉
  73. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
  74. GPIO_Init(GPIOA,&GPIO_InitStructure);
  75. if(Check_WKUP()==0) //也是和我们手机开机一样,手机开机也是需要长按电源键,如果在长按电源键的期间,频繁的松开电源键,此时手机是开不开机的;
  76. //开发板也是这样,初始化时先检测如果是非正常开机,那么直接进入待机模式
  77. {
  78. Sys_Enter_Standby();//不是正常的开机,进入待机模式
  79. }
  80. SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);//PA0连接到中断线0
  81. EXTI_InitTypeDef EXTI_InitStructure;
  82. EXTI_InitStructure.EXTI_Line=EXTI_Line0;
  83. EXTI_InitStructure.EXTI_LineCmd=ENABLE;
  84. EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
  85. EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;//上升沿触发
  86. EXTI_Init(&EXTI_InitStructure);
  87. NVIC_InitTypeDef NVIC_InitStructure;
  88. NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;//外部中断0
  89. NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  90. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02;
  91. NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x02;
  92. NVIC_Init(&NVIC_InitStructure);
  93. }

6.3 WKUP.h

  1. #ifndef _WKUP__H_
  2. #define _WKUP__H_
  3. #define WKUP_KD PAin(0)
  4. void Sys_Enter_Standby(void);
  5. u8 Check_WKUP(void);
  6. void EXTI0_IRQHandler(void);
  7. void WKUP_Init(void);
  8. #endif

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/437383
推荐阅读
相关标签
  

闽ICP备14008679号