【Maker電子學】Modbus RTU的傳輸資料格式

作者:Ryan Hu

上篇只有稍微介紹完 Modbus 的種類,接下來就從 Modbus protocol packet format 繼續吧!

Modbus RTU protocol 傳輸資料格式 (packet format)

如同上篇所述,我主要會專注在目前主流 Modbus – Modbus RTU 做介紹,我們就直接來看 master 傳出去的資料以及格式是什麼吧!(Modbus TCP 傳出去的資料會在實作過程中稍微提及)

(圖片來源:source

這個 format 剛開始看到一定會霧煞煞,因為包括 function code,和使用到的 register type,都屬於 Modbus protocol 自定義的一部份。就一個個來看吧。

Device address 應該不難懂,即 master 要將這整個 packet 傳給哪個 slave,slave address 則可以事先定義好,在我自己的開發專案中,RTU slave 就是電子標籤本身,所以可以事前在 MCU 中 define slave address。

而要講 function code 之前,一定要先瞭解 Modbus 自定義的 register type。

(圖片來源:source

嚴格來說,不能稱以上這些被定義的 register 為 register,最多稱之為 “Object”,只是有四種不同的形式,即上圖所示的 Discrete Inputs、Coils、Input Registers 和 Holding Registers。

之所以不能稱之為 register 的原因,相信如果有接觸單晶片開發的同好朋友一定知道,因為 MCU (device) 本身內部就是由一堆 registers 的設定,才能做出不同的功能表現。而這裡和實體那些擁有特定 address 的 register 不同,此為軟體模擬,和硬體不直接相關,因此用 Object 稱之會較為準確。

Discrete Inputs 和 Coils 只有 single byte,很明顯就是用來做 I/O 的 digital INPUT/OUTPUT,由表中也可得知此二種不同的 typologies 的差別:Coil 是 R/W,Discrete Inputs 則是只能 Read

而 Input Registers 和 Holding Registers 皆是可存 0-65535 值(2 bytes)的 typologies。最常見的就是 analog 值的應用以及其他客製化所需的資料,像是進入 ISR 的次數等等。

講到這,應該還是很難想像那到底要怎麼使用這些 typologies?slave 的 code 到底要設定哪些東西才能讓 master 在對應的位置抓到或是寫入有效的資料呢?下圖見分曉。

(圖片來源:source

既然已經定義了各種 typologies(Discrete Inputs、Coils、Input Registers 和 Holding Registers),那給不同 typologies 不同的軟體位置定義其實也就搞定了。如上圖,00001 – 09999 就屬於 Coils 的部分,或者也可以用 prefix 的角度,如果是 0 開頭的就一定是 Coils,以此類推做出四種 typologies 的區別,至於 PDU address 的部分,下方會和 function code 的部分一起做解釋。

截至目前,應該對於 register type(以免搞混我這不用 Object 就用原先的講法吧)有稍微的理解,現在可以進一步前進至 function code 的部分了。

(圖片來源:source

由於解釋完了四種 typologies,上方 related area 這個 column 的內容應該就可以對得起來了。也就是說,我們退回到 Modbus RTU packet format 來看,device address 後便是 function code,假設 master 期望對 slave 的某個 GPIO(eg. LED)做 ON/OFF 的動作,那 function code 就會植入 5,目的是告訴 slave 我(master)要來「寫」你的 Single Coil 了。

在講下去之前,要先認識一個詞:PDU(protocol data unit),整個 Modbus RTU packet 中 PDU 的部分包含 function code 和 data(包含 register number 和 register count),如下結構:

function code
Starting Address HI
Starting Address LO
Count of Register HI
Count of Register LO

而一組 PDU 最多(maximum)是 256 bytes。

回到主線,因為不同的 function code 就會對不同的 typologies 做各式的動作,這也是為什麼在講 typologies 時的那張圖,最後一個 column – PDU address,不論 typologies 為何,皆是 0000 – 9998。舉例來說,如果 function code 為 1,接下來的 byte 就是填要從哪個 register 開始(eg. 0x00),然後從開始的 register 數起共多少個 registers(eg. 0x0A),一次最多讀取 2000 的 coils。

至於 CRC error checking 就是大家常見的標準款,沒什麼特別 (雖是這樣說,我還是覺得發明的人真的太強…)。master 傳過去的 packet format 大致介紹是這樣,接下來,slave 在得到 master 的 packet 後回應的部分,我覺得也相當有趣,下方和大家分享。

Modbus RTU slave reponse

Modbus RTU slave 在收到 master 訊息後,只有兩種情況,正確接收和出現錯誤。

在正確接受的情況下,slave 會回的東西很簡單,exactly 就是 master 傳來的東西,packet 的結構完全和 master 的 packet 相同,包含 function code + data + CRC error check。

比較有趣的是出現錯誤的時候,slave 會將來自 master packet 裡的 function code 的 MSB,變為 logic 1,除此之外,原先來自 master data 位置的內容物會被 Modbus protocol 所定義的 exception code 所取代,如下圖:

(圖片來源:source

從 master 來的 function code 假設是 3(0000 0011),若有錯誤產生,slave 丟回給 master 的 packet 中的 function code 會是 131(1000 0011),data 的部分則是上圖中某個數字,端看錯誤的情形決定。

以上快速交代了 Modbus RTU protocol master 和 slave 互傳的資料內容,若有誤歡迎指教交流,下篇就會進入實作的部分,從透過 Modbus TCP 將 PC(master)和 Ardunio UNO + ENC28J60 ( slave )打通的故事說起。

( 責任編輯:楊子嫻)

Ryan Hu

對於 IOT 軟硬整合相關有極大興趣,鍾愛無人機,目前獨自完成的專案像是瓦力號、GPS 自動語音導覽系統、NTP 網路自動校時時鐘,喜歡流浪。
Ryan Hu

Author: Ryan Hu

對於 IOT 軟硬整合相關有極大興趣,鍾愛無人機,目前獨自完成的專案像是瓦力號、GPS 自動語音導覽系統、NTP 網路自動校時時鐘,喜歡流浪。

Share This Post On

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *