问题
在调试接收串口数据的Qt程序中发现,数据存在延迟和粘包现象。下位机发送数据包频率是100Hz,一包56字节,波特率115200,在打印port->readAll()
的值的时候发现并不是每10ms读到一包数据,而是大概每50ms左右一次接收到5包数据,在其他电脑上调试,以及下载其他串口助手调试后发现存在同样问题,排除Qt和 Windows 系统的原因。
再看转接线USB-RS485/422用的芯片是FT232R,驱动是FTDI官网下的VCP驱动程序,在网上找到的资料如下:
The latency timer is a form of time-out mechanism for the read buffer of FTDI devices. When a FT_Read instruction is sent to the device, data will not be sent back to the host PC until the requested number of bytes has been read. If the requested number of bytes never comes, the device would not send data back.
The latency timer counts from the last time data was sent back to the PC. If the latency timer expires, the device will send what data it has available to the PC regardless of how many bytes it is waiting on. The latency timer will then reset and begin counting again.
The default value for the latency timer is 16ms. This value may be customised by adding or changing the following entries in the FTDIPORT.INF file of the driver before installation.
[FtdiPort232.NT.HW.AddReg]
HKR,,”LatencyTimer”,0x00010001,16
This example will set the default latency timer value to 16ms. The valid range for the latency timer is 1ms – 255ms, although 1ms is not recommended as this is the same as the USB frame length.
The latency timer value is held in the registry under
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetEnumFTDIBUS{Device VID, PID and serial number}000Device ParametersLatencyTimer
Please see AN232B-04 Data Throughput, Latency and Handshaking for additional information on the latency timer.
解决办法
FT232R中内置定时器(延迟定时器),芯⽚测量⾃上次将数据发送到 PC 以来的时间。定时器的默认值设置为 16 毫秒。每次数据发送回 PC 时,计时器都会重置。如果超时,芯⽚将发回 2 个状态字节以及缓冲区中保存的任何数据。
猜测是因为接收到每10ms一包数据后,在FTDI芯片的延迟时间(16ms)内又接到了新的数据,直到缓冲区满了才发送到电脑。在 Windows 设备管理器中找到对应端口 USB Serial Port(COM4),右键->属性->端口设置->高级,将延迟计时器从16ms改为2ms
不建议使用 1ms,因为这与 USB 帧长度相同
调试后解决延迟和粘包问题。
参考
关于 Arduino FTDI 延迟的说明
设置自定义缺省延迟定时器值