解决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:

问题解决

物联沃分享整理
物联沃-IOTWORD物联网 » 解决STM32延时中断无法触发的问题

发表评论