解决STM32延时中断无法触发的问题
问题:
在使用zigbee模块时,使用串口作为无线收发的载体,与stm32通信,使用DHT11作为简单的受控源,出现了bug:
当在while(1)里使用delay函数,或者使用DHT11_Read_Data函数时,程序无法进入串口接收中断,无法使用远程控制
其中的while函数为:
while (1){
DHT11_Read_Data(&temp,&humi);//DHT11读取温度
bufFun();
if(dht11Res){
USART2_SendByte('1');
OLED_ShowNum(1,8,temp,2);
temp++;
}else{
USART2_SendByte('2');
}
delay_ms(1000);
}
解决思路:
一、常规检查
检查接线之后,我首先想到的是可能数据量过大无法进入中断,或者是某一步出错,使用STlink debug后,发现程序一直在主函数里,没有进入串口接收中断
二、延时函数
随后我仔细排查函数体,发现DHT11_Read_Data 或者其他函数体内,都存在延时函数,在之前的学习开发中,也遇到过因为滴答定时器优先级问题而出现的奇怪bug,尝试使用简单的软件延时代替:
//粗延时函数,微秒
void delay_us(u16 time)
{
u16 i=0;
while(time--)
{
i=10; //自己定义
while(i--) ;
}
}
//毫秒级的延时
void delay_ms(u16 time)
{
u16 i=0;
while(time--)
{
i=12000; //自己定义
while(i--) ;
}
}
无果后尝试另一种无需中断的硬件延时:
#include "delay.h"
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD = 9*nus;
SysTick->VAL=0X00;//清空计数器
SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源
do
{
temp=SysTick->CTRL;//读取当前倒计数值
}while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD = 9000*nms;
SysTick->VAL=0X00;//清空计数器
SysTick->CTRL=0X01;//使能,减到零是无动作,采用外部时钟源
do
{
temp=SysTick->CTRL;//读取当前倒计数值
}while((temp&0x01)&&(!(temp&(1<<16))));//等待时间到达
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
三、串口处理函数
经过以上调试后,我开始注意到串口处理函数:bufFun
原本的想法是把它放在主函数里,读取数据帧,然后用来判断命令
void bufFun(void){//数据帧接收
if(res){
switch(USARTReceIn){
case 0:
if(udata=='@'){//头
databuf[USARTReceIn++] = udata;
}
else{
USARTReceIn = 0;
}
break;
default:
databuf[USARTReceIn++] = udata;
break;
}
res=0;
}
if(USARTReceIn >= maxSizebuf)//数据帧接收完成
{
USARTReceFullFlag = 1;
}
dataProcess();
}
void dataProcess(void){//数据帧处理
if(USARTReceFullFlag)
{
//处理
//USART_Send_Str(databuf,maxSizebuf);
func();
//清空
USARTReceFullFlag = 0;
USARTReceIn = 0;
memset(databuf,0x00,sizeof(udata));
}
}
但是此处逻辑出现问题:
读取数据帧的前提是,串口接收中断成功接收一组数据帧,同时,while(1)里运行到bufFun,才可以识别一帧数据
但是当有延时,或者while中出现大量代码时,可能会出现,数据已经接收好,但是程序还没有运行到读取位,出现bug
尝试修改为在USART2_IRQHandler中运行bufFun:
问题解决