2014-12-28 38 views
0

我有一些需要從串口設備讀取的代碼。這是一個輪詢功能,被調用率爲r使用boost asio從串口讀取最新數據

該設備吐出數據輸出線由\r\n分開,其快速,在100Hz左右。每當我輪詢時,我想讀取整個串行緩衝區。我發現這很難用boost :: asio做,因爲它似乎沒有爲我提供available()函數。

我試過的方法之一是使用read_until(),但它不能解決我的問題,因爲在\r\n^停止在緩衝區後可能有更新的數據。

我在讀取緩衝區後嘗試使用consume(),但直到我知道我已經從設備讀取最新數據後,仍然是黑客作業。

任何人都有關於此問題的建議?

+0

這是你必須照顧好自己的事情,boost :: asio不認爲'\ r \ n'是所有特別的東西。使用緩衝區。 –

+0

@HansPassant當然,我也考慮過這個問題,並使用read_until()函數來處理它。但是我在想的是,如果我使用read_until(),它將從緩衝棧頂部讀取數據。我想要的數據是最新的,因此將在堆棧的底部。我如何反轉緩衝區? – Nopestradamus

+0

只是不補充緩衝區,直到它是空的。串口驅動程序已經有一個接收緩衝區。 –

回答

1

由於串行端口是作爲流讀取的,而不是隨機訪問句柄,因此必須按照接收順序讀取數據。鑑於此行爲,以下是一些獲取最新數據的選項:

  • 從流中讀取,直到讀取操作失敗並出現超時。雖然Boost.Asio既不提供非阻塞同步讀取也不提供串行I/O對象超時讀取,但可以使用異步讀取和定時器來實現此行爲。 Boost.Asio提供了一個超時集合examples。由於「\r\n」字符序列正用於數據邊界,因此請考慮使用async_read_until()來尊重數據邊界,而不必在應用程序代碼中引入邊界處理。如果入口速率大於消耗速率,則超時可能不確定。
  • 使用串口的native_handle()與系統特定的調用來確定可供讀取的字節量。然後,制定一種閱讀策略,使用可用字節數來確定何時停止閱讀。請注意,可用字節數量可能不會直接落在數據邊界上。因此,應用程序將需要處理碎片。例如,可能有一個async_read_until()超時。但是,一旦先前已知的可用字節數已被消耗,異步調用鏈就可以明確停止。即使入口速率超過消耗速率,這也爲異步呼叫鏈提供了確定性的結束。請查閱系統文檔以確定如何查詢可供讀取的可用字節,但Linux上通常爲ioctl(..., FIONREAD, ...),Windows上通常爲ClearCommError()
  • 從串口解耦消耗的數據並查詢最近接收到的數據。在責任分離的情況下,消費者線程將通過async_read_until()調用鏈連續讀取串行端口,並保留最近讀取的數據。根據訪問最新數據的方式,可能需要同步機制(例如互斥鎖)來避免競爭條件。一種替代方法是在讀取串行端口之後刪除鎖定需求的方法是使用未來/承諾,並將滿足承諾的操作發佈到正在運行async_read_until()循環的同一條鏈中。
  • 如果正在以足夠高的頻率寫入數據,並且在輪詢內等待完整的樣本可以接受,那麼可以使用flush the serial port's receive buffer,導致所有數據被丟棄。一旦丟棄,可以從串口讀取數據,等待寫入發生,從而產生最新的數據。由於清空緩衝區可能會丟棄樣本的一部分,因此可能需要讀取第二個數據邊界以確保已讀取完整的樣本。