問題 在調試接收串口數據的Qt程式中發現,數據存在延遲和粘包現象。下位機發送數據包頻率是100Hz,一包56位元組,波特率115200,在列印port->readAll()的值的時候發現並不是每10ms讀到一包數據,而是大概每50ms左右一次接收到5包數據,在其他電腦上調試,以及下載其他串口助手調試後 ...
問題
在調試接收串口數據的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_MACHINE\SYSTEM\CurrentControlSet\Enum\FTDIBUS{Device VID, PID and serial number}\0000\Device Parameters\LatencyTimer
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 延遲的說明
設置自定義預設延遲定時器值