公司网站可以免费建吗,免费app做logo的网站,深圳网站建设设计平台,深圳哪里有做网站的公司1)实验平台#xff1a;正点原子STM32mini开发板2)摘自《正点原子STM32 不完全手册(HAL 库版)》关注官方微信号公众号#xff0c;获取更多资料#xff1a;正点原子第十九章 待机唤醒实验本章我们将向大家介绍 STM32 的待机唤醒功能。在本章中#xff0c;我们将使用 WK_UP 按…1)实验平台正点原子STM32mini开发板2)摘自《正点原子STM32 不完全手册(HAL 库版)》关注官方微信号公众号获取更多资料正点原子第十九章 待机唤醒实验本章我们将向大家介绍 STM32 的待机唤醒功能。在本章中我们将使用 WK_UP 按键来实现唤醒和进入待机模式的功能然后使用 DS0 指示状态。本章将分为如下几个部分19.1 STM32 待机模式简介19.2 硬件设计19.3 软件设计19.4 下载验证19.1 STM32 待机模式简介很多单片机都有低功耗模式STM32 也不例外。在系统或电源复位以后微控制器处于运行状态。运行状态下的 HCLK 为 CPU 提供时钟内核执行程序代码。当 CPU 不需继续运行时可以利用多个低功耗模式来节省功耗例如等待某个外部事件时。用户需要根据最低电源消耗最快速启动时间和可用的唤醒源等条件选定一个最佳的低功耗模式。STM32 的 3 种低功耗模式我们在 5.2.4 节有粗略介绍这里我们再回顾一下。STM32 的低功耗模式有 3 种1)睡眠模式(CM3 内核停止外设仍然运行)2)停止模式(所有时钟都停止)3)待机模式(1.8V 内核电源关闭)在运行模式下我们也可以通过降低系统时钟关闭 APB 和 AHB 总线上未被使用的外设的时钟来降低功耗。三种低功耗模式一览表见表 19.1.1 所示表 19.1.1 STM32 低功耗一览表在这三种低功耗模式中最低功耗的是待机模式在此模式下最低只需要 2uA 左右的电流。停机模式是次低功耗的其典型的电流消耗在 20uA 左右。最后就是睡眠模式了。用户可以根据自己的需求来决定使用哪种低功耗模式。本章我们仅对 STM32 的最低功耗模式-待机模式来做介绍。待机模式可实现 STM32的最低功耗。该模式是在CM3 深睡眠模式时关闭电压调节器。整个1.8V 供电区域被断电。PLL、HSI和HSE振荡器也被断电。SRAM和寄存器内容丢失。仅备份的寄存器和待机电路维持供电。那么我们如何进入待机模式呢其实很简单只要按图 19.1.1 所示的步骤执行就可以了图 19.1.1 STM32 进入及退出待机模式的条件图 19.1.1 还列出了退出待机模式的操作从图 19.1.1 可知我们有 4 种方式可以退出待机模式即当一个外部复位(NRST 引脚)、IWDG 复位、WKUP 引脚上的上升沿或 RTC 闹钟事件发生时微控制器从待机模式退出。从待机唤醒后除了电源控制/状态寄存器(PWR_CSR)所有寄存器被复位。从待机模式唤醒后的代码执行等同于复位后的执行(采样启动模式引脚读取复位向量等)。电源控制/状态寄存器(PWR_CSR)将会指示内核由待机状态退出。在进入待机模式后除了复位引脚以及被设置为防侵入或校准输出时的 TAMPER 引脚和被使能的唤醒引脚(WK_UP 脚)其他的 IO 引脚都将处于高阻态。图 19.1.1 已经清楚的说明了进入待机模式的通用步骤其中涉及到 2 个寄存器即电源控制寄存器(PWR_CR)和电源控制/状态寄存器(PWR_CSR)。下面我们介绍一下这两个寄存器电源控制寄存器(PWR_CR)该寄存器的各位描述如图 19.1.2 所示这里我们通过设置 PWR_CR 的 PDDS 位使 CPU 进入深度睡眠时进入待机模式同时我们通过 CWUF 位清除之前的唤醒位。电源控制/状态寄存器(PWR_CSR)的各位描述如图 19.1.3所示图 19.1.3 PWR_ CSR 寄存器各位描述这里我们通过设置 PWR_CSR 的 EWUP 位来使能 WKUP 引脚用于待机模式唤醒。我们还可以从 WUF 来检查是否发生了唤醒事件。不过本章我们并没有用到。通过以上介绍我们了解了进入待机模式的方法以及设置 WK_UP 引脚用于把 STM32从待机模式唤醒的方法。具体步骤如下1)使能 PWR 时钟。因为要配置 PWR 寄存器所以必须先使能 PWR 时钟。在 HAL 库中使能 PWR 时钟的方法是__HAL_RCC_PWR_CLK_ENABLE(); //使能 PWR 时钟2) 设置 WK_UP 引脚作为唤醒源。使能时钟之后后再设置 PWR_CSR 的 EWUP 位使能 WK_UP 用于将 CPU 从待机模式唤醒。在 HAL 库中设置使能 WK_UP 用于唤醒 CPU 待机模式的函数是HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1); //设置 WKUP 用于唤醒3)设置 SLEEPDEEP 位设置 PDDS 位执行 WFI 指令进入待机模式。进入待机模式首先要设置 SLEEPDEEP 位(详见《CM3 权威指南》第 182 页表 13.1)接着我们通过 PWR_CR 设置 PDDS 位使得 CPU 进入深度睡眠时进入待机模式最后执行WFI 指令开始进入待机模式并等待 WK_UP 中断的到来。在库函数中进行上面三个功能进入待机模式是在函数 HAL_PWR_EnterSTANDBYMode 中实现的void HAL_PWR_EnterSTANDBYMode(void);4)最后编写 WK_UP 中断服务函数。因为我们通过 WK_UP 中断(PA0 中断)来唤醒 CPU所以我们有必要设置一下该中断函数同时我们也通过该函数里面进入待机模式。关于外部中断服务函数以及中断服务回调函数的使用方法请参考外部中断实验这里我们就不做过多讲解。通过以上几个步骤的设置我们就可以使用 STM32F1 的待机模式了并且可以通过KEY_UP 来唤醒 CPU我们最终要实现这样一个功能通过长按(3 秒)KEY_UP 按键开机并且通过 DS0 的闪烁指示程序已经开始运行再次长按该键则进入待机模式DS0 关闭程序停止运行。类似于手机的开关机。19.2 硬件设计本实验用到的硬件资源有1) 指示灯 DS02) WK_UP 按键3) TFTLCD 模块本章我们使用了 WK_UP 按键用于唤醒和进入待机模式。然后通过 DS0 和 TFTLCD 模块来指示程序是否在运行。这几个硬件的连接前面均有介绍。19.3 软件设计打开待机唤醒实验工程我们可以发现工程中多了一个 wkup.c 和 wkup.h 文件相关的用户代码写在这两个文件中。同时对于待机唤醒功能我们需要引入 stm32f1xx_hal_pwr.c 和stm32f1xx_hal_pwr.h 文件。打开 wkup.c可以看到如下关键代码//系统进入待机模式void Sys_Enter_Standby(void){__HAL_RCC_APB2_FORCE_RESET(); //复位所有 IO 口__HAL_RCC_PWR_CLK_ENABLE(); //使能 PWR 时钟__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); //清除 Wake_UP 标志HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1); //设置 WKUP 用于唤醒HAL_PWR_EnterSTANDBYMode(); //进入待机模式}//检测 WKUP 脚的信号//返回值 1:连续按下 3s 以上// 0:错误的触发u8 Check_WKUP(void){u8 t0; //记录按下的时间LED00; //亮灯 DS0while(1){if(WKUP_KD){t;//已经按下了delay_ms(30);if(t100)//按下超过 3 秒钟{LED00;//点亮 DS0return 1; //按下 3s 以上了}}else{LED01;return 0; //按下不足 3 秒}}}//外部中断线 0 中断服务函数void EXTI0_IRQHandler(void){HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);}//中断线 0 中断处理过程//此函数会被 HAL_GPIO_EXTI_IRQHandler()调用//GPIO_Pin:引脚void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){if(GPIO_PinGPIO_PIN_0)//PA0{if(Check_WKUP())//关机{Sys_Enter_Standby();//进入待机模式}}}//PA0 WKUP 唤醒初始化void WKUP_Init(void){GPIO_InitTypeDef GPIO_Initure;__HAL_RCC_GPIOA_CLK_ENABLE();//开启 GPIOA 时钟GPIO_Initure.PinGPIO_PIN_0;//PA0GPIO_Initure.ModeGPIO_MODE_IT_RISING; //中断,上升沿GPIO_Initure.PullGPIO_PULLDOWN; //下拉GPIO_Initure.SpeedGPIO_SPEED_FREQ_HIGH; //快速HAL_GPIO_Init(GPIOA,GPIO_Initure);//检查是否是正常开机if(Check_WKUP()0){Sys_Enter_Standby();//不是开机进入待机模式}HAL_NVIC_SetPriority(EXTI0_IRQn,0x02,0x02);//抢占优先级 2子优先级 2HAL_NVIC_EnableIRQ(EXTI0_IRQn);}该部分代码比较简单我们在这里说明三点1在 void Sys_Enter_Standby(void)函数里面我们要在进入待机模式前把所有开启的外设全部关闭我们这里仅仅复位了所有的 IO 口使得 IO 口全部为浮空输入。其他外设(比如ADC 等)大家根据自己所开启的情况进行一一关闭就可这样才能达到最低功耗 然后我们调 用 __HAL_RCC_PWR_CLK_ENABLE() 来 使 能PWR时 钟 调 用 函 数HAL_PWR_EnableWakeUpPin() 用 来 设 置 WK_UP 引脚作为唤醒源。 最后调用HAL_PWR_EnterSTANDBYMode()函数进入待机模式。2在 void WKUP_Init(void)函数里面我们首先要使能 GPIOA 时钟然后对 GPIOA 初始化为下拉输入上升沿触发中断同时初始化 NVIC 中断优先级。这上面的步骤实际上跟我们之前的外部中断实验知识是一样的所以不理解的地方大家可以翻到外部中断实验章节看看。接下来程序通过判断 WK_UP 是否按下了 3 秒钟来决定要不要开机如果没有按下 3 秒钟程序直接就进入了待机模式。所以在下载完代码的时候是看不到任何反应的。我们必须先按WK_UP 按键 3 秒开机才能看到 DS0 闪烁。3外部中断回调函数 HAL_GPIO_EXTI_Callback 内我们通过调用函数 Check_WKUP()来判断 WK_UP 按下的时间长短来决定是否进入待机模式如果按下时间超过 3 秒则进入待机否则退出中断。wkup.h 部分代码比较简单我们就不多说了。最后我们看看 main 函数内容如下int main(void){HAL_Init();//初始化 HAL 库Stm32_Clock_Init(RCC_PLL_MUL9); //设置时钟,72Mdelay_init(72);//初始化延时函数uart_init(115200);//初始化串口usmart_dev.init(84);//初始化 USMARTLED_Init();//初始化 LEDLCD_Init();//初始化 LCDWKUP_Init();//待机唤醒初始化POINT_COLORRED;LCD_ShowString(30,50,200,16,16,Mini STM32);LCD_ShowString(30,70,200,16,16,WKUP TEST);LCD_ShowString(30,90,200,16,16,ATOMALIENTEK);LCD_ShowString(30,110,200,16,16,2019/11/15);while(1){LED0!LED0;delay_ms(250);}}这里我们先初始化 LED 和 WK_UP 按键(通过 WKUP_Init()函数初始化)如果检测到有长按 WK_UP 按键 3 秒以上则开机并执行 LCD 初始化在 LCD 上面显示一些内容如果没有长按则在 WKUP_Init 里面调用 Sys_Enter_Standby 函数直接进入待机模式了。开机后在死循环里面等待 WK_UP 中断的到来在得到中断后在中断函数里面判断WK_UP 按下的时间长短来决定是否进入待机模式如果按下时间超过 3 秒则进入待机否则退出中断继续执行 main 函数的死循环等待同时不停的取反 LED0让红灯闪烁。代码部分就介绍到这里大家记住下载代码后一定要长按 WK_UP 按键来开机否则将直接进入待机模式无任何现象。19.4 下载与测试在代码编译成功之后下载代码到 ALIENTEK MiniSTM32 开发板上此时看到开发板DS0 亮了一下(Check_WKUP 函数执行了 LED00 的操作)就没有反应了。其实这是正常的在程序下载完之后开发板检测不到 WK_UP 的持续按下(3 秒以上)所以直接进入待机模式看起来和没有下载代码一样。此时我们长按 WK_UP 按键 3 秒钟左右可以看到 DS0 开始闪烁。然后再长按 WK_UPDS0 会灭掉程序再次进入待机模式。