STM32低功耗串口唤醒(RS485)

@[TOC]STM32低功耗串口唤醒(RS485)

STM32的低功耗模式

对于STM32的低功耗模式,有睡眠模式,停止模式以及待机模式三种,可以根据实际需求选择对应的模式,这三种模式的特点是,功耗P(睡眠)>P(停止)>P(待机),响应时间为T(睡眠)>T(停止)>T(待机)。本次采用常用的停止模式,其唤醒方式更多,并且和待机模式功耗接近,官方手册给出的停止模式功耗为20uA,待机模式为2uA,而睡眠模式为mA级。使用串口唤醒的方式进行唤醒。

RS485通讯唤醒

串口唤醒方式网上的例程有很多,但是使用RS485进行通讯的时候,需要注意一点,当我们将RX配置成外部中断的引脚之后,我们还必须确定接收使能的引脚,下图为485硬件电路,使能引脚为SP3485的2,3引脚。 以下是进入停止模式的自定义函数,在该函数中,最后一句 语句表示进入停止模式,在之前需要将485的接收引脚配置为低电平,一些可能消耗的外设引脚可根据具体项目设计,如此例中的风扇控制引脚,旨在将功耗降到最低。 根据停止模式的特性,进入停止模式之后各个IO状态是保持进入之前的IO状态且之后无法更改,所以可以在此处配置以便无法进行串口唤醒功能。

// An highlighted block
void system_enter_stopmode(void)
{
          
   
	//进入停止模式之前,设置以下IO口状态;停止模式保持IO状态不变
	GPIO_ResetBits(GPIOA,GPIO_Pin_11); //485接收引脚,设为0才能实现串口接收唤醒
	delay_ms(1);
	GPIO_ResetBits(GPIOA,GPIO_Pin_15);    //风扇控制引脚,避免该回路产生多余功耗
	uart_exti_int();  
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);	//使能PWR外设时钟
	PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);
}

下图为RX配置为外部触发引脚部分代码,上升沿触发,触发之后进入外部中断中,在中断中为了不影响之后的串口通讯等功能,需要将各个时钟重新初始化,最简单粗暴的方法就是直接系统复位。

//串口外部中断配置
void uart_exti_int(void)
{
          
   
	GPIO_InitTypeDef GPIO_InitStructure; 
	NVIC_InitTypeDef NVIC_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;

	//使能GPIOA和复用使用
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_10;//PA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //下拉输入
 	GPIO_Init(GPIOA, &GPIO_InitStructure);//

	//RX连接至PA10,上升沿触发
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource10);
	EXTI_InitStructure.EXTI_Line=EXTI_Line10;

	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);	 
	
	NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);

}

void EXTI15_10_IRQHandler(void)
{
          
   
  if(EXTI_GetFlagStatus(EXTI_Line10) != RESET)
	{
          
   
		EXTI_ClearITPendingBit(EXTI_Line10); 	
	  NVIC_SystemReset();  //复位重启
		
	}

}

如何在主函数中进入停止模式? 只需要在对应位置调用函数system_enter_stopmode()即可。本例程在while循环中用标志位判断的方式进入停止模式。

while(1)
	{
          
    
		if(flag_stop_mode	== 1) //系统判断需要进入停止模式
		{
          
   
		   system_enter_stopmode();
		}
经验分享 程序员 微信小程序 职场和发展