超低功耗研发-STM32L151C8T6芯片(一)时钟系统概述
超低功耗研发-STM32L151C8T6芯片(二)低功耗模式
超低功耗研发-STM32L151C8T6芯片(三)RTC自动唤醒机制
在前面的文章中,详细分析了STM32L151 的 低功耗的各种概念和相关知识,在应用中,还有一种常见的需求,就是CPU被外部唤醒。 RTC唤醒是用于正常的业务需求,而外部唤醒也是需要的,比如说我们需要将CPU唤醒,与CPU进行通信,实现一些参数的配置。
总的来讲,CPU唤醒,是 需要外部中断的,即便是RTC唤醒机制,本质上也是通过外部中断EXTI来 实现的,所以思路就是触发外部中断,方式有很多种, 我们可以通过在硬件电路设计中,预留一个引脚,通过给这个引脚相应的电平来触发中断,进而唤醒CPU,这样做的方式相对简单,不过需要在电路中预留。还有一种方式就是我们把串口1的RX引脚利用起来,毕竟很多的硬件设计,串口1都是标配的,不管是烧写程序,还是信息打印,还是数据通信等。
串口接收唤醒机制的思路是:CPU进入STOP模式前,配置RX引脚为 “输入”&&“外部中断”模式,这样等到串口接收到数据后,会触发中断,进而唤醒CPU。为什么串口接收数据就会触发中断呢?因为串口接收数据是按bit位的,而且有起始位+停止位,也就是说,即便接收的数据是FF(11111111b),接收引脚RX因为有起始位和停止位,也是存在电平切换的,所以会引发中断。RX引脚对应的中断服务函数内,要立刻对RX引脚重新配置,配置成 功能接口(AF)&& 上拉,也就是恢复到串口引脚的正常配置状态。
我们来分析一下程序代码:假设我们设置的是USART1的RX引脚PA10
void BPS_PA10_EXIT_Config( void )
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
//enable GPIOA Clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
// config PA10 as input floating
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; //very import
GPIO_Init(GPIOA, &GPIO_InitStructure);
//enable syscfg clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
// connect EXTI10 line to PA0 pin
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource10);
//config EXTI10 Line
EXTI_InitStructure.EXTI_Line = EXTI_Line10;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// enable and set EXTI0 interrupu to the lowest priority
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI15_10_IRQHandler( void )
{
GPIO_InitTypeDef GPIO_InitStructure;
if(EXTI_GetITStatus(EXTI_Line10) != RESET){
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
gFlag_PA10_Wakeup = 1;
EXTI_ClearITPendingBit(EXTI_Line10); //Clear the EXTI line 10 pending bit
}
}
在实际的使用过程中,只需要在进入STOP模式前,调用BPS_PA10_EXIT_Config( void )即可。
特别注意:务必配置PA10为“下拉”&& “输入”&&“上升沿触发”,这样设置的原因:
(1)串口TX和RX默认为高电平,所以设置成上升沿触发,抗干扰性强些,毕竟上升沿触发,需要先有低电平再有高电平。
(2)由于引脚是输入模式,如果设置成“上拉”,就相当于VCC直接接入 到IO口上,会带来额外的功耗,而设置成“下拉”,相当于接地,因为是输入模式,所以不会有额外功耗。
(3)不能将PA10设置为“无上下拉”模式,这是因为“无上下拉”表示IO口的电平状态是不定的,可以是高,也可以是低, 也可以是中间电平, 极大可能会带来额外的功耗。