cortex_m3_stm32嵌入式学习笔记(十五):待机唤醒实验(WK_UP外部中断)

https://blog.csdn.net/qq_16255321/article/details/43086403

很多单片机都有低功耗模式, STM32 也不例外。在系统或电源复位以后,微控制器处于运行状态。运行状态下的 HCLK 为 CPU 提供时钟,内核执行程序代码。当 CPU 不需继续运行时,可以利用多个低功耗模式来节省功耗,例如等待某个外部事件时。用户需要根据最低电源消耗,最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。

 

STM32 的低功耗模式有 3 种:
1)睡眠模式( CM3 内核停止,外设仍然运行)
2)停止模式(所有时钟都停止)
3)待机模式( 1.8V 内核电源关闭)

   

在这三种低功耗模式中,最低功耗的是待机模式,在此模式下,最低只需要 2uA 左右的电流。停机模式是次低功耗的,其典型的电流消耗在 20uA 左右。最后就是睡眠模式了。用户可以根据自己的需求来决定使用哪种低功耗模式。
本节实验是待机模式的实验,根据上表可以看到有4种方式进入待机模式,我们选择第一种,即通过WK_UP的外部中断来触发进入待机模式的方式

配置步骤:

1)使能电源时钟。
2) 设置 WK_UP 引脚作为唤醒源。

3)设置 SLEEPDEEP 位,设置 PDDS 位,执行 WFI 指令,进入待机模式。

4)最后编写 WK_UP 中断函数。
 

 

wkup.c 

 
  1. #include "wkup.h"

  2. //待命模式

  3. void Sys_Standby(void)

  4. {

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

  6. PWR_WakeUpPinCmd(ENABLE); //使能唤醒管脚功能

  7. PWR_EnterSTANDBYMode(); //进入待命( STANDBY)模式

  8. }

  9. //系统进入待机模式

  10. void Sys_Enter_Standby(void)

  11. {

  12. RCC_APB2PeriphResetCmd(0X01FC,DISABLE); //复位所有 IO 口

  13. Sys_Standby();

  14. }

  15.  
  16. //检测 WKUP 脚的信号

  17. //返回值 1:连续按下 3s 以上

  18. // 返回值 0:错误的触发

  19. u8 Check_WKUP(void)

  20. {

  21. u8 t=0;

  22. LED0=0;

  23. while(1)

  24. {

  25. if(WKUP_KD)

  26. {

  27. t++;

  28. delay_ms(30);

  29. if(t>=100)

  30. {

  31. LED0=0;

  32. return 1;

  33. }

  34. }

  35. else

  36. {

  37. LED0=1;

  38. return 0;

  39. }

  40. }

  41. }

  42. void EXTI0_IRQHandler(void)

  43. {

  44. EXTI_ClearITPendingBit(EXTI_Line0);// 清除 LINE10 上的中断标志位

  45. if(Check_WKUP())

  46. {

  47. Sys_Enter_Standby();

  48. }

  49. }

  50. void WKUP_Init(void)

  51. {

  52. GPIO_InitTypeDef GPIO_ist;

  53. NVIC_InitTypeDef NVIC_ist;

  54. EXTI_InitTypeDef EXTI_ist;

  55. //使能GPIOA和复用功能时钟

  56. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);

  57. GPIO_ist.GPIO_Pin=GPIO_Pin_0;//PA0

  58. GPIO_ist.GPIO_Mode =GPIO_Mode_IPD;//下拉输入

  59. GPIO_Init(GPIOA,&GPIO_ist);

  60. //中断线 0 连接 GPIOA.0

  61. GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);

  62. EXTI_ist.EXTI_Line=EXTI_Line0;

  63. EXTI_ist.EXTI_Mode= EXTI_Mode_Interrupt;

  64. EXTI_ist.EXTI_Trigger=EXTI_Trigger_Rising;

  65. EXTI_ist.EXTI_LineCmd= ENABLE;

  66. EXTI_Init(&EXTI_ist);//初始化外部中断

  67.  
  68. NVIC_ist.NVIC_IRQChannel=EXTI0_IRQn;

  69. NVIC_ist.NVIC_IRQChannelPreemptionPriority=2;

  70. NVIC_ist.NVIC_IRQChannelSubPriority=2;

  71. NVIC_ist.NVIC_IRQChannelCmd=ENABLE;

  72. NVIC_Init(&NVIC_ist);

  73. if(!Check_WKUP())Sys_Standby();

  74. }




以看到我们设定的是3秒有效,即按下WK_UP键3秒以上才会进入待机模式(关机)然后再按3秒以上便会开机。

可能对开机有点不大理解 我们找到关机函数中复位IO口那个函数源码

 
  1. void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)

  2. {

  3. /* Check the parameters */

  4. assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));

  5. assert_param(IS_FUNCTIONAL_STATE(NewState));

  6. if (NewState != DISABLE)

  7. {

  8. RCC->APB2RSTR |= RCC_APB2Periph;

  9. }

  10. else

  11. {

  12. RCC->APB2RSTR &= ~RCC_APB2Periph;

  13. }

  14. }


 

因为我们传进去的第二个参数是DISABLE 所以它会执行 RCC->APB2RSTR &= ~RCC_APB2Periph;

可以看到每次都对 APB2Periph取反后按位与, 达到开关机的效果。。

 

wkup.h

 
  1. #ifndef _WKUP_H

  2. #define _WKUP_H

  3. #include "led.h"

  4. #include "delay.h"

  5. #include "sys.h"

  6. #include "usart.h"

  7.  
  8. #define WKUP_KD PAin(0)//PA0 检测是否外部 WK_UP 按键按下

  9. u8 Check_WKUP(void);//检测 WKUP 脚的信号

  10. void WKUP_Init(void);//PA0 WKUP 唤醒初始化

  11. void Sys_Enter_Standby(void);//系统进入待机模式

  12. #endif


主函数直接保留上一节时钟的代码(加了WKUP的初始化)。。在LCD上显示时间,按WP_UP3秒关机

 
  1. #include "led.h"

  2. #include "delay.h"

  3. #include "sys.h"

  4. #include "usart.h"

  5. #include "lcd.h"

  6. #include "usmart.h"

  7. #include "rtc.h"

  8. #include "wkup.h"

  9. void init(void)

  10. {

  11. NVIC_Configuration();

  12. delay_init();

  13. uart_init(9600);

  14. LED_Init();

  15. LCD_Init();

  16. WKUP_Init();

  17. usmart_dev.init(72);//初始化SMART组件

  18. }

  19. int main(void)

  20. {

  21. u8 t;

  22. init();

  23. POINT_COLOR=RED;

  24. while(RTC_Init()) //RTC初始化 ,一定要初始化成功

  25. {

  26. LCD_ShowString(60,130,200,16,16,"RTC ERROR! ");

  27. delay_ms(800);

  28. LCD_ShowString(60,130,200,16,16,"RTC Trying...");

  29. }

  30. //显示时间

  31. POINT_COLOR=BLUE;//设置字体为蓝色

  32. LCD_ShowString(60,130,200,16,16," - - ");

  33. LCD_ShowString(60,162,200,16,16," : : ");

  34. while(1)

  35. {

  36. if(t!=calendar.sec)

  37. {

  38. t=calendar.sec;

  39. LCD_ShowNum(60,130,calendar.w_year,4,16);

  40. LCD_ShowNum(100,130,calendar.w_month,1,16);

  41. LCD_ShowNum(124,130,calendar.w_date,2,16);

  42. switch(calendar.week)

  43. {

  44. case 0:

  45. LCD_ShowString(60,148,200,16,16,"Sunday ");

  46. break;

  47. case 1:

  48. LCD_ShowString(60,148,200,16,16,"Monday ");

  49. break;

  50. case 2:

  51. LCD_ShowString(60,148,200,16,16,"Tuesday ");

  52. break;

  53. case 3:

  54. LCD_ShowString(60,148,200,16,16,"Wednesday");

  55. break;

  56. case 4:

  57. LCD_ShowString(60,148,200,16,16,"Thursday ");

  58. break;

  59. case 5:

  60. LCD_ShowString(60,148,200,16,16,"Friday ");

  61. break;

  62. case 6:

  63. LCD_ShowString(60,148,200,16,16,"Saturday ");

  64. break;

  65. }

  66. LCD_ShowNum(60,162,calendar.hour,2,16);

  67. LCD_ShowNum(84,162,calendar.min,2,16);

  68. LCD_ShowNum(108,162,calendar.sec,2,16);

  69. LED0=!LED0;

  70. }

  71. delay_ms(10);

  72. }

  73. }

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐