STM32 操作系统串口中断发送异常问题
使用串口中断发送数据时好时坏,有时能收到有时为错误数据,但数据长度正确
问题代码分析
uint8_t analogOutChlSet(uint8_t dev,analog_out_ch_e channel,uint16_t val)
{
uint8_t ret=0;
uint8_t send_buf[32]={0};
uint16_t send_len=0;
mb_req_s req={0};
MSGQUEUE_OBJ_t msg;
req.Id=dev;
req.Func=0x06;
req.RW_Reg=channel;
req.RW_Value[0]=val;
// 生成命令
ret=mbMasGen(send_buf,&send_len,&req);
if(ret){
LOG_ERROR(0,"mbMasGen Param Error:%d",ret);
return 1;
}
// 发送命令
rs485Send(LINK_RS485_UP,send_buf,send_len);
// 等待响应
if(osMessageQueueGet(gParam.os_msg_com_ext,&msg,NULL,1000)!=osOK){
LOG_ERROR(0,"mbMasGen no reply");
return 2;
}
// 重新打开接收
uartComExtRecv();
// 判定响应是否正确
ret=mbMasAth(msg.msg_buf,msg.msg_length,&req);
if(ret){
LOG_ERROR(0,"mbMasAth response error:%d",ret);
return 3;
}
return 0;
}
该代码生成Modbus请求并验证modbus响应是否正确,问题在于我使用的串口中断发送函数为非阻塞,DMA发送同理,发送函数执行完成后等待消息队列会阻塞线程进而导致上下文切换。
现在来看第四行的变量声明,该变量为局部变量,当上下文切换后该变量对于串口中断外设后不可访问,发送出来的数据实际上是不确定任务的栈内数据。
至于为何问题时断时续是因为受到数据长度影响,数据短(比如几字节)情况下可能还未上下文切换串口外设已经发送完成了,此时数据接收到的肯定没问题
解决方案
使用static修饰变量或者将变量设置为全局变量。
带操作系统下应该使用非阻塞式函数,涉及到发送数据时要注意消息buffer变量的作用域。
文章作者:四文鱼Max
本文链接:https://blog.awolon.fun/archives/stm32-uart-send-abnormal.html
许可协议:CC BY-SA 4.0