STM32 RS232串口接收数据帧被拆分问题排查记录

STM32 RS232串口接收数据被拆分问题排查记录

1.问题描述

如图1所示,与上层设备的串口Modbus RTU通讯,存在数据截断接收情况(实际串口请求数据长度是25字节,被拆分为16+9字节)。

图1 Modbus通讯报错 图1 Modbus通讯报错

2.背景阐述

2.1开发环境

芯片型号:STM32F767IGT6SP3232,如图2、图3所示。

图2 主芯片型号 图2 主芯片型号
图2 RS232芯片型号 图3 RS232芯片型号

开发环境:STM32CubeMXSTM32CubeIDE,如图4、图5所示。

图3 STM32CubeMX版本信息 图4 STM32CubeMX版本信息
图4 STM32CubeIDE版本信息 图5 STM32CubeIDE版本信息
2.2数据接收

串口通讯主要的难点在于 命令帧之间的区分应答的及时性,具体的数据处理逻辑如 ST32RS485串口DMA发送问题记录及调试解决 文章所示,为避免来回地跳转,此处再对相关部分进行阐述。

如图6所示,在文档Modbus_over_serial_line_V1 2.5.1.1节阐述,在MODBUS RTU模式中,消息帧之间的最小间隔时间是3.5字符的时间(具体时间由串口比特率及单个字符包含的位数决定,如比特率为9600bits/s,单个字符包含1个起始位,8个数据位,0个校验位,1个停止位,则最小间隔时间具体值t3.5=1/9600*(1+8+0+1)*3.5≈3.65ms)。因此数据接收可以使用芯片自带的超时功能实现,如图7所示,除了要使能接收器超时中断外,同时也要使能接收器超时功能,并使能DMA接收的循环模式,即数据接收采用 串口接收器超时中断+DMA接收循环模式 的方式,在串口中断中判断是否是超时中断,若是则获取此次中断录入DMA的新数据长度值,数据长度值的存储采用10级的循环缓冲区实现,并在程序主循环中判断存储数据长度值的缓冲区是否为空,若不为空则根据存储的数据长度值读取DMA接收缓冲区相应的数据量,然后送入Modbus协议解析函数中进行处理。

图6 MODBUS Message RTU Framing 图6 MODBUS Message RTU Framing
图7 MODBUS通信 图7 MODBUS通信

3.问题分析

图8 串口通讯参数设置 图8 串口通讯参数设置
图9 串口数据线极性定义 图9 串口数据线极性定义

命令帧之间的区分是通过芯片自带的超时功能实现的,再根据图8、图9所示,也就是说若一帧数据刚好被拆分成两帧,理论上是因为一帧数据内会有一段空闲高电平的时间≥t3.5=1/115200*(1+8+0+1)*3.5≈304us

刚开始是完全不认为一帧数据内会存在如此长时间的空闲状态,便初步怀疑会不会是RS232电平转TTL电平的SP3232芯片转换速率不足,但通过实际查看芯片手册,SP3232芯片是完全能够支持1M比特率的通讯。于是决定先用示波器采集串口线路上的电平状态,看是否存在问题,具体如下所示。

读保持寄存器:串口请求数据为8个字节,实际所用时间≈660us、690us(理论时间8*10/115200*1000*1000≈694us),串口响应数据为47个字节,实际所用时间≈4.07ms、4.06ms(理论时间47*10/115200*1000≈4ms),底层数据解析处理时间≈1.23ms、850us;

写多个寄存器:串口请求数据为25个字节,实际所用时间≈2.154ms(理论时间25*10/115200*1000≈2.17ms),串口响应数据为8个字节,实际所用时间≈683us(理论时间8*10/115200*1000*1000≈694us),底层数据解析处理时间≈550us。

所以串口线路上的电平变化是符合串口通讯参数设置的,同时虽然底层的串口通讯数据接收是中断方式,但命令解析处理是轮询方式(轮询周期1ms,所以通讯最大响应时间≤1.5ms),因此示波器采集到的数据也是与程序处理逻辑相符的。

图10 读保持寄存器:串口请求数据时间 图10 读保持寄存器:串口请求数据时间
图11 读保持寄存器:串口请求数据时间01 图11 读保持寄存器:串口请求数据时间01
图12 读保持寄存器:数据解析处理时间 图12 读保持寄存器:数据解析处理时间
图13 读保持寄存器:数据解析处理时间01 图13 读保持寄存器:数据解析处理时间01
图14 读保持寄存器:通讯交互总时间 图14 读保持寄存器:通讯交互总时间
图15 读保持寄存器:通讯交互总时间01 图15 读保持寄存器:通讯交互总时间01
图16 写多个寄存器:串口请求数据时间 图16 写多个寄存器:串口请求数据时间
图17 写多个寄存器:数据解析处理时间 图17 写多个寄存器:数据解析处理时间
图18 写多个寄存器:通讯交互总时间 图18 写多个寄存器:通讯交互总时间

但还是不认为一帧数据内会存在如此长时间的空闲状态,甚至开始怀疑芯片自带的接收超时功能是否有问题,于是想确认下通讯发生错误时串口数据线上的实际电平状态,便在程序串口接收超时中断处增加IO口电平的切换逻辑,以便在数据接收有问题时,给示波器提供触发源,以捕捉到错误时串口数据线上的电平状态。最终捕获到信号如图19、20所示(其中通道1接提供触发信号的IO口,通道2接RS232 PC-TXD,通道4接TTL PC-TXD),在一帧数据内可能会有390us左右的空闲高电平,而串口接收器超时判断的时间是3.5个字符(3.5*10/115200*1000*1000≈304us),导致触发了串口接收超时中断,同时空闲帧和停止位在串口线上均是高电平状态,并且这段空闲电平刚好是两个字符之间,从而一帧数据的内容实际未出现错误,只是被拆分接收了。

图19 帧内偶发有几百us的空闲高电平 图19 帧内偶发有几百us的空闲高电平
图20 帧内触发串口接收超时中断 图20 帧内触发串口接收超时中断

4.解决方案

因暂时无法定位到一帧数据内果然偶发有几百us空闲电平的原因,只能先通过增大接收器超时值(由3.5个字符增大到5个字符),如图21所示,尽量屏蔽掉帧内的空闲高电平触发串口接收器超时中断。

图21 增大接收超时器值 图21 增大接收超时器值

需要清楚的是若帧内空闲高电平的时间≥t5=1/115200*(1+8+0+1)*5≈434us,则仍是会存在一帧数据被拆分的现象,只能后续有机会再想办法找到一帧数据内偶发有几百us空闲电平的原因。

5.验证结果

如图22所示,串口Modbus RTU通讯交互报错的频率大大降低了。

图22 增加接收超时时间后通讯报错频率 图22 增加接收超时时间后通讯报错频率

经过此次问题排查过程,给我最大的感受是不要轻易怀疑芯片的功能,同时跟硬件打交道真是让人“欲仙欲死”。

  • 40
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值