STM32串口唤醒STOP模式的实现

前言

STM32常见的低功耗模式有三种:睡眠模式、STOP模式以及待机模式,STM32L系列还有其他低功耗模式。这里主要讲的是STOP模式,STOP模式可以通过外部中断或事件唤醒,但是不能通过串口中断唤醒,因为串口中断本身不是外部中断,那么如何才能实现串口唤醒STOP模式呢?

因为我这里只是为了做验证,为了快速验证,我也就没有用RT-Thread的PM电源管理组件进入STOP模式,感兴趣的读者可以用RT-Thread的电源管理组件去实现进行STOP模式。

 

一、为什么要串口唤醒STOP模式?

想象一下,在某些场合,如果你有一个无线通信模块(例如ESP8266、SIM800C)和STM32通过串口发送AT命令来对接服务器实现与服务器的数据交互,那么如果在没有进行数据交互的时候,我们是不是可以让STM32进入STOP模式来达到省电的状态,从而让电池续航更长。例如:STM32+ESP8266与后台服务器进行数据交互,当不用发送数据完毕,等待下次发送数据或等待后台下发数据给设备的这段时间可以让STM32进入STOP模式来达到省电,当后台服务器下发数据给设备的时候,我们可以向让后台发送一个唤醒设备的指令,ESP8266接收到后台的这条指令之后通过串口下发给STM32,那么就可以唤醒STM32了,这时候STM32就可以继续接收后台下发的数据。

 

二、串口唤醒STOP模式的思路

1、我们知道STOP模式只能外部中断或事件唤醒,那么想象一下,在STM32进行STOP模式之前,是不是可以先将UART_RX对应的GPIO引脚配置为外部中断引脚,而串口接收到字符相当于接收到01010...这样的高低电平,从二可以唤醒串口,当唤醒之后,我们再马上重新初始化串口,把UART_RX对应的GPIO引脚配置为接收中断模式?答案当然是可以的。

2、唤醒之后的程序是从哪里开始执行?答案是从进行STOP模式之前的那个地方重新开始执行,一会进行验证。

 

三、串口唤醒STOP模式实验

光说不练都是假把式,接下来进行实验。

1、实验平台:中国移动物联网OneNET NB开发板(板载STM32)。

2、STM32F103RET6、12M外部晶振、串口3进行实验。

3、操作系统:RT-Thread。

4、用RT-Thread创建两个线程,一个线程用于读取按键是否按下,按下则调用进入STOP模式函数进入STOP模式,另一个线程读取串口接收到的数据。

1、如何进行STOP模式?

实验时用的是标准库,在这里主要实现在进入STOP模式前将RX对应的GPIO引脚配置为外部中断模式以及进入STOP模式,代码如下:

/**************************************************************
函数名称:system_enter_stop
函数功能:系统进入STOP模式
输入参数:无
返 回 值:无
备    注:无
**************************************************************/
void system_enter_stop(void)
{
        uart_exti_init(); /* 进入STOP模式前配置RX引脚为外部中断模式 */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE); /* 开电源管理时钟 */
	//PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI); /* 进入STOP模式,外部中断唤醒 */
	PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE); /* 进入STOP模式,外部中断或事件唤醒 */
}

 

2、配置RX对应的GPIO引脚为外部中断模式

这里采用RT-Thread的PIN设备进行配置,在配置之前需要先关闭UART中断、复位UART、复位GPIO,然后在进行配置为外部中断模式,代码如下:

/**************************************************************
函数名称:uart_exti_init
函数功能:RX引脚配置为外部中断
输入参数:无
返 回 值:无
备    注:无
**************************************************************/
void uart_exti_init(void)
{
        /* 关闭UART中断、复位UART、复位GPIO */
	USART_ITConfig(USART3, USART_IT_RXNE, DISABLE);
	USART_Cmd(USART3, DISABLE);
	GPIO_DeInit(GPIOB);
	USART_DeInit(USART3);

	/* 配置RX对应的GPIO引脚为外部中断模式 */
	rt_pin_mode(PIN_UART3_RX, PIN_MODE_INPUT_PULLUP);
	rt_pin_attach_irq(PIN_UART3_RX, PIN_IRQ_MODE_FALLING, uart_exti_callback, RT_NULL);
	rt_pin_irq_enable(PIN_UART3_RX, PIN_IRQ_ENABLE);
}

 

3、接收中断回调函数

在上面的配置中,有一个接收回调函数uart_exti_callback,就是在发送中断的时候要执行的事情,在接收回调函数里面,我们主要实现SystemInit,重新初始化串口,代码如下:

/**************************************************************
函数名称:uart_exti_callback
函数功能:RX引脚外部中断唤醒回调函数
输入参数:args:回调函数入口参数
返 回 值:无
备    注:无
**************************************************************/
void uart_exti_callback(void *args)
{
	SystemInit();
	uart_reinit();		/* 重新初始化串口 */
	rt_kprintf("wake up\r\n");

}

 

4、进入STOP模式的线程

这里,创建一个线程来实现判断是否按键按下,按下则调用system_enter_stop函数进入STOP模式,同时为了验证唤醒之后时钟正常以及程序是从进行STOP模式之前的那个地方重新开始执行,我们设计LED灯500ms亮500ms灭,再一个计数变量,每隔1秒自动加1并打印,代码如下:

static void sleep_thread_entry(void *parameter)
{
	unsigned char key;
	unsigned int count=0;
	
	while(1)
	{
		key = key_scan(0);

		if(key == KEY4_PRES)
		{
			rt_kprintf("system_enter_stop\r\n");
			system_enter_stop();
		}
		LED1(1);
		rt_thread_mdelay(500);
		LED1(0);
		rt_thread_mdelay(500);
		rt_kprintf("count:%d\r\n",count);
		count++;
	}
}

 

5、实验操作和现象

1、开机之后,LED闪烁,串口打印count每隔1秒加1的值,等待一小会按下按键KEY4进入STOP模式:

FinSH抓取的串口打印信息

2、对比进入STOP模式前和STOP模式之后的电流情况(这里进入STOP模式之后电流还是很大是因为我们板子还接了其他耗电的模块,我们这对比电流有没有降下来就可以了),很明显,电流降下来了:

进入STOP模式前的电流

 

进入STOP模式后的电流
进入STOP模式后的电流

 

3、通过串口发送一个字符“A”,唤醒了STM32,这时候串口并不会打印字符“A”,因为唤醒之后要重新初始化串口,第二次发送字符“A”才能显示,这时候,我们观察FinSH打印出来的信息,可以看到count是从9开始打印,说明STOP唤醒之后会从原来进入STOP模式之前的地方重新执行代码:

验证代码的执行情况

 

唤醒之后第二次发一个字符能正常打印

 

4、接下来,我们再次按下KEY4重新然STM32进入STO模式,然后发送一个比较长的字符串来唤醒STM32,例如发“ABCDEFGHIJKLMNOPQ1234567890”,这时候,我们发现第一次发送之后,竟然会有字符出来,不是说没有吗?而且这些字符和我们发送的不一样,少了,第二次才正常:

唤醒之后打印字符不正常

 

 

四、串口唤醒存在的问题

1、上面我们提到,发送一个字符唤醒就很正常,而发送比较长的字符串唤醒却出现了不然正常的现象,这是为什么呢?想象一下m如果你是发一串很长的数据来唤醒串口,这串数据也是通过0101010等二进制来发送的,当RX引脚被触发中断唤醒MCU之后,唤醒之后串口初始化完成了,剩余的数据也就会接着以010101的高低电平发给STM32的串口,有可能导致有些字符的01丢失了一部分(例如上面出现了K567890),从而可以接下来的字符会打印出来。如果是发一个字符,一个字符的01010101其实也就8位,发送很快的,唤醒之后都已经发送结束了,所以就会直接唤醒,也就不会接收这个字符,只有第二次发送的时候才会接收到这个字符。

 

由于CSDN博客上传不了附件,我也不想上传到CSND资源去让大家还要用积分下载,所以我将实验代码上传到了原子论坛帖子附件:http://www.openedv.com/thread-289358-1-1.html

 

  • 14
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
PE WFE是指基于云计算的工作流引擎(Process Engine, Workflow Engine),是一种用于管理和执行工作流程的软件工具。它通过自动化和协调各个流程环节,提高了组织的效率和生产力。 PE WFE的主要功能包括流程定义、流程管理、流程执行和流程监控。首先,它允许用户以图形化方式定义和设计工作流程,将各个任务和环节安排并连接起来,形成一个完整的工作流程。其次,PE WFE可以对已定义好的工作流程进行管理,包括流程的部署、更新和删除等操作,保证流程的有效性和及时性。然后,PE WFE能够执行已定义好的工作流程,将任务分配给相应的执行者,并跟踪和记录流程的执行情况,确保流程的顺利进行。最后,PE WFE可以实时监控工作流程的状态和进度,提供可视化的界面和报表,帮助用户进行流程分析和优化。 PE WFE的应用领域广泛,包括但不限于企业内部流程管理、电子商务、客户关系管理、供应链管理等。它能够帮助组织提高工作效率、降低成本、提升服务质量,并通过自动化和标准化的流程实现组织的持续改进和创新。同时,PE WFE还可以与其他系统集成,实现业务流程的无缝衔接和数据的交换共享。 总之,PE WFE是一种强大的工作流引擎,通过管理和执行工作流程,提高了组织的效率和生产力。它具有图形化设计、流程管理、流程执行和流程监控等功能,适用于各个领域的工作流程管理需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值