OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2388|回复: 1

《STM32F407 探索者开发指南》第二十九章 低功耗实验(下)

[复制链接]

1140

主题

1152

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4895
金钱
4895
注册时间
2019-5-8
在线时间
1248 小时
发表于 2023-7-31 15:14:32 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2023-7-29 14:22 编辑

第二十九章 低功耗实验

1)实验平台:正点原子探索者STM32F407开发板

2) 章节摘自【正点原子】STM32F407开发指南 V1.1

3)购买链接:https://detail.tmall.com/item.htm?id=609294673401

4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/stm32/zdyz_stm32f407_explorerV3.html

5)正点原子官方B站:https://space.bilibili.com/394620890

6)STM32技术交流QQ群:151941872

155537c2odj87vz1z9vj6l.jpg


155537nfqovl2gg9faaol9.png

29.3 睡眠模式实验
本小节我们来学习睡眠模式实验,该部分的知识点内容请回顾29.1.2.3电源管理。我们直接从寄存器介绍开始。

29.3.1 EXTI寄存器
本实验我们用到外部中断来唤醒睡眠模式。我们用到WFI指令(参考29.1.3电源管理对这个指令的讲解)进入睡眠模式,这个后面会讲,进入睡眠模式后,使用外部中断唤醒。进入外部中断后,EXTI_IMR寄存器的值会自动清零,我们需要对对应的外部中断线位置1,取消屏蔽,相当于其他中断的中断标志位进入中断后硬件自动置1,需要手动清零。

l  EXTI中断屏蔽寄存器(EXTI_IMR
EXTI中断屏蔽寄存器描述如图29.3.1.1所示:
image001.png
图29.3.1.1 EXTI_IMR寄存器

本实验使用WK_UP(PA0)唤醒,即EXTI0线中断,所以在外部中断服务函数要把MR0位置1。

l  EXTI上升沿触发选择寄存器(EXTI_RTSR
EXTI上升沿触发选择寄存器描述如图29.3.1.2所示:     
image003.png
图29.3.1.2 EXTI_RTSR寄存器

我们要使用到EXTI0线中断,所以TR0位要置1,即EXTI0使用的是上升沿进行触发。

l  EXTI挂起寄存器(EXTI_PR
EXTI挂起寄存器描述如图29.3.1.3所示:     
image005.png
图29.3.1.3 EXTI_PR寄存器

在EXTI0中断服务函数里面,需要清除EXTI0中断标记,即对PR0位写1。

29.3.2 硬件设计
1. 例程功能
LED0闪烁,表明代码正在运行。按下按键KEY0后,LED1点亮,提示进入睡眠模式,此时LED0不再闪烁,说明已经进入睡眠模式。按下按键WK_UP后,LED1熄灭,提示退出睡眠模式,此时LED0继续闪烁,说明已经退出睡眠模式。

2. 硬件资源
1)LED灯
   LED0 – PF9
LED1 – PF10
2)独立按键
KEY0 – PE4
WK_UP – PA0
3)电池管理(低功耗模式 - 睡眠模式)
4)正点原子 2.8/3.5/4.3/7寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)

3. 原理图
PWR属于STM32F407的内部资源,只需要软件设置好即可正常工作。我们通过KEY0让CPU进入睡眠模式,再通过WK_UP触发EXTI中断来唤醒CPU。LED0指示程序是否执行,LED1指示CPU是否进入睡眠模式。

29.3.3 程序设计
29.3.3.1 PWRHAL库驱动
1.HAL_PWR_EnterSLEEPMode函数
进入睡眠模式函数,其声明如下:
  1. <font face="Tahoma">voidHAL_PWR_EnterSLEEPMode (uint32_t Regulator, uint8_t SLEEPEntry);</font>
复制代码

l  函数描述:
用于设置CPU进入睡眠模式。

l  函数形参:
形参1指定稳压器的状态。有两个选择,PWR_MAINREGULATOR_ON表示稳压器处于正常模式,PWR_LOWPOWERREGULATOR_ON表示稳压器处于低功耗模式。对应的是PWR_CR寄存器的LPDS位的设置(该形参在该函数中没有实质用处)。
形参2指定进入睡眠模式的方式。有两个选择,PWR_SLEEPENTRY_WFI表示使用WFI指令,PWR_SLEEPENTRY_WFE表示使用WFE指令。我们选择前者,这两个指令的区别,请参考本教程29.1.3电源管理的描述。

l  函数返回值:

睡眠模式配置步骤
1)配置唤醒睡眠模式的方式
这里我们用外部中断的方式唤醒睡眠模式,所以这里需要配置一个外部中断功能,我们用WK_UP按键作为中断触发源,接下来就是配置PA0(连接按键WK_UP)。
通过__HAL_RCC_GPIOA_CLK_ENABLE函数使能GPIOA的时钟。
通过HAL_GPIO_Init函数配置PA0为具有上升边缘触发检测的外部中断模式,开启下拉电阻等。
通过HAL_NVIC_EnableIRQ函数使能EXTI0中断。
通过HAL_NVIC_SetPriority函数设置中断优先级。
编写EXTI0_IRQHandle中断函数,在中断服务函数中调用HAL_GPIO_EXTI_IRQHandler函数。
最后编写HAL_GPIO_EXTI_Callback回调函数。由于前面已经介绍过外部中断的配置步骤,这里就介绍到这里,详见本例程源码。

2)进入CPU睡眠模式
通过HAL_PWR_EnterSLEEPMode函数进入睡眠模式。

3)通过按下按键触发外部中断唤醒睡眠模式
在本实验中,通过按下KEY0按键进入睡眠模式,然后通过按下WK_UP按键触发外部中断唤醒睡眠模式。

29.3.3.2 程序流程图
QQ截图20230729141932.png
图29.3.3.2.1 睡眠模式实验程序流程图

29.3.3.3 程序解析
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。PWR源码包括两个文件:pwr.c和pwr.h。睡眠模式实验代码在电压监控实验源码后追加。

首先看本实验在pwr.h头文件定义的几个宏定义:
  1. <font face="Tahoma">/* PWR WKUP 按键 引脚和中断 定义
  2. * 我们通过WK_UP按键唤醒 MCU,  因此必须定义这个按键及其对应的中断服务函数
  3. */
  4. #define PWR_WKUP_GPIO_PORT          GPIOA
  5. #define PWR_WKUP_GPIO_PIN           GPIO_PIN_0
  6. /* PA口时钟使能 */
  7. #define PWR_WKUP_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE();}while(0)
  8. #define PWR_WKUP_INT_IRQn           EXTI0_IRQn
  9. #define PWR_WKUP_INT_IRQHandler    EXTI0_IRQHandler</font>
复制代码
这些定义是WK_UP按键的相关宏定义,以及其对应的外部中断线0的相关定义。

pwr.h头文件就介绍这部分的程序,下面是pwr.c文件,先看低功耗模式下的按键初始化函数,其定义如下:
  1. <font face="Tahoma">/**
  2. * @brief       低功耗模式下的按键初始化(用于唤醒睡眠模式/停止模式/待机模式)
  3. * @param       无
  4. * @retval      无
  5. */
  6. void pwr_wkup_key_init(void)
  7. {
  8.    GPIO_InitTypeDef gpio_init_struct;
  9.    PWR_WKUP_GPIO_CLK_ENABLE();                                 /* WKUP时钟使能 */
  10.    gpio_init_struct.Pin = PWR_WKUP_GPIO_PIN;               /* WKUP引脚 */
  11.    gpio_init_struct.Mode = GPIO_MODE_IT_RISING;            /* 中断,上升沿 */
  12.    gpio_init_struct.Pull = GPIO_PULLDOWN;                    /* 下拉 */
  13.    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;         /* 高速 */
  14.     HAL_GPIO_Init(PWR_WKUP_GPIO_PORT, &gpio_init_struct);  /* WKUP引脚初始化 */
  15.    HAL_NVIC_SetPriority(PWR_WKUP_INT_IRQn, 2, 2);     /* 抢占优先级2,子优先级2 */
  16.    HAL_NVIC_EnableIRQ(PWR_WKUP_INT_IRQn);
  17. }</font>
复制代码
该函数初始化WK_UP按键(PA0),并设置上升沿触发的外部中断线0,最后设置中断优先级并使能外部中断线0。

下面介绍的是进入CPU睡眠模式函数,其定义如下:
  1. <font face="Tahoma">/**
  2. * @brief       进入CPU睡眠模式
  3. * @param       无
  4. * @retval      无
  5. */
  6. void pwr_enter_sleep(void)
  7. {
  8. /* 进入睡眠模式 */
  9.    HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
  10. }</font>
复制代码
函数内直接调用HAL_PWR_EnterSLEEPMode函数使用WFI指令进入睡眠模式。

下面介绍的是WK_UP按键外部中断服务函数及其回调函数,函数定义如下:
  1. <font face="Tahoma">/**
  2. * @brief       WK_UP按键 外部中断服务程序
  3. * @param       无
  4. * @retval      无
  5. */
  6. voidPWR_WKUP_INT_IRQHandler(void)
  7. {
  8.    HAL_GPIO_EXTI_IRQHandler(PWR_WKUP_GPIO_PIN);
  9. }
  10. /**
  11. * @brief       外部中断回调函数
  12. * @param       GPIO_Pin:中断线引脚
  13. * @note        此函数会被PWR_WKUP_INT_IRQHandler()调用
  14. * @retval      无
  15. */
  16. voidHAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
  17. {
  18.     if (GPIO_Pin == PWR_WKUP_GPIO_PIN)
  19.     {
  20.         /* HAL_GPIO_EXTI_IRQHandler()函数已经为我们清除了中断标志位,
  21. 所以我们进了回调函数可以只关注中断时的控制逻辑,不用再操作寄存器 */
  22.     }
  23. }</font>
复制代码
在WK_UP按键外部中断服务函数中我们调用HAL库的HAL_GPIO_EXTI_IRQHandler函数来处理外部中断。该函数会调用__HAL_GPIO_EXTI_CLEAR_IT函数取消屏蔽对应的外部中断线位,这里是EXTI_IMR寄存器相应位,还有其他寄存器控制其他外部中断线。我们只是唤醒睡眠模式而已,不需要其他的逻辑程序,所以HAL_GPIO_EXTI_Callback回调函数可以什么都不用做,甚至也可以不重新定义这个回调函数(屏蔽该回调函数也可以)。

最后在main.c里面编写如下代码:
  1. <font face="Tahoma">int main(void)
  2. {
  3.     uint8_t t=0;
  4.     uint8_t key = 0;
  5.     HAL_Init();                             /*初始化HAL库*/
  6.    sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟, 168Mhz */
  7.     delay_init(168);                        /* 延时初始化 */
  8.     usart_init(115200);                    /* 串口初始化为115200 */
  9.     led_init();                              /* 初始化LED */
  10.     lcd_init();                              /* 初始化LCD */
  11.     key_init();                              /* 初始化按键 */
  12.    pwr_wkup_key_init();                   /* 唤醒按键初始化 */
  13.     lcd_show_string(30, 50,  200, 16, 16, "STM32", RED);
  14.     lcd_show_string(30, 70,  200, 16, 16, "SLEEPTEST", RED);
  15.     lcd_show_string(30, 90,  200, 16, 16, "ATOM@ALIENTEK", RED);
  16.     lcd_show_string(30, 110, 200, 16, 16, "KEY0:Enter SLEEP MODE", RED);
  17.     lcd_show_string(30, 130, 200, 16, 16, "KEY_UP:Exit SLEEP MODE", RED);
  18.     while (1)
  19.     {
  20.         key = key_scan(0);
  21.         if (key == KEY0_PRES)
  22.         {
  23.             LED1(0);                    /* 点亮绿灯,提示进入睡眠模式 */
  24.            pwr_enter_sleep();        /* 进入睡眠模式 */
  25.             LED1(1);                    /* 关闭绿灯,提示退出睡眠模式 */
  26.         }
  27.         if ((t % 20) == 0)
  28.         {
  29.            LED0_TOGGLE();            /* 每200ms,翻转一次LED0 */
  30.         }
  31.         delay_ms(10);
  32.         t++;
  33.     }
  34. }</font>
复制代码
该部分程序,功能就是按下KEY0后,点亮LED1,进入睡眠模式。然后一直等待外部中断唤醒,当按下按键WK_UP,就触发外部中断,睡眠模式就被唤醒,然后继续执行后面的程序,关闭LED1等。

29.3.4 下载验证
下载代码后,LED0闪烁,表明代码正在运行。按下按键KEY0后,LED1点亮,提示进入睡眠模式,此时LED0不再闪烁,说明已经进入睡眠模式。按下按键WK_UP后,LED1熄灭,提示退出睡眠模式,此时LED0继续闪烁,说明已经退出睡眠模式。

29.4 停止模式实验
本小节我们来学习停止模式实验,该部分的知识点内容请回顾29.1.2.3电源管理。我们直接从寄存器介绍开始。

29.4.1PWR寄存器
本实验我们用到外部中断来唤醒停止模式。我们用到WFI指令进入停止模式,这个后面会讲,进入停止模式后,使用外部中断唤醒。外部中断部分内容参照睡眠模式即可,都是共用同样的配置。
下面主要介绍PWR_CR寄存器相关位。

l  PWR控制寄存器(PWR_CR
PWR的控制寄存器描述如图29.4.1.1所示:     
image009.png
图29.4.1.1 PWR_CR寄存器

通过PDDS位选择进入停止模式还是待机模式,停止模式即对PDDS位置0即可。在停止模式下,电压调节器有两种模式:开启或者低功耗,选择低功耗模式,即LPDS置1。

l  系统控制寄存器(SCB_SCR
系统控制寄存器描述如图29.4.1.2所示:     
image011.png
图29.4.1.2 系统控制寄存器

该寄存器存在于ARM内核中,详细描述可查阅《Cortex-M4权威指南》,在本实验中,我们需要把SLEEPDEEP位置1,这样子后面调用WFI命令时,进入的就是停止模式了。在唤醒后,需要清除SLEEPDEEP位,进行置0。

29.4.2硬件设计
1. 例程功能
LED0闪烁,表明代码正在运行。按下按键KEY0后,LED1点亮,提示进入停止模式,此时LED0不再闪烁,说明已经进入停止模式。按下按键WK_UP后,LED1熄灭,提示退出停止模式,此时LED0继续闪烁,说明已经退出停止模式。

2. 硬件资源
1)LED灯
    LED0 – PF9
LED1 – PF10
2)独立按键
KEY0 – PE4
WK_UP– PA0
3)电池管理(低功耗模式–停止模式)
4)正点原子 2.8/3.5/4.3/7寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)

3. 原理图
PWR属于STM32F407的内部资源,只需要软件设置好即可正常工作。我们通过KEY0让CPU进入停止模式,再通过WK_UP触发EXTI中断来唤醒CPU。LED0指示程序是否执行,LED1指示CPU是否进入停止模式。

29.4.3程序设计
29.4.3.1 PWRHAL库驱动
1. HAL_PWR_EnterSTOPMode函数
进入睡眠模式函数,其声明如下:
  1. <font face="Tahoma">voidHAL_PWR_EnterSTOPMode (uint32_t Regulator, uint8_t STOPEntry);</font>
复制代码

l  函数描述:
用于设置CPU进入停止模式。

l  函数形参:
形参1指定稳压器在睡眠模式下的状态。有两个选择,PWR_MAINREGULATOR_ON表示稳压器处于正常模式,PWR_LOWPOWERREGULATOR_ON表示稳压器处于低功耗模式。对应的是PWR_CR1寄存器的LPDS位的设置。
形参2指定用WFI还是WFE指令进入停止模式。有两个选择,PWR_STOPENTRY_WFI表示使用WFI指令,PWR_STOPENTRY_WFE表示使用WFE指令。我们选择前者,不了解这两种指令的区别,可以回看29.1.3小节的知识。

l 函数返回值:

停止模式配置步骤
1)配置唤醒停止模式的方式
这里我们用外部中断的方式唤醒停止模式,所以这里需要配置一个外部中断功能,我们用WK_UP按键作为中断触发源,接下来就是配置PA0(连接按键WK_UP)。
通过__HAL_RCC_GPIOA_CLK_ENABLE函数使能GPIOA的时钟。
通过HAL_GPIO_Init函数配置PA0为具有上升边缘触发检测的外部中断模式,开启下拉电阻等。
通过HAL_NVIC_EnableIRQ函数使能EXTI0中断。
通过HAL_NVIC_SetPriority函数设置中断优先级。
编写EXTI0_IRQHandle中断函数,在中断服务函数中调用HAL_GPIO_EXTI_IRQHandler函数。
最后编写HAL_GPIO_EXTI_Callback回调函数。由于前面已经介绍过外部中断的配置步骤,这里就介绍到这里,详见本例程源码。

2)进入CPU停止模式
通过HAL_PWR_EnterSTOPMode函数进入停止模式。

3)通过按下按键触发外部中断唤醒停止模式
在本实验中,通过按下KEY0按键进入停止模式,然后通过按下WK_UP按键触发外部中断唤醒停止模式。

29.4.3.2 程序流程图
QQ截图20230729142018.png
图29.4.3.2.1 停止模式实验程序流程图

29.4.3.3 程序解析
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。PWR源码包括两个文件:pwr.c和pwr.h。停止模式实验代码在睡眠模式实验源码后追加。

首先看pwr.h头文件,因为我们还是用到WK_UP对应的外部中断线来唤醒停止模式的CPU,pwr.h头文件的WK_UP按键对应的宏定义我们也是用到的,上个实验已经讲过,这里不再赘述。下面是pwr.c文件,WK_UP按键的相关函数我们还是用上个实验的,我们主要介绍进入停止模式函数,其定义如下:
  1. <font face="Tahoma">/**
  2. * @brief      进入停止模式
  3. * @param      无
  4. * @retval     无
  5. */
  6. void pwr_enter_stop(void)
  7. {
  8.     __HAL_RCC_PWR_CLK_ENABLE();
  9.     HAL_SuspendTick();  /* 暂停滴答时钟,防止通过滴答时钟中断唤醒 */
  10.     /* 进入停止模式,掉电并进入低功耗模式并待机 */
  11.     HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
  12. }</font>
复制代码
该函数先调用__HAL_RCC_PWR_CLK_ENABLE函数使能PWR时钟,然后调用HAL_SuspendTick函数暂停滴答时钟,最后调用HAL_PWR_EnterSTOPMode函数进入停止模式,形参1选择PWR_LOWPOWERREGULATOR_ON表示设置稳压器为低功耗模式,形参2则是选择WFI指令。

最后在main.c里面编写如下代码:
  1. <font face="Tahoma">int main(void)
  2. {
  3.     uint8_t t=0;
  4.     uint8_t key = 0;
  5.     HAL_Init();                             /* 初始化HAL库 */
  6.     sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟, 168Mhz */
  7.     delay_init(168);                        /* 延时初始化 */
  8.     usart_init(115200);                   /* 串口初始化为115200 */
  9.     led_init();                             /* 初始化LED */
  10.     lcd_init();                             /* 初始化LCD */
  11.     key_init();                             /* 初始化按键 */
  12.     pwr_wkup_key_init();                  /* 唤醒按键初始化 */
  13.    
  14.     lcd_show_string(30,  50, 200, 16, 16, "STM32", RED);
  15.     lcd_show_string(30,  70, 200, 16, 16, "STOP TEST", RED);
  16.     lcd_show_string(30,  90, 200, 16, 16, "ATOM@ALIENTEK", RED);
  17.     lcd_show_string(30, 110, 200, 16, 16, "KEY0:EnterSTOP MODE", RED);
  18.     lcd_show_string(30, 130, 200, 16, 16, "KEY_UP:ExitSTOP MODE", RED);
  19.     while (1)
  20.     {
  21.         key = key_scan(0);
  22.         if (key == KEY0_PRES)
  23.         {
  24.             LED1(0);                             /* 点亮绿灯,提示进入停止模式 */
  25.             pwr_enter_stop();                  /* 进入停止模式 */
  26.             /* 从停止模式唤醒, 需要重新设置系统时钟, 168Mhz */
  27.             sys_stm32_clock_init(336, 8, 2, 7);  /* 设置时钟, 168Mhz */
  28. delay_init(168);                        /* 延时初始化 */
  29.             LED1(1);                                 /* 关闭绿灯,提示退出停止模式 */
  30.         }
  31.         if ((t % 20) == 0)
  32.         {
  33.             LED0_TOGGLE();                       /* 每200ms,翻转一次LED0 */
  34.         }
  35.         delay_ms(10);
  36.         t++;
  37.     }
  38. }</font>
复制代码
该部分程序,功能就是按下KEY0后,点亮LED1、暂停滴答时钟并进入停止模式。然后一直等待外部中断唤醒,当按下按键WK_UP,就触发外部中断,停止模式就被唤醒,然后继续执行后面的程序,重新设置系统时钟168Mhz和延时初始化,关闭LED1等。

29.4.4下载验证
下载代码后,LED0闪烁,表明代码正在运行。按下按键KEY0后,LED1点亮,提示进入停止模式,此时LED0不再闪烁,说明已经进入停止模式。按下按键WK_UP后,LED1熄灭,提示退出停止模式,此时LED0继续闪烁,说明已经退出停止模式。

29.5 待机模式实验
本小节我们来学习待机模式实验,该部分的知识点内容请回顾29.1.2.3电源管理。我们直接从寄存器介绍开始。

29.5.1 PWR寄存器
本实验是先对相关的电源控制寄存器配置待机模式的参数,然后通过WFI指令进入待机模式,使用WKUP引脚的上升沿来唤醒。
下面主要介绍PWR_CR寄存器相关位。

l  PWR控制寄存器(PWR_CR
PWR的控制寄存器描述如图29.5.1.1所示:     
image015.png
图29.5.1.1 PWR_CR寄存器(部分)

这里我们通过设置PDDS位,使CPU进入深度睡眠时进入待机模式,同时,我们可以通过CWUF位清除之前的唤醒位。

l  电源控制/状态寄存器(PWR_CSR
电源控制/状态寄存器描述如图29.5.1.2所示:     
image017.png
图29.5.1.1 PWR_CSR寄存器

该寄存器我们只关心EWUP位,设置EWUP为1,即WKUP引脚作为待机模式的唤醒源。

29.5.2 硬件设计
1. 例程功能
LED0闪烁,表明代码正在运行。按下按键KEY0后,进入待机模式,待机模式下大部分引脚处于高阻态,所以说这时候LED0会熄灭,TFTLCD也会熄灭。按下WK_UP按键后,退出待机模式(相当于复位操作),程序重新执行,LED0继续闪烁,TFTLCD屏点亮。

2. 硬件资源
1)LED灯
LED0 – PF9
2)独立按键
KEY0 – PE4
WK_UP – PA0
3)电池管理(低功耗模式 – 待机模式)
4)正点原子 2.8/3.5/4.3/7寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)

3. 原理图
PWR属于STM32F407的内部资源,只需要软件设置好即可正常工作。我们通过KEY0让CPU进入待机模式,再通过WK_UP上升沿来唤醒CPU。LED0指示程序是否执行。

29.5.3 程序设计
29.5.3.1 PWRHAL库驱动
1. HAL_PWR_EnableWakeUpPin函数
使能唤醒引脚函数,其声明如下:
  1. voidHAL_PWR_EnableWakeUpPin (uint32_t WakeUpPinPolarity);
复制代码

l  函数描述:
用于使能唤醒引脚。

l  函数形参:.
形参1取值范围:PWR_WAKEUP_PIN1。

l  函数返回值:

l  注意事项:
禁止某个唤醒引脚使用的函数如下:
  1. voidHAL_PWR_DisableWakeUpPin (uint32_t WakeUpPinPolarity);
复制代码

2. HAL_PWR_EnterSTANDBYMode函数
进入待机模式函数,其声明如下:
  1. voidHAL_PWR_EnterSTANDBYMode (void);
复制代码

l  函数描述:
用于使CPU进入待机模式,进入待机模式,首先要设置SLEEPDEEP位,接着我们通过PWR_CR设置PDDS位,使得CPU进入深度睡眠时进入待机模式,最后执行WFI指令开始进入待机模式,并等待WK_UP上升沿的到来。

l  函数形参:

l  函数返回值:

待机模式配置步骤
1)进入CPU待机模式
在进入待机模式之前我们需要做一些准备:
涉及到操作PWR寄存器的内容,所以首先先进行PWR时钟的初始化,调用__HAL_RCC_PWR_CLK_ENABLE函数实现。
通过HAL_PWR_EnableWakeUpPin函数使能WKUP的唤醒功能。
通过__HAL_PWR_CLEAR_FLAG函数清除唤醒标记,详看源码。
通过HAL_PWR_EnterSTANDBYMode函数进入待机模式。

2通过WKUP引脚上升沿触发唤醒睡眠模式
在本实验中,通过按下KEY0按键进入待机模式,然后通过按下WK_UP按键,使用待机模式中的WKUP引脚上升沿的唤醒信号,而不是普通的外部中断,唤醒待机模式。

29.5.3.2 程序流程图
QQ截图20230729142152.png
图29.4.3.2.1 待机模式实验程序流程图

29.5.3.3 程序解析
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。PWR源码包括两个文件:pwr.c和pwr.h。待机模式实验代码在停止模式实验源码后追加。

首先看pwr.h头文件,因为我们用到WKUP引脚上升沿来唤醒待机模式的CPU,pwr.h头文件的WK_UP按键对应的宏定义我们也是用到的,上个实验已经讲过,这里不再赘述。下面是pwr.c文件,WK_UP按键的相关函数我们还是用上个实验的,我们主要介绍进入待机模式函数,其定义如下:
  1. /**
  2. * @brief       进入待机模式
  3. * @param       无
  4. * @retval      无
  5. */
  6. void pwr_enter_standby(void)
  7. {
  8.    __HAL_RCC_PWR_CLK_ENABLE();                   /* 使能电源时钟 */
  9.    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);  /* 使能KEY_UP引脚的唤醒功能 */
  10.    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);           /* 需要清此标记,否则将保持唤醒状态 */
  11.    HAL_PWR_EnterSTANDBYMode();                   /* 进入待机模式 */
  12. }
复制代码
该函数首先是调用__HAL_RCC_PWR_CLK_ENABLE来使能PWR时钟,然后调用函数HAL_PWR_EnableWakeUpPin 来设置 WK_UP 脚作为唤醒源。最后调用函数HAL_PWR_EnterSTANDBYMode进入待机模式。

最后在main.c里面编写如下代码:
  1. int main(void)
  2. {
  3.     uint8_t t=0;
  4.     uint8_t key = 0;
  5.     HAL_Init();                              /* 初始化HAL库 */
  6.    sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟, 168Mhz */
  7.     delay_init(168);                       /* 延时初始化 */
  8.     usart_init(115200);                    /* 串口初始化为115200 */
  9.     led_init();                             /* 初始化LED */
  10.     lcd_init();                              /* 初始化LCD */
  11.     key_init();                              /* 初始化按键 */
  12.    pwr_wkup_key_init();                   /* 唤醒按键初始化 */
  13.     lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
  14.     lcd_show_string(30, 70, 200, 16, 16, "STANDBY TEST", RED);
  15.     lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
  16.     lcd_show_string(30, 110, 200, 16, 16, "KEY0:Enter STANDBY MODE", RED);
  17.     lcd_show_string(30, 130, 200, 16, 16, "KEY_UP:Exit STANDBY MODE", RED);
  18.     while (1)
  19.     {
  20.         key = key_scan(0);
  21.         if (key == KEY0_PRES)
  22.         {
  23.            pwr_enter_standby();        /* 进入待机模式 */
  24.             /* 从待机模式唤醒相当于系统重启(复位), 因此不会执行到这里 */
  25.         }
  26.         if ((t % 20) == 0)
  27.         {
  28.            LED0_TOGGLE();              /* 每200ms,翻转一次LED0 */
  29.         }
  30.         delay_ms(10);
  31.         t++;
  32.     }
  33. }
复制代码
该部分程序,经过一系列初始化后,判断到KEY0按下就调用pwr_enter_standby函数进入待机模式,然后等待按下WK_UP按键产生WKUP上升沿唤醒CPU。注意待机模式唤醒后,系统会进行复位。

29.5.4 下载验证
下载代码后,LED0闪烁,表明代码正在运行。按下按键KEY0后,TFTLCD屏熄灭,提示进入停止模式,此时LED0不再闪烁,说明已经进入待机模式。按下按键WK_UP后,TFTLCD屏点亮,提示退出待机模式,此时LED0继续闪烁,说明已经退出待机模式。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

474

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6244
金钱
6244
注册时间
2018-6-27
在线时间
534 小时
发表于 2023-8-22 17:06:54 | 显示全部楼层
学习学习,学习学习。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-24 06:49

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表