本帖最后由 DDZZ669 于 2020-10-24 23:45 编辑
本篇将几个小功能通过FreeRTOS系统进行整合。
1 彩色物体跟踪
本部分参考之前的文章:【GD32450I-EVAL】+ 08图像识别-彩色物体跟踪
2 休眠与唤醒
很多单片机都有低功耗模式。在系统或电源复位以后,微控制器处于运行状态。运行状态下的HCLK为CPU提供时钟,内核执行程序代码。当CPU不需继续运行时,可以利用多个低功耗模式来节省功耗。用户需要根据最低电源消耗,最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。GFD32F450有3种低功耗模式:睡眠模式、深度睡眠模式和待机模式。
2.1 睡眠模式
睡眠模式与Cortex-M4 的 SLEEPING 模式相对应。在该模式下,仅关闭 Cortex-M4 的时钟。
如需进入睡眠模式,只要
- 清除 Cortex-M4 系统控制寄存器中的 SLEEPDEEP 位
- 并执行一条WFI 或 WFE 指令即可
如果睡眠模式是通过执行 WFI 指令进入的,任何中断都可以唤醒系统。如果睡眠模式是通过执行 WFE 指令进入的,任何唤醒事件都可以唤醒系统。由于无需在进入或退出中断上消耗时间,该模式所需的唤醒时间最短。
进入睡眠模式的代码如下:
- void pmu_to_sleepmode(uint8_t sleepmodecmd)
- {
-
- SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
-
-
- if(WFI_CMD == sleepmodecmd){
- __WFI();
- }else{
- __WFE();
- }
- }
2.2 深度睡眠模式
深度睡眠模式与Cortex-M4 的 SLEEPDEEP 模式相对应。在深度睡眠模式下, 1.2V 域中的所有时钟全部关闭, IRC16M 、 HXTAL 及 PLLs 也全部被禁用。 SRAM 和寄存器中的内容被保留。根据 PMU_CTL寄存器的LDOLP位的配置,可控制LDO 工作在正常模式或低功耗模式 。
进入深度睡眠模式之前
- 先将Cortex-M4系统控制寄存器的SLEEPDEEP位置1
- 再清除PMU_CTL寄存器的STBMOD位
- 然后执行WFI或WFE指令即可进入深度睡眠模式
如果睡眠模式是通过执行WFI 指令进入的, 任何来自EXTI的中断可以将系统从深度睡眠模式中唤醒。如果睡眠模式是通过执行WFE 指令进入的, 任何来自EXTI的事件可以将系统从深度睡眠模式中唤醒。
注:为顺利进入深度睡眠模式,所有EXTI线上的挂起状态(在EXTI_PD寄存器中)和RTC闹钟标志必须被复位。否则,程序将直接跳过深度睡眠模式进入过程而继续执行后面的程序。
进入深度睡眠模式的代码如下:
- void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd)
- {
-
- PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP));
-
-
- PMU_CTL |= ldo;
-
-
- SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
-
-
- if(WFI_CMD == deepsleepmodecmd){
- __WFI();
- }else{
- __SEV();
- __WFE();
- __WFE();
- }
-
- SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
- }
2.3 待机模式
待机模式是基于Cortex-M4 的 SLEEPDEEP 模式实现的。在待机模式下,整个 1.2V 域全部停止供电,同时 LDO 和包括 IRC16M 、 HXTAL 和 PLL 也会被关闭。
进入待机模式前
- 先将Cortex-M4 系统控制寄存器的 SLEEPDEEP 位置 1
- 再将 PMU_CTL 寄存器的 STBMOD 位置 1
- 再清除 PMU_CS 寄存器的 WUF 位
- 然后执行 WFI 或 WFE 指令
系统进入待机模式,PMU_CS 寄存器的 STBF 位状态表示 MCU 是否已进入待机模式。
待机模式有四个唤醒源,包括来自 NRST 引脚的外部复位, RTC 报警, FWDGT 复位, WKUP 引脚的上升沿。待机模式可以达到最低的功耗,但唤醒时间最长。另外,一旦进入待机模式, SRAM 和 1.2V 电源域寄存器(除了备份 SRAM ,当 BLDOON 置位 时 )的内容都会丢失。
退出待机模式时,会发生上电复位,复位之后 Cortex-M4 将从 0x00000000 地址开始执行指令代码。
进入待机模式的代码如下:
- void pmu_to_standbymode(uint8_t standbymodecmd)
- {
-
- SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
-
-
- PMU_CTL |= PMU_CTL_STBMOD;
-
-
- PMU_CTL |= PMU_CTL_WURST;
-
-
- if(WFI_CMD == standbymodecmd){
- __WFI();
- }else{
- __WFE();
- }
- }
三种省电模式对别如下,本测试使用待机模式。
3 RTC时钟
RTC模块提供了一个包含日期(年/月/日)和时间(时/分/秒/亚秒)的日历功能。除亚秒用二进制码显示外,时间和日期都以BCD码的形式显示。
RTC 结构框图如下:
RTC 单元有三个可选的独立时钟源:
- LXTAL
- IRC32K
- HXTAL的2-31(由 RCU_CFG 寄存器配置)分频后的时钟
上电复位后,大多数RTC寄存器是被写保护的。写入这些寄存器的第一步是解锁这些保护。通过下面的步骤,可以解锁这些保护:
- 写0xCA到 RTC_WPK 寄存器
- 写0x53到 RTC_WPK 寄存器
RTC在省电模式下也是可以工作的,如下表,深度睡眠或待机模式需要使用LXTAL或IRC32K时钟源。
RTC测试效果如下,使用IRC32K作为时钟源,在待机模式下,RTC仍能运行。
4 GuiLite测试
GuiLite是一个具有5000行C++代码的准系统GUI框架,只使用基本的C ++特性(类,虚函数),所有渲染都基于draw_pixel,可以运行在无操作系统的单片机上。
测试GuiLite例子中的波形显示:
测试GuiLite例子中的3D波浪:
5 FreeRTOS多任务管理
FreeRTOS的基础介绍参考之前的文章 【GD32450I-EVAL】+ 05FreeRTOS移植与任务创建
创建多个任务,分别实现不同的功能,通过FreeRTOS的任务调度实现多任务管理。
-
创建两个独立的LED灯任务,用于测试系统是否正常运行
-
创建系统管理任务,用于检测休眠键是否长按进行休眠,同时,RTC时间在LCD上的显示也可以放到该任务中
-
创建彩色物体追踪任务,将结果显示在LCD上,同时,也可将GuiLite的显示测试放到该任务中,因为它们都需要用到LCD显示,但又是交替时间使用
测试效果视频如下:
|