我所有通過UART與PC通信的微控制器設備都使用ASCII字符串發送命令和接收數據(在Arduino中實現)。這就是我開始研究電子產品時學到的,我總是發現發送裸線就足夠了。但是我注意到,我遇到的大多數設備都使用複雜的二進制協議,其中包括功能代碼,地址和CRC錯誤檢查。商用設備是否使用這種ASCII?工業的?
我所有通過UART與PC通信的微控制器設備都使用ASCII字符串發送命令和接收數據(在Arduino中實現)。這就是我開始研究電子產品時學到的,我總是發現發送裸線就足夠了。但是我注意到,我遇到的大多數設備都使用複雜的二進制協議,其中包括功能代碼,地址和CRC錯誤檢查。商用設備是否使用這種ASCII?工業的?
ASCII和CRC不互斥。 ASCII是一種編碼,而CRC用於錯誤檢查。
任何內容都可以ASCII形式發送。我們的老人們肯定記得UUEncoding,它將任何東西轉換為ASCII字符串。
A)對我來說,這通常是速度和效率的問題。通過ASCII發送大的32位數字可能會花費很長時間,但是通過串行協議以二進制形式將其發送為二進制僅需要4個字節。
B)通過ASCII發送數字意味著您必須轉換數字轉換為ASCII,這是一個明顯的額外步驟(這是“ printf”操作的一部分)。 ,獲得錯誤的字節序等,二進制通信協議肯定可以解決問題。如果要發送ASCII,只需進入並查找數據流,就可以更輕鬆地從亂碼中恢復。
這裡有一些想法:
在最簡單的級別上,您可以說一個簡單的通信協議具有三層:物理層,傳輸層和應用程序。 (有些模型具有更多功能,例如帶有7的 OSI或具有4的 TCP / IP。在此問題中,層數並不是很重要。)
應用程序層是您直接在代碼中處理的層,也是問題的焦點。就傳輸層而言,您在send_data中傳遞給它的字節只是一個二進制模式,但是您可以在應用程序代碼中將其解釋為字母“ A”。無論您認為字節是'A',0x41還是0b01000001,CRC或校驗和的計算都是相同的。
傳輸層是數據包級別,在其中具有消息頭和錯誤檢查(無論是CRC還是基本校驗和)。在固件環境中,您可能具有諸如send_data之類的功能,在其中向其傳遞了一個字節以進行發送。在該函數內部,它放入一個數據包,其中說:“嘿,這是一條正常消息,需要確認,校驗和為0x47,當前時間為X。”該數據包通過物理層發送到接收節點。
物理層是定義電子設備和接口的地方:連接器,電壓電平,時序等。該層的範圍可以是幾個跟踪PCB上基本UART的運行TTL信號,直到某些 CAN實現中的完全隔離差分對。
在接收節點,數據包進入物理節點層,在傳輸層解壓縮,然後您的二進制模式可用於應用程序層。由接收節點應用程序層決定該模式應解釋為“ A”,0x41還是0b01000001,以及如何處理。
最後,如果應用程序需要發送ASCII字符,幾乎總是可以接受的。重要的是要了解您的通信方案,並包括一個錯誤檢查機制。
尚未提及的一點是,無論是使用ASCII還是二進制協議,在每個數據包之前發送擦除字符都將確保即使在數據包開始之前出現了線路噪聲或成幀錯誤,所有字符都將在之後在沒有進一步噪音的情況下,可將畫框正確構圖。否則,如果一個人連續發送數據包並且不包含任何保證能夠實現重新同步的字符,則一個小故障可能會破壞隨後的所有內容,直到下一次傳輸暫停為止。 0xFF字符很不錯,因為它保證了任何接收者都可以在下一個字符上重新同步。
(*)0xFF-之所以稱為“擦出”,是因為有人在將數據輸入到紙膠帶可以按“後退膠帶”按鈕,然後按一下摩擦鍵,將錯誤打孔的字符替換為0xFF,大多數接收者會忽略它。)
發送ASCII字符串的一個優點是控制代碼可用於發信號通知消息的開始/結束。例如STX(字符2)和ETX(字符3)可以發出開始傳輸和結束傳輸的信號。或者,您可以添加簡單的換行符來標記傳輸的結束。
在發送二進制數據時,這變得更加複雜,因為無法為控制代碼保留特定的位模式(沒有一些額外的開銷或複雜性)因為有效的數據字節可能具有相同的模式。
ASCII很好,我幾乎在所有項目中都使用它。
另一個好處是,我使用串行無線電設備在arduinos之間獲取消息,並且可以使用連接到我的筆記本電腦的串行監視器並註入消息以使某些事情發生。非常適合測試。
同樣,以二進制形式發送消息並不是不可能的調試,並且取決於您的工具,您可以提取二進制並將其轉換為人類可讀的內容。或者,如果您知道要查找的內容,則可以直觀地檢查數據流並識別應該將其放在哪裡的值,並通過這種方式進行故障查找,儘管不那麼容易。即,您將識別字節模式並識別期望值
考慮使用 HDLC代替Modbus。您將獲得錯誤檢測(這對於嘈雜的串行線路很重要)。同步功能強大,轉義功能強大。
我在RS-485網絡中使用HDLC沒問題,而PPP也使用了它。
ASCII最為流行,部分原因是:
在調試時,它是人類可讀的(我還沒有看到不能解碼ASCII的邏輯分析儀)。 / p>
這很容易實現,您已經通過快速google標準化了ASCII表。
它具有
基本上,整個嗜好者世界都已經通過ASCII設置了自己,因此任何新方法都必須處理,但這絕非易事。
然後,當您開始發送特定的編碼時會遇到這種情況,例如,將float的內存表示形式與轉換相比進行發送浮點數轉換為ASCII,通過串行方式發送(可以超過4個字節),然後將其轉換回主機上的內存中表示形式。相反,您每次只發送4字節表示形式。當然,您可以自己開始處理編碼,但隨後需要設置開始/結束標籤,順序等。
相反,可以使用諸如 Protobuf之類的東西。這實際上是在我正在從事的項目中使用的,它非常有益,它可以處理可變長度的消息,為您處理字節序,以及其他一些很酷的功能。它的代碼大小也不大,您可以指定在啟動時靜態分配的所有內容。如果需要,您將不得不自己放入校驗和。