OpenEdv-开源电子网

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

《MiniPRO H750开发指南》第二十九章 低功耗实验(下)

[复制链接]

1140

主题

1152

帖子

2

精华

超级版主

Rank: 8Rank: 8

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

第二十九章 低功耗实验

1)实验平台:正点原子MiniPro STM32H750开发板

2) 章节摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

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

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

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

6)MiniPro STM32H750技术交流QQ群:170313895

155537c2odj87vz1z9vj6l.jpg

155537nfqovl2gg9faaol9.png

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

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

l  PWR控制寄存器 1(PWR_CR1
PWR的控制寄存器1描述如图29.4.1.1所示:
image001.png

图29.4.1.1 PWR_CR1寄存器


进入停止模式,我们设置稳压器为低功耗模式,等待中断唤醒,所以位LPDS置1。

l  PWR CPU控制寄存器(PWR_CPUCR
PWR CPU控制寄存器描述如图29.4.1.2所示:
image003.png
图29.4.1.2 PWR_CPUCR寄存器

位PDDS_D1~ PDDS_D3都设置为0,保持D1/D2/D3进入深度睡眠后,进入停止模式。在设置该寄存器前,我们要使能系统控制寄存器SCR的位2(SLEEPDEEP),该位置1,该寄存器在M7内核手册。然后在停止模式后,关闭SLEEPDEEP位。

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

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

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

29.4.3 程序设计
29.4.3.1 PWR的HAL库驱动
1.HAL_PWR_EnterSTOPMode函数
进入停止模式函数,其声明如下:
  1. void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry);
复制代码
l  函数描述:
用于设置CPU进入停止模式。

l  函数形参:
形参1指定稳压器在停止模式下的状态。有两个选择,PWR_MAINREGULATOR_ON表示稳压器处于主模式,PWR_LOWPOWERREGULATOR_ON表示稳压器处于低功耗模式。对应的是PWR_CR1寄存器的LPDS位的设置。
形参2指定用WFI还是WFE指令进入停止模式。有两个选择,PWR_STOPENTRY_WFI表示使用WFI指令,PWR_STOPENTRY_WFE表示使用WFE指令。我们选择前者,不了解这两种指令的区别,请问度娘。

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停止模式
通过sys_stm32_clock_init函数降频。降低性能前,应先减小系统频率,再更改电压调节。
通过HAL_PWR_EnterSTOPMode函数进入停止模式。

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

29.4.3.2 程序流程图
image006.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. /**
  2. *@brief        进入停止模式
  3. *@param        无
  4. *@retval       无
  5. */
  6. voidpwr_enter_stop(void)
  7. {
  8.    sys_stm32_clock_init(200, 2, 2, 4); /* 设置时钟,400Mhz,降频 */
  9.     /* 当SVOS3进入停止模式时,设置稳压器为低功耗模式,等待中断唤醒 */
  10.    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
  11. }
复制代码
该函数首先是调用sys_stm32_clock_init函数重新设置系统时钟频率,降频到400MHZ。然后调用HAL_PWR_EnterSTOPMode函数进入停止模式,形参1选择PWR_LOWPOWERREGU LATOR_ON表示设置稳压器为低功耗模式,形参2则是选择WFI指令。这里我们不再需要像睡眠模式实验一样要暂停滴答时钟,因为滴答时钟中断无法唤醒停止模式,只有外部中断可以唤醒。

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

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

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

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

l  PWR唤醒使能和极性寄存器(PWR_WKUPEPR
PWR唤醒使能和极性寄存器描述如图29.5.1.1所示:
image007.png
图29.5.1.1 PWR_WKUPEPR寄存器

本章,我们使用PA0的上升沿来唤醒MCU,PA0对应的WKUP源为:WKUP1,因此,对于PWR_WKUPEPR寄存器,我们需要设置的位如下:
1,设置WKUPEN1位为1,使能WKUP1的唤醒功能。
2,设置WKUPPP1位为0,选择上升沿唤醒。
3,设置WKUPPUPD1[1:0]位为2,选择使用下拉电阻,以保持WKUP1脚的低电平状态。
根据这三个步骤,设置好PWR_WKUPEPR寄存器,就可以设置PA0引脚的上升沿唤醒MCU了。

l  PWR唤醒清除寄存器(PWR_WKUPCR
PWR唤醒清除寄存器描述如图29.5.1.2所示:
image009.png
图29.5.1.2 PWR_WKUPCR寄存器

该寄存器我们只关心WKUPC1位,设置WKUPC1为1,可以清除PA0的唤醒标志位。

l  PWR CPU控制寄存器(PWR_CPUCR
PWR CPU控制寄存器描述如图29.5.1.3所示:
image011.png
图29.5.1.3 PWR_CPUCR寄存器

该寄存器我们只需要关心最低3个位,分别用于设置在D1域、D2域和D3域进入深度睡眠模式时,允许待机模式,已达到最低功耗的目的。所以这三个位都要设置为1。

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

该寄存器我们只关心:SLEEPDEEP位,要进入待机模式,我们必须设置该位为1。

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

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

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

29.5.3 程序设计
29.5.3.1 PWR的HAL库驱动
1.HAL_PWR_EnableWakeUpPin函数
使能唤醒引脚函数,其声明如下:
  1. void HAL_PWR_EnableWakeUpPin(uint32_t WakeUpPinPolarity);
复制代码
l  函数描述:
用于使能唤醒引脚,实际上该函数设置PWR唤醒使能和极性寄存器(PWR_WKUPEPR)的位[5:0]和位[13:8]。

l  函数形参:
形参1取值范围:PWR_WAKEUP_PIN1_HIGH~ PWR_WAKEUP_PIN6_HIGH(等同于PWR_WAKEUP_PIN1~PWR_WAKEUP_PIN6)、PWR_WAKEUP_PIN1_LOW~ PWR_WAKEUP_PIN6_LOW。

l  函数返回值:

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

2.HAL_PWR_EnterSTANDBYMode函数
进入待机模式函数,其声明如下:
  1. void HAL_PWR_EnterSTANDBYMode(void);
复制代码
l  函数描述:
用于使CPU进入待机模式,进入待机模式,首先要设置SLEEPDEEP位,接着我们通过PWR_CR设置PDDS位,使得CPU进入深度睡眠时进入待机模式,最后执行WFI指令开始进入待机模式,并等待WK_UP唤醒的到来。

l  函数形参:

l  函数返回值:

待机模式配置步骤
1)进入CPU待机模式
在进入待机模式之前我们需要做一些准备,比如:关闭RTC相关中断、清除RTC相关中断标志位等一些操作,只是防止RTC中断唤醒。这里就不细讲,详见本例程源码。
通过__HAL_PWR_CLEAR_FLAG函数清除唤醒标志位。
通过HAL_PWR_EnableWakeUpPin函数使能PA0的唤醒功能。
通过HAL_PWR_EnterSTANDBYMode函数进入待机模式。

2)通过按下WKUP引脚上升沿触发唤醒待机模式
在本实验中,通过按下KEY0按键进入待机模式,然后通过按下WK_UP按键(特定唤醒源)触发唤醒待机模式。

29.5.3.2 程序流程图
image016.png

图29.4.3.2.1待机模式实验程序流程图

29.5.3.3 程序解析
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。PWR驱动源码包括两个文件:pwr.c和pwr.h。

pwr.h头文件上的宏定义我们是没有用到的,这里我们使用的是特定唤醒源,与外部中断无关。下面是pwr.c文件,我们主要介绍进入待机模式函数,其定义如下:
  1. /**
  2. *@brief        进入待机模式
  3. *@param        无
  4. *@retval       无
  5. */
  6. voidpwr_enter_standby(void)
  7. {
  8.    __HAL_GPIO_EXTI_CLEAR_IT(PWR_WKUP_GPIO_PIN);   /* 清除WKUP上的中断标志位 */
  9.    HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1_HIGH); /* 禁止唤醒 */
  10.    __HAL_RCC_BACKUPRESET_FORCE();      /* 复位备份区域 */
  11.    HAL_PWR_EnableBkUpAccess();          /* 后备区域访问使能 */
  12.    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
  13.    __HAL_RTC_WRITEPROTECTION_DISABLE(&g_rtc_handle);  /* 关闭RTC写保护 */
  14.    __HAL_RTC_WAKEUPTIMER_DISABLE_IT(&g_rtc_handle, RTC_IT_WUT);/*关RTC相关中断*/
  15.    __HAL_RTC_TIMESTAMP_DISABLE_IT(&g_rtc_handle, RTC_IT_TS);
  16.    __HAL_RTC_ALARM_DISABLE_IT(&g_rtc_handle, RTC_IT_ALRA | RTC_IT_ALRB);
  17.     /* 清除RTC相关中断标志位 */
  18.    __HAL_RTC_ALARM_CLEAR_FLAG(&g_rtc_handle, RTC_FLAG_ALRAF | RTC_FLAG_ALRBF);
  19.    __HAL_RTC_TIMESTAMP_CLEAR_FLAG(&g_rtc_handle, RTC_FLAG_TSF);
  20.    __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&g_rtc_handle, RTC_FLAG_WUTF);
  21.    __HAL_RCC_BACKUPRESET_RELEASE();                      /* 备份区域复位结束 */
  22.    __HAL_RTC_WRITEPROTECTION_ENABLE(&g_rtc_handle);   /* 使能RTC写保护 */
  23.    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1_HIGH);     /* 使能WK_UP唤醒功能 */
  24.    HAL_PWR_EnterSTANDBYMode();                             /* 进入待机模式 */
  25. }
复制代码
该函数首先是关闭RTC相关中断,清除RTC相关中断标志位。然后使能WKUP引脚上升沿来唤醒待机模式。最后调用HAL_PWR_EnterSTANDBYMode函数进入待机模式。

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

29.5.4 下载验证
下载代码后,LED0闪烁,表明代码正在运行。按下按键KEY0后,TFTLCD屏熄灭,此时LED0不再闪烁,说明已经进入待机模式。按下按键WK_UP后,TFTLCD屏点亮,此时LED0继续闪烁,说明系统从待机模式中唤醒相当于复位。

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

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-24 20:35

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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