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

文章目录

  • @[toc]
  • STM32 RS232串口接收数据被拆分问题排查记录
  • 1.问题描述
  • 2.背景阐述
  • 2.1开发环境
  • 2.2数据接收
  • 3.问题分析
  • 4.解决方案
  • 5.验证结果
  • 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 增加接收超时时间后通讯报错频率

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

    作者:青争.

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32 RS232串口接收数据帧拆分问题排查记录

    发表评论