← 所有文章

FIELD NOTES / 工業通訊與網路

CRC驗證失敗時如何保存原始封包供追查

工業通訊與網路作者:站長預估 5 分鐘閱讀

以Modbus RTU向量保存原始框架、收到CRC與計算CRC,分開不完整框架、CRC不符及後續資料有效性。

本文目錄

先分清協定再保存收到的資料

CRC失敗時只留下通訊錯誤四個字,通常無法知道是線路、封包邊界還是計算方式出了問題。先保存真正收到的位元組,再把接收、格式、CRC與資料有效性分開記錄。本篇用Modbus RTU作具體案例,教你留下可離線重算的證據。

先確認目前是RTU、ASCII或Modbus TCP。RTU使用二進位框架及兩位元組CRC;ASCII模式使用LRC;標準Modbus TCP以MBAP標頭承載PDU,並不附RTU那兩個CRC位元組。不能因三者都叫Modbus,就將同一檢查流程直接套用。

資料收集器建立FrameRecord,保存來源介面、方向、接收時間、原始長度、raw bytes、接收狀態與解析器版本。這些是本文設計的診斷欄位,不是Modbus原生資料欄,也不保證所有PLC模組都能提供失敗框架的原文。

若使用Q06UDVCPU與QJ71C24N,先查實際串列模式和接收程式。封包可能由模組或上層程式處理,錯誤資料也可能已被丟棄;沒有raw能力時應如實記錄限制,必要時使用合適且經確認的監測方式,不捏造一份收到的封包。

保留raw不等於把任何收到的資料發布為有效量測。即使畫面仍顯示最後有效值,也要另列最後成功時間與本次CrcMismatch狀態。不要讓保留舊值的顯示習慣,掩蓋目前資料已經無法通過驗證。

用八個位元組核對CRC

本例原始請求為01 03 00 00 00 0A C5 CD,空格只是顯示分隔,共八個位元組。前六個是站號、功能碼、起始地址與數量,最後C5 CD是收到的CRC。這是離線教學向量,不表示已向現場設備送出。

依RTU規則,CRC暫存值先設FFFF,逐個處理前六個message bytes,每個byte做八次右移及條件互斥或,反射形式常數為A001。全部處理完得到十六位CRC值0xCDC5,放上通訊線時先低byte,所以依序是C5、CD。

計算輸入是六個數值byte,不是文字字元。若把顯示字串「01 03」的0、1、空格、0、3當成ASCII碼送入CRC,計算對象就不同。紀錄應提供raw十六進位及byte數,讓接手人能重建相同輸入。

比對時可把收到C5 CD重組為0xCDC5,與計算值比較;也可把計算值拆成C5 CD,逐byte比對。兩種表達都可以,但報告要分清數值和線上順序。若一邊用CDC5、一邊用C5CD直接比字串,就會製造假的錯誤。

驗收第一組應看到received_crc=CDC5、calculated_crc=CDC5、crc_ok=true。第二組保留前六bytes,將收到的尾端改成C5 CE,收到值為CEC5,計算仍是CDC5,因此crc_ok=false。這個合成案例只證明比對能識別不一致。

失敗時保留哪些欄位

CRC不相等時,保存完整raw、收到CRC、計算CRC、算法識別及解析步驟。不要先改正尾端再把改過的框架存成raw。若需要產生修正版做離線研究,另存derived資料並註明來源,原始證據不能被覆蓋。

來源欄位至少能區分哪個實體介面、哪個方向和哪次接收工作。RTU本身沒有TCP交易識別欄,應用層若另有request_id,要標明是收集器的工作識別。CRC失敗框架內的站號也可能受損,只能記錄聲稱站號,不能當作已驗證身份。

接收層若判定字元錯誤、片段中斷或框架不完整,另記framing_status。只收到01 03 00 00時,本例不可能形成完整讀取請求,不為了湊足八bytes補零。保留收到的四bytes並標IncompleteFrame,避免把補造資料拿去追查現場。

RTU利用時間間隔界定框架,與CRC內容檢查是不同工作。一般應用日誌的時間解析度可能不足以證明字元間隔;若沒有可靠時間證據,就記錄未量測,而不是依毫秒顯示臆測已符合所有串列時序。

同時保存expected_length與received_length,但長度規則應依方向、功能碼及正常或例外回覆決定。不能將本例八byte請求長度硬套所有RTU回覆,否則正確但不同長度的封包也會被錯誤拒絕。

若診斷程式把raw轉成十六進位字串,另存原始byte數與編碼版本。空格、大小寫只是顯示方式,不能在重播時變成額外byte。載回後先比較長度及每個byte與原紀錄一致,再開始計算;這一步能排除複製文字時遺漏前導零造成的假故障。

排查順序與保存容量

第一步核對raw輸入與CRC算法,尤其初值、常數、是否把CRC本身再次納入,以及高低byte順序。本文採計算message部分再比對尾端的方法;其他實作若採整框架餘數檢查,需依同一規格驗證,不混用兩種方法的預期結果。

第二步查框架起訖、長度及是否把兩個框架黏在一起或中途切斷。第三步才根據實際串列錯誤、發生時機和多次紀錄,檢查通訊格式與實體連線。CRC不符只能證明收到內容與校驗不相符,不能單憑它判定某條電纜損壞。

若每筆都錯且低高byte剛好互換,優先查軟體順序;若只有特定功能碼錯,查長度與格式;若偶發且伴隨串列字元錯誤,再查設備和線路證據。保存正常框架與異常框架的對照,比只存一筆壞資料更容易定位。

診斷記錄也要有容量。假設每筆固定保存二百bytes原始內容與一百bytes欄位,僅資料內容三百bytes,保存一萬筆約三百萬bytes;實際檔案、索引與封裝還有額外成本。這是容量假設,不是所有RTU框架都二百bytes。

容量滿可採保留最近紀錄並計數淘汰,或先存摘要再限制重複原文,依維護需求明訂。任何省略都記dropped_records和期間,不能報告完全無CRC錯誤卻只是日誌滿了。限制診斷寫入負載,避免異常風暴反過來阻塞接收。

完成結果與常見問題

測試至少包含正確C5 CD、錯誤C5 CE、截斷四bytes、CRC順序顛倒及ASCII文字誤作raw。完成後應能由保存檔重算正確向量,且每種失敗都保留原資料和不同原因。

問:CRC通過就可以發布數值嗎?答:還要檢查框架、站號、功能碼、資料長度、型別及對應請求。CRC相符不證明工程單位正確,也不是來源身份驗證。

問:收到C5 CE,可以改成C5 CD再當正常資料嗎?答:不可以。原文必須保留,本次資料應標無效;自行修正校驗碼不能恢復可能受損的內容。

問:所有CRC-16函式都會算出CDC5嗎?答:不會。CRC-16有不同變體,需確認RTU算法、初值、輸入bytes與線上順序,不能只看函式名稱。

問:Modbus TCP封包末尾也要加這兩bytes嗎?答:標準Modbus TCP不加RTU CRC。若使用特殊RTU透傳隧道,必須另依隧道規格辨識,不能混稱標準Modbus TCP。

參考:Modbus over Serial Line V1.02:RTU框架與CRC產生、ASCII LRC。

參考:Modbus Application Protocol V1.1b3:串列與TCP ADU的差異。

延伸閱讀