[APM32F1] 分别通过GPIO的中断、事件唤醒APM32F103xE的stop模式

[复制链接]
 楼主| zjh20070904 发表于 2022-6-12 11:56 | 显示全部楼层 |阅读模式

1 概述1.1 MCU低功耗模式
MCU处于死等状态时,可让MCU进入低功耗模式,或者降低系统工作时钟;当需要MCU执行动作时,可产生唤醒信号唤醒MCU,或者恢复至高速时钟。这样可以降低系统在整个运行期间的功耗,且不影响系统的运行。
APM32F103xEsleepstopstandby、备份域供电的低功耗工作模式。
通常是通过停止MCU的内部资源来降低功耗,例如关闭内核、关闭时钟源、调整电源域的工作模式、SRAM是否供电、关闭各种外设的时钟。不同的低功耗模式关闭的资源也不一样,具体内容可参考用户手册。
而且唤醒后,因为关闭的资源不同,恢复到进入低功耗模式的工作状态的动作也是不一样的,唤醒的时间也不一样。
1.2 唤醒方式
可通过MCU的内部资源唤醒MCU,例如GPIO、串口、SPI等外设。每种外设唤醒的方式由分为中断唤醒、事件唤醒,但并不是所有的外设都支持事件唤醒,手册中有专门描述支持的唤醒事件。使用事件唤醒,不需要配置对应的中断;使用中断方式唤醒后,会立刻进入对应的中断(前提是使能中断,且没有触发其它高优先级的中断)。
例如,GPIO即可支持事件唤醒,由支持中断唤醒,但是呢,各种低功耗模式下让不让你唤醒又是另一回事了,例如standby模式下,只支持WKUP引脚的上升沿、RTC闹钟事件、NRST引脚的外部复位、IWDT复位,GPIO产生的中断、事件就无法唤醒standby模式。
以下是记录了调试分别通过GPIO的中断、事件唤醒APM32F103xEstop模式的代码、现象。
2 硬件电路
选择的开发板是APM32F103ZEmini板。按键B2连接MCUPA0引脚,通过按键产生上升沿或者下降沿触发MCU中断或者产生事件唤醒MCU另外能唤醒standby模式的GPIO只有PA0,为了减少后续代码的开发,选择PA0作为唤醒GPIO
                              
1.png

3 代码
  1. #include "main.h"
  2. #include "apm32f10x_pmu.h"
  3. #include "stdio.h"

  4. void USART1_Init(void)
  5. {
  6.     GPIO_Config_T GPIO_ConfigStruct;
  7.     USART_Config_T USART_ConfigStruct;
  8.        
  9.     RCM_EnableAPB2PeriphClock((RCM_APB2_PERIPH_T)(RCM_APB2_PERIPH_GPIOA | RCM_APB2_PERIPH_USART1));
  10.   
  11.     GPIO_ConfigStruct.mode = GPIO_MODE_AF_PP;
  12.     GPIO_ConfigStruct.pin = GPIO_PIN_9;
  13.     GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
  14.     GPIO_Config(GPIOA, &GPIO_ConfigStruct);

  15.     USART_ConfigStruct.baudRate = 115200;
  16.     USART_ConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
  17.     USART_ConfigStruct.mode = USART_MODE_TX;
  18.     USART_ConfigStruct.parity = USART_PARITY_NONE;
  19.     USART_ConfigStruct.stopBits = USART_STOP_BIT_1;
  20.     USART_ConfigStruct.wordLength = USART_WORD_LEN_8B;
  21.     USART_Config(USART1, &USART_ConfigStruct);

  22.     USART_Enable(USART1);       
  23.         while(USART_ReadStatusFlag(USART1, USART_FLAG_TXBE) == RESET);               
  24. }

  25. void T_PWR_SleepPA0EventWakeUp(void)
  26. {
  27.         GPIO_Config_T PA0_GPIO_Config;
  28.         EINT_Config_T PA0_EVENT_Config;
  29.        
  30.         RCM_EnableAPB1PeriphClock((RCM_APB1_PERIPH_T)(RCM_APB1_PERIPH_PMU | RCM_APB1_PERIPH_BAKR));
  31.         RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);
  32.                
  33.         PA0_GPIO_Config.mode = GPIO_MODE_IN_PU;
  34.         PA0_GPIO_Config.pin = GPIO_PIN_0;
  35.         GPIO_Config(GPIOA, &PA0_GPIO_Config);
  36.        
  37.         PA0_EVENT_Config.line = EINT_LINE_0;
  38.         PA0_EVENT_Config.mode = EINT_MODE_EVENT;
  39.         PA0_EVENT_Config.trigger = EINT_TRIGGER_RISING;
  40.         PA0_EVENT_Config.lineCmd = ENABLE;
  41.         EINT_Config(&PA0_EVENT_Config);
  42.          
  43.         GPIO_ConfigEINTLine(GPIO_PORT_SOURCE_A, GPIO_PIN_SOURCE_0);       

  44.         printf("1进入stop模式\n\r");
  45.         PMU_EnterSTOPMode(PMU_REGULATOR_ON,PMU_STOP_ENTRY_WFE);
  46.         SystemInit();

  47.         USART1_Init();
  48.         printf("2通过事件唤醒,退出stop模式\n\r\n\r");
  49. }



  50. void T_PWR_SleepPA0IntWakeUp(void)
  51. {
  52.         GPIO_Config_T PA0_GPIO_Config;
  53.         EINT_Config_T PA0_Int_Config;
  54.        
  55.         RCM_EnableAPB1PeriphClock((RCM_APB1_PERIPH_T)(RCM_APB1_PERIPH_PMU | RCM_APB1_PERIPH_BAKR));
  56.         RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);
  57.                
  58.         PA0_GPIO_Config.mode = GPIO_MODE_IN_PU;
  59.         PA0_GPIO_Config.pin = GPIO_PIN_0;
  60.         GPIO_Config(GPIOA, &PA0_GPIO_Config);
  61.        
  62.         NVIC_EnableIRQRequest(EINT0_IRQn,0x01,0x01);
  63.        
  64.         PA0_Int_Config.line = EINT_LINE_0;
  65.         PA0_Int_Config.mode = EINT_MODE_INTERRUPT;
  66.         PA0_Int_Config.trigger = EINT_TRIGGER_RISING;
  67.         PA0_Int_Config.lineCmd = ENABLE;
  68.         EINT_Config(&PA0_Int_Config);
  69.          
  70.         GPIO_ConfigEINTLine(GPIO_PORT_SOURCE_A, GPIO_PIN_SOURCE_0);       

  71.         printf("1进入stop模式\n\r");
  72.         PMU_EnterSTOPMode(PMU_REGULATOR_ON,PMU_STOP_ENTRY_WFE);
  73.         SystemInit();

  74.         USART1_Init();
  75.         printf("3通过中断唤醒,退出stop模式\n\r\n\r");
  76.        
  77. }

  78. void EINT0_IRQHandler(void)
  79. {
  80.         if(EINT_ReadStatusFlag(EINT_LINE_0) != RESET)
  81.         {
  82.                 EINT_ClearIntFlag(EINT_LINE_0);
  83.                 USART1_Init();
  84.                 printf("2通过中断唤醒,退出stop模式,进入中断处理函数EINT0_IRQHandler\n\r");       
  85.         }
  86. }

  87. //重定向c库函数printf到串口,重定向后可使用printf函数
  88. int fputc(int ch, FILE *f)
  89. {
  90.         USART_TxData(USART1, (char) ch);
  91.         while(USART_ReadStatusFlag(USART1, USART_FLAG_TXC) == RESET);
  92.         return (ch);
  93. }

  94. //重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
  95. int fgetc(FILE *f)
  96. {
  97.         while (USART_ReadStatusFlag(USART1, USART_FLAG_RXBNE) == RESET);
  98.         return (int)USART_RxData(USART1);
  99. }



  100. int main(void)
  101. {

  102.         USART1_Init();
  103.         T_PWR_SleepPA0EventWakeUp();
  104. //        T_PWR_SleepPA0IntWakeUp();
  105.     while(1)
  106.     {
  107.     }
  108. }

4 现象4.1 通过事件唤醒stop模式,串口记录数据如下:
2.png

4.2 通过中断唤醒stop模式,串口记录数据如下:
3.png
通过中断唤醒,会优先进入中断处理函数。
5 Keil工程附件
stop_GPIO_interrupt_wakeup.zip (514.39 KB, 下载次数: 1)


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

本版积分规则

认证:极海半导体
简介:珠海极海半导体有限公司是一家致力于开发工业级/车规级微控制器、模拟与混合信号IC及系统级芯片的集成电路设计型企业。极海团队拥有20年集成电路设计经验和嵌入式系统开发能力,可为客户提供核心可靠的芯片产品及方案,实现准确感应、安全传输和实时控制,助力客户在智慧家居、高端消费电子、工业控制、汽车电子、智慧能源以及通信设施等领域的拓展创新。

29

主题

68

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部