← 所有文章

32位元累計值拆成兩個暫存器如何驗證組合順序

· 站長

用已知32位元測試值核對byte與word順序,再以低word進位案例辨識撕裂與快照限制。

先拿到四個不同的測試位元組

設備回覆兩個暫存器,畫面卻出現十幾億的累計量,先不要調倍率。把回覆中的兩個原始word保留下來,核對哪一個是高十六位、哪一個是低十六位,再處理有號性與單位。本篇以無號三十二位元累計值為主,教你建立能分辨順序錯誤的驗收資料。

Modbus應用協定的資料編碼規定,十六位元暫存器在封包中先送高位元組。例如一個word為0x1234,封包資料是12、34。兩個word如何組成廠商的三十二位元欄位,則還要看該設備資料表;不能把協定的位元組規則直接推成所有產品都高word在前。

準備測試值0x12345678很有用,因為四個byte都不同。全零或0xFFFFFFFF不適合單獨用來驗收排列,交換後仍相同;小整數有時也只讓你看到零在哪一邊,無法同時辨識單word內交換與跨word交換。測試值應由來源設備的受控測試模式或離線資料產生。

記錄起始位址的表示方式、讀取功能碼、暫存器數量、回覆資料與產品欄位名稱。本例只處理取得的兩個word,不指定40001等標記與PDU位址的換算,也不假設每一台設備都有可寫測試暫存器。不要為了製造數字去改動生產累計量。

本文適用於需自行解碼的資料介面。若驅動程式已提供三十二位元型別並做交換,應先查驅動設定,再決定程式是否還需要交換;重複交換常使原本正確的資料再次出錯。範例公式是數學說明,不是某台PLC可直接貼上的指令。

一步一步組合並排除四種排列

先把回覆依十六位元解析為R0=0x1234、R1=0x5678。若契約規定高word在前,令H=R0、L=R1,無號結果U=H×65536+L,得到305419896,也就是0x12345678。乘法和加法必須使用能容納完整無號三十二位元範圍的中間型別。

若同一組回覆的契約規定低word在前,H=R1、L=R0,結果是0x56781234,也就是1450709556。這兩個結果並非隨便挑一個看起來合理的數字;要用來源設定的已知測試值與產品排列說明決定,並保存設定證據。

另外兩種常見候選是單word內byte都交換後的0x34127856,以及byte和word都交換後的0x78563412。它們不是標準Modbus封包需要任意嘗試的選項,而是用來定位驅動、自訂資料映射或廠商特殊欄位是否額外做過處理。

接著測0x00000001與0x00010000。高word在前時,前者應讀到0000、0001;後者應讀到0001、0000。若累計每增加一單位,接收端卻增加65536,就優先核對高低word映射,而不是先把倍率除以65536來掩蓋問題。

最後測0xFFFFFFFF:無號解讀是4294967295;若同樣位元依有號二補數解讀則是−1。本文的累計契約採無號,因此不能讓接收端用有號整數顯示−1後,再誤認設備回報故障。若資料表把全一當無效碼,則需先按該契約判無效。

順序正確仍可能讀到撕裂資料

考慮來源計數從65535變65536,即0x0000FFFF變0x00010000。更新前高低word是0000、FFFF,更新後是0001、0000;如果接收端取得舊高word配新低word,組成0;取得新高word配舊低word,則組成131071。這兩個值都不是本次正常加一的結果。

把兩個暫存器放在同一個Modbus請求,可避免分成兩次往返,但不能只憑這一點宣稱原子快照。還要知道伺服器何時讀取來源資料、來源如何更新兩個word,以及通訊緩衝是否一次鎖存完整欄位。這些是產品或應用程式的保證,不是回覆格式本身的保證。

最清楚的做法是使用設備明確提供的鎖存快照,或按設備規定讀取帶版本的資料。例如版本方案需要寫入方遵守先標更新中、更新所有欄位、再公布完成版本的協定;讀取方只能接受前後相同且代表完成的版本。版本的原子讀寫與回捲條件也必須成立。

常見高、低、高重讀並非萬用解法。若來源先改低word、稍後才改高word,讀者可能在這段時間兩次都看到舊高word,仍接受錯誤值。只有來源更新模型、每個讀取的原子性、讀取順序與版本回捲限制都被證明符合演算法時,才能採用特定重讀策略。

驗收時刻意把讀取安排在低word從FFFF進位附近,觀察是否出現0或131071。沒有出現只能表示此次測試未捕捉到問題,不能代替原子性設計證明。來源未提供保證時,將一致性限制寫入文件,避免直接把可能撕裂的值作為重要控制條件。

完成後的結果與失敗排查

建立一張驗收表,每列包含來源測試值、R0、R1、交換設定、解碼型別、預期整數與實際結果。正常向量至少含零、一、65535、65536、0x12345678及型別上界。每次更換驅動設定只改一項,再重跑整組向量,才能指出是哪個處理造成差異。

若所有資料都固定錯位,先查word與byte處理是否重複;若只在32767或2147483647附近變負,先查有號性;若平時正確、跨低word進位才偶發巨大跳變,先查快照一致性。這三條排查路徑處理的是不同問題,不應一律加平均濾波。

通訊逾時要保存上次有效資料的時刻並標示新資料缺失。若畫面保留最後值,必須顯示它已過期,不能讓0代替失敗回覆。Modbus普通暫存器沒有自動附帶通用品質旗標,品質狀態需由設備欄位或接收應用自行建立並說明來源。

為重試設定次數與截止時間,避免在來源持續更新時無限重讀。達到限制後的反應依用途設計,例如報表留下缺值與原因;控制流程則依設備要求處理資料不可用。不得從一串失敗結果中挑一個看似正常的數字就當作成功。

完成後應能同時證明兩件事:位元排列符合已知向量,以及來源一致性符合文件約定。若只完成前者,交付時清楚列出後者仍待確認。

常見問題

問:Modbus一律高word在前嗎?答:協定規範單個暫存器的編碼,跨暫存器的三十二位元欄位要查產品資料表。

問:看到合理數字就代表排列正確嗎?答:不代表。應由來源產生可辨識測試值,再比較完整raw與解碼結果。

問:一次讀兩個暫存器就不會撕裂嗎?答:還要有來源更新與鎖存保證,同一請求不足以證明。

問:高低高讀到相同高word就能接受嗎?答:需先證明來源更新模型符合該演算法;兩個word依次更新時,仍可能取得中間狀態。

參考:Modbus Application Protocol V1.1b3,4.2資料編碼;不替外部產品定義32位元排列。

延伸閱讀


使用 PLC 工具箱 →