一、需求
为了降低stm32单片机在非工作状态下的功耗,需要实现通过手机端软件,通过蓝牙通讯的方式,发送待机指令,实现stm32单片机进入待机模式、蓝牙通讯模块实现低功耗运行。上述功能的手机端软件类似于遥控器的功能,能够遥控stm32单片机电路进入开机或待机状态下。
二、硬件电路
1、蓝牙模块
蓝牙模块采用周立功ZLG52810P0-1-TC,蓝牙模块的典型应用电路如下图所示:
蓝牙低功耗模式查询与设置指令说明,如下图:
蓝牙模块17管脚P0.20的说明如下图:
ZLG52810P0-1-TC 主要工作在透传模式下,也能配置标准 iBeacon 功能,或者发送自定
义广播数据。 默认出厂情况下,模块启动后会自动进行广播,使用 BLE 主机对其进行扫描连接,连 接成功之后就可以通过 BLE 在模块和 BLE 主机之间进行数据透传。用户也可以通过特定的
串口 AT 指令,对某些通讯参数进行修改(例如:串口波特率、广播间隔等)。
自定义广播包/iBeacon 模式等,在自定义广播包/iBeacon 模式下用户可以通过 AT 指令配置广播包自定义数据,模块会根据用户设置的自定义数据进行广播。
2、STM32103CBT6TR电路
单片机STM32103CBT6TR的管脚与蓝牙模块的连接如下:
1)PA9-------USART1_TX
2)PA10------USART1_RX
3) PA0--------P0.20
4) PA2--------BL_RST
采用PA0口做一键唤醒用,PA0即WKUP引脚的上升沿,可以使MCU退出待机模式。
总体实现思路:
1)需要省电待机时:手机APP软件发送待机命令给MCU,MCU接收到后再发送低功耗设置的AT命令给蓝牙模块,蓝牙模块进入低功耗模式下,此时P0.20引脚由高电平变为低电平,设置PA0为下降沿外部中断,中断服务程序中执行程序,使得MCU进入待机模式;注意:因为正常情况下,蓝牙模块处于透传模式,手机APP软件直接发送AT命令,蓝牙模块不会执行,只能透传到MCU接收变量的数据区内。
2)需要唤醒工作时:利用上述设置的低功耗模式1,手机APP软件发送任意数据,蓝牙模块接收到BLE数据可被唤醒,从而P0.20引脚由低电平变为高电平,此时PA0引脚的上升沿实现MCU退出待机模式,进入正常工作状态。
三、软件
1)MCU中蓝牙接收待机命令后的处理程序:
if((Modbus_HoldReg[33]&0x00FF)==0x08)
{
//透传回复数据
USART_TX_BUFF[0]=USART_RX_BUFF[0];
USART_TX_BUFF[1]=USART_RX_BUFF[1];
USART_TX_BUFF[2]=USART_RX_BUFF[2];
USART_TX_BUFF[3]=USART_RX_BUFF[3];
USART_TX_BUFF[4]=USART_RX_BUFF[4];
USART_TX_BUFF[5]=USART_RX_BUFF[5];
calCRC=CRC_Compute(USART_TX_BUFF,6);
USART_TX_BUFF[7]=calCRC&0xFF;
USART_TX_BUFF[6]=(calCRC>>8)&0xFF;
Slave_SendData(USART_TX_BUFF,8);
delay_ms(300);
//AT+LOWL:1 (41 54 2B 4C 4F 57 4C 3A 31)
USART_TX_BUFF[0]=0x41;
USART_TX_BUFF[1]=0x54;
USART_TX_BUFF[2]=0x2B;
USART_TX_BUFF[3]=0x4C;
USART_TX_BUFF[4]=0x4F;
USART_TX_BUFF[5]=0x57;
USART_TX_BUFF[6]=0x4C;
USART_TX_BUFF[7]=0x3A;
USART_TX_BUFF[8]=0x31;
Slave_SendData(USART_TX_BUFF,9);
}
上述程序中 "Slave_SendData(USART_TX_BUFF,8)"主要做接收待机命令后,利用透传模式还未失效,返回原数据,用于手机端APP判断指令发送成功与否;
"Slave_SendData(USART_TX_BUFF,9)"用于MCU发送"AT+LOW:1"指令到蓝牙模块上,注意:要将该指令字符串转为ASCII码,数组变量下的多字节发送。
2)唤醒初始化及PA0中断服务程序
//PA0 WKUP唤醒初始化
void WKUP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);//使能
GPIOA和复用功能时钟
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0; //PA.0
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPD;//下拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO
//使用外部中断方式
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); //中断线0连接GPIOA.0
EXTI_InitStructure.EXTI_Line = EXTI_Line0; //设置信号所有的外部线路
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //设外外部中断模式:EXTI线路为中断请求
//EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); // 初始化外部中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能信号所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5; //先占优先级2级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5; //从优先级2级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}
void Sys_Standby(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //使能PWR外设时钟
PWR_WakeUpPinCmd(ENABLE); //使能唤醒管脚功能
PWR_EnterSTANDBYMode(); //进入待命(STANDBY)模式
}
//系统进入待机模式
void Sys_Enter_Standby(void)
{
RCC_APB2PeriphResetCmd(0X01FC,DISABLE); //复位所有IO口
Sys_Standby();
}
//检测WKUP脚的信号
//返回值1:低电平连续3s以上
// 0:错误的触发
u8 Check_WKUP(void)
{
u8 t=0; //记录低电平的时间
LED0=0; //亮灯DS0
while(1)
{
if(WKUP_KD==0)
{
t++; //处于低电平
delay_ms(30);
if(t>=100) //低电平超过3秒钟
{
LED0=0; //点亮DS0
return 1; //按下3s以上了
}
}else
{
LED0=1;
return 0; //低电平不足3s
}
}
}
//中断,检测到PA0脚的一个下升沿.
//中断线0线上的中断检测
void EXTI0_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line0); // 清除LINE0上的中断标志位
if(Check_WKUP())//待机?
{
Sys_Enter_Standby();
}
}
需要注意的是:PA0需要设置为下拉输入方式;PA0作为外部中断需要设置成下降沿触发,相应的中断服务程序里面WKUP_KD等于0时,即低电平时执行待机程序。
四、实现效果
待机前:电路板电流42mA左右,待机后,电路板电流8mA左右,实现了功耗电流的降低,并且手机端软件遥控实现一键待机,一键唤醒开机。