超低功耗研发-STM32L151C8T6芯片(四)串口接收唤醒机制、注意事项、C代码

超低功耗研发-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口的电平状态是不定的,可以是高,也可以是低, 也可以是中间电平, 极大可能会带来额外的功耗。

发布了247 篇原创文章 · 获赞 257 · 访问量 62万+

猜你喜欢

转载自blog.csdn.net/u012351051/article/details/97897609