0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

第5章_Modbus通訊協(xié)議

嵌入式Linux那些事 ? 來源:嵌入式Linux那些事 ? 作者:嵌入式Linux那些事 ? 2024-06-29 14:35 ? 次閱讀

5.1 學(xué)習(xí)Modbus的快速方法

5.1.1 寄存器速記

作為初學(xué)者,你閱讀Modbus協(xié)議時(shí)會(huì)發(fā)現(xiàn)它的概念別扭、重復(fù)、不易區(qū)分,比如線圈狀態(tài)(Coil Status)、離散輸入狀態(tài)(Discrete Input Status)、保持寄存器(Holding Register)、輸入寄存器(Input Register)。

回到事情的本質(zhì),在工業(yè)控制PLC領(lǐng)域,涉及數(shù)字信號(hào)的輸入、輸出,模擬信號(hào)的輸入、輸出,如下圖所示:

img

對于軟件開發(fā)而言:

  • 想得到按鍵輸入狀態(tài)時(shí),讀取到的是一位數(shù)據(jù);
  • 想控制LED時(shí),需要輸出一位數(shù)據(jù),想讀取LED當(dāng)前狀態(tài)時(shí),也可以讀取到一位數(shù)據(jù)
  • 想讀取模擬信號(hào)時(shí),讀取到的是多位數(shù)據(jù),比如16位數(shù)據(jù)
  • 想輸出模擬信號(hào)時(shí),寫入的是多位數(shù)據(jù),比如16位數(shù)據(jù);也可以讀取“模擬量輸出”的當(dāng)前值。

在上圖中,“數(shù)字量輸入DI”是只讀的,“數(shù)字量輸出DO”是可讀可寫的,“模擬量輸入AI”是只讀的,“模擬量輸出AO”是可讀可寫的。

上圖里的“模擬量輸入AI”、“模擬量輸出AO”都表示“多位數(shù)值”,這些“多位數(shù)值”無需局限于只表示“模擬量”,也可以表示“多位數(shù)字量”。把AI、AO的含義擴(kuò)展后,如下圖所示:

img

對于軟件開發(fā)而言:

  • 想得到按鍵輸入狀態(tài)時(shí),讀取到的是一位數(shù)據(jù);
  • 想控制LED時(shí),需要輸出一位數(shù)據(jù),想讀取LED當(dāng)前狀態(tài)時(shí),也可以讀取到一位數(shù)據(jù)
  • 想讀取參數(shù)時(shí),讀取到的“輸入寄存器”,得到多位數(shù)據(jù),比如16位數(shù)據(jù)
  • 想設(shè)置參數(shù)時(shí),寫的是“保存寄存器”,寫入的是多位數(shù)據(jù),比如16位數(shù)據(jù);也可以讀“保存寄存器”

電子系統(tǒng)里,無論是單bit的數(shù)值、多bit的數(shù)值,都是保存在寄存器里。根據(jù)上圖,這些寄存器可以分為4類:

寄存器種類說明與PLC類比舉例說明
線圈狀態(tài)(Coil Status)輸出端口??稍O(shè)定端口輸出狀態(tài),也可以讀取該位的輸出狀態(tài)??煞譃閮煞N不同的執(zhí)行狀態(tài),列如保持型或邊沿觸發(fā)型DO(數(shù)字量輸出)電磁閥輸出、MOSFEF輸出、LED顯示等
離散輸入狀態(tài)(Discrete Input Status)輸入端口。通過外部設(shè)定改變輸入狀態(tài),可讀但不可以寫DI(數(shù)字量輸入)撥碼開關(guān)、接近開關(guān)等
保持寄存器(Holding Register)輸出參數(shù)或保持參數(shù),控制器運(yùn)行時(shí)被設(shè)定的某些參數(shù),可讀可寫AO(模擬量輸出)模擬量輸出設(shè)定值,PID運(yùn)行參數(shù),變量閥輸出大小,傳感器報(bào)警上限下限
輸入寄存器(Input Register)輸入?yún)?shù)??刂破鬟\(yùn)行時(shí)從外部設(shè)備獲得的參數(shù),但可讀不可寫AI(模擬量輸入)模擬量輸入

在Modbus中,多位操作時(shí)都是16位(2bytes)的,總結(jié)如下:

  • bit操作涉及的寄存器有2類:線圈狀態(tài)(可讀可寫)、離散輸入狀態(tài)(只讀)
  • 16bit操作的寄存器有2類:保存寄存器(可讀可寫)、輸入寄存器(只讀)

一個(gè)設(shè)備里,可能有多個(gè)“線圈狀態(tài)”、多個(gè)“離散輸入狀態(tài)”、多個(gè)“保存寄存器”、多個(gè)“輸入寄存器”。怎么分辨某類寄存器中的某一個(gè)?它們有“寄存器地址”,如下圖所示:

寄存器種類PLC寄存器地址范圍Modbus寄存器地址范圍簡稱讀寫狀態(tài)
線圈狀態(tài)00001~099990000H~FFFFH0x可讀可寫
離散輸入狀態(tài)10001~199990000H~FFFFH1x只讀
保持寄存器40001~499990000H~FFFFH4x可讀可寫
輸入寄存器30001~399990000H~FFFFH3x只讀

在上表中,“線圈狀態(tài)”的寄存器N、“離散輸入狀態(tài)”的寄存器N,是兩個(gè)不同的寄存器。

簡單記憶方法:“

  • 偶數(shù)類的寄存器”是可讀可寫的,比如“0x”和“4x”;
  • “奇數(shù)類的寄存器”是只讀的,比如“1x”和“3x”;
  • “0x”和“1x”是bit寄存器;
  • “3x”和“4x”是16bit寄存器。

5.1.2 協(xié)議速記

Modbus是一主多從的協(xié)議,如下圖所示:

img

主控發(fā)出的數(shù)據(jù)里,必定含有如下信息

  • 設(shè)備地址:你要訪問從設(shè)備1,還是訪問從設(shè)備2
  • 訪問哪類寄存器,是讀還是寫,只訪問1個(gè)寄存器,還是多個(gè)寄存器:這被稱為功能碼
  • 起始寄存器地址、寄存器數(shù)量:這在數(shù)據(jù)里定義
  • 為了保證數(shù)據(jù)傳輸?shù)目煽?,還附帶有CRC檢驗(yàn)碼

以Modbus RTU協(xié)議為例,主控發(fā)出的數(shù)據(jù)包格式如下:

img

功能代碼有哪些?常用的功能碼如下:

  • 讀線圈狀態(tài)(01)
  • 讀離散輸入狀態(tài)(02)
  • 寫單個(gè)線圈(05)、寫多個(gè)線圈(15)
  • 讀保持寄存器(03)
  • 讀輸入寄存器(04)
  • 寫單個(gè)保存寄存器(06)、寫多個(gè)保存寄存器(16)

數(shù)據(jù)的格式,由功能代碼確定。以“讀線圈狀態(tài)”為例,主控發(fā)出的請求、從設(shè)備返回的響應(yīng)包,或者從設(shè)備返回的錯(cuò)誤包,格式如下:

img

上圖中,寄存器起始地址(“Starting Address”)是16位的,先傳輸高字節(jié),再傳輸?shù)妥止?jié)。線圈數(shù)量(“Quantiti of coils”)也是16位的,先傳輸高字節(jié),再傳輸?shù)妥止?jié)。

響應(yīng)包回復(fù)多少個(gè)數(shù)據(jù)呢(上圖中N為多少)?N = Quantiti of coils / 8,如果余數(shù)不等于0,則N再加1。比如Quantiti of coils=9,則返回2個(gè)字節(jié)。

在《Modbus_Application_Protocol_V1_1b3.pdf》中,列出了如下功能表。根據(jù)次表,在結(jié)合《5.5 Moubus功能碼詳解》的示例,就可以對Modbus RTU協(xié)議有很好的理解了。

img

5.2 初識(shí)Modbus

5.2.1 背景

Modbus誕生于1979年莫迪康(Modicon)公司,后來被施耐德電氣公司收購。Modbus提供通用語言用于彼此通信的設(shè)備和設(shè)備,是全球第一個(gè)真正用于工業(yè)現(xiàn)場的總線協(xié)議。Modbus已經(jīng)成為工業(yè)領(lǐng)域通信協(xié)議的業(yè)界標(biāo)準(zhǔn),并且現(xiàn)在是工業(yè)電子設(shè)備之間常用的連接方式。Modbus作為目前工業(yè)領(lǐng)域應(yīng)用最廣泛的協(xié)議,之后為了更好地普及和推動(dòng)Modbus基于以太網(wǎng) (TCP/IP) 的分布式應(yīng)用,施耐德公司已將Modbus協(xié)議的所有權(quán)移交給IDA (Interface for Distributed Automation,分布式自動(dòng)化接口)組織,并成立了Modbus-IDA組織,此組織的成立和發(fā)展進(jìn)一步推動(dòng)了Modbus協(xié)議的廣泛應(yīng)用。

img

5.2.2 什么是Modbus?

1. Modbus簡介

Modbus協(xié)議是一種已廣泛應(yīng)用于當(dāng)今工業(yè)控制領(lǐng)域的通用通訊協(xié)議。通過此協(xié)議,控制器相互之間、或控制器經(jīng)由網(wǎng)絡(luò)(如以太網(wǎng))可以和其它設(shè)備之間進(jìn)行通信。Modbus協(xié)議使用的是主從通訊技術(shù),即由主設(shè)備主動(dòng)查詢和操作從設(shè)備。一般將主控設(shè)備方所使用的協(xié)議稱為Modbus Master,從設(shè)備方使用的協(xié)議稱為Modbus Slave。典型的主設(shè)備包括工控機(jī)和工業(yè)控制器等;典型的從設(shè)備如PLC可編程控制器等。有了它,不同廠商生產(chǎn)的控制設(shè)備就可以連接成工業(yè)網(wǎng)絡(luò),進(jìn)行集中監(jiān)控。Modbus協(xié)議定義了一個(gè)控制器能夠認(rèn)識(shí)和使用的消息結(jié)構(gòu),而不管它們是經(jīng)過何種網(wǎng)絡(luò)進(jìn)行通信的;而且描述了控制器請求訪問其他設(shè)備的過程,如何應(yīng)答來自其他設(shè)備的請求,以及怎樣偵測錯(cuò)誤并記錄,并制定了統(tǒng)一的消息域的結(jié)構(gòu)和內(nèi)容。 當(dāng)在Modbus網(wǎng)絡(luò)上通信時(shí),Modbus協(xié)議決定了每個(gè)控制器必須要知道它們的設(shè)備地址,識(shí)別按地址發(fā)來的消息決定要產(chǎn)生何種行為。如果需要回應(yīng),則控制器將生成反饋信息并通過Modbus協(xié)議發(fā)送。

Modbus通訊物理接口可以選用串口(包括RS232、RS485RS422等),也可以選擇以太網(wǎng)口。其通信遵循以下的過程:

  • 主設(shè)備向從設(shè)備發(fā)送請求
  • 從設(shè)備分析并處理主設(shè)備的請求,然后向主設(shè)備發(fā)送結(jié)果
  • 如果出現(xiàn)任何差錯(cuò),從設(shè)備將返回一個(gè)異常功能碼

此協(xié)議定義了一個(gè)控制器能認(rèn)識(shí)使用的消息結(jié)構(gòu),而不管它們是經(jīng)過何種網(wǎng)絡(luò)進(jìn)行通信的。它描述了一控制器請求訪問其它設(shè)備的過程,如何回應(yīng)來自其它設(shè)備的請求,以及怎樣偵測錯(cuò)誤并記錄。它制定了消息域格局和內(nèi)容的公共格式。

當(dāng)在Modbus網(wǎng)絡(luò)上通信時(shí),此協(xié)議決定了每個(gè)控制器須要知道它們的設(shè)備地址,識(shí)別按地址發(fā)來的消息,決定要產(chǎn)生何種行動(dòng)。如果需要回應(yīng),控制器將生成反饋信息并用Modbus協(xié)議發(fā)出。在其它網(wǎng)絡(luò)上,包含了Modbus協(xié)議的消息轉(zhuǎn)換為在此網(wǎng)絡(luò)上使用的幀或包結(jié)構(gòu)。這種轉(zhuǎn)換也擴(kuò)展了根據(jù)具體的網(wǎng)絡(luò)解決節(jié)地址、路由路徑及錯(cuò)誤檢測的方法。

Modbus的工作方式是請求/應(yīng)答,每次通訊都是主站先發(fā)送指令,可以是廣播,或是向特定從站的單播;從站響應(yīng)指令,并按要求應(yīng)答,或者報(bào)告異常。當(dāng)主站不發(fā)送請求時(shí),從站不會(huì)自己發(fā)出數(shù)據(jù),從站和從站之間不能直接通訊。

MODBUS 是一種應(yīng)用層消息傳遞協(xié)議,位于 OSI 模型的第 7 層。它提供連接在不同類型總線或網(wǎng)絡(luò)上的設(shè)備之間的客戶端/服務(wù)器通信。

Modbus通信棧如下:

img

2. Modbus特點(diǎn)

Modbus通信協(xié)議具有以下幾個(gè)特點(diǎn):

  • Modbus協(xié)議標(biāo)準(zhǔn)開放、公開發(fā)表且無版稅要求。用戶可以免費(fèi)獲取并使用Modbus協(xié)議,不需要交納許可證費(fèi),也不會(huì)侵犯知識(shí)產(chǎn)權(quán)。
  • Modbus協(xié)議支持多種電氣接口,如RS232、RS485、TCP/IP等,還可以在各種介質(zhì)上傳輸,如雙絞線、光纖、紅外、無線。
  • Modbus協(xié)議消息幀格式簡單、緊湊、通俗易懂。用戶理解和使用簡單,廠商容易開發(fā)和集成,方便形成工業(yè)控制網(wǎng)絡(luò)。
  • 可靠性: Modbus 是最古老的工業(yè)自動(dòng)化通信協(xié)議。它使用和編程簡單,因此學(xué)習(xí)曲線較低。
  • 遺留基礎(chǔ)設(shè)施:許多制造商在早期自動(dòng)化方面投入了大量資金。Modbus 對于配置、DLR、節(jié)點(diǎn)、子站和其他基礎(chǔ)設(shè)施非常友好,這些基礎(chǔ)設(shè)施可能會(huì)被新的或更先進(jìn)的協(xié)議所淘汰。
  • 快速部署: Modbus 可以輕松、立即集成到 SCADA和其他控制系統(tǒng)
  • 靈活性: Modbus 已適應(yīng)新興技術(shù)。例如,Modbus TCP 可以通過話配器進(jìn)行轉(zhuǎn)換,以與LAN 和遠(yuǎn)程控制系統(tǒng)集成。它還可以利用基于網(wǎng)絡(luò)和基于云的平臺(tái)。
  • 簡單性:由于通信簡單,因此可以輕松擴(kuò)展到新技術(shù)。例如,Modbus TCP/P 由于指令集簡單,部署速度很快。它還可以與以太網(wǎng)配合使用,無需添加芯片或板。

3. Modbus常用術(shù)語

名詞意義
Master主(站) 設(shè)備
Slave從 (站) 設(shè)備
Client客戶端
Server服務(wù)器端
ADU應(yīng)用數(shù)據(jù)單元(Application Data Unit)
PDU協(xié)議數(shù)據(jù)單元 (Protocol Data Unit)
MSB最高有效位(Most Significant Bit)
LSB最低有效位 (Least Significant Bit)
MBAPModbus應(yīng)用協(xié)議(Modbus Application Protocol)
PLC可編程邏輯控制器(Programmable Logic Controller)

4. Modbus事務(wù)處理

Modbus協(xié)議允許在各種網(wǎng)終體系結(jié)構(gòu)內(nèi)進(jìn)行簡單通信,每種設(shè)備 (包括PLC、HMI、控制面板、驅(qū)動(dòng)程序、動(dòng)作控制、輸入/輸出設(shè)備) 都能使用Modbus協(xié)議啟動(dòng)遠(yuǎn)程操作。在基于串行鏈路和以太網(wǎng) (TCP/IP)的Modbus上可以進(jìn)行相互通信。一些網(wǎng)關(guān)允許在幾種使用MODBUS協(xié)議的總線或網(wǎng)絡(luò)之間進(jìn)行通訊。

MOUBUS網(wǎng)絡(luò)體系結(jié)構(gòu)的實(shí)例:

img

Modbus是一個(gè)請求、應(yīng)答協(xié)議,并且提供統(tǒng)一的功能碼用于數(shù)據(jù)傳輸服務(wù)。Modbus功能碼是Modbus請求/應(yīng)答PDU (Protocol Data Unit,協(xié)議數(shù)據(jù)單元)的元素之一,所謂的PDU其實(shí)就是Modbus協(xié)議定義的一個(gè)與基礎(chǔ)通信層無關(guān)的簡單協(xié)議數(shù)據(jù)單元。特定總線或網(wǎng)絡(luò)上的Modbus協(xié)議映射能夠在ADU (Application Data UInit ,應(yīng)用數(shù)據(jù)單元)上引入一些附加域,從而實(shí)現(xiàn)完整而準(zhǔn)確的數(shù)據(jù)傳輸。

為了尋求一種簡潔的通信格式,Modbus協(xié)議定義了PDU模型,即功能碼+數(shù)據(jù)的格式,而為了適應(yīng)多種傳輸模式,又在PDU的基礎(chǔ)上增加了必要的前綴 (如地址域)和后綴(如差錯(cuò)校驗(yàn)) ,形成了ADU模型(見下圖)。

通用MODBUS幀如下:

img

Modbus事務(wù)處理過程:

  • 主機(jī)設(shè)備 (或客戶端)創(chuàng)建Modbus應(yīng)用數(shù)據(jù)單元形成查詢報(bào)文,其中功能碼標(biāo)識(shí)了向從機(jī)設(shè)備 (或服務(wù)器端)指示將要執(zhí)行的操作。其中功能碼占用1字節(jié),有效的碼字范圍是十進(jìn)制1 ~ 255 (其中128 ~255為異常響應(yīng)保留) 。查詢報(bào)文創(chuàng)建完畢,主機(jī)設(shè)備 (或客戶端) 向從機(jī)設(shè)備 (或服務(wù)器端)發(fā)送報(bào)文,從機(jī)設(shè)備 (或服務(wù)器端)接收報(bào)文后根據(jù)功能碼做出相應(yīng)的動(dòng)作,并將響應(yīng)報(bào)文返回給主機(jī)設(shè)備 (或客戶端),如圖下所示:
    MouBus事務(wù)處理(無異常)

img

  • 如果在一個(gè)正確接收的Modbus ADU中不出現(xiàn)與請求Modbus功能有關(guān)的差錯(cuò),那么從機(jī)設(shè)備 (或服務(wù)器端) 將返回正常的響應(yīng)報(bào)文。如果出現(xiàn)與請求Modbus功能有關(guān)的差錯(cuò),那么響應(yīng)報(bào)文的功能碼域?qū)ㄒ粋€(gè)異常碼,主機(jī)設(shè)備(或客戶端)能夠根據(jù)異常碼確定下一步執(zhí)行的操作;對于異常響應(yīng),服務(wù)器返回一個(gè)與原始功能碼等同的碼,設(shè)置該原始功能碼的最高有效位為邏輯1,用于通知主設(shè)備(客戶端)。如下圖所示:
    MouBus事務(wù)處理(異常響應(yīng))

img

5.3 Modbus軟件與使用

5.3.1 Modbus軟件簡介

為了更好的學(xué)習(xí)和理解Modbus,這里推出三個(gè)軟件Modbus Poll(主站設(shè)備)、Modbus Slave(從站設(shè)備)和虛擬串口軟件,借助三款設(shè)備我們可以在PC上做一些基礎(chǔ)實(shí)驗(yàn),更加直觀地觀察通信數(shù)據(jù),加深我們的理解,我們將它稱為Modbus學(xué)習(xí)必備三件套,這是一個(gè)很好的入門方法。

5.3.2 Modbus Poll(主站設(shè)備)

1. Modbus Poll簡介

Modbus Poll是Modbus主站設(shè)備仿真器,用于測試和調(diào)試Modbus從設(shè)備便于觀察Modbus通信過程中的各種報(bào)文數(shù)據(jù)。該軟件支持ModbusRTU、ASCII、TCP/IP。用來幫助開發(fā)人員測試Modbus從設(shè)備,或者其它Modbus協(xié)議的測試和仿真。它支持多文檔接口,即,可以同時(shí)監(jiān)視多個(gè)從設(shè)備/數(shù)據(jù)域。每個(gè)窗口簡單地設(shè)定從設(shè)備ID,功能,地址,大小和輪詢間隔。你可以從任意一個(gè)窗口讀寫寄存器和線圈。如果你想改變一個(gè)單獨(dú)的寄存器,簡單地雙擊這個(gè)值即可?;蛘吣憧梢愿淖兌鄠€(gè)寄存器/線圈值。提供數(shù)據(jù)的多種格式方式,比如浮點(diǎn)、雙精度、長整型(可以字節(jié)序列交換)。該軟件支持Modbus RTU、ASCII、TCP/IP等協(xié)議模式。

Modbus Poll支持下列協(xié)議模式:

Modbus RTUModbus RTU Over TCP/IP
Modbus ASCIIModbus ASCI Over TCP/IP
Modbus TCP/IPModbus RTU Over UDP/IP
Modbus UDP/IPModbus ASCII Over UDP/IP

2. Modbus Poll 使用

點(diǎn)擊鏈接獲取軟件,按照提示安裝即可;鏈接:

https://pan.baidu.com/s/1SpTRz6Z1XlkoCZjDozwqog 提取碼:timc

下載完界面如下:

img

狀態(tài)欄:

  • Tx = 0表示向主站發(fā)送數(shù)據(jù)幀次數(shù),圖中為0次;
  • Err = 0表示通訊錯(cuò)誤次數(shù),圖中為0次;
  • ID = 1表示模擬的Modbus子設(shè)備的設(shè)備地址,圖中地址為1;
  • F = 03表示所使用的Modbus功能碼,圖中為03功能碼;
  • SR = 1000ms表示發(fā)送周期,1S一次。
  • 紅字部分,表示當(dāng)前的錯(cuò)誤狀態(tài),“No Connection”表示未連接狀態(tài)。

建立連接:

點(diǎn)擊Connection->Connect進(jìn)入配置頁面,選擇我們想要的連接,選擇我們虛擬出來的串口,選擇模式,例如:我們選擇串口的連接方式,選則RTU模式,對應(yīng)我們的Modbus RTU協(xié)議;接下來在設(shè)置波特率、比特位、校驗(yàn)位、停止位,如下圖所示:

img

設(shè)置參數(shù):點(diǎn)擊Setup->Read/Write Definition進(jìn)入配置頁面,配置從機(jī)地址、功能碼、地址類型、寄存器地址、訪問數(shù)量、輪詢時(shí)間,具體配置如下圖:

img

5.3.3 Modbus Slave(從站設(shè)備)

1. Modbus Slave簡介

Modbus從設(shè)備仿真器,可以仿真32個(gè)從設(shè)備/地址域。每個(gè)接口都提供了對EXCEL報(bào)表的OLE自動(dòng)化支持。主要用來模擬Modbus從站設(shè)備,接收主站的命令包,回送數(shù)據(jù)包。幫助Modbus通訊設(shè)備開發(fā)人員進(jìn)行Modbus通訊協(xié)議的模擬和測試,用于模擬、測試、調(diào)試Modbus通訊設(shè)備,便于觀察Modbus通信過程中的各種報(bào)文數(shù)據(jù);可以32個(gè)窗口中模擬多達(dá)32個(gè)Modbus子設(shè)備。與Modbus Poll的用戶界面相同,支持功能01, 02, 03, 04, 05, 06, 15, 16, 22和23,監(jiān)視串口數(shù)據(jù)。

Modbus Slave支持下列協(xié)議模式:

Modbus RTUModbus RTU Over TCP/IP
Modbus ASCIIModbus ASCI Over TCP/IP
Modbus TCP/IPModbus RTU Over UDP/IP
Modbus UDP/IPModbus ASCII Over UDP/IP

2. Modbus Slave使用

獲取軟件鏈接同上,下載完后主頁面如圖所示:

img

建立連接:

點(diǎn)擊Connection->Connect進(jìn)入配置頁面,選擇我們想要的連接,選擇我們虛擬出來的串口,選擇模式,接下來在設(shè)置波特率、比特位、校驗(yàn)位、停止位,如下圖所示:

img

設(shè)置參數(shù):點(diǎn)擊Setup->Read/Write Definition進(jìn)入配置頁面,配置從機(jī)地址、功能碼、地址類型、寄存器地址、訪問數(shù)量,具體配置如下圖:

img

這里有兩點(diǎn)需要我們注意一下:

  • 一是:Function列表框選擇功能中的0x~4x,表示的是存儲(chǔ)區(qū)0區(qū)、1區(qū)、3區(qū)、4區(qū)
    • 輸出線圈
    • 輸入線圈
    • 保持寄存器
    • 輸入寄存器

img

Modbus協(xié)議規(guī)定了4個(gè)存儲(chǔ)區(qū) 分別是0、1、3、4區(qū) 其中0區(qū)和4區(qū)是可讀可寫,1區(qū)和3區(qū)是只讀。

區(qū)號(hào)名稱讀寫地址范圍
0區(qū)輸出線圈可讀可寫布爾量00001-09999
1區(qū)輸入線圈只讀布爾量10001-19999
3區(qū)輸入寄存器只讀寄存器30001-39999
4區(qū)保持寄存器可讀可寫寄存器40001-49999
  • 二是:Address項(xiàng),這里需要特別強(qiáng)調(diào)一下,Address表示Modbus寄存器地址,其取值范圍與設(shè)備寄存器地址存在映射關(guān)系,如下表所示:
Device addressModbus addressDescriptionFunctionR/W
1…10000address - 1Coils(outputs)01Read/Write
10001…20000address - 10001Discrete Inputs02Read
40001…50000address - 40001Holding Registers03Read/Write
30001…40000address - 30001Input Registers04Read

這里我們只簡單介紹下地址和存儲(chǔ)區(qū),下面我們會(huì)詳細(xì)展開。

5.3.4 虛擬串口軟件

1.軟件簡介

虛擬串口工具,可以創(chuàng)建2個(gè)互聯(lián)的串口,如下圖所示:

img

比如Modbus Poll工具使用COM1發(fā)送數(shù)據(jù)給COM2,Modbus Slave從COM2讀到數(shù)據(jù)。使用虛擬串口,就可以不使用開發(fā)板也可以體驗(yàn)Modbus Poll、Modbus Slave。

軟件在網(wǎng)盤里:

img

2.虛擬串口的使用

安裝后運(yùn)行虛擬串口程序“Virtual Serial Port Tools”,安裝下圖創(chuàng)建2個(gè)串口:

img

打開設(shè)備管理器,可以看到如下串口:

img

5.3.5 Modbus Poll 與 Modbus Slave互聯(lián)/通

下面我們進(jìn)行Modbus Poll 與 Modbus Slave互聯(lián)互通實(shí)驗(yàn),通過形象直觀的方式展示Modbus數(shù)據(jù)流,根據(jù)前面的設(shè)定我們已將知道了如何運(yùn)用Modbus學(xué)習(xí)必備三件套,下面我們就通過三件套來進(jìn)行實(shí)驗(yàn),首先打開VSPD虛擬串口軟件,設(shè)置虛擬串口,我這里就以上面設(shè)訂COM1,COM2為例,接下來我們再來配置我們的Modbus Poll 與 Modbus Slave;

我們首先打開Modbus Slave端,設(shè)置連接,連接方式我們選擇Serial Port串口連接,選擇我們設(shè)置的串口COM1,模式選擇RTU模式,如下圖所示:

  • Modbus Slave連接設(shè)定

img

在設(shè)置參數(shù),從機(jī)地址我們設(shè)定1(你也可以自己隨意設(shè)定),F(xiàn)unction項(xiàng)我們選擇03 Holding Register(4x),地址類型我們選擇DEC(十進(jìn)制格式),Address首地址我們設(shè)置為0,訪問寄存器數(shù)量設(shè)置為10,如下圖所示:

  • Modbus Slave參數(shù)設(shè)定

img

接下來我們再來設(shè)置Modbus Poll端,設(shè)置方法也是和Modbus Slave端一一對應(yīng)的,連接設(shè)定,參數(shù)設(shè)定,如下圖所示:

  • Modbus Poll連接設(shè)定

img

注意這里串口要選擇我們設(shè)定的COM20,其它串口參數(shù)必須一一對應(yīng)。

  • Modbus Poll參數(shù)設(shè)定

img

設(shè)置好后,我們主設(shè)備和從設(shè)備分別連接了我們設(shè)置的COM1,COM2,這樣我們便可觀察當(dāng)前寄存器的讀取情況。

我們雙擊Modbus Poll(主設(shè)備端)地址中的0值,便可打開值設(shè)置窗口如下圖所示:

img

修改值為66,點(diǎn)擊Send打開Modbus Slave(從設(shè)備端)便可發(fā)現(xiàn)也做出了改變,如下圖所示:

img

我們還可以打開Modbus Poll,點(diǎn)擊Display,選擇Commuaction,查看發(fā)送的報(bào)文:

img

TX是我們主站發(fā)送的報(bào)文,RX是從站返回的報(bào)文,報(bào)文我們下面會(huì)展開說明,帶領(lǐng)大家一起看報(bào)文;

5.4 Modbus協(xié)議細(xì)節(jié)

5.4.1 Modbus協(xié)議概述

簡而言之,Modbus 協(xié)議是一種單主/多從的通信協(xié)議,其特點(diǎn)是在同一時(shí)間總線上只能有一個(gè)主設(shè)備,但可以有一個(gè)或者多個(gè)(最多 247 個(gè))從設(shè)備。Modbus通信總是由主設(shè)備發(fā)起,當(dāng)從設(shè)備沒有收到來自主設(shè)備的請求時(shí),從設(shè)備不會(huì)主動(dòng)發(fā)送數(shù)據(jù)。從設(shè)備之間不能相互通信,主設(shè)備只能同時(shí)啟動(dòng)一個(gè) Modbus 訪回事務(wù)處理。 主設(shè)備可以采用兩種方式向從設(shè)備發(fā)送 Modbus 請求報(bào)文,即主設(shè)備可以對指定的單個(gè)從設(shè)備或者線路上所有的從設(shè)備發(fā)送請求報(bào)文,而從設(shè)備只能在被被動(dòng)接收請求報(bào)文后給出響應(yīng)報(bào)文,即應(yīng)答。這兩種模式分別如下圖所示:

Modbus請求應(yīng)答周期

img

單播模式。主設(shè)備僅僅尋址單個(gè)從設(shè)備,從設(shè)備接收并處理請求后,向主設(shè)備返回一個(gè)響應(yīng)報(bào)文,即應(yīng)答。在這種模式下,一個(gè) Modbus 事務(wù)處理包含兩個(gè)報(bào)文:一個(gè)是主設(shè)備的請求報(bào)文,另一個(gè)是從設(shè)備的響應(yīng)報(bào)文。

每個(gè)從設(shè)備必須有唯一的地址(地址范圍為 1~247),這樣才能區(qū)別于其它從設(shè)備,從而可以獨(dú)立被尋址,同時(shí)主設(shè)備不占用地址。

img

廣播模式。此種模式下,主設(shè)備可以向所有從設(shè)備發(fā)送請求指令,而從設(shè)備在接收到廣播指令后僅進(jìn)行相關(guān)指令的事務(wù)處理,而不要求返回應(yīng)答。因此廣播模式下,請求指令必須是 Modbus 標(biāo)準(zhǔn)功能中的寫指令。

根據(jù) Modbus 標(biāo)準(zhǔn)協(xié)議的要求,所有從設(shè)備必須接收廣播模式下的寫指令,且地址0被保留,用來識(shí)別廣播通信

img

  • 請求:
    主設(shè)備發(fā)送的請求報(bào)文主要包括從設(shè)備地址(或廣播地址0)、功能碼、傳輸?shù)臄?shù)據(jù)以及差錯(cuò)檢測字段。
    查詢消息中的功能碼告訴我們被選中的從設(shè)備地址要執(zhí)行何種功能。數(shù)據(jù)段包含從設(shè)備要執(zhí)行功能的所有附加信息。例如,功能代碼 03 要求從設(shè)備讀取保持寄存器并返回其內(nèi)容。

數(shù)據(jù)段必須包含要告訴從設(shè)備的信息:從哪個(gè)寄存器開始讀取及要讀取的寄存器數(shù)量。差錯(cuò)檢測域?yàn)閺脑O(shè)備提供一種驗(yàn)證消息內(nèi)容是否正確的方法。

  • 應(yīng)答:
    從設(shè)備的應(yīng)答報(bào)文包括地址、功能碼、差錯(cuò)檢測域等; 如果從設(shè)備產(chǎn)生了一個(gè)正常的回應(yīng),則回應(yīng)消息中的功能碼是查詢消息中的功能碼的回應(yīng)。數(shù)據(jù)段包括從設(shè)備收集的數(shù)據(jù),如寄存器值或狀態(tài)。如果有錯(cuò)誤發(fā)生,則功能碼將被修改以用于指出回應(yīng)消息是錯(cuò)誤的,同時(shí)數(shù)據(jù)段包含描述此錯(cuò)誤信息的代碼。差錯(cuò)檢測域允許主設(shè)備確認(rèn)消息內(nèi)容是否可用。

對于串行鏈路來說,又存在兩種傳輸模式:ASCII(American StandardCode for Information Interchange,美國標(biāo)準(zhǔn)信息交換碼)模式和 RTU(RemoteTerminal Unit,遠(yuǎn)程終端單元)模式。但是,對于同一網(wǎng)絡(luò)或鏈路來說,所有設(shè)備必須保持統(tǒng)一,要么統(tǒng)一為 ASCII 模式,要么統(tǒng)一為 RTU 模式,不可共存。相對來說,RTU模式的傳輸效率更高,因此在當(dāng)前普遍的生產(chǎn)環(huán)境中,RTU 模式獲得了廣泛應(yīng)用,而 ASCII模式只能作為特殊情況下的可選項(xiàng)。

5.4.2 Modbus寄存器(存儲(chǔ)區(qū))

Modbus 協(xié)議中的一個(gè)重要概念是寄存器,所有數(shù)據(jù)均存放于寄存器。最初,Modbus 協(xié)議借鑒了 PLC 中寄存器的含義,但是隨著 Modbus 協(xié)議的廣泛應(yīng)用,寄存器的概念進(jìn)一步泛化,它不再是指具體的物理寄存器,也可能是指一塊內(nèi)存區(qū)域Modbus 寄存器根據(jù)存放的數(shù)據(jù)類型以及各自的讀寫特性將寄存器分為四部分,這四部分既可以連續(xù),也可以不連續(xù),由開發(fā)者決定。寄存器意義如下表所示:

Modbus寄存器(存儲(chǔ)區(qū))

寄存器種類說明與PLC類比舉例說明
線圈狀態(tài)(Coil Status)輸出端口??稍O(shè)定端口輸出狀態(tài),也可以讀取該位的輸出狀態(tài)??煞譃閮煞N不同的執(zhí)行狀態(tài),列如保持型或邊沿觸發(fā)型DO(數(shù)字量輸出)電磁閥輸出、MOSFEF輸出、LED顯示等
離散輸入狀態(tài)(Input Status)輸入端口。通過外部設(shè)定改變輸入狀態(tài),可讀但不可以寫DI(數(shù)字量輸入)撥碼開關(guān)、接近開關(guān)等
保持寄存器(Holding Register)輸出參數(shù)或保持參數(shù),控制器運(yùn)行時(shí)被設(shè)定的某些參數(shù),可讀可寫AO(模擬量輸出)模擬量輸出設(shè)定值,PID運(yùn)行參數(shù),變量閥輸出大小,傳感器報(bào)警上限下限
輸入寄存器輸入?yún)?shù)??刂破鬟\(yùn)行時(shí)從外部設(shè)備獲得的參數(shù),但可讀不可寫AI(模擬量輸入)模擬量輸入

(PLC)數(shù)據(jù)的傳輸離不開存儲(chǔ)和讀寫操作,為了更好存儲(chǔ)不同的數(shù)據(jù)類型,我們可以理解Modbus 會(huì)將布爾和非布爾的數(shù)據(jù)分開存儲(chǔ)。

1. 存儲(chǔ)區(qū)類型

我們可以將存儲(chǔ)區(qū)類型分為布爾類型和非布爾類型,布爾類型我們用線圈(Coil)表示,非布爾用寄存器(Register)表示;

  • 什么是布爾?
    • 布爾類型只有兩個(gè)值,false 和 true。
    • 通常用來判斷條件是否成立。
    • C語言語法規(guī)定,如果變量值為 0 就是 false,否則為 true,布爾變量只有這兩個(gè)值。

因此,我們便有了線圈和寄存器的概念;

  • 那線圈和寄存器又是什么?
  • 線圈: 從電氣角度來看,在電氣控制回路中,一般都是靠接觸器或中間繼電器來實(shí)現(xiàn)控制,接觸器或中繼最終靠的是線圈的得電和失電來控制觸點(diǎn)閉合和斷開,因此用線圈表示布爾量;
    • 寄存器: 用來暫時(shí)存放參與運(yùn)算的數(shù)據(jù)和運(yùn)算結(jié)果,具有接收數(shù)據(jù)、存放數(shù)據(jù)和輸出數(shù)據(jù)的功能。
    • 而寄存器在計(jì)算機(jī)中,就是用來存儲(chǔ)數(shù)據(jù)的,因此非布爾的數(shù)據(jù)放在寄存器里。

回到存儲(chǔ)區(qū)分類,目的就是: 更好地存儲(chǔ)和區(qū)分不同的數(shù)據(jù)類型。

Modbus的線圈和寄存器應(yīng)該也按照只讀、讀寫來進(jìn)一步劃分,因此這就形成了Modbus的存儲(chǔ)區(qū),如下表所示:

  • Modbus存儲(chǔ)區(qū)類型及名稱
序號(hào)讀寫存儲(chǔ)類型存儲(chǔ)區(qū)名稱
1只讀線圈輸入線圈
2讀寫線圈輸出線圈
3只讀寄存器輸入寄存器
4讀寫寄存器保持寄存器
  • 存儲(chǔ)區(qū)代號(hào):

為什么需要存儲(chǔ)區(qū)代號(hào)?上面表格里的存儲(chǔ)區(qū)名稱是一個(gè)全稱,開發(fā)和使用中使用全稱會(huì)比較麻煩,因此需要給他們?nèi)€(gè)別名。所以Modbus也要給這些存儲(chǔ)區(qū)取一個(gè)代號(hào),干脆直接用數(shù)字吧,于是,就有了下面的規(guī)定:

存儲(chǔ)區(qū)名稱存儲(chǔ)區(qū)代號(hào)
輸入線圈1區(qū)
輸出線圈0區(qū)
輸入寄存器3區(qū)
保持寄存器4區(qū)

存儲(chǔ)區(qū)代號(hào)其實(shí)可以簡單理解為我們的名字,例如我們的名字有全名,和小名,全名呢是正式場合,外人叫的,小名呢是我們的親近的人,日常場合叫的。這么一說是不是就理解為什么有存儲(chǔ)區(qū)代號(hào)啦。

  • 存儲(chǔ)區(qū)范圍:
    • 無論是什么存儲(chǔ)區(qū),都會(huì)有一個(gè)范圍的限制;Modbus的每個(gè)存儲(chǔ)區(qū)也規(guī)定了一個(gè)范圍,不能無限制使用。
    • Modbus規(guī)定每個(gè)存儲(chǔ)區(qū)的最大范圍是65536,也就是0~65535。

2. 協(xié)議地址模型

PLC地址是我們常見的,但它是怎么組成的的,它是由存儲(chǔ)區(qū)代號(hào) + 地址組成,我們把這樣的地址稱為絕對地址,把后面的地址成為相對地址;而我們的Modbus地址跟PLC地址也是類似的;

Modbus地址公式:存儲(chǔ)區(qū)代號(hào) + (地址 + 1)如下表所示:

  • Modbus長地址模型
存儲(chǔ)區(qū)名稱存儲(chǔ)區(qū)代號(hào)絕對地址范圍相對地址范圍
輸入線圈1區(qū)100001~1655360~65535
輸出線圈0區(qū)000001~0655360~65535
輸入寄存器3區(qū)300001~3655360~65535
保持寄存器4區(qū)400001~4655360~65535

Modbus地址分為長地址模型和短地址模型,上面Modbus長地址模型,但是在實(shí)際使用中,我們一般用不了這么多地址,一般情況下,10000以內(nèi)就已經(jīng)足夠使用了;因此,為了方便我們便有了另一種短的地址模型,如下圖所示:

  • Modbus短地址模型
存儲(chǔ)區(qū)名稱存儲(chǔ)區(qū)代號(hào)絕對地址范圍相對地址范圍
輸入線圈1區(qū)10001~199990~9998
輸出線圈0區(qū)00001~099990~9998
輸入寄存器3區(qū)30001~399990~9998
保持寄存器4區(qū)40001~499990~9998

5.4.3 Modbus常用功能碼

Modbus功能碼占用1字節(jié),取值范圍是1127。之所以127以上不能用,是因?yàn)镸odbus規(guī)定當(dāng)出現(xiàn)異常時(shí),功能碼+0x80(十進(jìn)制128)代表異常狀態(tài),因此129(1+128)255(127+128)的取值代表異常碼。

  • Modbus常用功能碼
功能碼描述寄存器PLC地址位/字操作操作數(shù)量
01H讀線圈寄存器(讀輸出線圈)00001~09999位操作單個(gè)或多個(gè)
02H讀離散輸入寄存器(讀輸入線圈)10001~19999位操作單個(gè)或多個(gè)
03H讀保持寄存器40001~49999字操作單個(gè)或多個(gè)
04H讀輸入寄存器30001~39999字操作單個(gè)或多個(gè)
05H寫單個(gè)線圈寄存器00001~09999位操作單個(gè)
06H寫單個(gè)保持寄存器40001~49999字操作單個(gè)
0FH(15)寫多個(gè)線圈寄存器00001~09999位操作多個(gè)
10H(16)寫多個(gè)保持寄存器40001~49999字操作多個(gè)

功能碼可以分為位操作和字操作兩類。位操作的最小為1位(bit),字操作的最小單位為2字節(jié)。

① 位操作指令:讀取線圈狀態(tài)的功能碼 01 ,讀(離散)輸入狀態(tài)功能碼 02 ,寫單個(gè)線圈功能碼 05 和寫多個(gè)線圈功能碼 15。
② 字操作指令:讀保持寄存器功能碼 03 ,讀輸入寄存器功能碼 04 ,寫單個(gè)保持寄存器功能碼 06 ,寫多個(gè)保持寄存器功能碼 16 。

5.4.4 Modbus協(xié)議類型

Modbus可以在各種介質(zhì)上傳輸,那么他的傳輸模式也分為三種。包括ASCII、RTU(遠(yuǎn)程終端控制系統(tǒng))、TCP三種報(bào)文類型

  • 常用Modbus協(xié)議
Modbus協(xié)議Modbus協(xié)議
Modbus RTUModbus RTU Over TCP/IP
Modbus ASCIIModbus ASCI Over TCP/IP
Modbus TCP/IPModbus RTU Over UDP/IP
Modbus UDP/IPModbus ASCII Over UDP/IP

Modbus協(xié)議使用串口傳輸時(shí)可以選擇RTU或ASCII模式,并規(guī)定了消息、數(shù)據(jù)結(jié)構(gòu)、命令和應(yīng)答方式并需要對數(shù)據(jù)進(jìn)行校驗(yàn)。ASCII 模式采用LRC校驗(yàn),RTU模式采用16 位CRC校驗(yàn)。通過以太網(wǎng)傳輸時(shí)使用TCP,這種模式不使用校驗(yàn),因?yàn)門CP協(xié)議是一個(gè)面向連接的可靠協(xié)議。

5.4.5 Modbus報(bào)文幀

一個(gè)報(bào)文就是一幀數(shù)據(jù),一個(gè)數(shù)據(jù)幀就一個(gè)報(bào)文: 指的是一串完整的指令數(shù)據(jù),本質(zhì)就是一串?dāng)?shù)據(jù)。

Modbus報(bào)文是指主機(jī)發(fā)送給從機(jī)的一幀數(shù)據(jù),其中包含著從機(jī)的地址,主機(jī)想執(zhí)行的操作,校驗(yàn)碼等內(nèi)容

1. Modbus ASCII 模式

**當(dāng)控制器設(shè)為在Modbus網(wǎng)絡(luò)上以ASCII模式通信時(shí),在消息中每個(gè)8位(b)字節(jié)都將作為兩個(gè) ASCII字符發(fā)送。這種方式的主要優(yōu)點(diǎn)是字符發(fā)送的時(shí)間可隔可達(dá)到 1秒且不產(chǎn)生錯(cuò)誤。 **

**在ASCII模式下,消息以冒號(hào)(:)字符(ASCII碼為 0x3A)開始,以回車換行奇結(jié)束(ASCII碼為 0x0D、0x0A)。消息的其他字段(域)可以使用的傳輸字符是十六進(jìn)制的0···9、A···F。處于網(wǎng)絡(luò)上的 Modbus 設(shè)備不斷偵測“:”字符,當(dāng)接收到一個(gè)冒號(hào)時(shí),每個(gè)設(shè)備進(jìn)入解碼階段,并解碼下一個(gè)字段(地址域)以判斷是否是發(fā)給自己的。消息幀中的字符間發(fā)送的時(shí)間間隔最長不能超過 1秒,否則接收設(shè)備將認(rèn)為發(fā)生傳輸錯(cuò)誤。 **

下表是一個(gè)典型的ASCII報(bào)文格式:

開始字符地址功能碼數(shù)據(jù)LRC校驗(yàn)結(jié)束字符
1byte (:)2byte2byteNbyte2byteCR、LF

2. Modbus RTU 模式

Modbus協(xié)議RTU報(bào)文格式如下所示:

從機(jī)地址功能碼數(shù)據(jù)CRC校驗(yàn)
1byte1byteNbyte2byte
  • **幀結(jié)構(gòu) = 從機(jī)地址 + 功能碼 + 數(shù)據(jù) + 校驗(yàn) **
    • 從機(jī)地址: 每個(gè)從機(jī)都有唯一地址,占用一個(gè)字節(jié),范圍0-255,其中有效范圍是1-247,其中255是廣播地址(廣播就是對所有從機(jī)發(fā)送應(yīng)答)
    • 功能碼: 占用一個(gè)字節(jié),功能碼的意義就是,知道這個(gè)指令是干啥的,比如你可以查詢從機(jī)的數(shù)據(jù),也可以修改從機(jī)的數(shù)據(jù),所以不同功能碼對應(yīng)不同功能.
    • 數(shù)據(jù): 根據(jù)功能碼不同,有不同功能,比方說功能碼是查詢從機(jī)的數(shù)據(jù),這里就是查詢數(shù)據(jù)的地址和查詢字節(jié)數(shù)等。
    • 校驗(yàn): 在數(shù)據(jù)傳輸過程中可能數(shù)據(jù)會(huì)發(fā)生錯(cuò)誤,CRC檢驗(yàn)檢測接收的數(shù)據(jù)是否正確

3. 串行報(bào)文幀總結(jié):

ModbusASCII有開始字符(和結(jié)束字符(CR LF),可以作為一幀數(shù)據(jù)開始和結(jié)束的標(biāo)志,而ModbusRTU沒有這樣的標(biāo)志,需要用時(shí)間間隔來判斷一幀報(bào)文的開始和結(jié)束,協(xié)議規(guī)定的時(shí)間為3.5個(gè)字符周期,就是說一幀報(bào)文開始前,必須有大于3.5個(gè)字符周期的空閑時(shí)間,一幀報(bào)文結(jié)束后,也必須要有3.5個(gè)字符周期的空閑時(shí)間否則就會(huì)出現(xiàn)粘包的情況。

**注意:針對3.5個(gè)字符周期,其實(shí)是一個(gè)具體時(shí)間,但是這個(gè)時(shí)間跟波特率相關(guān)。 在串口通信中,1個(gè)字符包括1位起始位、8位數(shù)據(jù)位(一般情況)、1位校驗(yàn)位(或者沒有)、1位停止位(一般情況下),因此1個(gè)字符包括11個(gè)位,那么3.5個(gè)字符就是38.5個(gè)位,波特率表示的含義是每秒傳輸?shù)亩M(jìn)制位的個(gè)位,因此如果是9600波特率,3.5個(gè)字符周期=38.5/9600=0.00401s*1000=4.01ms**

5.4.6 Modbus 差錯(cuò)校驗(yàn)

在Modbus串行通信中,根據(jù)傳輸模式(ASCII或RTU)的不同,差錯(cuò)校驗(yàn)域?qū)⒉捎貌煌男r?yàn)方法。

  • ASCII模式
    在ASCII模式中,報(bào)文包含一個(gè)錯(cuò)誤校驗(yàn)字段,該字段由兩個(gè)字符組成,其基于對全部報(bào)文內(nèi)容執(zhí)行的縱向冗余校驗(yàn)(Longitudinal Redundancy ChedLRC)計(jì)算的結(jié)果而來,計(jì)算對象不包括起始的冒號(hào)(:)和回車換行符號(hào)(CR LF)。
  • **RTU模式 **
    在RTU模式中,報(bào)文同樣包含一個(gè)錯(cuò)誤校驗(yàn)字段。與ASCII模式不同的是該字段由 16 個(gè)比特位共2字節(jié)組成,其值基于對全部報(bào)文內(nèi)容執(zhí)行的循環(huán)冗余校驗(yàn)(Cyclical Redundancy Check,CRC)計(jì)算的結(jié)果而來,計(jì)算對象包括校驗(yàn)域之的所有字節(jié)。

1. LRC校驗(yàn)

在ASCII模式中,消息是由特定的字符作為幀頭和幀尾分隔的。

一條消息必須以“冒號(hào)”(:)字符(ASCII碼為0x3A)開始,以“回車換行(CRLF)(ASCII碼為 0x0D 和 0x0A)結(jié)束。LRC 校驗(yàn)算法的計(jì)算范圍為“:” “CRLF”之間的字符。

從算法本質(zhì)來說,LRC域自身為1字節(jié),即包含一個(gè) 8位二進(jìn)制數(shù)據(jù),由發(fā)送設(shè)備通過LRC算法把計(jì)算值附到信息末尾。接收設(shè)備在接收信息時(shí)通過 LRC法重新計(jì)算值,并把計(jì)算值與 LRC 字段中接收的實(shí)際值進(jìn)行比較。若兩者不同,則產(chǎn)生一個(gè)錯(cuò)誤,返回一個(gè)異常響應(yīng)幀,即對報(bào)文中的所有相鄰的兩個(gè) 8位字相加,丟棄任何進(jìn)位,然后對結(jié)果進(jìn)行二進(jìn)制補(bǔ)碼,計(jì)算出 LRC值。

必須注意的是,計(jì)算 LRC 校驗(yàn)碼的時(shí)機(jī)是在對報(bào)文中每個(gè)原始字節(jié)進(jìn)行ASCII碼編碼之前,對每個(gè)原始字節(jié)進(jìn)行LRC校驗(yàn)的計(jì)算操作。

  • LRC校驗(yàn)流程:
    • 將消息中的全部字節(jié)相加(不包括起始“:”和結(jié)束符(CRLF),并把結(jié)果送入8位數(shù)據(jù)區(qū),舍棄進(jìn)位。
    • 由0xFF(即全 1)減去最終的數(shù)據(jù)值,產(chǎn)生1的補(bǔ)碼(即二進(jìn)制反碼)
    • 加1產(chǎn)生二進(jìn)制補(bǔ)碼。

以上產(chǎn)生的LRC值占用1字節(jié),但實(shí)際上在通過串行鏈路由ASCII模式傳遞消息頓時(shí),LRC的結(jié)果(1字節(jié))被編碼為2字節(jié)的ASCII字符,并將其放置在ASCII模式報(bào)文幀的CRLF字段之前。

Modbus 標(biāo)準(zhǔn)協(xié)議的英文版提供了 LRC算法,其中的參數(shù)意義如下unsigned char*auchMsg:含有生成LRC所使用的二進(jìn)制數(shù)據(jù)的報(bào)文緩存區(qū)指針。 unsigned short usDataLen:報(bào)文緩存區(qū)中的字節(jié)數(shù)。

LCR的代碼如下:

/*函數(shù)返回unsigned char類型的 LRC值*/
?
static unsigned char LRC(unsigned char * auchMsg, unsigned short usDatalen)
?
{
?
  unsigned char uchLRC=0;       /*LRC字節(jié)初始化*/
?

?
  while(usDataLen--)          /*遍歷報(bào)文緩沖區(qū)*/
?
    uchLRC+=*auchMsg++;       /*緩沖區(qū)宇節(jié)相加,自動(dòng)舍棄進(jìn)位*/
?
  
?
return ((unsigned char)(-(( char)uchLRC))); /*返回二進(jìn)制補(bǔ)碼*/
?
}

下面舉一個(gè)簡單的例子。假設(shè)從設(shè)備地址為 1,要求讀取輸人寄存器地址30001的值,則具體的查詢消息幀如下:

":" , "0" , "1" , "0" , "4" , "0" ,"0" ,"0" ,"0" ,"0" ,"0" ,"0" , "1" , "F" , "A" ,CR/LF

其中,“F”, “A”即為LRC值在 ASCII模式下的形式,即0xFA.

2. CRC校驗(yàn)

在Modbus RTU傳輸模式下,通信報(bào)文(幀)包括一個(gè)基于循環(huán)冗余校驗(yàn)方法的差錯(cuò)校驗(yàn)字段。

Modbus協(xié)議采用了CRC-16標(biāo)準(zhǔn)校驗(yàn)方法。在RTU模式下,CRC自身由2字節(jié)組成,即CRC是一個(gè)16位的值。CRC字段校驗(yàn)整個(gè)報(bào)文的內(nèi)容,無論報(bào)文中的單個(gè)字節(jié)采用何種奇偶校驗(yàn)方式,整個(gè)通信報(bào)文均可使用CRC-16校驗(yàn)算法,CRC字段作為報(bào)文的最后字段添加在整個(gè)報(bào)文末尾。

需要注意的是,因?yàn)镃RC-16是由2字節(jié)組成,所以涉及哪個(gè)字節(jié)放在前面,哪個(gè)字節(jié)放在后面?zhèn)鬏數(shù)膯栴},即大小端模式的選擇問題。另外,由于Modbus協(xié)議規(guī)定寄存器為16位(即2字節(jié))長度,因此大小端問題的存在給很多初學(xué)者造成了困擾,下一章我們會(huì)重點(diǎn)講一下大小端的問題。

  • CRC校驗(yàn)流程:
    • 預(yù)置一個(gè)16位寄存器為0xFFFF(全1),稱之為CRC寄存器。
    • 把數(shù)據(jù)幀中的第一個(gè)字節(jié)的8位與CRC寄存器中的低字節(jié)進(jìn)行異或運(yùn)算,結(jié)果存回CRC寄存器。
    • 將CRC寄存器向右移一位,最高位填以0,最低位移出并檢測是0還是1。
    • 如果最低位為0:重復(fù)第三步(再次右移一位);如果最低位為1:將CRC寄存器與一個(gè)預(yù)設(shè)的固定值(0xA001)進(jìn)行異或運(yùn)算。
    • 重復(fù)第三步和第四步直到8次移位。這樣處理完了一個(gè)完整的八位。
    • 重復(fù)第2步到第5步來處理下一個(gè)八位,直到所有的字節(jié)處理結(jié)束。
    • 將該通信消息幀的所有字節(jié)按上述步驟計(jì)算完成后,再將得到的16位CRC寄存器的高、低位字節(jié)進(jìn)行交換,即發(fā)送時(shí)首先添加低位字節(jié),然后添加高位字節(jié)。
    • 最終CRC寄存器的值就是CRC的校驗(yàn)碼。

需要注意的是,在進(jìn)行CRC計(jì)算時(shí)只有串行鏈路上的每個(gè)字符的8個(gè)數(shù)據(jù)位參與計(jì)算,從而起始位、停止位、奇偶校驗(yàn)位等都不參與CRC計(jì)算。

常用的CRC-16算法有查表法、計(jì)算法。

查表法:

CRC查表法是將位移異或的計(jì)算結(jié)果做成了一個(gè)表,即將0~256 放入一個(gè)度為16位的寄存器的低8位,高8位填充0,然后將該寄存器與多項(xiàng)式0xA001照上述步驟3、4直到8 位全部移出,最后寄存器中的值就是表格中的數(shù)據(jù),高8位、低 8 位分別單獨(dú)做成一個(gè)表。 實(shí)際上,Modbus 標(biāo)準(zhǔn)協(xié)議的英文版提供了CRC 查表算法 函數(shù)的輸入?yún)?shù)意義如下:

unsigned char * puchMsg;         /*要進(jìn)行CRC校驗(yàn)的消息*/
?
unsigned short usDataLen;      /*消息中的字節(jié)數(shù)*/
?
/*函數(shù)返回 unsigned short(即2個(gè)字節(jié))類型的 CRC值*/
?
unsigned short CRC16(unsigned char *puchMsg,unsigned short usDataLen)
?
{
?
  unsigned charuchCRCHi=0xFF;         /*高 CRC字節(jié)初始化* /
?
  unsigned char uchCRCLo=0xFF;         /*低 CRC字節(jié)初始化*/
?
  unsigned short uIndex;            /*CRC 循環(huán)表中的索引*/
?
  
?
  while (usDataLen--)             /* 循環(huán)處理傳輸緩沖區(qū)消息 */
?
  {
?
    uIndex=uchCRCHi ^ * puchMsg++;        /*計(jì)算 CRC* /
?
    uchCRCHi=uchCRCLo ^ auchCRCHi[uIndex];
?
    uchCRCLo=auchCRCLo[uIndex];
?
  }
?
  return (uchCRCHi < 

其中,auchCRCHi和auchCRCLo的定義分別如下:

static unsigned char auchcRCHi[] = 
?
{
?
  0x00,0xC1,0x81,0x48,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,
?
  0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,
?
  0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,
?
  0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x01,
?
  0x00,0xc1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,
?
  0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
?
  0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,
?
  0xc0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
?
  0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,
?
  0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,
?
  0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xCl,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,
?
  0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
?
  0x00,0xc1,0x81,0x40,0x00,0xc1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,
?
  0x40,0x01,0xc0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01.0xC0,
?
  0x80,0x41,0x00,0xc1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,
?
  0xc0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
?
  0x00,0xc1,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,0xc0,0x80,0x41,0x00,0xC1,0x81,
?
  0x40
?
};
static char auchCRCLo[]=
?
{
?
  0x00,0xc0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,
?
  0x04,0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09,
?
  0x08,0xc8,0xDB,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,0x1E,0XDE,0XDE,0x1F,0xDD,
?
  0x1D,0x1C,0xDC,0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,
?
  0x11,0xD1,0xD0,0x10,0xF0,0x30,0x31,0xF1,0x33,0xE3,0xE2,0x32,0x36,0xF6,0xF7,
?
  0x37,0xF5,0x35,0x34,0xF4,0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,
?
  0x3B,0xFB,0x39,0xF9,0xF8,0x38,0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,0xEE,
?
  0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,
?
  0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,
?
  0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,
?
  0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xAB,0x68,0x78,0xB8,0xB9,0x79,0xBB,
?
  0x7B,0x7A,0xBA,0xBE,0x7E,0x7E,0xBE,0x7D,0xBD,0xBC,0x7C,0xB4,0x74,0x75,0xB5,
?
  0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,0x50,0x90,0x91,
?
  0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,0x9C,0x5C,
?
  0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98,0x88,
?
  0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8E,0x4F,0x8D,0x4D,0x4C,0x8C,
?
  0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,
?
  0x40
?
};

注意:實(shí)際編程時(shí),auchcRCHi[]和auchCRCLo[]的定義應(yīng)該放在函數(shù)CRC-16()之前。

查表法可以進(jìn)一步化簡如下:

unsigned short CRC16(unsigned char * puchMsg,unsigned short usDataLen)
?
{
?
  static const unsigned short usCRCTable[]=
?
  {
?
    0x0000,0xC0C1,0xC181,0x0140,0XC301,0X03C0,0X0280,0xc241,
?
    0XC601,0X06C0,0x0780,0XC741,0X0500,0XC5C1,0XC481,0X0440,
?
    0xCC01,0X0CC0,0X0D80,0XCD41,0X0F00,0XCEC1,0XCE81,0X0E40,
?
    0X0A00,0XCAC1,0XCB81,0X0B40,0XC901,0X09C0,0X0880,0XC841,
?
    0XD801,0x18c0,0X1980,0XD941,0X1B00,0XDBC1,0XDA81,0X1A40,
?
    0X1E00,0XDEC1,0XDF81,0X1F40,0XDD01,0X1DC0,0X1C80,0XDC41,
?
    0x1400,0XD4C1,0XD581,0X1540,0XD701,0X17C0,0X1680,0XD641,
?
    0XD201,0X12c0,0X1380,0XD341,0X1100,0XD1C1,0XD081,0X1040,
?
    0XF001,0X30C0,0X3180,0XE141,0X3300,0XE3C1,0XE281,0X3240,
?
    0X3600,0XF6C1,0XE781,0X3740,0XE501,0X35C0,0X3480,0XE441,
?
    0X3C00,0XFCC1,0XFD81,0X3D40,0XFF01,0X3FC0,0X3EB0,0XFE41,
?
    0XFA01,0X3AC0,0X3B80,0XFB41,0X3900,0XE9C1,0XF881,0X3840,
?
    0X2800,0XE8C1,0XE981,0X2940,0XEB01,0X2BC0,0X2A80,0XEA41,
?
    0XEE01,0X2EC0,0X2F80,0XEF41,0X2D00,0XEDC1,0XEC81,0X2C40,
?
    0XE401,0X24C0,0X2580,0XE541,0X2700,0XE7C1,0XE681,0X2640,
?
    0x2200,0XE2C1,0XE381,0X2340,0XE101,0X21C0,0X2080,0XE041,
?
    0XA001,0X60C0,0X6180,0XA141,0X6300,0XA3C1,0XA281,0X6240,
?
    0X6600,0XA6c1,0XA781,0X6740,0XA501,0X65C0,0X6480,0XA441,
?
    0X6C00,0XACC1,0XAD81,0X6D40,0XAF01,0X6EC0,0X6E80,0XAE41,
?
    0XAA01,0X6AC0,0X6B80,0XAB41,0X6900,0XA9C1,0XA881,0X6840,
?
    0X7800,0XB8C1,0XB981,0X7940,0XBB01,0X7BC0,0X7A80,0XBA41,
?
    0XBE01,0X7EC0,0X7F80,0XBF41,0X7D00,0XBDC1,0XBC81,0X7C40,
?
    0XB401,0X74C0,0X7580,0XB541,0X7700,0XB7C1,0XB681,0X7640,
?
    0X7200,0XB2C1,0XB381,0X7340,0XB101,0X71C0,0X7080,0XB041,
?
    0X5000,0X90c1,0X9181,0X5140,0X9301,0X53c0,0X5280,0X9241,
?
    0X9601,0X56C0,0X5780,0X9741,0X5500,0X95c1,0X9481,0X5440,
?
    0X9C01,0X5cc0,0X5D80,0X9D41,0X5E00,0X9FC1,0X9E81,0X5E40,
?
    0X5A00,0X9AC1,0X9B81,0X5B40,0x9901,0x59c0,0x5880,0X9841,
?
    0x8801,0X4BC0,0X4980,0X8941,0X4B00,0XBBC1,0X8AB1,0X4A40,
?
    0X4E00,0X8EC1,0X8F81,0X4F40,0X8D01,0X4DC0,0X4C80,0X8C41,
?
    0X4400,0X84c1,0x8581,0X4540,0X8701,0X47C0,0X4680,0X8641,
?
    0x8201,0X42c0,0x4380,0X8341,0X4100,0XB1C1,0X8081,0X4040,
?
  };
?
  unsigned char nTemp;
?
  unsigned short usRegCRC = 0xFFFF;
?
  while (usDataLen--)
?
  {
?
    nTemp = * puchMsg ++ ^ usRegCRC;
?
    usRegCRC > > = 8;
?
    usRegCRC ^= usCRCTable[nTemp];
?
  }
?
  return usRegCRC;
?
}

查表法的特點(diǎn)是以字節(jié)為單位進(jìn)行計(jì)算,速度快,語句少,但表格會(huì)占用一定的程序空間。

  • 計(jì)算法:

計(jì)算法按位計(jì)算,適用于所有長度的數(shù)據(jù)校驗(yàn),最為靈活;但由于是按位計(jì)算,其效率并不是最優(yōu)的,只適用于對速度不敏感的場合。計(jì)算法的基本算法如下; 輸入?yún)?shù)的意義:

unsigned char * puchMsg;       /*要進(jìn)行 CRC校驗(yàn)的消息* /
?
unsigned short usDataLen;      /*消息中的字節(jié)數(shù)*/
?
/*函數(shù)返回unsigned short(即 2個(gè)字節(jié))類型的CRC值*/
?
unsigned short CRC16(unsigned char *puchMsg,unsigned short usDataLen)
?
{
?
  int i,j;                     /*循環(huán)變量*/
?
  unsigned shortusRegCRC =0xFFFF;         /*用于保存CRC值*/
?
  
?
  for(i=0;i < usDataLen;i++)            /*循環(huán)處理傳輸緩沖區(qū)消息*/
?
  {
?
    usRegCRC ^= * puchMsg++;             /*異或算法得到CRC值*/
?
    for(j=0;j< 8;j++)                 /*循環(huán)處理每個(gè) bit位*/
?
    {
?
      if (usRegCRC &0x0001)
?
        usRegCRC =usRegCRC > >1^0xA001;
?
      else
?
        usRegCRC > >=1;
?
    }
?
  }
?
  
?
  return usRegCRC;
?
}

下面舉一個(gè)簡單的例子。假設(shè)從設(shè)備地址為 1,要求讀取輸入寄存器地址30001的值,則RTU模式下的具體查詢消息幀如下:

0x01,0x04,0x00,0x00,0x00,0x01,0x31,0xCA

其中,0xCA31即為CRC值。因?yàn)镸odbus規(guī)定發(fā)送時(shí)CRC必須低字節(jié)在前、高字節(jié)在后,因此實(shí)際的消息幀的發(fā)送順序?yàn)?x31,0xCA。

5.4.7 字節(jié)序和大小端

Modbus中傳輸?shù)臄?shù)據(jù),按照“大字節(jié)序”來傳輸,比如:

img

寄存器數(shù)值是0x1234,先傳輸0x12,再傳輸0x34。

在 Modbus 寄存器中,對于一個(gè)由 2字節(jié)組成的16數(shù),在內(nèi)存中存儲(chǔ)這兩個(gè)字節(jié)有兩種方法:一種是將低序字節(jié)存儲(chǔ)在起始地址為小端(Little-Endian)字節(jié)序;另一種方法是將高序字節(jié)存儲(chǔ)在起始地稱為大端(Big-Endian)字節(jié)序。Modbus 通信協(xié)議中具體規(guī)定了字節(jié)高低位發(fā)送順序,這樣就自然引出了字節(jié)序和大小端的問題。

  • 什么是大端:
    所謂大端,是指數(shù)據(jù)的低位保存在內(nèi)存的高地址中,數(shù)據(jù)的高位保存在內(nèi)存的低地址中。
  • 什么是小端:
    所謂小端,是指數(shù)據(jù)的低位保存在內(nèi)存的低地址中,數(shù)據(jù)的高位保存在內(nèi)存的高地址中。
  • 為什么會(huì)有大小端:
    計(jì)算機(jī)系統(tǒng)是以字節(jié)為單位的,每個(gè)地址單元都對應(yīng)著1個(gè)字節(jié),一個(gè)字節(jié)為8bit。但在C語言中除了8bit的char類型,還有16bit的short類型和32bit的long類型,還有就是對于位數(shù)大于8位的處理器,如16位或32位的處理器,由于寄存器寬度大于一個(gè)字節(jié),那么必然存在一個(gè)如何將多個(gè)字節(jié)安排的問題。因此就導(dǎo)致了大端存儲(chǔ)模式和小端存儲(chǔ)模式的出現(xiàn)。

低位字節(jié)和高位字節(jié):好比如:123456 其中的1就是高位數(shù)字,6就是低位數(shù)字。

舉一個(gè)例子,在32位數(shù)字0x12345678在內(nèi)存中的表示形式為:

1)大端模式

低地址————高地址
0x120x340x560x78

2)小端模式:

低地址————高地址
0x780x560x340x12

5.4.8 Modbus報(bào)文分析

在第二章中我們已經(jīng)生成了一個(gè)報(bào)文,我們就拿此報(bào)文來逐步分析一下,報(bào)文如下:

img

我們可以看到上面報(bào)文都是循環(huán)發(fā)送的,這樣看起來不太容易分析,我摘抄下來其中一組來給大家分析

發(fā)送:

從機(jī)地址功能碼起始地址高位起始地址低位寄存器數(shù)量高位寄存器數(shù)量低位CRC高位CRC低位
01030000000AC5CD

響應(yīng):

從機(jī)地址功能碼返回字節(jié)數(shù)數(shù)據(jù)位CRC高位CRC低位
01031400 42…CF10

這里我們就以03功能碼為例來分析一下報(bào)文;

  • 03發(fā)送報(bào)文格式:從機(jī)地址+功能碼+加起始地址+寄存器數(shù)量+CRC校驗(yàn)
  • 03接受報(bào)文格式:從機(jī)地址+功能碼+字節(jié)數(shù)+具體數(shù)據(jù)+CRC校驗(yàn)

首先我們看一下發(fā)送報(bào)文:

從機(jī)地址是01,功能碼03,起始地址00,寄存器數(shù)量是十六進(jìn)制0A也就是10,和門設(shè)置的是一樣的,我們來對對照一下我們設(shè)置的參數(shù):

img

我們再來看一下接收報(bào)文:

從機(jī)地址是01,功能碼03,返回字節(jié)數(shù)是十六進(jìn)制14也就是返回20給字節(jié),我們發(fā)送是個(gè)返回20個(gè)字節(jié)也是對的上的,第一個(gè)數(shù)據(jù)位是00 42 也是和我們發(fā)送的可以對上,十六機(jī)制42,也就66,我們來看一下我們之前設(shè)置的參數(shù):

img

5.4.9 Moubus TCP 消息幀格式

1.協(xié)議描述

在Modbus TCP/IP中,串行鏈路中的主/從設(shè)備分別演變?yōu)榭蛻舳?服務(wù)器端設(shè)備,即客戶端相當(dāng)于主站設(shè)備,服務(wù)器端設(shè)備相當(dāng)于從設(shè)備。基于TCP/IP網(wǎng)絡(luò)的傳輸特性,串行鏈路上一主多從的機(jī)構(gòu)也演變?yōu)槎嗫蛻舳?多服務(wù)器端的構(gòu)造模型。Modbus協(xié)議在TCP/IP上的實(shí)現(xiàn)是在TCP/IP層上的應(yīng)用,它需要一個(gè)完整的TCP/IP棧作為支撐,Modbus TCP/IP服務(wù)器端通常使用端口502作為接收報(bào)文的端口。

下圖為Moubus TCP的通訊結(jié)構(gòu):

img

ModbusTCP與ModbusUDP的報(bào)文格式是一樣的,它們之間的區(qū)別其實(shí)就是TCP與UDP的區(qū)別,因此下面就針對ModbusTCP的協(xié)議進(jìn)行分析,ModbusTCP與ModbusRtu(ModbusASCII)之間的區(qū)別如下圖:

img

從上圖可以看出,ModbusTCP在Modbus串行通信的基礎(chǔ)上,去除了校驗(yàn)(由于TCP本身就帶有校驗(yàn)和)和設(shè)備地址(ModbusTCP弱化了設(shè)備地址,用IP地址來取代),再加上MBAP報(bào)文頭(占7 bytes),下面針對MBAP進(jìn)行分析說明:

字段名長度描述主站(客戶端)從站(服務(wù)器端)
事務(wù)處理標(biāo)識(shí)符(Transaction Identifier)2字節(jié)Modbus 請求/應(yīng)答傳輸過程的事務(wù)處理的識(shí)別碼,可以設(shè)置為0,也可以設(shè)置為每次通訊時(shí)自動(dòng)+1主站(客戶端)生成應(yīng)答時(shí)從主站(客戶端)復(fù)制該值
協(xié)議標(biāo)識(shí)符(Protocol Identifier)2字節(jié)00表示是 Modbus協(xié)議,固定值主站(客戶端)生成應(yīng)答時(shí)從主站(客戶端)復(fù)制該值
長度(Lendgth)2字節(jié)從單元標(biāo)識(shí)符開始,整個(gè)PDU的數(shù)據(jù)長度,分為字節(jié)長度Hi和Lo請求時(shí)生成應(yīng)答時(shí)重新生成
單元標(biāo)識(shí)符(Unit Identifier)1字節(jié)串行鏈路或其他總線上連接的遠(yuǎn)程從站的識(shí)別碼,可以設(shè)置為從機(jī)設(shè)備的地址主站(客戶端)生成應(yīng)答時(shí)從主站(客戶端)復(fù)制該值

事務(wù)處理標(biāo)識(shí)符:

事務(wù)處理標(biāo)識(shí)用于在查詢報(bào)文與未來響應(yīng)之間建立聯(lián)系。因此,對 TCP/IP 連接來說,在同一時(shí)刻這個(gè)標(biāo)識(shí)符必須是唯一的。有以下幾種使用此標(biāo)識(shí)符的方式。

例如,可以將傳輸標(biāo)識(shí)作為一個(gè)帶有計(jì)數(shù)器的簡單“TCP 發(fā)送順序號(hào)”,在每個(gè)請求發(fā)送時(shí)自動(dòng)+1;也可以用作智能索引或指針,用來識(shí)別事務(wù)處理的內(nèi)容,以便記憶當(dāng)前的遠(yuǎn)端服務(wù)器和未處理的請求。

服務(wù)器端可接收的請求數(shù)量取決于其容量,即服務(wù)器資源量和 TCP 窗口尺同樣,客戶端同時(shí)啟動(dòng)事務(wù)處理的數(shù)量也取決于客戶端的資源容量。

單元標(biāo)識(shí)符:

在對Modbus或 Modbus+等串行鏈路子網(wǎng)中的設(shè)備進(jìn)行尋址時(shí),這個(gè)域用于路由的目的。在這種情況下,單元標(biāo)識(shí)符(Unit Identifier) 攜帶一個(gè)遠(yuǎn)端設(shè)備的Modbus 從站地址。

如果 Modbus 服務(wù)器連接到 Modbus+或 Modbus 串行鏈路子網(wǎng),并通過一個(gè)網(wǎng)橋或網(wǎng)關(guān)配置這個(gè)服務(wù)器的IP 地址,則 Modbus 單元標(biāo)識(shí)符對識(shí)別連接到網(wǎng)橋或網(wǎng)關(guān)后的子網(wǎng)的從站設(shè)備是必需的。TCP 連接中的目的 IP 地址識(shí)別了網(wǎng)橋本身的地址,而網(wǎng)橋則使用 Modbus 單元標(biāo)識(shí)符將請求轉(zhuǎn)交給正確的從站設(shè)備。 分配給串行鏈路上的 Modbus 從站設(shè)備地址為 1~247(十進(jìn)制),地址0作為廣播地址。

對單純的 Modbus TCP/IP 設(shè)備來說用IP 地址即可尋址 Modbus 服務(wù)器端設(shè)備,此時(shí) Modbus 單元標(biāo)識(shí)符是無用的,必須使用值0xFF 填充。當(dāng)對直接連接到 TCP/IP 網(wǎng)絡(luò)上的 Modbus 服務(wù)器尋址時(shí),建議不要在“單元標(biāo)識(shí)符”域使用有效的Modbus從站地址。

以上是MBAP報(bào)文頭個(gè)字段含義的詳細(xì)說明。

實(shí)際上,在 Modbus TCP/IP傳輸過程中,服務(wù)端(從機(jī))返回的響應(yīng)報(bào)文中同樣包含 MBAP報(bào)頭,除了 Length 字段外,其他字段均與客戶端一致。Modbus消息由 TCP/IP 層提供,不需要像串行鏈路那樣自己判斷一幀是否結(jié)束,所有數(shù)據(jù)傳輸均由 TCP/IP層處理。因?yàn)榈讓拥?TCP/IP 確保了端到端的連接,而且 TCP/IP鏈路層已確保傳輸數(shù)據(jù)的準(zhǔn)確性,所以 Modbus TCP/IP 中已不再需要 LRC或CRC 等校驗(yàn)功能。

2. 查詢與響應(yīng)報(bào)文示例

對于Modbus TCP消息幀格式,下面舉例說明各部分的含義。

  • 查詢報(bào)文:00 00 00 00 00 06 09 03 00 04 00 01。
    • 0x06: 后續(xù)還有6字節(jié)。
    • 0x09: 單元標(biāo)識(shí)符為9。
    • 0x03: 功能碼 3,即讀保持寄存器的值。
    • 0x00 0x04: Modbus起始地址4(即40005)。
    • 0x00 0x01: 讀取寄存器個(gè)數(shù)為1。
  • 響應(yīng)報(bào)文:00 00 00 00 00 05 09 03 02 00 05。
    • 0x05:表示后續(xù)還有5字節(jié)。
    • 0x09:同查詢報(bào)文,單元標(biāo)識(shí)符。
    • 0x03:功能碼,同查詢報(bào)文。
    • 0x02:返回?cái)?shù)據(jù)字節(jié)數(shù)。
    • 0x00 0x05:寄存器的值。

可見,在Modbus TCP模式下,差錯(cuò)校驗(yàn)字段已不復(fù)存在。但在某些特殊場合,例如串行Modbus協(xié)議轉(zhuǎn)Modbus TCP的情況下,串行協(xié)議數(shù)據(jù)可以完整地裝載到Modbus TCP的數(shù)據(jù)字段,這時(shí)CRC或LRC差錯(cuò)校驗(yàn)字段仍然存在。例如,Modbus RTU Over TCP/IP 或 Modbus ASCII Over TCP/IP等。

5.5 Moubus功能碼詳解

本節(jié)大部分內(nèi)容參考《Modbus軟件開發(fā)實(shí)戰(zhàn)指南》。

5.5.1 功能碼概要

Modbus標(biāo)準(zhǔn)在協(xié)議中規(guī)定了以下3類Modbus功能碼。

  • 公共功能碼:
    • 被明確定義的功能碼;
    • 保證唯一性;
    • 由Modbus協(xié)會(huì)確認(rèn),并提供公開的文檔;
    • 可進(jìn)行一致性測試;
    • 包括協(xié)議定義的功能碼和保留將來使用的功能碼。
  • 用戶自定義功能碼:
    • 有兩個(gè)用戶自定義功能碼區(qū)域,分別是6572和100110;
    • 用戶自定義,無法保證唯一性。
  • 保留功能碼:
    保留功能碼因?yàn)闅v史遺留原因,某些公司的傳統(tǒng)產(chǎn)品現(xiàn)行使用的功能碼不作為公共使用。

5.5.2 01(0x01)讀取線圈

1.功能說明

01功能碼用于讀取從設(shè)備的線圈或離散量輸出的狀態(tài),即各Do(Discrete Output,離散輸出)的ON/OFF狀態(tài)。消息幀中指定了需要讀取的線圈起始地址和線圈數(shù)目。需要注意的是,在Modbus協(xié)議規(guī)定的PDU中,所有線圈或寄存器地址都必須從0開始計(jì)算。

2. 查詢報(bào)文

如下表所示,查詢幀的消息中定義了從設(shè)備地址為3,并讀取從設(shè)備的Modbus地址0001900055(線圈地址0002000056)共計(jì)37個(gè)狀態(tài)值。起始線圈地址為0x13(即十進(jìn)制00019),因?yàn)榫€圈地址是從0開始計(jì)數(shù)的。

功能碼01查詢報(bào)文示例

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x03“0”,“3”0x03
功能碼0x01“0”,“1”0x01
起始地址(高位)0x00“0”,“0”0x00
起始地址(低位)0x13“1”,“3”0x13
寄存器數(shù)(高位)0x00“0”,“0”0x00
寄存器數(shù)(低位)0x25“2”,“5”0x25
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

Modbus協(xié)議規(guī)定,起始地址由2字節(jié)構(gòu)成,取值范圍為0x0000 ~ 0xFFFF: 線圈數(shù)量由2字節(jié)構(gòu)成,取值范圍為0x0001~ 0x07D0 (即+進(jìn)制1~2000)另外,注意觀察ASCII模式和RTU模式的區(qū)別,ASCII模式直接按每4位拆分成對應(yīng)的字符表示。

3. 響應(yīng)報(bào)文

**在響應(yīng)報(bào)文的數(shù)據(jù)字段中,每個(gè)線圈占用1位 (bit),狀態(tài)被表示為1=ON和O=OFF兩種類型。第1個(gè)數(shù)據(jù)字節(jié)的LSB(最低有效位)標(biāo)識(shí)查詢報(bào)文中的起始地址線圈的狀態(tài)值,其他線圈以此類推,一直到這個(gè)字節(jié)的MSB(最高有效位)為止,并在后續(xù)字節(jié)中按照同樣的方式(由低到高)排列。**

例如,下表中線圈20~27的狀態(tài)值分別是ON - ON - OFF OFF - ON - OFF - ON - OFF表示為二進(jìn)制則為01010011 (0x53),注意觀察對應(yīng)的順序。1字節(jié)可以表示8個(gè)線圈的狀態(tài)如果最后的數(shù)據(jù)字節(jié)中不能填滿8個(gè)線圈的狀態(tài),則用0填充。對應(yīng)于查詢報(bào)文中需要讀取37個(gè)線圈的狀態(tài),共需要5字節(jié)保存狀態(tài)值。

功能碼01響應(yīng)報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x03“0”,“3”0x03
功能碼0x01“0”,“1”0x01
數(shù)據(jù)域字節(jié)數(shù)0x05“0”,“5”0x05
數(shù)據(jù)10x53“5”,“3”0x53
數(shù)據(jù)20x6B“6”,“B”0x6B
數(shù)據(jù)30x01“0”,“1”0x01
數(shù)據(jù)40xF4“F”,“B”0xF4
數(shù)據(jù)50x1B“1”,“B”0x1B
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)2110

5.5.3 02 (0x02) 讀取離散量輸入值

1. 功能說明

02功能碼用于讀取從設(shè)備的離散輸入,即DI (Discrete Input) 的ON/OFF狀態(tài)。消息頓中指定了需要讀取的離散輸入寄存器的起始地址和數(shù)目,可以讀取1 ~ 2000個(gè)連續(xù)的離散量輸入狀態(tài)如果從設(shè)備接受主設(shè)備的請求則回復(fù)功能碼02,并返回離散量且輸入各變量的當(dāng)前狀態(tài)。如果返回的離散輸入數(shù)量的個(gè)數(shù)不是8的整數(shù)倍,將用0填充最后的數(shù)據(jù)字節(jié)的剩余位。

2. 查詢報(bào)文

如下表所示,查詢頓的消息中定義了從設(shè)備的地址為3,并讀取從設(shè)備的離散輸入寄存器中地址1010110120 (Modbus地址表示為十進(jìn)制100119) 共計(jì)20個(gè)離散輸入狀態(tài)值。從下表中可以發(fā)現(xiàn),起始地址為0x64 (即十進(jìn)制100),因?yàn)橄DU中的Modbus地址從0開始計(jì)數(shù)。

功能碼02查詢報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x03“0”,“3”0x03
功能碼0x02“0”,“2”0x02
起始地址(高位)0x00“0”,“0”0x00
起始地址(低位)0x64“6”,“4”0x64
寄存器數(shù)(高位)0x00“0”,“0”0x00
寄存器數(shù)(低位)0x14“1”,“4”0x14
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

與5.4.2節(jié)中的功能碼 (01 (0x01) 讀取線圈/離散量輸出狀態(tài) (Read Coil status/DOs))一樣,本功能碼的起始地址由2字節(jié)構(gòu)成,取值范圍為0x0000 ~ 0xFFFF;離散量數(shù)量由2字節(jié)構(gòu)成,取值范圍為0x0001 0x07D0 (即十進(jìn)制1 2000),最多一次性可讀取2000人離散輸入狀態(tài)值。

3. 響應(yīng)報(bào)文

響應(yīng)報(bào)文的各項(xiàng)構(gòu)成和意義與5.4.2章節(jié)的功能碼(01(0x01)讀取線圈/離散量輸出狀態(tài)(Re-ad Coil Status/DOs))一樣,如下表所示:

功能碼02響應(yīng)報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x03“0”,“3”0x03
功能碼0x02“0”,“2”0x02
數(shù)據(jù)域字節(jié)數(shù)0x03“0”,“3”0x03
數(shù)據(jù)10x53“5”,“3”0x53
數(shù)據(jù)20x6B“6”,“B”0x6B
數(shù)據(jù)30x01“0”,“1”0x01
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)2110

5.5.4 03(0x03)讀取保持寄存器值

1. 功能說明

03功能碼用于讀取從設(shè)備保持寄存器的內(nèi)容,不支持廣播模式。消息頓中指定了需要讀取的保持寄存器的起始地址和數(shù)目。而保持寄存器中各地址的具體內(nèi)容和意義則由設(shè)備開發(fā)者自行規(guī)定。

2. 查詢報(bào)文

在查詢報(bào)文中,必須指定保持寄存器的開始地址和需要讀取的寄存器數(shù)量,例如,如下表所示,從設(shè)備地址為7 (0x07),需要讀取保持寄存器地址40201 ~ 40203共計(jì)3個(gè)寄存器的內(nèi)容即讀取Modbus協(xié)議地址200~ 202的內(nèi)容,在報(bào)文中表示如下。

起始地址: 0x00C8 (十進(jìn)制200)。
讀取數(shù)量: 0x0003 (十進(jìn)制3)。

功能碼03查詢報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x07“0”,“7”0x07
功能碼0x03“0”,“3”0x03
起始地址(高位)0x00“0”,“0”0x00
起始地址(低位)0xC8“C”,“8”0xC8
寄存器數(shù)(高位)0x00“0”,“0”0x00
寄存器數(shù)(低位)0x03“0”,“3”0x03
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

本功能碼的起始地址由2字節(jié)構(gòu)成,取值范圍為0x00000xFFFF;寄存器數(shù)量由2字節(jié)構(gòu)成取值范圍為0x00010x007D (即十進(jìn)制1~125) ,即最多可以連續(xù)讀取125個(gè)寄存器。

需要特別注意的是,Modbus的保持寄存器和輸入寄存器是以字 (Word) 為基本單位的(1Word=2Byte),所以如果讀取保持寄存器地址為40001開始的一個(gè)16位 (bit) 的無符號(hào)數(shù),那么返回2字節(jié),并可以從40002開始讀取下一個(gè)16位的無符號(hào)數(shù)。如果需要讀取寄存器地址為40001開始的一個(gè)32位浮點(diǎn)數(shù),則需要返回4字節(jié),即必須連續(xù)讀取40001和40002的內(nèi)容,而且下一個(gè)32位的浮點(diǎn)數(shù)必須從40003開始讀取。對于浮點(diǎn)數(shù)(或者32位的整數(shù))而言,連續(xù)讀取的兩個(gè)寄存器之間存在字節(jié)序和大小端的問題,這一點(diǎn)在開發(fā)時(shí)必須引起注意。

3. 響應(yīng)報(bào)文

響應(yīng)報(bào)文的各項(xiàng)構(gòu)成和意義如下表所示。因?yàn)镸odbus的保持寄存器和輸入寄存器是以字為基本單位的,在上面的例子中,查詢報(bào)文連續(xù)讀取3個(gè)寄存器的內(nèi)容,將返回6字節(jié),參考表下表中數(shù)據(jù)1~3的高位和低位。

功能碼03響應(yīng)報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x07“0”,“7”0x07
功能碼0x03“0”,“3”0x03
數(shù)據(jù)域字節(jié)數(shù)0x06“0”,“6”0x06
數(shù)據(jù)1(高位)0x03“0”,“3”0x03
數(shù)據(jù)1(低位)0x53“5”,“3”0x53
數(shù)據(jù)2(高位)0x01“0”,“1”0x01
數(shù)據(jù)2(低位)0xF3“F”,“3”0xF3
數(shù)據(jù)3(高位)0x01“0”,“1”0x01
數(shù)據(jù)3(低位)0x05“0”,“5”0x05
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)2311

5.5.5 04 (0x04)讀取輸入寄存器值

1.功能說明

與功能碼03類似,04功能碼用于讀取從設(shè)備輸入寄存器的內(nèi)容,不支持廣播模式。消息頓中指定了需要讀取的輸入寄存器的起始地址和數(shù)目,而輸入寄存器中各地址的具體內(nèi)容和意義則由設(shè)備開發(fā)者自行規(guī)定。

2.查詢報(bào)文

在查詢報(bào)文中必須指定輸入寄存器的起始地址和需要讀取的寄存器數(shù)量。例如,如表4-9所示,從設(shè)備地址為7 (0x07),需要讀取輸入寄存器地址30301 ~ 30303共計(jì)3個(gè)寄存器的內(nèi)容即讀取Modbus協(xié)議地址300 ~302的內(nèi)容,在報(bào)文中表示如下。

起始地址: 0x012C (十進(jìn)制300) 。
讀取數(shù)量: 0x0003 (十進(jìn)制3)。

功能碼04查詢報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x07“0”,“7”0x07
功能碼0x04“0”,“4”0x04
起始地址(高位)0x01“0”,“1”0x01
起始地址(低位)0x2C“2”,“C”0x2C
寄存器數(shù)(高位)0x00“0”,“0”0x00
寄存器數(shù)(低位)0x03“0”,“3”0x03
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

本功能碼中,起始地址由2字節(jié)構(gòu)成,取值范圍為0x0000 ~ 0xFFFF;寄存器數(shù)量由2字節(jié)構(gòu)成,取值范圍為0x0001 0x007D (即十進(jìn)制1125) ,即最多可以連續(xù)讀取125個(gè)寄存器同樣有一點(diǎn)需要注意,Modbus的保持寄存器和輸入寄存器是以字為基本單位的。所以對于浮點(diǎn)數(shù)(或者32位的整數(shù))而言,連續(xù)讀取的兩個(gè)寄存器之間存在字節(jié)序和大小端的問題,這一點(diǎn)在開發(fā)時(shí)必須引起注意。

3.響應(yīng)報(bào)文

響應(yīng)報(bào)文的各項(xiàng)構(gòu)成和意義如下表所示。因?yàn)镸odbus的保持寄存器和輸入寄存器是以字為基本單位的,上面的例子中,查詢報(bào)文連續(xù)讀取3個(gè)寄存器的內(nèi)容,那么將返回6字節(jié),參考下表中數(shù)據(jù)1~3的高位和低位。

功能碼04響應(yīng)報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x07“0”,“7”0x07
功能碼0x04“0”,“4”0x04
數(shù)據(jù)域字節(jié)數(shù)0x06“0”,“6”0x06
數(shù)據(jù)1(高位)0x03“0”,“3”0x03
數(shù)據(jù)1(低位)0x53“5”,“3”0x53
數(shù)據(jù)2(高位)0x01“0”,“1”0x01
數(shù)據(jù)2(低位)0xF3“F”,“3”0xF3
數(shù)據(jù)3(高位)0x01“0”,“1”0x01
數(shù)據(jù)3(低位)0x05“0”,“5”0x05
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)2311

5.5.6 05 (0x05)寫單個(gè)線圈

1. 功能說明

05功能碼用于將單個(gè)線圈寄存器 (或離散輸入)設(shè)置為ON或OFF,該功能碼支持廣播模式在廣播模式下,所有從站設(shè)備的同一地址的值將被統(tǒng)一修改。查詢報(bào)文中的ON/OFF狀態(tài)由報(bào)文數(shù)據(jù)字段的常數(shù)指定,0xFF00表示ON狀態(tài),0x0000表示OFF狀態(tài)。其他值均是非法的,并且對寄存器不起作用,將會(huì)返回異常響應(yīng)。

2. 查詢報(bào)文

查詢報(bào)文中需要指定從設(shè)備地址以及需要變更的線圈地址和設(shè)定的狀態(tài)值。需要注意的是,在查詢報(bào)文中,線圈地址從地址0開始計(jì)數(shù)。例如,如下表所示,從設(shè)備地址為3,設(shè)置線圈地址00150為ON狀態(tài),則查詢報(bào)文中的線圈地址設(shè)置為0x95 (149)。

功能碼05查詢報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x03“0”,“3”0x03
功能碼0x05“0”,“5”0x05
起始地址(高位)0x00“0”,“0”0x00
起始地址(低位)0x95“9”,“5”0x95
變更數(shù)據(jù)(高位)0xFF“F”,“F”0xFF
變更數(shù)據(jù)(低位)0x00“0”,“0”0x00
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

本功能碼中,起始地址由2字節(jié)構(gòu)成,取值范圍為0x0000~0xFFFF:變更目標(biāo)數(shù)據(jù)由2字節(jié)構(gòu)成,取值只能為0xFF00或0x0000。

3.響應(yīng)報(bào)文

響應(yīng)報(bào)文的各項(xiàng)構(gòu)成和意義如下表所示。對于從設(shè)備,在線圈或離散輸出寄存器正常變更的情況下會(huì)返回與查詢報(bào)文相同的響應(yīng)報(bào)文。如果修改失敗,則會(huì)返回一個(gè)異常響應(yīng),對于異常響應(yīng),后續(xù)章節(jié)會(huì)進(jìn)一步詳細(xì)介紹。

功能碼05響應(yīng)報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x03“0”,“3”0x03
功能碼0x05“0”,“5”0x05
起始地址(高位)0x00“0”,“0”0x00
起始地址(低位)0x95“9”,“5”0x95
變更數(shù)據(jù)(高位)0xFF“F”,“F”0xFF
變更數(shù)據(jù)(低位)0x00“0”,“0”0x00
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

5.5.7 06 (0x06) 寫單個(gè)保持寄存器

1.功能說明

06功能碼用于更新從設(shè)備的單個(gè)保持寄存器的值,該功能碼支持廣播模式,在廣播模式下所有從設(shè)備的同一地址的值將被統(tǒng)一修改。

2. 查詢報(bào)文

查詢報(bào)文中需要指定從設(shè)備地址以及需要變更的保持寄存器地址和設(shè)定的值。需要注意的是查詢報(bào)文中,寄存器地址從地址0開始計(jì)數(shù)。例如,如下表所示,從設(shè)備地址為3,設(shè)置寄存器地址40150為1200 (即0x04B0) ,則查詢報(bào)文中的地址字段設(shè)置為0x95 (149)。

功能碼06查詢報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x03“0”,“3”0x03
功能碼0x06“0”,“6”0x06
起始地址(高位)0x00“0”,“0”0x00
起始地址(低位)0x95“9”,“5”0x95
變更數(shù)據(jù)(高位)0x04“0”,“4”0x04
變更數(shù)據(jù)(低位)0xB0“B”,“0”0xB0
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

本功能碼中,起始地址由2字節(jié)構(gòu)成,取值范圍為0x00000xFFFF; 變更目標(biāo)數(shù)據(jù)由2字節(jié)構(gòu)成,取值范圍為0x00000xFFFF。

3.響應(yīng)報(bào)文

響應(yīng)報(bào)文的各項(xiàng)構(gòu)成和意義,如下表所示。對于從設(shè)備,在保持寄存器正常變更的情況下會(huì)返回與查詢報(bào)文相同的響應(yīng)報(bào)文。如果修改失敗,則返回個(gè)異常響應(yīng)。

功能碼06響應(yīng)報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x03“0”,“3”0x03
功能碼0x06“0”,“6”0x06
起始地址(高位)0x00“0”,“0”0x00
起始地址(低位)0x95“9”,“5”0x95
變更數(shù)據(jù)(高位)0x04“0”,“4”0x04
變更數(shù)據(jù)(低位)0xB0“B”,“0”0xB0
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

5.5.8 08 (0x08) 診斷功能

1.功能說明

08功能碼僅用于串行鏈路,主要用于檢測主設(shè)備和從設(shè)備之間的通信故障,或檢測從設(shè)備的各種內(nèi)部故障,該功能碼不支持廣播。為了區(qū)別各診斷類型,查詢報(bào)文中提供了2字節(jié)的子功能碼字段。

通常在正常的響應(yīng)報(bào)文中,從設(shè)備將原樣回復(fù)功能碼和子功能碼.

2. 查詢報(bào)文

查詢報(bào)文中需要指定從設(shè)備地址、功能碼以及子功能碼。

例如,下表中標(biāo)識(shí)了子功能碼“原樣返回查詢數(shù)據(jù)”的診斷功能,其中子功能碼為0(0x0000)。在子功能碼為0x0000的情況下,數(shù)據(jù)字段可以為任意值。各子功能碼的詳細(xì)意義可參考下表。

功能碼08查詢報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x05“0”,“5”0x05
功能碼0x08“0”,“8”0x08
子功能碼(高位)0x00“0”,“0”0x00
子功能碼(低位)0x00“0”,“0”0x00
數(shù)據(jù)(高位)0x04“0”,“4”0x04
數(shù)據(jù)(低位)0xB0“B”,“0”0xB0
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

本功能碼中,子功能碼由2字節(jié)構(gòu)成,取值則根據(jù)意義而不同;數(shù)據(jù)字段由2字節(jié)構(gòu)成,其取值由子功能碼確定。

3.響應(yīng)報(bào)文

響應(yīng)報(bào)文的各項(xiàng)構(gòu)成和意義如下表所示。對于從設(shè)備,在保持寄存器正常變更的情況下會(huì)返回與查詢報(bào)文相同的響應(yīng)報(bào)文。如果修改失敗,則返回一個(gè)異常響應(yīng)。

功能碼08響應(yīng)報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x05“0”,“5”0x05
功能碼0x08“0”,“8”0x08
子功能碼(高位)0x00“0”,“0”0x00
子功能碼(低位)0x00“0”,“0”0x00
數(shù)據(jù)(高位)0x04“0”,“4”0x04
數(shù)據(jù)(低位)0xB0“B”,“0”0xB0
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

4. 診斷子功能碼

各常用的診斷子功能碼的定義如下。

Return Query Data(00)

診斷內(nèi)容原樣返回查詢報(bào)文
子功能碼0x00,0x00
查詢報(bào)文數(shù)據(jù)字段任意16位數(shù)據(jù)
響應(yīng)報(bào)文數(shù)據(jù)字段同查詢報(bào)文

Restart Communication Option(01)

診斷內(nèi)容重啟通信選項(xiàng); 用于初始化并重新啟動(dòng)從站設(shè)備,清楚所有通信事件計(jì)數(shù)器; 如果端口處于 Listen Only Mode,則不返回響應(yīng);否則在重啟之前返回響應(yīng)
子功能碼0x00,0x01
查詢報(bào)文數(shù)據(jù)字段0x00, 0x00 保持事件記錄; 0xFF,0x00 清除事件記錄
響應(yīng)報(bào)文數(shù)據(jù)字段同查詢報(bào)文

Return Diagnostics Register(02)

診斷內(nèi)容返回診斷寄存器
子功能碼0x00,0x04
查詢報(bào)文數(shù)據(jù)字段0x00,0x00
響應(yīng)報(bào)文數(shù)據(jù)字段診斷寄存器的內(nèi)容

Force Listen Only Mode

診斷內(nèi)容強(qiáng)制只聽模式; 強(qiáng)制被尋址的從站設(shè)備進(jìn)入只聽模式,使得此設(shè)備與網(wǎng)絡(luò)中的其他設(shè)備斷開,不返回響應(yīng)
子功能碼0x00,0x04
查詢報(bào)文數(shù)據(jù)字段0x00,0x00
響應(yīng)報(bào)文數(shù)據(jù)字段不返回響應(yīng)

Clear Counters and Diagnostic Register

診斷內(nèi)容清除計(jì)數(shù)器和診斷寄存器
子功能碼0x00,0x0A
查詢報(bào)文數(shù)據(jù)字段0x00,0x00
響應(yīng)報(bào)文數(shù)據(jù)字段同查詢報(bào)文

Return Bus Message Count(11,0x0B)

診斷內(nèi)容返回總線報(bào)文計(jì)數(shù)
子功能碼0x00,0x0B
查詢報(bào)文數(shù)據(jù)字段0x00,0x00
響應(yīng)報(bào)文數(shù)據(jù)字段返回報(bào)文的技數(shù)值

Return Bus Communication Error Count(12,0x0C)

診斷內(nèi)容返回總線通信CRC差錯(cuò)計(jì)數(shù)
子功能碼0x00,0x0C
查詢報(bào)文數(shù)據(jù)字段0x00,0x00
響應(yīng)報(bào)文數(shù)據(jù)字段返回報(bào)文的CRC出錯(cuò)總數(shù)

Return Bus Exception Error Count(13,0x0D)

診斷內(nèi)容返回總線異常差錯(cuò)計(jì)數(shù)
子功能碼0x00,0x0D
查詢報(bào)文數(shù)據(jù)字段0x00,0x00
響應(yīng)報(bào)文數(shù)據(jù)字段返回異常響應(yīng)的總數(shù)

Return Slave Message Count(14,0x0E)

診斷內(nèi)容返回從站設(shè)備報(bào)文總數(shù)
子功能碼0x00,0x0E
查詢報(bào)文數(shù)據(jù)字段0x00,0x00
響應(yīng)報(bào)文數(shù)據(jù)字段返回從站設(shè)備接收報(bào)文總數(shù)

Return Slave No Response Counrt(15,0x0F)

診斷內(nèi)容返回從站設(shè)備無響應(yīng)計(jì)數(shù)
子功能碼0x00,0x0F
查詢報(bào)文數(shù)據(jù)字段0x00,0x00
響應(yīng)報(bào)文數(shù)據(jù)字段返回加電后沒有返回響應(yīng)的報(bào)文的保文數(shù)量

Return Slave Busy Count(17,0x11)

診斷內(nèi)容返回從站設(shè)備忙計(jì)數(shù)
子功能碼0x00,0x11
查詢報(bào)文數(shù)據(jù)字段0x00,0x00
響應(yīng)報(bào)文數(shù)據(jù)字段返回加電后異常響應(yīng)忙的報(bào)文數(shù)量

Return Bus Character Overrun Count(18,0x12)

診斷內(nèi)容返回總線字符超限計(jì)數(shù)
子功能碼0x00,0x12
查詢報(bào)文數(shù)據(jù)字段0x00,0x00
響應(yīng)報(bào)文數(shù)據(jù)字段返回超限的報(bào)文數(shù)量

5.5.9 11 (0x0B) 獲取通信事件計(jì)數(shù)器

1. 功能說明

11功能碼主要用于獲取從設(shè)備通信計(jì)數(shù)器中的狀態(tài)字和事件計(jì)數(shù)的值,本功能碼不支持廣播模式。通過在通信報(bào)文之前和之后讀取通信事件計(jì)數(shù)值,可以確定從設(shè)備是否正常處理報(bào)文。

對于正常完成報(bào)文處理和傳輸?shù)膱龊希录?jì)數(shù)器增加1;而對于異常響應(yīng)、輪詢命令或讀事件計(jì)數(shù)器(即Ox0B功能碼)的場合,則計(jì)數(shù)器不變。通過【0x08診斷功能】 中的子功能碼【Restart Communication Option ( 0x0001 )】 和 【Clear Counters and Diagnostic Register (0x000A) 】 可以復(fù)位事件寄存器。

2. 查詢報(bào)文

下表中的示例表示獲取通信事件計(jì)數(shù)器的查詢報(bào)文內(nèi)容,其中從站設(shè)備地址為5.

功能碼11查詢報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x05“0”,“5”0x05
功能碼0x0B“0”,“B”0x0B
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)94

3. 響應(yīng)報(bào)文

對于從設(shè)備,在正常情況下,響應(yīng)報(bào)文返回2字節(jié)的狀態(tài)字和2字節(jié)的事件計(jì)數(shù)。其中,如果從站設(shè)備處于忙狀態(tài),那么狀態(tài)字為0xFFFF,否則狀態(tài)字為0x0000。在表4-18的示例中,狀態(tài)字為0x0000,表示從站設(shè)備外于空閑狀態(tài)。事件計(jì)數(shù)的值為0x03E8,表示記錄了1000 (0x03E8)個(gè)事件。

功能碼11響應(yīng)報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x05“0”,“5”0x05
功能碼0x0B“0”,“B”0x0B
子功能碼(高位)0x00“0”,“0”0x00
子功能碼(低位)0x00“0”,“0”0x00
數(shù)據(jù)(高位)0x03“0”,“3”0x03
數(shù)據(jù)(低位)0xE8“E”,“8”0xB8
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

5.5.10 12 (0x0C) 獲取通信事件記錄

1. 功能說明

12功能碼主要用于從從設(shè)備獲取狀態(tài)字、事件計(jì)數(shù)、報(bào)文計(jì)數(shù)以及事件字節(jié)字段。其中,狀態(tài)字和事件計(jì)數(shù)與功能碼11 (0x0B) 獲取的值一致。報(bào)文計(jì)數(shù)包含加電重啟、清除計(jì)數(shù)器之后的報(bào)文數(shù)量,報(bào)文計(jì)數(shù)與通過診斷功能碼08 (0x08)、子功能碼11 (0x0B) 獲取的值一致。事件字節(jié)字段包含0~64字節(jié),用來定義各種事件。

2. 查詢報(bào)文

下表中的示例表示獲取通信事件記錄的查詢報(bào)文內(nèi)容,其中從站地址位5。

功能碼12查詢報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x05“0”,“5”0x05
功能碼0x0C“0”,“C”0x0C
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)94

3. 響應(yīng)報(bào)文

對于從站設(shè)備,在正常情況下,響應(yīng)報(bào)文包括一個(gè)2字節(jié)的狀態(tài)字字段、一個(gè)2字節(jié)的事件計(jì)數(shù)字段、一個(gè)2字節(jié)的消息計(jì)數(shù)字段以及0~ 64字節(jié)的事件字段。因?yàn)槭录侄问亲冮L的,所以增加了一個(gè)1字節(jié)的數(shù)據(jù)長度字段,以方便讀取響應(yīng)數(shù)據(jù),如下表所示;

功能碼12響應(yīng)報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x05“0”,“5”0x05
功能碼0x0C“0”,“C”0x0C
字節(jié)數(shù)0x08“0”,“8”0x08
狀態(tài)字(高位)0x00“0”,“0”0x00
狀態(tài)字(低位)0x00“0”,“0”0x00
事件計(jì)數(shù)(高位)0x03“0”,“3”0x03
事件計(jì)數(shù)(低位)0xE8“E”,“8”0xE8
消息計(jì)數(shù)(高位)0x01“0”,“1”0x01
消息計(jì)數(shù)(低位)0xF6”F“,”6“0xF6
事件00x20”2“,”0“0x20
事件10x00”0“,”0“0x00
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

5.5.11 15(0x0F)寫多個(gè)線圈

1.功能說明

15功能碼用于將連續(xù)的多個(gè)線圈或離散輸出設(shè)置為ON/OFF狀態(tài),支持廣播模式,在廣播模式下,所有從站設(shè)備的同一地址的值將被統(tǒng)一修改。15功能碼中,起始地址字段由2字節(jié)構(gòu)成,取值范圍為0x00000xFFFF:而寄存器數(shù)量字段由2字節(jié)構(gòu)成,取值范用為0x00010x07B0.

2. 查詢報(bào)文

查詢報(bào)文中包含請求數(shù)據(jù)字段,用于定義ON或OFF狀態(tài)。數(shù)據(jù)字段中為邏輯1的位對應(yīng)ON;邏輯0的位對應(yīng)OFF。其中,ON/OFF與數(shù)據(jù)字段的對應(yīng)關(guān)系可參考前面的童節(jié)“01 (0x01) 讀取線圈,離散量輸出狀態(tài) (Read Coil status/DOs)” 中的內(nèi)容舉例說明,假設(shè)從站設(shè)備地址為5,需要設(shè)置線圈地址20 ~30的狀態(tài)如下表所示。

線圈狀態(tài):

1101000100000101
線圈2726252423222120302928

那么,寫入的數(shù)據(jù)字段被劃分為2字節(jié),值分別為0xD1,對應(yīng)于27 ~ 20的線圈,值0x05對應(yīng)于30~28的線圈,注意細(xì)體會(huì)其中的高低位的對應(yīng)關(guān)系。需要注意的是,在查詢報(bào)文中,Modbus協(xié)議的起始地址為19 (0x13) ,即比線圈起始地址20少1。如下表所示,其中字節(jié)數(shù)字段表示需要變更數(shù)據(jù)的字節(jié)總數(shù)。

功能碼15查詢報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x05“0”,“5”0x05
功能碼0x0F“0”,“F”0x0F
起始地址(高位)0x00“0”,“0”0x00
起始地址(低位)0x13“1”,“3”0x13
寄存器數(shù)(高位)0x00“0”,“0”0x00
寄存器數(shù)(低位)0x0B“0”,“B”0x08
字節(jié)數(shù)0x02“0”,“2”0x02
變更數(shù)據(jù)(高位)0xD1”D“,”1“0xD1
變更數(shù)據(jù)(低位)0x05”0“,”5“0x05
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)2311

3. 響應(yīng)報(bào)文

對于從設(shè)備,在正常情況下,響應(yīng)報(bào)文包括功能碼、起始地址以及寫入的線圈數(shù)量,如下表所示。

功能碼15響應(yīng)報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x05“0”,“5”0x05
功能碼0x0F“0”,“F”0x0F
起始地址(高位)0x00“0”,“0”0x00
起始地址(低位)0x13“1”,“3”0x13
寄存器數(shù)(高位)0x00“0”,“0”0x00
寄存器數(shù)(低位)0x0B“0”,“B”0x08
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

5.5.12 16 (0x10) 寫多個(gè)保持寄存器

1. 功能說明

16功能碼用于設(shè)置或?qū)懭霃脑O(shè)備保持寄存器的多個(gè)連續(xù)的地址塊 (1 ~ 123個(gè)寄存器),支持廣播模式,在廣播模式下,所有從站設(shè)備的同一地址的值將被統(tǒng)一修改。本功能碼中,起始地址字段由2字節(jié)構(gòu)成,取值范圍為0x0000 ~ 0xFFFF;而寄存器數(shù)量字段由2字節(jié)構(gòu)成,取值范圍為0x0001~0x007B。

2. 查詢報(bào)文

查詢報(bào)文包含請求數(shù)據(jù)字段。數(shù)據(jù)字段保存需要寫入的數(shù)值,各數(shù)據(jù)按每個(gè)寄存器2字節(jié)存放。舉例說明,從站設(shè)備地址為5,需要將保持寄存器地址40020 ~ 40022設(shè)置為如下表所示的數(shù)值。

寄存器的設(shè)置:

寄存器地址設(shè)定值寄存器地址設(shè)定值
400200x0155400220x0157
400210x0156

對應(yīng)于40020~40022的寄存器,注意仔細(xì)體會(huì)其中的高低位的對應(yīng)關(guān)系。需要注意的是,在查詢報(bào)文中,Modbus協(xié)議的起始地址為19 (0x13),即比寄存器起始地址20少1。如下表所示,其中字節(jié)數(shù)字段表示需要變更數(shù)據(jù)的字節(jié)總數(shù)。

功能碼16查詢報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x05“0”,“5”0x05
功能碼0x10“0”,“F”0x0F
起始地址(高位)0x00“0”,“0”0x00
起始地址(低位)0x13“1”,“3”0x13
寄存器數(shù)(高位)0x00“0”,“0”0x00
寄存器數(shù)(低位)0x03“0”,“B”0x08
字節(jié)數(shù)0x06”0“,”6“0x06
變更數(shù)據(jù)1(高位)0x01”0“,”1“0x01
變更數(shù)據(jù)1(低位)0x55”5“,”5“0x56
變更數(shù)據(jù)2(高位)0x01”0“,”1“0x01
變更數(shù)據(jù)2(低位)0x56”5“,”6“0x56
變更數(shù)據(jù)3(高位)0x01”0“,”1“0x01
變更數(shù)據(jù)3(低位)0x57”5“,”7“0x57
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)3115

3. 響應(yīng)報(bào)文

對于從設(shè)備,在正常情況下,響應(yīng)報(bào)文包括功能碼、起始地址及寫入的寄存器數(shù)量,如下表所示。

功能碼16響應(yīng)報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x05“0”,“5”0x05
功能碼0x10“1”,“0”0x10
起始地址(高位)0x00“0”,“0”0x00
起始地址(低位)0x13“1”,“3”0x13
寄存器數(shù)(高位)0x00“0”,“0”0x00
寄存器數(shù)(低位)0x03“0”,“3”0x03
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

在實(shí)際開發(fā)過程中,功能碼“16 (0x10) 寫多個(gè)寄存器 (Preset Multiple Registers) ”通常用于方便用戶寫入多字節(jié)類型的數(shù)據(jù)。

例如,假設(shè)從站設(shè)備地址為5,需要向保持寄存器寫入一個(gè)32位 (4字節(jié)) 的浮點(diǎn)數(shù),那么此浮點(diǎn)數(shù)將占用2個(gè)寄存器地址。假設(shè)浮點(diǎn)數(shù)將存放在40001和40002寄存器中,設(shè)定值為1.235(即0x3F9E 147A)實(shí)際的查詢和響應(yīng)報(bào)文如下(其中標(biāo)記部分為設(shè)定的浮點(diǎn)數(shù)值,假設(shè)字節(jié)序?yàn)锳B-CD,參考第5.3.7章字節(jié)序和大小端的內(nèi)容)。

查詢報(bào)文: 05 10 00 00 00 02 04 3F 9E 14 7A 05 86
響應(yīng)報(bào)文: 05 10 00 00 00 02 40 4C

對于64位(8字節(jié))的雙精度浮點(diǎn)數(shù),同理將占用4個(gè)寄存器地址共8字節(jié)的空間。特別需要注意的是字節(jié)序及大小端的問題,前面討論過多字節(jié)存在大小端問題,因此主站設(shè)備和從站設(shè)備必須保持一致的規(guī)則處理,約定Modbus傳輸中的數(shù)據(jù)字段的字節(jié)序,否則會(huì)因?yàn)榇笮《瞬灰恢露a(chǎn)生數(shù)據(jù)處理錯(cuò)誤。

5.5.13 17 (0x11) 報(bào)告從站ID (僅用于串行鏈路)

1. 功能說明

17功能碼用于讀取從站設(shè)備的ID、類型描述、當(dāng)前狀態(tài)以及其他信息,不支持廣播模式。響應(yīng)消息的構(gòu)成依賴于設(shè)備而不盡相同。

2. 查詢報(bào)文

查詢報(bào)文中不包含請求數(shù)據(jù)字段。舉例說明,從站設(shè)備地址為5,獲取相關(guān)信息,如下表所示。

功能碼17查詢報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x05“0”,“5”0x05
功能碼0x11“1”,“1”0x11
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)94

3. 響應(yīng)報(bào)文

**對于從設(shè)備,在正常情況下,響應(yīng)報(bào)文包括從站ID、運(yùn)行狀態(tài)以及其他附加信息,如下表所示。運(yùn)行狀態(tài)字段占用1字節(jié),且0x00=OFF,0xFF=ON,而響應(yīng)報(bào)文的組成則由開發(fā)者決定。**

功能碼17響應(yīng)報(bào)文示例:

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x05“0”,“5”0x05
功能碼0x11“1”,“1”0x11
字節(jié)數(shù)設(shè)備相關(guān)設(shè)備相關(guān)設(shè)備相關(guān)
從設(shè)備ID設(shè)備相關(guān)設(shè)備相關(guān)設(shè)備相關(guān)
運(yùn)行狀態(tài)0xFF“F”,“F”0xFF
附加情報(bào)1設(shè)備相關(guān)設(shè)備相關(guān)設(shè)備相關(guān)
……設(shè)備相關(guān)設(shè)備相關(guān)設(shè)備相關(guān)
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

5.5.14 Modbus異常響應(yīng)

以上介紹了一些常見的公共功能碼的報(bào)文 (消息頓)構(gòu)成,廣播模式以外的查詢報(bào)文都希望能夠獲取一個(gè)正常的響應(yīng)報(bào)文。在通常情況下,從站設(shè)備將返回一個(gè)正常響應(yīng)報(bào)文,但是在某些特殊情況下將返回異常響應(yīng)報(bào)文。

對于查詢報(bào)文,存在以下4種處理反饋:

  • 正常接收,正常處理,返回正常響應(yīng)報(bào)文;
  • 因?yàn)橥ㄐ佩e(cuò)誤等原因造成從站設(shè)備沒有接收到查詢報(bào)文,主站設(shè)備將按超時(shí)處理:從站設(shè)備接收到的查詢報(bào)文存在通信錯(cuò)誤 (如LRC、CRC錯(cuò)誤等),此時(shí)從站設(shè)備將丟棄報(bào)文不響應(yīng),主站設(shè)備將按超時(shí)處理;
  • 從站設(shè)備接收到正確的報(bào)文,但是超過處理范圍(如不存在的功能碼或者寄存器等),此時(shí)從站設(shè)備將返回包含異常碼 (Exception Code) 的響應(yīng)報(bào)文。
  • 異常響應(yīng)報(bào)文由從站地址、功能碼以及異常碼構(gòu)成。其中,功能碼與正常響應(yīng)報(bào)文不同,在異常響應(yīng)報(bào)文中,功能碼最高位 (即MSB) 被設(shè)置為1。因?yàn)镸odbus協(xié)議中的功能碼占用1字節(jié)故用表達(dá)式描述為:
異常功能碼=正常功能碼+0x80

舉例說明,如下表所示,查詢報(bào)文的起始地址為0x012C (十進(jìn)制300) ,即需要讀取寄存器地址為30301開始的值。若從站設(shè)備中不存在輸入寄存器30301,則從站設(shè)備將返回一個(gè)異常響應(yīng)報(bào)文,參見下表的功能碼和異常碼。

異常響應(yīng)示例(功能碼04查詢報(bào)文 ):

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x07“0”,“7”0x07
功能碼0x04“0”,“4”0x04
起始地址(高位)0x01“0”,“1”0x01
起始地址(低位)0x2C“2”,“C”0x2C
寄存器數(shù)(高位)0x00“0”,“0”0x00
寄存器數(shù)(低位)0x03“0”,“3”0x03
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)178

異常響應(yīng)示例(功能碼04響應(yīng)報(bào)文 )

字段例(Hex)ASCII模式字符型RTU模式8位(Hex)
幀頭“:”
從設(shè)備地址0x07“0”,“7”0x07
功能碼0x84“8”,“4”0x84
異常碼0x02“0”,“2”0x02
差錯(cuò)校驗(yàn)LRC(2字符)CRC(2字節(jié))
幀尾CR/LF
合計(jì)字節(jié)數(shù)115

常見的異常碼如下表所示:

常見異常碼說明:

異常碼名稱說明
01非法功能碼從站設(shè)備不支持此功能碼
02非法數(shù)據(jù)地址指定的數(shù)據(jù)地址在從站設(shè)備中不存在
03非法數(shù)據(jù)值指定的數(shù)據(jù)超過范圍或者不允許使用
04從站設(shè)備故障從站設(shè)備處理響應(yīng)的過程中出現(xiàn)未知錯(cuò)誤等
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5250

    瀏覽量

    119195
  • MODBUS
    +關(guān)注

    關(guān)注

    28

    文章

    1718

    瀏覽量

    76415
  • 通訊協(xié)議
    +關(guān)注

    關(guān)注

    10

    文章

    263

    瀏覽量

    20271
收藏 人收藏

    評論

    相關(guān)推薦

    什么是Modbus通訊協(xié)議?Modbus通訊協(xié)議有什么特點(diǎn)?

    什么是Modbus通訊協(xié)議:  Modbus是由Modicon(現(xiàn)為施耐德電氣公司的一個(gè)品牌)在1979年發(fā)明的,是全球第一個(gè)真正用于工業(yè)現(xiàn)場的總線
    發(fā)表于 11-11 10:35

    基于LabVIEW的Modbus串口通訊協(xié)議的實(shí)現(xiàn)

    基于LabVIEW 的Modbus 串口通訊協(xié)議的實(shí)現(xiàn)附件基于LabVIEW 的Modbus 串口通訊協(xié)
    發(fā)表于 10-16 10:50

    ModBus通訊協(xié)議簡介

    ModBus通訊協(xié)議通訊協(xié)議又稱通信規(guī)程,是指通信雙方對數(shù)據(jù)傳送控制的一種約定。約定中包括對數(shù)據(jù)格式,同步方式,傳送速度,傳送步驟,檢糾錯(cuò)方
    發(fā)表于 08-23 09:19

    如何通過VISA編寫Modbus通訊協(xié)議

    什么是Modbus通訊協(xié)議?如何通過VISA編寫Modbus通訊協(xié)議呢?
    發(fā)表于 09-29 07:44

    Modbus通訊協(xié)議的幾種實(shí)現(xiàn)方式

    RTU和TCP兩種協(xié)議中轉(zhuǎn)換,根據(jù)需要選擇不同協(xié)議。這是LabVIEW多態(tài)的一個(gè)非常好的示例。程序見下圖。   5.LabVIEW 采用TCP模塊實(shí)現(xiàn)Modbus
    發(fā)表于 05-05 16:19

    MODBUS通訊協(xié)議及編程

    ModBus通訊協(xié)議分為RTU協(xié)議和ASCII協(xié)議,下面就ModBus?RTU
    發(fā)表于 07-17 11:58 ?1.5w次閱讀

    Modbus_通訊協(xié)議詳解

    Modbus_通訊協(xié)議詳解,Modbus_通訊協(xié)議詳解
    發(fā)表于 12-08 14:13 ?0次下載

    MODBUS通訊協(xié)議及編程

    MODBUS通訊協(xié)議及編程標(biāo)準(zhǔn)通訊協(xié)議格式,工業(yè)通信的標(biāo)準(zhǔn)格式。
    發(fā)表于 03-10 11:45 ?64次下載

    MODBUS通訊協(xié)議詳細(xì)介紹

    MODBUS通訊協(xié)議詳細(xì)介紹標(biāo)準(zhǔn)通訊協(xié)議格式,工業(yè)通信的標(biāo)準(zhǔn)格式。
    發(fā)表于 03-10 11:42 ?38次下載

    MODBUS通訊協(xié)議中文版

    介紹了MODBUS通訊協(xié)議的架構(gòu),和應(yīng)用,分享給大家,歡迎下載。
    發(fā)表于 08-09 17:33 ?0次下載

    Modbus通訊協(xié)議的原理和標(biāo)準(zhǔn)

    Modbus通訊協(xié)議分為RTU和ASCLL兩種傳輸模式,已經(jīng)成為一種標(biāo)準(zhǔn)工業(yè)控制協(xié)議。
    發(fā)表于 11-02 18:31 ?12次下載

    基于Modbus通訊協(xié)議的智能儀表設(shè)計(jì)

    基于Modbus通訊協(xié)議的智能儀表設(shè)計(jì)
    發(fā)表于 02-07 18:05 ?28次下載

    解讀Modbus通訊協(xié)議

    作為工控人,Modbus 通訊協(xié)議想必都不陌生,Modbus 通訊協(xié)議可以說是工業(yè)自動(dòng)化領(lǐng)域應(yīng)用
    的頭像 發(fā)表于 11-09 16:39 ?1281次閱讀

    Modbus通訊協(xié)議的詳細(xì)資料講解

    作為工控人,Modbus 通訊協(xié)議想必都不陌生,Modbus 通訊協(xié)議可以說是工業(yè)自動(dòng)化領(lǐng)域應(yīng)用
    發(fā)表于 11-27 02:01 ?54次下載
    <b class='flag-5'>Modbus</b><b class='flag-5'>通訊</b><b class='flag-5'>協(xié)議</b>的詳細(xì)資料講解

    Modbus TCP通訊協(xié)議概述

    1? Modbus TCP通訊概述 MODBUS/TCP是簡單的、中立廠商的用于管理和控制自動(dòng)化設(shè)備的MODBUS系列訊協(xié)議的派生產(chǎn)品,顯而
    的頭像 發(fā)表于 01-04 17:51 ?3w次閱讀
    <b class='flag-5'>Modbus</b> TCP<b class='flag-5'>通訊</b><b class='flag-5'>協(xié)議</b>概述