題:
什麼時候應該從ASCII切換到高級串行協議?
I have no idea what I'm doing
2015-11-18 21:31:07 UTC
view on stackexchange narkive permalink

我所有通過UART與PC通信的微控制器設備都使用ASCII字符串發送命令和接收數據(在Arduino中實現)。這就是我開始研究電子產品時學到的,我總是發現發送裸線就足夠了。但是我注意到,我遇到的大多數設備都使用複雜的二進制協議,其中包括功能代碼,地址和CRC錯誤檢查。商用設備是否使用這種ASCII?工業的?

簡短的答案:當您的應用程序需要它時。是的,商用設備使用ASCII。以GPS NMEA為例。(同樣,我將在此處引用[我自己的問題](http://electronics.stackexchange.com/questions/186254/serial-protocol-delimiting-synchronization-techniques))
Modbus具有ASCII模式。請參見《 Modicon Modbus協議參考指南》(http://modbus.org/docs/PI_MBUS_300.pdf)
@EugeneSh:值得注意的是,NMEA具有校驗和字段,並且由於校驗和失敗(比您想像的要多發生)而丟棄單個樣本突發通常不是嚴重的失敗。對於其他協議,情況可能並非如此……*並且*對於那些可能確實至關重要(或採樣率高於1Hz的採樣)的應用,有很多二進制GPS協議(例如Garmin)正在使用費率是必需的,因為NMEA太冗長了。雖然這確實只會鞏固您的觀點。
八 答案:
Scott Seidman
2015-11-18 21:40:10 UTC
view on stackexchange narkive permalink
  1. ASCII和CRC不互斥。 ASCII是一種編碼,而CRC用於錯誤檢查。

  2. 任何內容都可以ASCII形式發送。我們的老人們肯定記得UUEncoding,它將任何東西轉換為ASCII字符串。

  3. A)對我來說,這通常是速度和效率的問題。通過ASCII發送大的32位數字可能會花費很長時間,但是通過串行協議以二進制形式將其發送為二進制僅需要4個字節。

    B)通過ASCII發送數字意味著您必須轉換數字轉換為ASCII,這是一個明顯的額外步驟(這是“ printf”操作的一部分)。 ,獲得錯誤的字節序等,二進制通信協議肯定可以解決問題。如果要發送ASCII,只需進入並查找數據流,就可以更輕鬆地從亂碼中恢復。

  4. ol>
+1為“ ASCII是一種編碼”。這不是協議;協議可以建立在ASCII之上。
對於基於文本的協議而言,從二進制壓縮協議中自動恢復並不是一件容易的事,但是對它進行檢查和調試確實可以。
@NickJohnson-絕對。一旦您要在十六進制編輯器中打開文件以查看可以恢復的內容,就SOP而言,您已經在FUBAR上了
@nickjohnson並不是真的。ASCII為您提供了許多帶外成幀/定界符選項,以幫助進行同步和恢復,如果該通道用於全寬二進制數據,則將需要額外的轉義,位填充,時間間隔或其他技巧。
-1
諸如換行符拆分之類的事情在許多串行訪問功能中實際上是免費的,甚至在沒有串行訪問功能的情況下也是微不足道的。相比之下,在8位二進制數據中插入和刪除成幀則比較棘手,並且還意味著大量數據的編碼大小取決於其內容。
在編寫協議時,我總是偏愛ASCII,以獲得所有明顯的好處(可讀性,可記錄性等)。在兩種情況下,使用二進制更有意義:首先,如果速度是一個問題,並且您需要二進制將盡可能多的數據塞入流中,其次,如果您有意試圖混淆或什至加密,則需要少量地處理。數據流阻礙或阻止逆向工程。那時,我已經對二進制協議進行了逆向工程,它在很大程度上給了我很大的刺激,而不是實際阻止這種行為。
@J ...我要補充一點,接收端的存儲空間曾經是一個實際問題,但實際上已經不復存在了。
MrSmith42
2015-11-18 21:37:43 UTC
view on stackexchange narkive permalink

這裡有一些想法:

  • ASCII很好,因為您可以使用串行監視器來手動查看發送的內容。
  • 如果您有連接是不可靠的,您必須預料到傳輸錯誤,並應使用CRC來檢查每個接收到的消息的完整性。這也可以在ASCII消息上完成。
  • 如果您的連接速度太慢,則可以通過切換為二進制格式來減小消息的大小
  • 在接收方,一種特殊的二進制格式可能比ASCII更容易解碼
Matt Young
2015-11-18 21:36:39 UTC
view on stackexchange narkive permalink

在最簡單的級別上,您可以說一個簡單的通信協議具有三層:物理層,傳輸層和應用程序。 (有些模型具有更多功能,例如帶有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協議也可以合併校驗和。我已經使用數字的ascii表示遇到了十六進制的ascii變體。
@EugeneSh。闡明了這一點
不用說挑剔,但是TCP並不是四層。它被視為適合OSI模型的第四層。串行通信並不十分適合OSI模型。
@batsplatsterson這很挑剔,與我要說的很不相關。
supercat
2015-11-20 00:06:07 UTC
view on stackexchange narkive permalink

尚未提及的一點是,無論是使用ASCII還是二進制協議,在每個數據包之前發送擦除字符都將確保即使在數據包開始之前出現了線路噪聲或成幀錯誤,所有字符都將在之後在沒有進一步噪音的情況下,可將畫框正確構圖。否則,如果一個人連續發送數據包並且不包含任何保證能夠實現重新同步的字符,則一個小故障可能會破壞隨後的所有內容,直到下一次傳輸暫停為止。 0xFF字符很不錯,因為它保證了任何接收者都可以在下一個字符上重新同步。

(*)0xFF-之所以稱為“擦出”,是因為有人在將數據輸入到紙膠帶可以按“後退膠帶”按鈕,然後按一下摩擦鍵,將錯誤打孔的字符替換為0xFF,大多數接收者會忽略它。)

Transistor
2015-11-19 00:40:13 UTC
view on stackexchange narkive permalink

發送ASCII字符串的一個優點是控制代碼可用於發信號通知消息的開始/結束。例如STX(字符2)和ETX(字符3)可以發出開始傳輸和結束傳輸的信號。或者,您可以添加簡單的換行符來標記傳輸的結束。

在發送二進制數據時,這變得更加複雜,因為無法為控制代碼保留特定的位模式(沒有一些額外的開銷或複雜性)因為有效的數據字節可能具有相同的模式。

許多二進制協議確實保留一個或多個位模式作為控制代碼,但是它們還包含轉義機制,用於在數據中出現這些代碼時處理這些代碼。
您可以保留任何模式來標記您想要的二進製文件。例如,我在一個項目中,一個快速的數據流和一個緩慢的數據流都出自同一項目。我將最大的負數int32保留為慢速數據的標誌,只是將最大的負數+1飽和了我的負數數據。
同意我希望我在編輯後的答案中對此進行了澄清。
Madivad
2015-11-19 07:41:35 UTC
view on stackexchange narkive permalink

ASCII很好,我幾乎在所有項目中都使用它。

另一個好處是,我使用串行無線電設備在arduinos之間獲取消息,並且可以使用連接到我的筆記本電腦的串行監視器並註入消息以使某些事情發生。非常適合測試。

同樣,以二進制形式發送消息並不是不可能的調試,並且取決於您的工具,您可以提取二進制並將其轉換為人類可讀的內容。或者,如果您知道要查找的內容,則可以直觀地檢查數據流並識別應該將其放在哪裡的值,並通過這種方式進行故障查找,儘管不那麼容易。即,您將識別字節模式並識別期望值

teambob
2015-11-20 12:38:47 UTC
view on stackexchange narkive permalink

考慮使用 HDLC代替Modbus。您將獲得錯誤檢測(這對於嘈雜的串行線路很重要)。同步功能強大,轉義功能強大。

我在RS-485網絡中使用HDLC沒問題,而PPP也使用了它。

如果您指出了為什麼要通過Modbus提出建議,那就太好了。
hak8or
2015-11-29 23:33:58 UTC
view on stackexchange narkive permalink
UART上的

ASCII最為流行,部分原因是:

  • 在調試時,它是人類可讀的(我還沒有看到不能解碼ASCII的邏輯分析儀)。 / p>

  • 這很容易實現,您已經通過快速google標準化了ASCII表。

  • 它具有

  • 基本上,整個嗜好者世界都已經通過ASCII設置了自己,因此任何新方法都必須處理,但這絕非易事。

然後,當您開始發送特定的編碼時會遇到這種情況,例如,將float的內存表示形式與轉換相比進行發送浮點數轉換為ASCII,通過串行方式發送(可以超過4個字節),然後將其轉換回主機上的內存中表示形式。相反,您每次只發送4字節表示形式。當然,您可以自己開始處理編碼,但隨後需要設置開始/結束標籤,順序等。

相反,可以使用諸如 Protobuf之類的東西。這實際上是在我正在從事的項目中使用的,它非常有益,它可以處理可變長度的消息,為您處理字節序,以及其他一些很酷的功能。它的代碼大小也不大,您可以指定在啟動時靜態分配的所有內容。如果需要,您將不得不自己放入校驗和。



該問答將自動從英語翻譯而來。原始內容可在stackexchange上找到,我們感謝它分發的cc by-sa 3.0許可。
Loading...