文章分享

開放、平等、協(xié)作、快速、分享

當(dāng)前位置:首頁(yè)>文章分享

Modbus?協(xié)議?深入?講解

摘錄:HCTech 無錫和控電子   時(shí)間:2020-08-14   訪問量:4725

概覽

Modbus是一種工業(yè)協(xié)議,于1979年開發(fā),旨在實(shí)現(xiàn)自動(dòng)化設(shè)備之間的通信。 Modbus最初是作為通過串行層傳輸數(shù)據(jù)的應(yīng)用級(jí)協(xié)議實(shí)現(xiàn)的,現(xiàn)已擴(kuò)展到包括通過串行、TCP/IP和用戶數(shù)據(jù)報(bào)協(xié)議(UDP)的實(shí)現(xiàn)。 本文檔提供了協(xié)議實(shí)現(xiàn)的深入講解。

內(nèi)容

什么是Modbus協(xié)議?

Modbus是使用主從關(guān)系實(shí)現(xiàn)的請(qǐng)求 - 響應(yīng)協(xié)議。 在主從關(guān)系中,通信總是成對(duì)發(fā)生 - 一個(gè)設(shè)備必須發(fā)起請(qǐng)求,然后等待響應(yīng) - 并且發(fā)起設(shè)備(主設(shè)備)負(fù)責(zé)發(fā)起每次交互。 通常,主設(shè)備是人機(jī)界面(HMI)或監(jiān)控和數(shù)據(jù)采集(SCADA)系統(tǒng),從設(shè)備是傳感器、可編程邏輯控制器(PLC)或可編程自動(dòng)化控制器(PAC)。 這些請(qǐng)求和響應(yīng)的內(nèi)容以及發(fā)送這些消息的網(wǎng)絡(luò)層由協(xié)議的不同層來定義。

blob.png
圖1. 主從網(wǎng)絡(luò)關(guān)系

Modbus協(xié)議層

在最初的做法中,Modbus是建立在串行端口之上的單一協(xié)議,因此它不能被分成多個(gè)層。 隨著時(shí)間的推移,該協(xié)議引入了不同的應(yīng)用程序數(shù)據(jù)單元來更改串行通信使用的數(shù)據(jù)包格式,或允許使用TCP/IP和用戶數(shù)據(jù)報(bào)協(xié)議(UDP)網(wǎng)絡(luò)。 這實(shí)現(xiàn)了定義協(xié)議數(shù)據(jù)單元(PDU)的核心協(xié)議和定義應(yīng)用數(shù)據(jù)單元(ADU)的網(wǎng)絡(luò)層的分離。

返回頂部

協(xié)議數(shù)據(jù)單元(PDU)

PDU及其處理代碼構(gòu)成了Modbus應(yīng)用協(xié)議規(guī)范的核心。 該規(guī)范定義了PDU的格式、協(xié)議使用的各種數(shù)據(jù)概念、如何使用功能代碼訪問數(shù)據(jù),以及每個(gè)功能代碼的具體實(shí)現(xiàn)和限制。

Modbus PDU格式被定義為一個(gè)功能代碼,后面跟著一組關(guān)聯(lián)的數(shù)據(jù)。 該數(shù)據(jù)的大小和內(nèi)容由功能代碼定義,整個(gè)PDU(功能代碼和數(shù)據(jù))的大小不能超過253個(gè)字節(jié)。 每個(gè)功能代碼都有一個(gè)特定的行為,從設(shè)備可以根據(jù)所需的應(yīng)用程序行為靈活地實(shí)現(xiàn)這些行為。 PDU規(guī)范定義了數(shù)據(jù)訪問和操作的核心概念;但是,從設(shè)備可能會(huì)以規(guī)范中未明確定義的方式處理數(shù)據(jù)。

訪問Modbus和Modbus數(shù)據(jù)模型中的數(shù)據(jù)

通常,Modbus可訪問的數(shù)據(jù)存儲(chǔ)在四個(gè)數(shù)據(jù)庫(kù)或地址范圍的其中一個(gè): 線圈狀態(tài)、離散量輸入、保持寄存器和輸入寄存器。 與許多規(guī)范一樣,名稱可能因行業(yè)或應(yīng)用而異。 例如,保持寄存器也可以稱為輸出寄存器,線圈狀態(tài)可能稱為數(shù)字或離散量輸出。 這些數(shù)據(jù)庫(kù)定義了所包含數(shù)據(jù)的類型和訪問權(quán)限。 從設(shè)備可以直接訪問這些數(shù)據(jù),因?yàn)檫@些數(shù)據(jù)由設(shè)備本地托管。 Modbus可訪問的數(shù)據(jù)通常是設(shè)備主存的一個(gè)子集。 相反,Modbus主設(shè)備必須通過各種功能代碼請(qǐng)求訪問這些數(shù)據(jù)。 表1中描述了每個(gè)區(qū)塊的行為。

 

內(nèi)存區(qū)塊 數(shù)據(jù)類型 主設(shè)備訪問 從設(shè)備訪問
線圈狀態(tài) 布爾 讀/寫 讀/寫
離散輸入 布爾 只讀 讀/寫
保持寄存器 無符號(hào)雙字節(jié)整型 讀/寫 讀/寫
輸入寄存器 無符號(hào)雙字節(jié)整型 只讀 讀/寫

表1. Modbus數(shù)據(jù)模型區(qū)塊

這些區(qū)塊允許您限制或允許訪問不同的數(shù)據(jù)元素,并且為應(yīng)用層提供簡(jiǎn)化的機(jī)制來訪問不同的數(shù)據(jù)類型。

這些區(qū)塊是完全概念性的。 它們可能作為獨(dú)立的內(nèi)存地址存在于給定的系統(tǒng)中,但也可能重疊。 例如,線圈狀態(tài)1可能存在于與保持寄存器1所代表的字的第一位相同的內(nèi)存中。 尋址方案完全由從設(shè)備定義,其對(duì)每個(gè)內(nèi)存區(qū)的解釋是設(shè)備數(shù)據(jù)模型的重要組成部分。

數(shù)據(jù)模型尋址

該規(guī)范將每個(gè)區(qū)塊定義為包含多達(dá)65,536(216)個(gè)元素的地址空間。 在PDU的定義中,Modbus定義了每個(gè)數(shù)據(jù)元素的地址,范圍從0到65,535。但是,每個(gè)數(shù)據(jù)元素的編號(hào)從1到n,其中n的最大值為65,536。也就是說,線圈狀態(tài)1位于地址0的線圈狀態(tài)區(qū)塊中,而保持寄存器54位于從機(jī)被定義為保持寄存器的內(nèi)存部分中的地址53。

規(guī)范允許的全部范圍不需要給定設(shè)備實(shí)現(xiàn)。 例如,設(shè)備可能會(huì)選擇不執(zhí)行線圈、離散輸入或輸入寄存器,而只使用保持寄存器150至175和200至225。這是完全可以接受的,并且通過例外來處理無效的訪問嘗試。

數(shù)據(jù)尋址范圍

雖然規(guī)范將不同的數(shù)據(jù)類型定義為存在于不同的區(qū)塊中,并為每種類型分配一個(gè)本地地址范圍,但這并不一定會(huì)轉(zhuǎn)化為用于記錄或理解給定設(shè)備的Modbus可訪問內(nèi)存的直觀編址方案。 為了簡(jiǎn)化對(duì)內(nèi)存區(qū)塊位置的理解,引入了一種編號(hào)方案,其將前綴添加到所討論的數(shù)據(jù)的地址中。

例如,設(shè)備手冊(cè)不會(huì)引用地址13寄存器14的數(shù)據(jù)項(xiàng),而是引用地址4,014,40,014或400,014的數(shù)據(jù)項(xiàng)。在任何情況下,第一個(gè)數(shù)字都是4,表示保持寄存器,剩余數(shù)字則表示指定地址。 4XXX、4XXXX和4XXXXX的區(qū)別取決于設(shè)備使用的地址空間。 如果所有65,536個(gè)寄存器都在使用中,應(yīng)該使用4XXXXX符號(hào),因?yàn)槠湓试S范圍為400,001~465,536。如果只使用幾個(gè)寄存器,通常的做法是使用范圍4,001到4,999。

在這種尋址方案中,每種數(shù)據(jù)類型都被分配了一個(gè)前綴,如表2所示。

 

數(shù)據(jù)區(qū)塊 前綴
線圈狀態(tài) 0
離散輸入 1
輸入寄存器 3
保持寄存器 4

表2. 數(shù)據(jù)范圍前綴

線圈狀態(tài)存在前綴為0的情況。這意味著4001的引用可能指的是保持寄存器1或線圈4001。因此,建議所有新尋址方案都采用帶前導(dǎo)零的6位尋址,并在文檔中進(jìn)行標(biāo)注。 因此,保持寄存器1的地址為400,001,而線圈4001的地址則為004,001。

數(shù)據(jù)地址起始值

內(nèi)存地址和參考數(shù)字之間的差異會(huì)由給定應(yīng)用程序選擇的索引進(jìn)一步復(fù)雜化。 如前所述,保存寄存器1位于地址零。 通常,參考號(hào)碼是1索引,這意味著給定范圍的起始值為1。 因此,400,001就表示為地址0的保持寄存器00001。一些做法選擇以零開始其范圍,這意味著400,000轉(zhuǎn)換為地址零的保持寄存器。 表3展示了這個(gè)概念。

地址 寄存器編號(hào) 編號(hào)1(1索引,標(biāo)準(zhǔn)) 編號(hào)(0索引,替換)
0 1 400001 400000
1 2 400002 400001
2 3 400003 400002

表3.寄存器索引方案

 

1索引范圍應(yīng)用較為廣泛,強(qiáng)烈建議采用。 無論哪種情況,每個(gè)范圍的起始值都應(yīng)在文檔中注明。

大數(shù)據(jù)類型

Modbus標(biāo)準(zhǔn)提供了一個(gè)相對(duì)簡(jiǎn)單的數(shù)據(jù)模型,它不包含無符號(hào)字和位值之外的其他數(shù)據(jù)類型。 如果系統(tǒng)的位值對(duì)應(yīng)于螺線管和繼電器,并且字值對(duì)應(yīng)于未縮放的ADC值,這是足夠的,但對(duì)于更高級(jí)的系統(tǒng)則可能不足。 因此,許多Modbus實(shí)現(xiàn)都包含跨寄存器邊界的數(shù)據(jù)類型。 NI LabVIEW數(shù)據(jù)記錄和監(jiān)控(DSC)模塊KEPServerEX都定義了許多參考類型。 例如,存儲(chǔ)在保持寄存器中的字符串遵循標(biāo)準(zhǔn)格式(400,001),但后跟一個(gè)十進(jìn)制數(shù)、長(zhǎng)度和字符串的字節(jié)順序(400,001.2H是指保持寄存器1中的兩個(gè)字符串,其中高位字節(jié)對(duì)應(yīng)到字符串的第一個(gè)字符)。 這是必需的,因?yàn)槊總€(gè)請(qǐng)求的大小都是有限的,所以Modbus主機(jī)必須知道字符串的確切范圍,而不是像NULL那樣搜索長(zhǎng)度或分隔符。

位訪問

除了允許訪問跨寄存器邊界的數(shù)據(jù)之外,一些Modbus主設(shè)備還支持對(duì)寄存器中各個(gè)位的引用。 這是有好處的,因?yàn)樗试S設(shè)備將相同內(nèi)存范圍內(nèi)的每種類型的數(shù)據(jù)組合在一起,而不必將二進(jìn)制數(shù)據(jù)分成線圈整體和離散量輸入范圍。 這通常使用小數(shù)點(diǎn)和位索引或數(shù)字進(jìn)行索引,具體取決于如何實(shí)現(xiàn)。 也就是說,第一個(gè)寄存器的第一位可能是400,001.00或400,001.01。 建議任何文檔都要說明所使用的索引方案。

數(shù)據(jù)字節(jié)順序

多寄存器數(shù)據(jù)(單精度浮點(diǎn)值),可以通過將數(shù)據(jù)拆分到兩個(gè)寄存器,輕松地在Modbus中傳輸。 由于這不是由標(biāo)準(zhǔn)定義的,因此分割的字節(jié)順序沒有規(guī)定。 盡管每個(gè)無符號(hào)字必須以網(wǎng)絡(luò)(big-endian)字節(jié)順序發(fā)送以滿足標(biāo)準(zhǔn),但許多設(shè)備會(huì)顛倒多字節(jié)數(shù)據(jù)的字節(jié)順序。 圖2所示的是一個(gè)不常見但有效的例子。

blob.png
圖2.多字?jǐn)?shù)據(jù)的字節(jié)順序交換

請(qǐng)務(wù)必理解設(shè)備如何將信息存儲(chǔ)在內(nèi)存中并對(duì)其進(jìn)行正確解碼。 建議文檔寫明系統(tǒng)所使用的字順序。 如果需要靈活性,也可以將Endian添加為系統(tǒng)配置選項(xiàng),提供基礎(chǔ)的編碼和解碼功能。

字符串

字符串可以很容易地存儲(chǔ)在Modbus寄存器中。 為了簡(jiǎn)單起見,一些方法要求字符串長(zhǎng)度為2的倍數(shù),并使用控制來填充額外的空間。 字節(jié)順序也是字符串交互中的一個(gè)變量。 字符串格式可能包含也可能不包含NULL作為最終值。 舉個(gè)例子,一些設(shè)備的數(shù)據(jù)存儲(chǔ)方法可能如圖3所示。

blob.png
圖3. Modbus字符串中的字節(jié)順序反轉(zhuǎn)

了解功能代碼

與數(shù)據(jù)模型可能因設(shè)備而異不同,功能代碼及其數(shù)據(jù)由標(biāo)準(zhǔn)明確定義。 每個(gè)功能都遵循一種模式。 首先,從設(shè)備會(huì)驗(yàn)證功能代碼、數(shù)據(jù)地址和數(shù)據(jù)范圍等輸入。 然后執(zhí)行所請(qǐng)求的操作并發(fā)送與代碼相符的響應(yīng)。 如果此過程中的任何步驟失敗,則會(huì)向請(qǐng)求程序返回異常。 這些請(qǐng)求的數(shù)據(jù)傳輸就稱為PDU。

Modbus PDU

PDU由一個(gè)單字節(jié)的功能代碼組成,后面跟著多達(dá)252字節(jié)的針對(duì)特定函數(shù)的數(shù)據(jù)。

blob.png
圖4. Modbus PDU

功能代碼是第一個(gè)需要驗(yàn)證的項(xiàng)。 如果功能代碼沒有被接收到請(qǐng)求的設(shè)備識(shí)別,則會(huì)回應(yīng)一個(gè)異常。 如果功能代碼被接受,則從設(shè)備根據(jù)功能定義開始分解數(shù)據(jù)。

 

由于數(shù)據(jù)包大小限制為253字節(jié),設(shè)備可傳輸?shù)臄?shù)據(jù)量有限。 最常見的功能代碼可以240到250字節(jié)的從設(shè)備數(shù)據(jù)模型數(shù)據(jù),具體取決于代碼。

從函數(shù)執(zhí)行

不同的函數(shù)由數(shù)據(jù)模型定義訪問不同的概念數(shù)據(jù)塊。 一個(gè)常見的做法是讓代碼訪問靜態(tài)內(nèi)存位置,但其他行為是可用的。 例如,功能代碼1(讀取線圈狀態(tài))和3(讀取保持寄存器)可以訪問內(nèi)存中相同的物理位置。 而功能代碼3(讀取保持寄存器)和16(寫入保持寄存器)可以訪問內(nèi)存中完全不同的位置。 因此,建議在定義從數(shù)據(jù)模型時(shí)同時(shí)考慮每個(gè)功能代碼的執(zhí)行。

無論執(zhí)行的是何種實(shí)際行為,所有的從設(shè)備都應(yīng)該遵循每個(gè)請(qǐng)求的簡(jiǎn)單狀態(tài)流程圖。 圖5是代碼1讀取線圈狀態(tài)的一個(gè)例子。

blob.png
圖5.Modbus協(xié)議規(guī)范定義的讀取線圈狀態(tài)流程圖

每個(gè)從設(shè)備必須驗(yàn)證功能代碼、輸入數(shù)量、起始地址、總范圍以及實(shí)際進(jìn)行讀取行為的從屬定義函數(shù)(slave-defined function)的執(zhí)行。

盡管上面的狀態(tài)圖包含了靜態(tài)地址范圍,但真實(shí)系統(tǒng)的需求可能會(huì)使靜態(tài)地址范圍與定義的數(shù)字有所不同。 在某些情況下,從設(shè)備無法傳輸協(xié)議定義的最大字節(jié)數(shù)。 也就是說,如果主設(shè)備請(qǐng)求0x07D0輸入,從設(shè)備只能用0x0400進(jìn)行響應(yīng)。 如果主設(shè)備從地址0開始請(qǐng)求125,則這是正確的,但是如果主設(shè)備從地址400開始發(fā)出相同的請(qǐng)求,最后一個(gè)線圈狀態(tài)將位于地址525,超出了該設(shè)備的范圍,會(huì)導(dǎo)致出現(xiàn)狀態(tài)圖定義的異常02。

標(biāo)準(zhǔn)功能代碼

每個(gè)標(biāo)準(zhǔn)功能代碼的定義都包含在說明書中。 即使對(duì)于最常見的功能代碼,在主設(shè)備上啟用的功能與從設(shè)備可以處理的功能之間也存在不可避免的不匹配。 為了解決這個(gè)問題,Modbus TCP規(guī)范的早期版本定義了三個(gè)一致性類。 官方的Modbus一致性測(cè)試規(guī)范沒有引用這些類,而是在每個(gè)功能的基礎(chǔ)上定義一致性;但是,這些仍然很容易理解。 建議任何文檔都遵循測(cè)試規(guī)范,并根據(jù)其支持的代碼而不是傳統(tǒng)分類來定義它們的一致性。

0類代碼

0類代碼通常被認(rèn)為是有用Modbus設(shè)備的最低配置,因?yàn)樗鼈兪怪髟O(shè)備能夠讀取或?qū)懭霐?shù)據(jù)模型。

代碼 說明
3 讀多寄存器
16 寫多寄存器

表4.0類一致性代碼

1類代碼

1類功能代碼由訪問所有類型的數(shù)據(jù)模型所需的其他代碼組成。 在原始定義中,這個(gè)列表包含功能代碼7(讀取異常)。 但是,此代碼由當(dāng)前規(guī)范定義為僅限于串行的代碼。

代碼 說明
1 讀線圈
2 讀離散輸入
4 讀輸入寄存器
5 寫單線圈
6 寫單寄存器
7 讀取異常狀態(tài)(僅限串行)

表5. 1類一致性代碼

2類代碼

2類功能代碼用于更為專業(yè)化的功能,不太常用。 例如,讀/寫多個(gè)寄存器可能有助于減少請(qǐng)求/響應(yīng)周期的總數(shù),但該行為仍可以用0類代碼實(shí)現(xiàn)。

 代碼 說明
15 寫多線圈
20 讀文件記錄
21 寫文件記錄
22 屏蔽寫寄存器
23 讀/寫多寄存器
24 讀取FIFO

表6. 2類一致性代碼

 
Modbus封裝接口

Modbus封裝接口(MEI)代碼功能43用于封裝Modbus數(shù)據(jù)包內(nèi)的其他數(shù)據(jù)。 目前,有兩個(gè)MEI號(hào)碼可用,13(CANopen)和14(設(shè)備識(shí)別)。

功能43/14(設(shè)備識(shí)別)非常有用,因?yàn)樗试S傳送多達(dá)256個(gè)唯一的對(duì)象。 其中一些對(duì)象已預(yù)定義且預(yù)留好,例如供應(yīng)商名稱和產(chǎn)品代碼,但應(yīng)用程序可以將其他對(duì)象定義為通用數(shù)據(jù)集。

此代碼并不常用。

例外

從設(shè)備使用異常來指示各種不良狀況,比如錯(cuò)誤請(qǐng)求或不正確輸入。 但是,異常也可以作為對(duì)無效請(qǐng)求的應(yīng)用程序級(jí)響應(yīng)。 從設(shè)備不響應(yīng)發(fā)出異常的請(qǐng)求。 相反,從設(shè)備忽略不完整或損壞的請(qǐng)求,并開始等待新的消息傳入。

異常以定義好的數(shù)據(jù)包格式報(bào)告給用戶。 首先將一個(gè)功能代碼返回給等同于與原始功能代碼的請(qǐng)求主設(shè)備,除了設(shè)置了最高有效位。 這等同于為原始功能代碼的值加上0x80。 異常響應(yīng)包括一個(gè)異常代碼來代替與給定函數(shù)響應(yīng)相關(guān)的正常數(shù)據(jù)。

在標(biāo)準(zhǔn)內(nèi),四種最常見的異常代碼是01,02,03和04。表7介紹了這些代碼以及每種功能的標(biāo)準(zhǔn)含義。

異常代碼 含義
01 不支持接收到功能代碼。 要確認(rèn)原始功能代碼,請(qǐng)從返回值中減去0x80。
02 嘗試訪問的請(qǐng)求是一個(gè)無效地址。 在標(biāo)準(zhǔn)中,只有起始地址和請(qǐng)求的數(shù)值超過216時(shí)才會(huì)發(fā)生這種情況。 但是,有些設(shè)備可能會(huì)限制其數(shù)據(jù)模型中的地址空間。
03 請(qǐng)求包含不正確的數(shù)據(jù)。 在某些情況下,這意味著參數(shù)不匹配,例如發(fā)送的寄存器的數(shù)量與“字節(jié)數(shù)”字段之間的參數(shù)不匹配。 更常見的情況是,主機(jī)請(qǐng)求的數(shù)據(jù)比從機(jī)或協(xié)議允許的要多。 例如,主設(shè)備一次只能讀取125個(gè)保持寄存器,而資源受限的設(shè)備可能會(huì)將此值限制為更少的寄存器。 例如,主設(shè)備一次只能讀取125個(gè)保持寄存器,而資源受限的設(shè)備可能會(huì)將此值限制為更少的寄存器。
04 嘗試處理請(qǐng)求時(shí)發(fā)生不可恢復(fù)的錯(cuò)誤。 這是一個(gè)異常的代碼,表示請(qǐng)求有效,但從設(shè)備無法執(zhí)行該請(qǐng)求。

表7.常見的Modbus異常代碼

 

每個(gè)功能代碼的狀態(tài)圖至少應(yīng)包含異常代碼01,通常包含異常代碼04,02,03,并且任何其他定義的異常代碼都是可選的。

返回頂部

應(yīng)用數(shù)據(jù)單元(ADU)

除了Modbus協(xié)議的PDU核心定義的功能外,您還可以使用多種網(wǎng)絡(luò)協(xié)議。 最常見的協(xié)議是串行和TCP/IP,但也可以使用其他協(xié)議,如UDP。 為了在這些層之間傳輸Modbus所需的數(shù)據(jù),Modbus包含一組適用于每種網(wǎng)絡(luò)協(xié)議的ADU。

通用特征

Modbus需要某些功能來提供可靠的通信。 單元ID或地址用在每個(gè)ADU格式中,為應(yīng)用層提供路由信息。 每個(gè)ADU都帶有一個(gè)完整的PDU,其中包含給定請(qǐng)求的功能代碼和相關(guān)數(shù)據(jù)。 為了可靠性,每條消息都包含錯(cuò)誤檢查信息。 最后,所有的ADU都提供了一種機(jī)制來確定請(qǐng)求幀的開始和結(jié)束,但實(shí)現(xiàn)這些機(jī)制的方式各不相同。

標(biāo)準(zhǔn)格式

ADU的三種標(biāo)準(zhǔn)格式是TCP、遠(yuǎn)程終端單元(RTU)和ASCII。 RTU和ASCII ADU通常用于串行線路,而TCP則用于現(xiàn)代TCP/IP或UDP/IP網(wǎng)絡(luò)。

TCP/IP

TCP ADU由Modbus應(yīng)用協(xié)議(MBAP)報(bào)文頭和Modbus PDU組成。 MBAP是一個(gè)通用的報(bào)文頭,依賴于可靠的網(wǎng)絡(luò)層。 此ADU的格式(包括報(bào)文頭)如圖6所示。

blob.png
圖6.TCP/IP ADU

報(bào)文頭的數(shù)據(jù)字段代表其用途。 首先,它包含一個(gè)事務(wù)處理標(biāo)識(shí)符。 這有助于網(wǎng)絡(luò)允許同時(shí)發(fā)生多個(gè)未處理的請(qǐng)求。 也就是說,主設(shè)備可以發(fā)送請(qǐng)求1、2和3。在稍后的時(shí)間點(diǎn),從設(shè)備可以以2、1、3的順序進(jìn)行響應(yīng),并且主設(shè)備可以將請(qǐng)求匹配到響應(yīng)并準(zhǔn)確解析數(shù)據(jù)。 這對(duì)以太網(wǎng)網(wǎng)絡(luò)很有用。

協(xié)議標(biāo)識(shí)符通常為零,但您可以使用它來擴(kuò)展協(xié)議的行為。 協(xié)議使用長(zhǎng)度字段來描述數(shù)據(jù)包其余部分的長(zhǎng)度。 這個(gè)元素的位置也表明了這個(gè)報(bào)文頭格式在可靠的網(wǎng)絡(luò)層上的依賴關(guān)系。 由于TCP數(shù)據(jù)包具有內(nèi)置的錯(cuò)誤檢查功能,可確保數(shù)據(jù)一致性和傳送,因此數(shù)據(jù)包長(zhǎng)度可位于報(bào)文頭的任何位置。 在可靠性較差的網(wǎng)絡(luò)上(比如串行網(wǎng)絡(luò)),數(shù)據(jù)包可能會(huì)丟失,其影響是即使應(yīng)用程序讀取的數(shù)據(jù)流包含有效的事務(wù)處理和協(xié)議信息,長(zhǎng)度信息的損壞也會(huì)使報(bào)文頭無效。 TCP為這種情況提供了適當(dāng)?shù)谋Wo(hù)。

TCP/IP設(shè)備通常不適用單元ID。 但是,Modbus是一種常見的協(xié)議,因此通常會(huì)開發(fā)一些網(wǎng)關(guān)來將Modbus協(xié)議轉(zhuǎn)換為另一種協(xié)議。 在最初的預(yù)期應(yīng)用中, Modbus TCP/IP轉(zhuǎn)串行網(wǎng)關(guān)用于連接新的TCP/IP網(wǎng)絡(luò)和舊的串行網(wǎng)絡(luò)。 這時(shí),單元ID用于確定PDU對(duì)應(yīng)的從設(shè)備的地址。

最后,ADU包含一個(gè)PDU。 對(duì)于標(biāo)準(zhǔn)協(xié)議,PDU的長(zhǎng)度仍限制為253字節(jié)。

RTU

RTU ADU看起來要簡(jiǎn)單得多,如圖7所示。

blob.png
圖7. RTU ADU

與較為復(fù)雜的TCP/IP ADU不同的是,除了核心PDU之外,該ADU僅包含兩條信息。 首先,地址用于定義PDU對(duì)應(yīng)的從設(shè)備。 在大多數(shù)網(wǎng)絡(luò)中,地址0定義的是“廣播”地址。 也就是說,主設(shè)備可以發(fā)送輸出命令到地址0,而所有從設(shè)備應(yīng)處理該請(qǐng)求,但是不做出任何響應(yīng)。 除了這個(gè)地址外,CRC還用于確保數(shù)據(jù)的完整性。

然而,現(xiàn)在的實(shí)現(xiàn)機(jī)制遠(yuǎn)沒有那么簡(jiǎn)單。 數(shù)據(jù)包的首尾一對(duì)沉默時(shí)間(silent time),即總線上沒有通信的時(shí)段。對(duì)于9,600的波特率,這個(gè)速率大約是4ms。該標(biāo)準(zhǔn)定義了一個(gè)最小沉默長(zhǎng)度,不論波特率如何,都低于2 ms。

 

首先,這存在性能缺陷,因?yàn)樵谔幚頂?shù)據(jù)包之前設(shè)備必須等待空閑時(shí)間結(jié)束。 然而,更危險(xiǎn)的是串行傳輸引入了不同技術(shù),并且波特率比標(biāo)準(zhǔn)更快。 例如,使用USB/串口轉(zhuǎn)換器電纜,您無法控制數(shù)據(jù)的數(shù)據(jù)包和數(shù)據(jù)傳輸。 測(cè)試表明,結(jié)合NI-VISA驅(qū)動(dòng)程序使用USB轉(zhuǎn)串口電纜會(huì)在數(shù)據(jù)流中引入了尺寸可變的大間隙,而這些間隙 – 沉默期 – 會(huì)“誘騙”符合規(guī)范的代碼相信消息是完整的。 由于消息不完整,通常會(huì)導(dǎo)致CRC無效,并導(dǎo)致設(shè)備將ADU解釋為損壞。

除了傳輸問題之外,現(xiàn)代驅(qū)動(dòng)程序技術(shù)還大量提取串行通信,并且通常需要應(yīng)用程序代碼中的輪詢機(jī)制。 例如,除非通過輪詢端口上的字節(jié),.NET Framework 4.5 SerialPort Class和NI-VISA驅(qū)動(dòng)程序都不提供檢測(cè)串行線路上的沉默的機(jī)制。 這會(huì)導(dǎo)致性能降低(如果輪詢執(zhí)行過慢)或CPU使用率過高(如果輪詢執(zhí)行過快)。

解決這些問題的常用方法是打破Modbus PDU和網(wǎng)絡(luò)層之間的抽象層。 也就是說,串行代碼詢問Modbus PDU數(shù)據(jù)包以確定功能代碼。 結(jié)合數(shù)據(jù)包中的其他數(shù)據(jù),可以發(fā)現(xiàn)剩余數(shù)據(jù)包的長(zhǎng)度,從而確定數(shù)據(jù)包的結(jié)尾。 利用這些信息,可以使用更長(zhǎng)的超時(shí)時(shí)間,以允許傳輸間隙,并且應(yīng)用程序級(jí)的輪詢速度可能更慢。 這種機(jī)制推薦用于新的開發(fā)。 不采用此方法可能會(huì)遇到大于預(yù)期數(shù)量的“損壞”數(shù)據(jù)包。

ASCII

如圖8所示,ASCII ADU比RTU更復(fù)雜,但也避免了RTU數(shù)據(jù)包的許多問題。 然而,它自身也有一些缺點(diǎn)。

blob.png
圖 8. ASCII ADU

為了解決確定數(shù)據(jù)包大小的問題,ASCII ADU為每個(gè)數(shù)據(jù)包定義了一個(gè)明確且唯一的開始和結(jié)束。 也就是說,每個(gè)數(shù)據(jù)包以“:”開始 并以回車(CR)和換行符(LF)結(jié)束。 另外,像NI-VISA和.NET Framework SerialPort Class這樣的串行API可以輕松讀取緩沖區(qū)中的數(shù)據(jù),直到收到特定字符的CR/LF為止。 這些特性有助于在現(xiàn)代應(yīng)用程序代碼中有效地處理串行線路上的數(shù)據(jù)流。

ASCII ADU的缺點(diǎn)是所有數(shù)據(jù)都以ASCII編碼的十六進(jìn)制字符進(jìn)行傳輸。 也就是說,針對(duì)功能代碼3(0x03)發(fā)送的不是單個(gè)字節(jié),而是發(fā)送ASCII字符“0”和“3”或0x30/0x33。 這使協(xié)議更具可讀性,但也意味著必須通過串行網(wǎng)絡(luò)傳輸兩倍的數(shù)據(jù),并且發(fā)送和接收應(yīng)用程序必須能夠解析ASCII值。

擴(kuò)展Modbus

Modbus是一種相對(duì)簡(jiǎn)單和開放的標(biāo)準(zhǔn),可以進(jìn)行修改以適應(yīng)給定應(yīng)用的需求。 這常用于HMI和PLC或PAC之間的通信,因?yàn)樵谶@種情況下組織可以控制協(xié)議的首尾。 例如,傳感器的開發(fā)人員更可能遵守書面標(biāo)準(zhǔn),因?yàn)樗麄兺ǔV豢刂破鋸脑O(shè)備的實(shí)現(xiàn),互通性也是可能實(shí)現(xiàn)的。

一般來說,不建議修改協(xié)議。 本節(jié)僅作為對(duì)其他人用來調(diào)整協(xié)議行為的機(jī)制的確認(rèn)。

返回頂部

新功能代碼

Modbus標(biāo)準(zhǔn)定義了一些功能代碼,但也可允許您開發(fā)更多的功能代碼。 具體而言,功能代碼1至64,73至99以及111至127是預(yù)留的并保證唯一的公共代碼。 其余代碼65至72和100至110可由用戶自定義。 使用這些用戶定義的代碼時(shí),您可以使用任何數(shù)據(jù)結(jié)構(gòu)。 數(shù)據(jù)甚至可能超過Modbus PDU的標(biāo)準(zhǔn)253字節(jié)限制,但應(yīng)驗(yàn)證整個(gè)應(yīng)用程序以確保其他層在PDU超過標(biāo)準(zhǔn)限制時(shí)按預(yù)期工作。 高于127的功能代碼預(yù)留作異常響應(yīng)。

返回頂部

網(wǎng)絡(luò)層

除了串行和TCP之外,Modbus還可以在許多網(wǎng)絡(luò)層上運(yùn)行。 一個(gè)可能的實(shí)現(xiàn)是UDP,因?yàn)樗m合于Modbus通信風(fēng)格。 Modbus本質(zhì)上是基于消息的協(xié)議,因此UDP能夠發(fā)送明確定義的信息包,而不需要任何額外的應(yīng)用程序級(jí)信息,如起始字符或長(zhǎng)度,這使得Modbus非常易于實(shí)現(xiàn)。 Modbus PDU數(shù)據(jù)包可以使用標(biāo)準(zhǔn)的UDP API發(fā)送,不需要額外的ADU或重新使用現(xiàn)有的ADU,并由另一端完全接收。 雖然由于其內(nèi)置確認(rèn)系統(tǒng),TCP對(duì)某些協(xié)議有利,但Modbus是在應(yīng)用層執(zhí)行確認(rèn)。 因此,以這種方式使用UDP會(huì)消除TCP ADU中的事務(wù)處理標(biāo)識(shí)符字段,從而消除了存在多個(gè)同時(shí)發(fā)生的未完成事務(wù)的可能性。 因此,主設(shè)備必須是同步主設(shè)備,或者UDP數(shù)據(jù)包必須有一個(gè)標(biāo)識(shí)符以幫助主設(shè)備組織請(qǐng)求和響應(yīng)。 建議的做法是在UDP網(wǎng)絡(luò)層上使用TCP/IP ADU。

返回頂部

ADU修改

最后,應(yīng)用程序可以選擇修改ADU,或使用現(xiàn)有ADU的未使用部分(如TCP)。 例如,TCP定義了一個(gè)16位長(zhǎng)度字段、一個(gè)16位協(xié)議和一個(gè)8位單元ID。鑒于最大的Modbus PDU是253字節(jié),長(zhǎng)度字段的高字節(jié)始終為零。 對(duì)于Modbus/TCP,協(xié)議字段和單元ID始終為零。 協(xié)議的簡(jiǎn)單擴(kuò)展可以通過將協(xié)議字段更改為非零數(shù)字并使用兩個(gè)未使用的字節(jié)(單元ID和長(zhǎng)度字段的高字節(jié))來發(fā)送兩個(gè)附加PDU的長(zhǎng)度,從而同時(shí)發(fā)送三個(gè)數(shù)據(jù)包(請(qǐng)參閱圖9)。

blob.png
圖9. TCP ADU修改示例

其他資源


上一篇:modbus官方網(wǎng)站 - The Modbus Organization

下一篇:Oracle, Odbc and DB2-CLI Template Library Programmer's Guide

在線咨詢

點(diǎn)擊這里給我發(fā)消息 售前咨詢專員

點(diǎn)擊這里給我發(fā)消息 售后服務(wù)專員

在線咨詢

免費(fèi)通話

24小時(shí)免費(fèi)咨詢

請(qǐng)輸入您的聯(lián)系電話,座機(jī)請(qǐng)加區(qū)號(hào)

免費(fèi)通話

微信掃一掃

微信聯(lián)系
返回頂部