對于初涉嵌入式通信的開發(fā)者而言,如何在LuatOS系統(tǒng)中快速搭建Modbus RTU通信通道是一大難點。本文以實踐為導(dǎo)向,系統(tǒng)梳理從環(huán)境搭建、串口配置、協(xié)議封裝到數(shù)據(jù)解析的完整技術(shù)路徑。結(jié)合LuatOS的API特性,逐步引導(dǎo)讀者完成一個完整的Modbus RTU通信實例,為后續(xù)工業(yè)物聯(lián)網(wǎng)項目開發(fā)奠定堅實基礎(chǔ)。
一、Modbus 總體介紹
1.1 Modbus 的誕生背景
在 1979 年,那時候的中國還處于改革開放初期,而工業(yè)界正面臨一個“大麻煩”。
當時的 PLC 廠商,例如 艾倫-布拉德利(Allen-Bradley,AB)、西門子、通用電氣(General Electric,GE)......每個公司都像是獨立的“小王國”,自己搞一套通信協(xié)議,誰也不跟誰兼容!
這就導(dǎo)致了一個什么結(jié)果?
你買了 A 家的 PLC,想用 B 家的上位機軟件去監(jiān)控?不行!
想把傳感器、儀表傳到 PLC 上?不好意思,得找廠家專門開發(fā)驅(qū)動,又貴又慢!
整個系統(tǒng)就像一張拼圖,每塊都是不同品牌,根本拼不到一起!
這叫啥?江湖人稱——“七國八制”!
并不是說真有七個國家,是說市面上協(xié)議多得像戰(zhàn)國七雄,各搞各的,誰也管不了誰!
這種局面,不僅讓用戶頭疼,也讓整個行業(yè)的發(fā)展卡住了脖子!
于是,一家叫Modicon的公司(現(xiàn)在屬于施耐德電氣 Schneider Electric)站了出來,他們的工程師 John D.(這位大佬名字有點模糊,但貢獻巨大?。е鴪F隊,憋出了一個神協(xié)議——Modbus!
他們設(shè)計的時候,便定了三條“鐵律”:
第一,簡單到爆!
協(xié)議結(jié)構(gòu)清晰,功能碼就那么幾個,工程師看一天就能上手,調(diào)試起來不頭禿!
第二,完全開源免費!
這是最關(guān)鍵的一步!Modicon 把協(xié)議規(guī)范直接公開,誰都能拿去用,不用交錢,不用簽合同!
——這在當時簡直是“革命性”的操作!別的廠商都在藏著掖著,它直接攤開給你看!
第三,通用性強!
采用“主從架構(gòu)”——一個主控電腦,管理一堆設(shè)備(PLC、傳感器、儀表)。
所以,為什么 Modbus 能活到現(xiàn)在,40 多年還被廣泛使用?
就是因為這三條“鐵律”!
不炫技、不復(fù)雜,但解決了最實際的問題——讓設(shè)備之間能“說上話”!
1.2 Modbus 的發(fā)展歷史
很多人以為 Modbus 發(fā)明完就火了——其實根本不是! 它最初只是 Modicon 自家 PLC 的“內(nèi)部通訊工具”,連名字都沒幾個人知道 至于它是怎么從“小眾協(xié)議”變成“工業(yè)普通話”的? 我們接著往下看。
發(fā)展歷史我將其分成了三個階段:
階段一:1979 – 1990s 中期 — 串口時代,野蠻生長
Modbus 由Modicon 公司(后被施耐德電氣 Schneider Electric 收購)于 1979 年首創(chuàng),最初作為其 PLC 與智能設(shè)備(如傳感器、儀表)之間的專用通信協(xié)議。
協(xié)議運行在RS-232 或 RS-485 物理層上,支持兩種傳輸方式:
Modbus RTU:緊湊的二進制編碼,效率高,適用于噪聲環(huán)境;
Modbus ASCII:以可讀字符(十六進制)編碼,便于調(diào)試,但效率較低。
由于協(xié)議結(jié)構(gòu)極其簡單、無授權(quán)費用、文檔易于逆向,大量第三方設(shè)備廠商在未獲官方許可的情況下自行實現(xiàn)Modbus 接口,并集成到變送器(特指將物理量(如壓力、溫度等)轉(zhuǎn)換為標準電信號(如 4–20 mA 或 0–10 V),并通過 Modbus 接口(如 RTU 或 TCP)將這些數(shù)據(jù)以數(shù)字形式上傳的設(shè)備)、HMI(人機界面,用于操作人員與控制系統(tǒng)交互,顯示實時數(shù)據(jù)、報警信息,并允許操作員下發(fā)控制命令(如啟停設(shè)備、修改參數(shù)))、驅(qū)動器(控制電機的轉(zhuǎn)速、方向、啟停等,常用于風機、泵、傳送帶等設(shè)備)等產(chǎn)品中。
這一時期的 Modbus 雖無正式標準,卻憑借“事實標準”(de facto standard)的地位,在工業(yè)現(xiàn)場迅速擴散,為后續(xù)生態(tài)奠定用戶基礎(chǔ)。
階段二:1990s 末 – 2001 年 — 轉(zhuǎn)型與融合,擁抱網(wǎng)絡(luò)
關(guān)鍵轉(zhuǎn)折點:1990 年代末,Modicon 主動開放 Modbus 協(xié)議規(guī)范,公開技術(shù)文檔,鼓勵第三方廠商開發(fā)兼容產(chǎn)品,并停止對協(xié)議使用的法律限制。
與此同時,工業(yè)以太網(wǎng)興起,傳統(tǒng)串行通信在速度、距離和 IT 融合方面面臨瓶頸。
2000 年,Modicon 正式發(fā)布Modbus TCP 規(guī)范,將 Modbus 應(yīng)用層協(xié)議映射到標準 TCP/IP 協(xié)議棧上:
使用IP 地址 + 端口 502定位設(shè)備;
引入MBAP 頭部(含事務(wù) ID、協(xié)議 ID、長度字段);
依賴 TCP 的可靠性,取消 CRC 校驗和從站地址字段(Unit Identifier 保留用于網(wǎng)關(guān)場景)。
此階段完成了 Modbus 從“串行總線協(xié)議”到“工業(yè)網(wǎng)絡(luò)協(xié)議”的關(guān)鍵躍遷,打通 OT(運營技術(shù))與 IT(信息技術(shù))的邊界,為遠程監(jiān)控、系統(tǒng)集成和數(shù)字化轉(zhuǎn)型鋪平道路。
階段三:2002 年至今 — 開放治理,全球標準
2002 年,為推動協(xié)議的中立化與可持續(xù)發(fā)展,Schneider Electric 聯(lián)合多家工業(yè)自動化廠商,發(fā)起成立 Modbus International Developers Association(Modbus-IDA),負責:
制定一致性測試規(guī)范;
提供互操作性認證;
維護官方技術(shù)文檔。
2004 年,為進一步增強開放性與國際代表性,Modbus-IDA 的全部職能移交至新成立的非營利獨立組織 —— Modbus Organization, Inc.(在美國注冊),全面接管:
協(xié)議規(guī)范維護
一致性測試與認證服務(wù);
成員協(xié)作與生態(tài)推廣。
Modbus 協(xié)議本身完全開放、免費,任何廠商均可自由實現(xiàn);但若需使用“Modbus 認證”標志或參與標準演進,則需加入成員計劃并通過官方測試。
協(xié)議生態(tài)持續(xù)擴展,衍生出多種傳輸方式以適應(yīng)不同場景:
Modbus TCP:標準以太網(wǎng)協(xié)議,主流于現(xiàn)代工業(yè)網(wǎng)絡(luò);
Modbus RTU over Ethernet:通過 TCP 或 UDP 透傳原始 RTU 幀,常用于串口服務(wù)器或網(wǎng)關(guān);
Modbus Plus:施耐德專用高速令牌環(huán)網(wǎng)絡(luò)(已逐漸退出主流)。
現(xiàn)狀:據(jù)行業(yè)普遍估計,Modbus 仍是全球部署最廣泛的工業(yè)通信協(xié)議之一,廣泛應(yīng)用于 PLC、HMI、變頻器、智能儀表、能源管理系統(tǒng)等設(shè)備,尤其在中小型自動化系統(tǒng)、國產(chǎn)設(shè)備和成本敏感場景中占據(jù)主導(dǎo)地位。
二、Modbus 通信機制與協(xié)議規(guī)范
2.1 Modbus 通信架構(gòu)模型
Modbus 協(xié)議是 OSI 七層模型中第 7 層上的應(yīng)用層報文傳輸協(xié)議,它在連接不同類型總線或網(wǎng)絡(luò)的設(shè)備之間提供客戶端/服務(wù)器通信。
它主要是定義了應(yīng)用層的消息結(jié)構(gòu)(功能碼 + 數(shù)據(jù)),其底層依賴于其他通信方式來實現(xiàn)完整的通信功能,包括傳統(tǒng)的串行總線(RS-232/RS-485)、專有網(wǎng)絡(luò)(Modbus+),以及現(xiàn)代的以太網(wǎng)(Modbus TCP/IP)。
Modbus 的通信架構(gòu)模型如下圖所示:

通過這張圖可以很清晰地看出 Modbus 協(xié)議的分層架構(gòu)以及在不同物理和網(wǎng)絡(luò)層上的實現(xiàn)方式,直觀說明 Modbus 應(yīng)用層如何“嫁接”到多種底層傳輸技術(shù)上。
接下來,我們從上到下、從左到右進行解讀:
1、頂層:Modbus 應(yīng)用層
這是整張圖的核心。無論底層使用何種物理或網(wǎng)絡(luò)技術(shù),Modbus 應(yīng)用層定義了設(shè)備之間數(shù)據(jù)交換的規(guī)則和格式。這是統(tǒng)一、標準化的部分。
2、底層實現(xiàn)方式
從應(yīng)用層往下,有四條不同的“通道”,代表了 Modbus 協(xié)議在不同硬件和網(wǎng)絡(luò)環(huán)境下的具體實現(xiàn):
1.最左側(cè):“Other”
這是一個占位符,只是表示除了圖中列舉的三種方式外,Modbus 應(yīng)用層還可以運行在其他的物理層或傳輸層上。
2.第二個:“MODBUS+ / HDLC”
這是 Modicon 公司開發(fā)的一種專有高速網(wǎng)絡(luò)協(xié)議,它基于 HDLC(High-level Data Link Control)協(xié)議,并使用特定的物理介質(zhì)(例如雙絞線)。
特點是速度較快,但是屬于私有協(xié)議,兼容性不如 Modbus RTU、Modbus TCP。
3.第三個:“Client / Server”
這是最經(jīng)典的 Modbus RTU 或 Modbus ASCII 的實現(xiàn)方式。物理層采用 EIA/TIA-232 或 EIA/TIA-485,也就是我們常說的 RS232 或 RS485.
在這種模式下,通信通常是主從式(Master/Slave),因此,我們也可以將客戶端稱為主站,服務(wù)器稱為從站。
4.最右側(cè):“Modbus on TCP”
這是 Modbus 應(yīng)用層數(shù)據(jù)被封裝在 TCP/IP 數(shù)據(jù)包中的形式。也被稱為 Modbus TCP/IP。通過 TCP/IP 和以太網(wǎng)協(xié)議進行通信。
2.2 Modbus 協(xié)議數(shù)據(jù)結(jié)構(gòu)
Modbus 協(xié)議定義了一個與基礎(chǔ)通信層無關(guān)的簡單協(xié)議數(shù)據(jù)單元(PDU)。
這句話的意思是,不論你是使用任何方式進行傳輸 Modbus 信息,這部分結(jié)構(gòu)都是完全一樣。
特定總線或網(wǎng)絡(luò)上的 Modbus 協(xié)議映射能夠在應(yīng)用數(shù)據(jù)單元(ADU)上引入一些附加字段。
這句話的意思是,當你決定通過某種方式進行傳輸這個 PDU 時,你需要為其套上一個額外的附加字段,這個附加字段與 PDU 組合后稱為 ADU。
通用協(xié)議結(jié)構(gòu)的格式如下圖所示:

接下來對 PDU 和 ADU 進行說明:
2.2.1 PDU(Protocol Data Unit,協(xié)議數(shù)據(jù)單元)
PDU 是獨立于通信網(wǎng)絡(luò)的、純粹的 Modbus 請求或響應(yīng)參數(shù),由功能碼 + 數(shù)據(jù)兩部分組成。
PDU 作為 Modbus 協(xié)議的核心,特點是對于任何傳輸方式來說其結(jié)構(gòu)都是完全相同的。
例如,一個讀保持寄存器的請求 PDU 結(jié)構(gòu)永遠都是
[功能碼][起始地址高字節(jié)][起始地址低字節(jié)][寄存器數(shù)量高字節(jié)][寄存器數(shù)量低字節(jié)]
其中,功能碼固定為0x03,起始地址、寄存器數(shù)量需要根據(jù)具體請求進行修改。
2.2.2 ADU(Application Data Unit,應(yīng)用數(shù)據(jù)單元)
ADU 是實際網(wǎng)絡(luò)中傳輸?shù)耐暾麛?shù)據(jù)幀,由附加地址 + PDU + 差錯校驗碼三部分組成。
ADU 的特點是 PDU 為了在特定網(wǎng)絡(luò)(如串行線、TCP/IP)上傳輸而添加的“頭”和“尾”。
不同的傳輸方式,ADU 的結(jié)構(gòu)也會不同。
PDU 與 ADU 最大長度限制說明:Modbus PDU 最大 253 字節(jié)是歷史遺留設(shè)計,源于 RS-485 ADU 最大 256 字節(jié)的限制; 在串行通信中,ADU = PDU + 1 字節(jié)地址 + 2 字節(jié) CRC = 256 字節(jié); 在 TCP 中,ADU = PDU + 7 字節(jié) MBAP = 260 字節(jié);
2.3 客戶端/服務(wù)器 與 主站/從站 的概念辨析
在 Modbus 協(xié)議中,“客戶端/服務(wù)器”和“主站/從站”是描述通信角色的兩種常用術(shù)語,它們在功能上高度相似,但在語義來源和適用場景上略有不同。
2.3.1 客戶端 (Client) 與 服務(wù)器 (Server)
來源:來源于計算機網(wǎng)絡(luò)領(lǐng)域的通用模型。
定義:
客戶端:主動發(fā)起請求的一方,負責發(fā)送功能碼和數(shù)據(jù)請求。
服務(wù)器:被動響應(yīng)請求的一方,負責執(zhí)行操作并返回結(jié)果。
適用場景:主要用于 Modbus TCP/IP 等基于網(wǎng)絡(luò)協(xié)議棧的實現(xiàn)中,更符合現(xiàn)代 IT 架構(gòu)的表達習慣。
特點:強調(diào)“請求-響應(yīng)”的交互模式,不強調(diào)物理拓撲或控制權(quán)。
2.3.2 主站 (Master) 與 從站 (Slave)
來源:來源于工業(yè)自動化和串行通信的歷史傳統(tǒng)。
定義:
主站:擁有通信控制權(quán)的一方,負責輪詢或指令下發(fā)。
從站:被動響應(yīng)主站指令,無權(quán)主動發(fā)起通信。
適用場景:主要用于 Modbus RTU/ASCII 等串行通信方式中,強調(diào)“控制權(quán)集中”和“單主多從”的物理拓撲。
特點:更強調(diào)控制關(guān)系和時序管理,常見于 RS-485 總線系統(tǒng)。
2.3.3 兩者關(guān)系說明

特別說明:目前 Modbus 組織(Modbus Organization)已正式推薦使用 “客戶端/服務(wù)器” 術(shù)語替代“主站/從站”,以避免潛在的社會文化敏感性問題,并統(tǒng)一跨平臺、跨協(xié)議的表述。 但在實際工程文檔和設(shè)備手冊中,“主站/從站”仍被廣泛使用。
2.4 Modbus 事務(wù)處理機制
2.4.1 正常響應(yīng)

在啟動請求階段,客戶端將功能碼和數(shù)據(jù)請求發(fā)給服務(wù)器。服務(wù)器收到客戶端發(fā)來的請求后進行分析與處理操作。處理結(jié)束后,服務(wù)器向客戶端發(fā)送處理結(jié)果,即返回功能碼和數(shù)據(jù)響應(yīng)。
在正常響應(yīng)時,返回的功能碼為客戶端請求時的功能碼,數(shù)據(jù)響應(yīng)為實際請求到的數(shù)據(jù)。
2.4.2 異常響應(yīng)

在異常響應(yīng)時,返回的功能碼為客戶端請求時的功能碼 + 0x80,稱為差錯碼。數(shù)據(jù)響應(yīng)為異常碼。
此處簡單介紹一下什么是差錯碼和異常碼:
1、差錯碼(Error Code):
它本質(zhì)上是原始請求功能碼的最高位被置為 1
原始功能碼是一個 1 字節(jié)數(shù)值,范圍是 1~127,HEX 表示為 0x01~0x7F
將這個值加上 128,即0x80,就得到了差錯碼。此時范圍是 129~255,HEX 表示為 0x81~0xFF
作用:告訴客戶端“你剛才發(fā)的請求不正確”。例如,如果客戶端請求時的功能碼為0x03,那么異常響應(yīng)中的差錯碼就是0x83(0x03 + 0x80)
2、異常碼(Exception Code):
也占用 1 個字節(jié)數(shù)值,緊跟在差錯碼后面,用于具體說明出錯的原因
作用:告訴客戶端究竟是哪里出了問題
舉 4 個常見的異常碼:
01:非法功能碼,表示從站設(shè)備不支持請求的功能碼
02:非法數(shù)據(jù)地址,表示請求的寄存器地址不存在或者無效
03:非法數(shù)據(jù)值,表示請求的數(shù)據(jù)字段無效
04:從站設(shè)備故障,表示從站設(shè)備在執(zhí)行請求時發(fā)生內(nèi)部錯誤
三、Modbus 數(shù)據(jù)模型
3.1 Modbus 四種基本數(shù)據(jù)類型
注:Modbus 協(xié)議中通常將這四類稱為“數(shù)據(jù)對象”(Data Objects),但在工程實踐中常簡稱為“數(shù)據(jù)類型”,本文將沿用此習慣進行介紹。
Modbus 協(xié)議定義了四種基本類型(線圈、離散輸入、輸入寄存器、保持寄存器)。采取這樣的劃分是基于工業(yè)控制系統(tǒng)中常見的硬件接口特性、數(shù)據(jù)訪問需求以及通信效率的綜合考量。通過將數(shù)據(jù)按照功能、讀寫屬性和物理意義進行分類,Modbus 在保持協(xié)議間接性的同時,可以有效映射真實設(shè)備的輸入輸出行為,為不同廠商設(shè)備之間的互操作性提供清晰、一致的數(shù)據(jù)模型基礎(chǔ)。
3.1.1 線圈(Coils)
中文別名:數(shù)字輸出、開關(guān)輸出、DO(Digital Output)
存儲單元:單比特(1 bit)
數(shù)值范圍:兩種狀態(tài):0(OFF)或 1(ON)
訪問權(quán)限:可讀可寫
功能碼:
01(0x01):讀單個或多個線圈
05(0x05):寫單個線圈
15(0x0F):寫多個線圈
典型用途:控制繼電器、開關(guān)、指示燈等數(shù)字輸出設(shè)備
實際應(yīng)用舉例:
控制繼電器的吸合或斷開
控制電機的啟動或停止
控制閥門的開啟或關(guān)閉
控制指示燈的點亮或熄滅
3.1.2 離散輸入(Discrete Inputs)
中文別名:數(shù)字輸入、開關(guān)輸入、DI(Digital Input)
存儲單元:單比特(1 bit)
數(shù)值范圍:兩種狀態(tài):0(OFF)或 1(ON)
訪問權(quán)限:只讀
功能碼:
02(0x02):讀單個或多個離散輸入
典型用途:讀取限位開關(guān)、按鈕、傳感器等數(shù)字輸入狀態(tài)
實際應(yīng)用舉例:
讀取一個按鈕是否被按下
檢測一個限位開關(guān)是否觸發(fā)
判斷門磁傳感器是否報警(門 開/關(guān))
查看故障報警信號的狀態(tài)
3.1.3 輸入寄存器(Input Registers)
中文別名:模擬量輸入、只讀寄存器、AI(Analog Input)
存儲單元:16 位(2 bytes)
數(shù)值范圍:0~65535(無符號)或者 -32768~32767(有符號,屬于非協(xié)議標準,需要主/從站設(shè)備配合實現(xiàn))
訪問權(quán)限:只讀
功能碼:
04(0x04):讀單個或多個輸入寄存器
典型用途:讀取傳感器溫度、壓力、電壓等模擬量輸入值
實際應(yīng)用舉例:
讀取溫度傳感器的測量值(如 25.4℃)
讀取壓力傳感器的實際壓力
讀取流量計的當前流量
讀取設(shè)備運行的累計時間(通常由設(shè)備內(nèi)部維護,此處只供讀?。?/p>
3.1.4 保持寄存器(Holding Registers)
中文別名:模擬量輸出、讀寫寄存器、AO(Analog Output)
存儲單元:0~65535(無符號)或者 -32768~32767(有符號,屬于非協(xié)議標準,需要主/從站設(shè)備配合實現(xiàn))
訪問權(quán)限:可讀可寫
功能碼:
03(0x03):讀單個或多個保持寄存器
06(0x06):寫單個保持寄存器
16(0x10):寫多個保持寄存器
典型用途:存儲配置參數(shù)、設(shè)定值、設(shè)備狀態(tài)等可被主站設(shè)備修改的數(shù)據(jù)
實際應(yīng)用舉例:
寫入方面:設(shè)置目標溫度、設(shè)定電機轉(zhuǎn)速、修改報警閾值、發(fā)送控制命令代碼
讀取方面:讀取設(shè)備內(nèi)部計算的參數(shù)、獲取系統(tǒng)狀態(tài)信息、讀取預(yù)置的配方數(shù)據(jù)
3.1.5 基本數(shù)據(jù)類型一覽表

3.2 Modbus 數(shù)據(jù)區(qū)與尋址
從實現(xiàn)的角度來看,Modbus 協(xié)議將這四種數(shù)據(jù)類型概念性地組織為四個獨立的數(shù)據(jù)區(qū)。
每個數(shù)據(jù)區(qū)都是一個線性的地址空間:

注意:表中“邏輯地址”是面向用戶的編號系統(tǒng)。實際 Modbus 報文(PDU)中傳輸?shù)氖菑?0 開始的偏移量,也正是我接下來開始介紹的 5.3 地址映射。
3.3 Modbus 地址映射
3.3.1 核心概念
1.寄存器地址/偏移量(Register Address/Offset)
含義:Modbus 報文 PDU 中實際傳輸?shù)募拇嫫?線圈起始地址,是從 0 開始的 16 位無符號整數(shù)偏移量。
特點:范圍理論上為 0-65535,但具體支持的地址范圍由從站設(shè)備內(nèi)部定義的數(shù)據(jù)模型決定。
示例:讀取保持寄存器 40001 -> 實際協(xié)議地址為 0x0000;讀取 40010 -> 協(xié)議地址為 0x0009。
2.邏輯地址/參考地址(Logical Address/Reference Address)
含義:面向用戶和工程師的地址表示法,用于配置和編程時直觀區(qū)分數(shù)據(jù)類型。由功能前綴 + 序號組成。
特點:通常為 5 位十進制數(shù),前綴固定表示數(shù)據(jù)區(qū)類型:
0xxxx:線圈(Coils)
1xxxx:離散輸入(Discrete Inputs)
3xxxx:輸入寄存器(Input Registers)
4xxxx:保持寄存器(Holding Registers)
示例:40001,30002,10005,00003
3.3.2 轉(zhuǎn)換關(guān)系與規(guī)則
轉(zhuǎn)換的核心規(guī)則是:協(xié)議地址 = 邏輯地址 - 基地址
這個“基地址”因數(shù)據(jù)類型而異,從而形成不同的邏輯地址范圍

重要提示:
表中的“9998”是一個常規(guī)上限,由于協(xié)議地址是 16 位無符號整數(shù),其理論范圍是 0-65535,此時 5 位數(shù)已經(jīng)無法滿足,于是也有許多廠商使用 6 位數(shù)字進行表示:
0xxxxx:線圈(Coils)
1xxxxx:離散輸入(Discrete Inputs)
3xxxxx:輸入寄存器(Input Registers)
4xxxxx:保持寄存器(Holding Registers)
這是對原始 5 位數(shù)表示的擴展,我們在平時使用時,一定要先查閱各個產(chǎn)品的設(shè)備手冊,查看邏輯地址和協(xié)議地址范圍。
3.3.3 轉(zhuǎn)換示例
假如你在 HMI(人機界面)或者上位機軟件中配置了一個數(shù)據(jù)標簽,標簽指向保持寄存器 40100。
1.確定數(shù)據(jù)類型:地址以 4 開頭,說明是保持寄存器。
2.應(yīng)用轉(zhuǎn)換公式:協(xié)議地址 = 設(shè)備地址 - 40001。
3.進行計算:40100 - 40001 = 99,這是十進制數(shù)值,十六進制表示為0x0063。
當主站設(shè)備需要讀取這個標簽時,它會組成這樣一個 PDU 報文:
功能碼:0x03(讀保持寄存器)
起始地址:0x000x63(高字節(jié)為 0,低字節(jié)為 99)
數(shù)量:0x000x01(讀取 1 個寄存器)
從站設(shè)備在收到請求后,便會去自己的保持寄存器數(shù)據(jù)區(qū)中,查找協(xié)議地址為 99 的寄存器,然后組成響應(yīng)報文后返回給主站設(shè)備
3.4 Modbus 數(shù)據(jù)模型相關(guān)說明
Modbus 協(xié)議本身只定義了數(shù)據(jù)的類型和訪問方式,但并沒有規(guī)定這些數(shù)據(jù)具體代表什么含義或如何被使用。
盡管協(xié)議定義了四種獨立的數(shù)據(jù)區(qū),但從抽象或?qū)崿F(xiàn)的角度看,可以認為它們在功能或存儲上是相互重疊、相互表示的。
解釋一:從邏輯上看,一個 16 位的寄存器可以看作是 16 個獨立的比特。因此,從數(shù)據(jù)存儲的潛力上來說,保持寄存器的地址空間(每個地址存 16 位)可以“覆蓋”或“包含”線圈的地址空間(每個地址存 1 位)。同理,輸入寄存器的地址空間也可以“覆蓋”離散輸入的地址空間。
解釋二:在某些系統(tǒng)的內(nèi)存實現(xiàn)中,這四種數(shù)據(jù)區(qū)可能最終都會映射到同一片物理內(nèi)存或處理邏輯上。雖然 Modbus 協(xié)議將它們分為四種數(shù)據(jù)區(qū),但底層硬件可能用統(tǒng)一的方式管理它們。
對于數(shù)據(jù)區(qū)中的任何一項,Modbus 協(xié)議都允許單個地選擇 65536 個數(shù)據(jù)項。
Modbus 協(xié)議允許在一次請求中,批量寫入多個連續(xù)的地址。你不需要為了讀取 10 個連續(xù)的保持寄存器而發(fā)送 10 次單獨的請求,只需要發(fā)送一次請求,并告訴從站設(shè)備“從地址 X 開始,給我 Y 個寄存器的值”。
雖然可以批量讀寫,但一次操作所能處理的最大數(shù)據(jù)量是有限制的。這個限制不是來自地址空間(65536),而主要取決于所使用的功能碼和 Modbus 傳輸模式。
通過 Modbus 處理的所有數(shù)據(jù)放置在設(shè)備應(yīng)用存儲器中。但是,存儲器的物理地址不應(yīng)該與數(shù)據(jù)參考混淆。要求僅僅是數(shù)據(jù)參考與物理地址的鏈接。
Modbus 功能碼中使用的 Modbus 邏輯參考數(shù)字是以 0 開始的無符號整數(shù)索引。
四、Modbus 功能碼
Modbus 協(xié)議定義了三類功能碼,分別為公共功能碼、用戶定義功能碼、保留功能碼。
在介紹這三類功能碼之前,有一點需要注意,我們平時在使用這些功能碼時需要先去查閱設(shè)備手冊,查看使用的設(shè)備都支持哪些功能碼,包括公共功能碼也并非是全部都支持。
4.1 公共功能碼(Public Function Codes)
這是最常用、被官方 Modbus 協(xié)議標準明確定義、保證唯一性且得到最廣泛支持的功能碼。它們用于執(zhí)行最核心的數(shù)據(jù)讀寫操作。
這類功能碼又可細分為核心數(shù)據(jù)訪問功能、診斷功能和其他專用功能三個類別。
1.核心數(shù)據(jù)訪問功能碼
這些是用于讀寫設(shè)備基本數(shù)據(jù)(線圈、離散輸入、寄存器)的最常用功能。

2. 診斷功能碼
這些功能碼用于查詢通信狀態(tài)、設(shè)備異常和設(shè)備標識信息,主要用于調(diào)試和監(jiān)控。

3. 其他專用功能

4.2 用戶定義功能碼(User-Defined Function Codes)
這類功能碼保留給公司或個人,用于為特定的設(shè)備開發(fā)自定義的功能。
范圍:65 至 72 和 100 至 110。
特點:
Modbus 官方標準沒有為這些代碼定義任何行為。
其功能和實現(xiàn)完全由用戶(設(shè)備廠商)自行定義。
不能保證被選功能碼的使用是唯一的。
使用這些功能碼的設(shè)備之間在進行通信時不具備通用性。必須完全依賴設(shè)備廠商提供的文檔來了解如何使用它們。
4.3 保留功能碼(Reserved Function Codes)
這些功能碼在過去被一些傳統(tǒng)的 Modbus 設(shè)備使用,或者被保留給未來可能的標準擴展使用。在新設(shè)備和項目中應(yīng)避免使用它們。
范圍:8/19;8/21-65535,9,10,13,14,41,42,90,91,125,126,127 功能碼。
特點:它們沒有公共定義,可能在某些老舊系統(tǒng)中存在,但不在現(xiàn)代 Modbus 標準之內(nèi)。
4.4 功能碼示例描述
4.4.1 (0x01)讀取線圈
該功能碼用于從從站設(shè)備中讀取1 ~ 2000 個連續(xù)的線圈(Coil)狀態(tài)。
請求 PDU 中指定了起始地址(即所請求的第一個線圈的地址)以及線圈數(shù)量。
在 PDU 中,線圈地址從 0 開始。因此,編號為 1 - 16 的線圈,其地址為 0 - 15。
響應(yīng)報文中的線圈狀態(tài)以每比特表示一個線圈的方式打包在數(shù)據(jù)字段中。
狀態(tài)值1 表示 ON(開啟),0 表示 OFF(關(guān)閉)。
第一個數(shù)據(jù)字節(jié)的最低有效位(LSB)對應(yīng)查詢中指定的起始地址線圈,其余線圈依次向該字節(jié)的高位排列,并在后續(xù)字節(jié)中繼續(xù)從低位到高位依次填充。
如果返回的線圈數(shù)量不是 8 的整數(shù)倍,則最后一個數(shù)據(jù)字節(jié)的高位將用 0 填充。
字節(jié)數(shù)字段表示數(shù)據(jù)字段中完整字節(jié)的數(shù)量。
請求 PDU:

響應(yīng) PDU:

N = 線圈數(shù)量 / 8 。
異常響應(yīng):

舉例分析:
以下為讀取線圈 20 - 38 的請求示例:

線圈 27 - 20 的狀態(tài)以字節(jié)值CD(十六進制)表示,即二進制1100 1101。
其中,線圈 27 位于該字節(jié)的最高有效位(MSB),線圈 20 位于最低有效位(LSB)。
按照慣例,字節(jié)內(nèi)的比特位從左到右依次表示 MSB 到 LSB。
因此,第一個字節(jié)中的線圈從左到右依次為27、26、25、24、23、22、21、20。
下一個字節(jié)則包含線圈35 - 28,同樣從左到右排列。
然而,在串行傳輸時,比特位是從 LSB 到 MSB 依次發(fā)送的,即:
20 → 21 → … → 27,接著 28 → 29 → … → 35,依此類推。
在最后一個數(shù)據(jù)字節(jié)中,線圈 38 - 36 的狀態(tài)以字節(jié)值05(十六進制)表示,即二進制0000 0101。
其中,線圈 36 位于 LSB(最右側(cè)),線圈 38 位于從左往右數(shù)的第 6 位(即 bit 2,從 0 開始計數(shù))。
該字節(jié)中剩余的高 5 位(bit 7 到 bit 3)均以 0 填充。
4.4.2 (0x02)讀取離散輸入
該功能碼用于從從站設(shè)備中讀取1 ~ 2000 個連續(xù)的離散輸入狀態(tài)。
請求 PDU 中指定了起始地址(即所請求的第一個離散輸入的地址)以及離散輸入的數(shù)量。
在 PDU 中,離散輸入的地址從 0 開始。因此,編號為 1 - 16 的離散輸入,其地址為 0 - 15。
響應(yīng)報文中的離散輸入狀態(tài)以每比特表示一個離散輸入的方式打包在數(shù)據(jù)字段中。
狀態(tài)值1 表示 ON(開啟),0 表示 OFF(關(guān)閉)。
第一個數(shù)據(jù)字節(jié)的最低有效位(LSB)對應(yīng)查詢中指定的起始地址離散輸入,其余離散輸入依次向該字節(jié)的高位排列,并在后續(xù)字節(jié)中繼續(xù)從低位到高位依次填充。
如果返回的離散輸入數(shù)量不是 8 的整數(shù)倍,則最后一個數(shù)據(jù)字節(jié)的高位將用 0 填充。
字節(jié)數(shù)字段表示數(shù)據(jù)字段中完整字節(jié)的數(shù)量。
請求 PDU:

響應(yīng) PDU:

N = 輸入數(shù)量 / 8 。
異常響應(yīng):

舉例分析:
以下為讀取離散輸入 197 - 218 的請求示例:

離散輸入 204 - 197 的狀態(tài)以字節(jié)值AC(十六進制)表示,即二進制1010 1100。
其中,離散輸入 204 位于該字節(jié)的最高有效位(MSB,最左側(cè)),離散輸入 197 位于最低有效位(LSB,最右側(cè))。
離散輸入 218 - 213 的狀態(tài)以字節(jié)值35(十六進制)表示,即二進制0011 0101。 其中,離散輸入 213 位于 LSB(最右側(cè)),離散輸入 218 位于從左往右數(shù)的第 3 位(即 bit 5,從 0 開始計數(shù))。
4.4.3 (0x03)讀取保持寄存器
該功能碼用于讀取從從站設(shè)備中讀取1 ~ 125 個連續(xù)的保持寄存器。
請求 PDU 中指定了寄存器起始地址和要讀取的寄存器數(shù)量。
在 PDU 中,寄存器地址從 0 開始。因此,編號為 1 - 16 的寄存器,其地址為 0 - 15。
響應(yīng)報文中的寄存器數(shù)據(jù)以每個寄存器占用兩個字節(jié)的方式打包,二進制數(shù)值在 16 位空間中右對齊(即采用標準整數(shù)格式)。
對于每個寄存器,第一個字節(jié)包含高字節(jié)(高 8 位),第二個字節(jié)包含低字節(jié)(低 8 位)。
請求 PDU:

響應(yīng) PDU:

N = 保持寄存器的數(shù)量 。
異常響應(yīng):

舉例分析:
以下為讀取保持寄存器 108 - 110 的請求示例:

保持寄存器 108 的內(nèi)容以兩個字節(jié)表示為02 2B(十六進制),即十進制555。
保持寄存器 109 - 110 的內(nèi)容分別為00 00和00 64(十六進制),即十進制0和100。
4.4.4 (0x04)讀取輸入寄存器
該功能碼用于從從站設(shè)備中讀取1 ~ 125 個連續(xù)的輸入寄存器。
請求 PDU 中指定了寄存器起始地址和要讀取的寄存器數(shù)量。
在 PDU 中,寄存器地址從 0 開始。因此,編號為 1 - 16 的輸入寄存器,其地址為 0 - 15。
響應(yīng)報文中的寄存器數(shù)據(jù)以每個寄存器占用兩個字節(jié)的方式打包,二進制數(shù)值在 16 位空間中右對齊(即采用標準整數(shù)格式)。
對于每個寄存器,第一個字節(jié)包含高字節(jié)(高 8 位),第二個字節(jié)包含低字節(jié)(低 8 位)。
請求 PDU:

響應(yīng) PDU:

N = 輸入寄存器的數(shù)量 。
異常響應(yīng):

舉例分析:
以下是讀取輸入寄存器 9 的請求示例:

輸入寄存器 9 的內(nèi)容以兩個字節(jié)表示為00 0A(十六進制),即十進制10。
4.4.5 (0x05)寫入單個線圈
該功能碼用于將從站設(shè)備中的單個線圈強制置為 ON 或 OFF。
請求數(shù)據(jù)字段中的一個常量用于指定所需的 ON/OFF 狀態(tài):
值為FF00(十六進制)表示將線圈置為ON;
值為0000(十六進制)表示將線圈置為OFF;
所有其他值均為非法,不會對線圈狀態(tài)產(chǎn)生任何影響。
請求 PDU 中指定了要操作的線圈地址。線圈地址從 0 開始,因此編號為 1 的線圈,其地址為0。
ON/OFF 狀態(tài)由輸出值字段中的常量指定:
0xFF00表示 ON,
0x0000表示 OFF,
其他值無效,線圈狀態(tài)保持不變。
正常響應(yīng)是在線圈狀態(tài)成功寫入后,原樣返回請求報文的內(nèi)容(即請求的回顯)。
請求 PDU:

響應(yīng) PDU:

異常響應(yīng):

舉例分析:
以下是將線圈 173 置為 ON 的寫請求示例:
4.4.6 (0x06)寫入單個寄存器
該功能碼用于向從站設(shè)備中寫入一個保持寄存器。
請求 PDU 中指定了要寫入的寄存器地址。寄存器地址從 0 開始,因此編號為 1 的寄存器,其地址為0。
正常響應(yīng)是在寄存器內(nèi)容成功寫入后,原樣返回請求報文的內(nèi)容(即請求的回顯)。
請求 PDU:

響應(yīng) PDU:

異常響應(yīng):

舉例分析:
以下是將寄存器 2 寫入值 00 03(十六進制)的請求示例:

4.4.7 (0x0F)寫多個線圈
該功能碼用于將從站設(shè)備中一段連續(xù)線圈序列中的每一個線圈強制置為 ON 或 OFF。
請求 PDU 中指定了要操作的線圈起始地址和數(shù)量。線圈地址從 0 開始,因此編號為 1 的線圈,其地址為 0。
請求數(shù)據(jù)字段中的每一位指定了對應(yīng)線圈的目標狀態(tài):
某一位為邏輯 ‘1’,表示將對應(yīng)的線圈置為ON;
某一位為邏輯 ‘0’,表示將對應(yīng)的線圈置為OFF。
正常響應(yīng)將返回功能碼、起始地址以及被強制寫入的線圈數(shù)量。
請求 PDU:

N = 線圈數(shù)量 / 8 。
響應(yīng) PDU:

異常響應(yīng):

舉例分析:
以下是一個從線圈 20 開始,連續(xù)寫入 10 個線圈的請求示例:
請求的數(shù)據(jù)內(nèi)容為兩個字節(jié):CD 01(十六進制),即二進制 1100 1101 0000 0001。
這些二進制位與線圈的對應(yīng)關(guān)系如下:

第一個傳輸?shù)淖止?jié)(CD hex)對應(yīng)線圈 27 - 20,其中最低有效位(LSB)對應(yīng)線圈 20。
下一個傳輸?shù)淖止?jié)(01 hex)對應(yīng)線圈 29 - 28,同樣,最低有效位對應(yīng)線圈 28。
最后一個數(shù)據(jù)字節(jié)中未使用的高位應(yīng)填充為 0。

4.4.8 (0x10)寫多個寄存器
該功能碼用于向從站設(shè)備中寫入1 - 123 個連續(xù)的寄存器塊。
請求數(shù)據(jù)字段中指定了要寫入的寄存器值,數(shù)據(jù)以每個寄存器兩個字節(jié)的方式打包。
正常響應(yīng)將返回功能碼、寄存器起始地址以及成功寫入的寄存器數(shù)量。
請求 PDU:

N = 寄存器數(shù)量 。
響應(yīng) PDU:

異常響應(yīng):

舉例分析:
以下是一個從寄存器 2 開始,連續(xù)寫入 2 個寄存器的請求示例:
請求寫入的寄存器內(nèi)容分別為 00 0A(十六進制)和 01 02(十六進制)。

4.5 異常響應(yīng)
4.5.1 異常碼說明
當主站設(shè)備向從站設(shè)備發(fā)送請求時,它期望得到一個正常響應(yīng)。主站設(shè)備的查詢可能導(dǎo)致以下四種情況發(fā)生其一:
如果從站設(shè)備收到請求且無通信錯誤,并能正常處理該查詢,則返回一個正常響應(yīng)。
如果從站設(shè)備因通信錯誤未能收到請求,則不會返回任何響應(yīng)。主站設(shè)備程序最終將處理此請求的超時狀態(tài)。
如果從站設(shè)備收到請求,但檢測到通信錯誤(奇偶校驗、LRC、CRC 等錯誤),則不會返回任何響應(yīng)。主站設(shè)備程序最終將處理此請求的超時狀態(tài)。
如果從站設(shè)備收到請求且無通信錯誤,但無法處理它(例如,請求讀取一個不存在的輸出或寄存器),從站設(shè)備將返回一個異常響應(yīng),通知主站設(shè)備錯誤的性質(zhì)。
異常響應(yīng)消息有兩個字段,使其與正常響應(yīng)區(qū)分開來:
功能碼字段:
在正常響應(yīng)中,從站設(shè)備會在響應(yīng)的功能碼字段中原樣回顯原始請求的功能碼。
所有功能碼的最高有效位(MSB)均為 0(它們的值都低于 80 十六進制)。
在異常響應(yīng)中,從站設(shè)備會將功能碼的 MSB 設(shè)置為 1。
這使得異常響應(yīng)中的功能碼值恰好比正常響應(yīng)時的值高 80 十六進制。
通過設(shè)置功能碼的 MSB,主站設(shè)備應(yīng)用程序可以識別出異常響應(yīng),并可以檢查數(shù)據(jù)字段中的異常代碼。
數(shù)據(jù)字段:
在正常響應(yīng)中,從站設(shè)備可能在數(shù)據(jù)字段中返回數(shù)據(jù)或統(tǒng)計信息(即請求中所要求的任何信息)。
在異常響應(yīng)中,從站設(shè)備則在數(shù)據(jù)字段中返回一個異常代碼。
該代碼定義了導(dǎo)致此次異常的從站設(shè)備端的具體情況。
主站設(shè)備請求與從站設(shè)備異常響應(yīng)示例:

在這個示例中,主站設(shè)備向從站設(shè)備發(fā)送了一個請求。功能碼(01)用于讀取輸出狀態(tài)操作。它請求讀取線圈地址 1185(04A1 十六進制) 的輸出狀態(tài)。
需要注意的是,此處設(shè)置的輸出數(shù)量字段的值為 0001 ,因此只讀取一個輸出。
如果設(shè)置的地址在從站設(shè)備中不存在,從站設(shè)備將會返回異常碼為 02 的異常響應(yīng)。表示從站設(shè)備接收到的是非法數(shù)據(jù)地址。
4.5.2 異常碼列表
異常碼列表如下:

五、Modbus 通信協(xié)議模式
下面將詳細介紹三種常見的 Modbus 通信協(xié)議模式以及擴展協(xié)議模式。
5.1 Modbus RTU 通信協(xié)議模式
Modbus RTU 是 Modbus 協(xié)議最早、最常用的串行傳輸模式,以其高效率和二進制傳輸著稱,廣泛應(yīng)用于工業(yè)自動化領(lǐng)域。
5.1.1 物理層與網(wǎng)絡(luò)基礎(chǔ)
Modbus RTU 協(xié)議通常運行在串行通信物理層上,最常用的是 RS-485 標準,在某些點對點場景下也會使用 RS-232。
傳輸介質(zhì):
RS-485:使用雙絞線(屏蔽雙絞線更佳)進行傳輸。支持多點通信,是構(gòu)建工業(yè)設(shè)備網(wǎng)絡(luò)的首選。
RS-232:通常使用 DB9 或 DB25 連接器和電纜。主要用于點對點短距離通信。
網(wǎng)絡(luò)拓撲:
RS-485 網(wǎng)絡(luò):采用總線型拓撲(或稱“手拉手”連接),所有設(shè)備并聯(lián)在同一條總線上。網(wǎng)絡(luò)兩端需要安裝終端電阻(通常為 120 歐姆)以抑制信號反射。
RS-232 連接:嚴格的點對點拓撲,僅支持一臺主站和一臺從站通信。
核心關(guān)系:
協(xié)議:Modbus RTU(定義幀格式和通信規(guī)則)
物理層標準:RS-485(多設(shè)備網(wǎng)絡(luò))或 RS-232(點對點連接)
5.1.2 幀格式
Modbus RTU 協(xié)議報文(或稱數(shù)據(jù)幀)由以下幾個部分組成,它們按順序連續(xù)傳輸,共同構(gòu)成一次完整的通信:

1. 從站地址

該字段占 1 個字節(jié)。取值范圍為 1 ~ 247(十進制)。
其中地址 0 被保留為廣播地址,設(shè)置為廣播地址時,所有從站設(shè)備都會接收并處理數(shù)據(jù),但是不會向主站設(shè)備進行響應(yīng)。
2.功能碼
該字段占 1 個字節(jié)。作用是指示從站設(shè)備執(zhí)行操作,詳細說明在“第六部分:Modbus 功能碼”。
3.數(shù)據(jù)
根據(jù) Modbus RTU 幀格式規(guī)范,該字段占 0 ~ 252 個字節(jié)。實際長度和內(nèi)容完全由功能碼決定。它包含了請求的詳細信息(例如: 要讀取的寄存器起始地址和數(shù)量)或者要寫入的具體數(shù)值。
4.CRC-16 校驗
該字段占 2 個字節(jié)。CRC-16 校驗即循環(huán)冗余校驗碼。由主站設(shè)備根據(jù)前面所有字節(jié)(從站地址、功能碼、數(shù)據(jù))計算得出,并附在報文末尾。從站設(shè)備收到報文后會用相同算法重新計算 CRC,并與接收到的 CRC 值進行比對。如果兩者不匹配,則表明傳輸過程中發(fā)生錯誤,該幀報文將被丟失,從而保證數(shù)據(jù)完整性。
示例:
向單個保持寄存器寫入數(shù)據(jù):
請求報文格式:[從站地址][功能碼][寄存器起始地址 寄存器值][CRC16 校驗]
舉例:01 06 00 00 00 01 48 0A
01 :從站地址
06 :向單個保持寄存器寫入數(shù)據(jù)功能碼
00 00 :寄存器起始地址
00 01 :寫入的單個寄存器數(shù)據(jù)
48 0A :CRC16 校驗值
響應(yīng)報文格式:[從站地址][功能碼][寄存器起始地址 寄存器值][CRC16 校驗]
舉例:01 06 00 00 00 01 48 0A
01 :從站地址
06 :向單個保持寄存器寫入數(shù)據(jù)功能碼
00 00 :寄存器起始地址
00 01 :寫入的單個寄存器數(shù)據(jù)
48 0A :CRC16 校驗值
異常響應(yīng)報文格式:[從站地址][功能碼][異常碼][CRC16 校驗]
舉例:01 86 02 83 A0
01 :從站地址
86 :原功能碼為 06,最高位為 1 表示異常響應(yīng)
02 :非法數(shù)據(jù)地址(請求中指定的數(shù)據(jù)地址是從站設(shè)備不允許的或不存在的)
83 A0 :CRC16 校驗值
向多個保持寄存器寫入數(shù)據(jù):
請求報文格式:[從站地址][功能碼][寄存器起始地址 寄存器數(shù)量 寄存器值字節(jié)數(shù) 寄存器值][CRC16 校驗]
舉例:01 10 00 00 00 02 04 00 01 00 05 62 6C
01 :從站地址
10 :寫多個寄存器功能碼
00 00 :寄存器起始地址
00 02 :要寫入的寄存器數(shù)量
04 :寄存器值的字節(jié)數(shù)
00 01 :寫入的第一個寄存器值
00 05 :寫入的第二個寄存器值
62 6C :CRC16 校驗值
響應(yīng)報文格式:[從站地址][功能碼][寄存器起始地址 寄存器數(shù)量][CRC16 校驗]
舉例:01 10 00 00 00 02 41 C8
01 :從站地址
10 :寫多個寄存器功能碼
00 00 :寄存器起始地址
00 02 :要寫入的寄存器數(shù)量
41 C8 :CRC16 校驗值
異常響應(yīng)報文格式:[從站地址][功能碼][異常碼][CRC16 校驗]
舉例:01 90 02 CD C1
01 :從站地址
90 :原功能碼為 10,最高位為 1 表示異常響應(yīng)
02 :非法數(shù)據(jù)地址(請求中指定的數(shù)據(jù)地址是從站設(shè)備不允許的或不存在的)
CD C1 :CRC16 校驗值
讀取保持寄存器數(shù)據(jù):
請求報文格式:[從站地址][功能碼][寄存器起始地址 寄存器數(shù)量][CRC16 校驗]
舉例:01 03 00 00 00 02 C4 0B
01 :從站地址
03 :讀單/多個保持寄存器功能碼
00 00 :寄存器起始地址
00 02 :要讀取的寄存器數(shù)量
C4 0B :CRC16 校驗值
響應(yīng)報文格式:[從站地址][功能碼][寄存器值字節(jié)數(shù) 寄存器值][CRC16 校驗]
舉例:01 03 04 00 01 00 05 6B F0
01 :從站地址
03 :讀單/多個保持寄存器功能碼
04 :寄存器值字節(jié)數(shù)
00 01 :讀取的第一個寄存器值
00 05 :讀取的第二個寄存器值
6B F0 :CRC16 校驗值
異常響應(yīng)報文格式:[從站地址][功能碼][異常碼][CRC16 校驗]
舉例:01 83 02 C0 F1
01 :從站地址
83 :原功能碼為 03,最高位為 1 表示異常響應(yīng)
02 :非法數(shù)據(jù)地址(請求中指定的數(shù)據(jù)地址是從站設(shè)備不允許的或不存在的)
C0 F1 :CRC16 校驗值
5.1.3 傳輸特點
1.二進制傳輸
數(shù)據(jù)以原始的 8 位二進制字節(jié)流形式直接傳輸。在文檔或調(diào)試中,每個字節(jié)通常用兩個十六進制字符表示(如0x4A),但這僅用于人類閱讀,實際串口上不傳輸任何十六進制字符。該模式編碼效率高,在相同波特率下比 ASCII 模式具有更高的數(shù)據(jù)吞吐量。
2.波特率與同步
通信雙方(主站設(shè)備和所有從站設(shè)備)必須設(shè)置為相同的波特率(如 9600, 19200 等),否則無法正確解碼。
依靠起始位和停止位來實現(xiàn)字符幀的同步。每個字節(jié)都封裝在起始位和停止位之間,接收方通過起始位來同步并讀取后續(xù)的數(shù)據(jù)位。
3.空閑間隔要求
報文幀之間必須保持一定的靜默時間(總線空閑時間),該時間必須大于傳輸 3.5 個字符所需的時間。
幀內(nèi)的字符間隔必須小于傳輸 1.5 個字符的時間。
這些要求是 RTU 模式區(qū)分報文開始與結(jié)束的關(guān)鍵機制(幀分隔),替代了 ASCII 模式中的特定起始/結(jié)束字符。
4.特別說明:
由于需要遵循 t1.5 和 t3.5 定時器規(guī)則,Modbus RTU 接收驅(qū)動器可能會涉及大量中斷處理。在高通信波特率下,將會導(dǎo)致較高的 CPU 負載。因此,當波特率等于或者低于 19200Baud 時,必須嚴格遵守這兩個定時器的時限要求。對于大于 19200Baud 的波特率,這兩個定時器應(yīng)采用固定值:建議將字符間超時(t1.5)設(shè)置為 750us ,幀間延遲(t3.5)設(shè)置為 1.750ms 。
5.1.4 參數(shù)配置
在一個 Modbus RTU 模式中,所有設(shè)備的串行通信參數(shù)必須完全一致,否則無法通信。主要參數(shù)配置包括:
注:以下為官方文檔描述,在實際使用時需要查閱設(shè)備手冊,與設(shè)備手冊中規(guī)定的參數(shù)一致。
1.波特率 (Baud Rate)- 定義通信速度(比特每秒)。常見值有:9600、19200、38400 等。9600 是最常用的默認值。
2.數(shù)據(jù)位 (Data Bits)- 固定為 8 位,最低有效位最先發(fā)送。這是 Modbus RTU 標準的規(guī)定。
3.停止位 (Stop Bits)- 可以是 1 位 或 2 位。該設(shè)置與校驗位的選擇直接相關(guān)。
4.校驗位 (Parity)-無 (None):無奇偶校驗。此時停止位必須設(shè)置為 2 位。 -奇 (Odd):奇校驗。 -偶 (Even):偶校驗。這是 Modbus 協(xié)議規(guī)定的默認和首選模式。當使用奇校驗或偶校驗時,停止位設(shè)置為 1 位。
5.2 Modbus ASCII(American Standard Code for Information Interchange)
Modbus ASCII 是 Modbus 協(xié)議的另一種串行傳輸模式,它采用可打印的 ASCII 字符編碼,犧牲了效率但換來了極強的可讀性,便于調(diào)試和診斷。
5.2.1 物理層與網(wǎng)絡(luò)基礎(chǔ)
與 Modbus RTU 相同,Modbus ASCII 協(xié)議也運行在串行通信物理層上,主要基于 RS-485 或 RS-232 標準。其物理層特性和網(wǎng)絡(luò)拓撲與 RTU 模式完全一致。
傳輸介質(zhì):雙絞線(用于 RS-485)或 串行電纜(用于 RS-232)。
網(wǎng)絡(luò)拓撲:
RS-485:總線型拓撲,需注意終端電阻。
RS-232:點對點拓撲。
核心關(guān)系:
協(xié)議:Modbus ASCII(采用 ASCII 編碼的 Modbus 協(xié)議)
物理層標準:RS-485 或 RS-232
注意:Modbus ASCII 和 Modbus RTU 可以共享相同的物理網(wǎng)絡(luò)(如相同的 RS-485 總線),但絕不能在同一個網(wǎng)絡(luò)上混合使用,因為它們的幀格式和編碼完全不同,會導(dǎo)致通信失敗。
5.2.2 幀格式
Modbus ASCII 協(xié)議報文有明確的開始和結(jié)束標志,其幀結(jié)構(gòu)如下:

1.起始符
起始符字段占 1 個字符。固定為冒號字符:(ASCII 值為0x3A)。
它標志著報文的開始,接收方通過檢測起始符來同步并開始接收一個新幀。
2.從站地址
從站地址字段占 2 個字符。使用 ASCII 字符表示。
例如,地址為17(十六進制0x11) 的從站,在幀中會以兩個字符'1''1'(ASCII 值為0x31,0x31) 表示。
3.功能碼
功能碼字段占 2 個字符。使用 ASCII 字符表示。
例如,功能碼03(讀保持寄存器) 會以兩個字符'0''3'(ASCII 值為0x30,0x33) 表示。
4.數(shù)據(jù)
Modbus 協(xié)議規(guī)定,Modbus ASCII 模式中,數(shù)據(jù)字段占 0 ~ 2 × 252 個字符。使用 ASCII 字符表示。
每個 8 位二進制字節(jié)被拆分為兩個 4 位半字節(jié),并分別轉(zhuǎn)換為對應(yīng)的 ASCII 字符。
例如,數(shù)據(jù)字節(jié)0x4B會轉(zhuǎn)換為'4'(0x34) 和'B'(0x42) 兩個字符進行傳輸。
5.LRC 校驗
LRC 校驗字段占 2 個字符。
LRC 校驗即縱向冗余校驗。發(fā)送方計算一個校驗和,并將其轉(zhuǎn)換為兩個 ASCII 字符附加在報文末尾。接收方執(zhí)行相同的計算進行驗證。
6.結(jié)束符
結(jié)束符字段占 2 個字節(jié)。固定為回車符和換行符CRLF(ASCII 值為0x0D,0x0A)。它們標志著報文的結(jié)束。
示例:
向單個保持寄存器寫入數(shù)據(jù):
報文格式:[:][從站地址][功能碼][寄存器起始地址 寄存器值][LRC 校驗][rn]
舉例::010600000001B8rn
‘:’ :起始符,HEX 值為 3A
‘0’ ‘1’ :從站地址,HEX 值為 30 31
‘0’ ‘6’ :向單個保持寄存器寫入數(shù)據(jù)功能碼,HEX 值為 30 36
‘0’ ‘0’ ‘0’ ‘0’ :寄存器起始地址,HEX 值為 30 30 30 30
‘0’ ‘0’ ‘0’ ‘1’ :寫入的單個寄存器數(shù)據(jù),HEX 值為 30 30 30 31
‘B’ ‘8’ :LRC 校驗值,HEX 值為 42 38
‘r’ ‘n’ :結(jié)束符,HEX 值為 0D 0A
響應(yīng)報文格式:[:][從站地址][功能碼][寄存器起始地址 寄存器值][LRC 校驗][rn]
舉例::010600000001B8rn
‘:’ :起始符,HEX 值為 3A
‘0’ ‘1’ :從站地址,HEX 值為 30 31
‘0’ ‘6’ :向單個保持寄存器寫入數(shù)據(jù)功能碼,HEX 值為 30 36
‘0’ ‘0’ ‘0’ ‘0’ :寄存器起始地址,HEX 值為 30 30 30 30
‘0’ ‘0’ ‘0’ ‘1’ :寫入的單個寄存器數(shù)據(jù),HEX 值為 30 30 30 31
‘B’ ‘8’ :LRC 校驗值,HEX 值為 42 38
‘r’ ‘n’ :結(jié)束符,HEX 值為 0D 0A
異常響應(yīng)報文格式:[:][從站地址][功能碼][異常碼][LRC 校驗][rn]
舉例::018602CFrn
‘:’ :起始符,HEX 值為 3A
‘0’ ‘1’ :從站地址,HEX 值為 30 31
‘8’ ‘6’ :原功能碼為 06,最高位為 1 表示異常響應(yīng),HEX 值為 38 36
‘0’ ‘2’ :非法數(shù)據(jù)地址(請求中指定的數(shù)據(jù)地址是從站設(shè)備不允許的或不存在的),HEX 值為 30 36
‘C’ ‘F’ :LRC 校驗值,HEX 值為 43 46
‘r’ ‘n’ :結(jié)束符,HEX 值為 0D 0A
向多個保持寄存器寫入數(shù)據(jù):
請求報文格式:[:][從站地址][功能碼][寄存器起始地址 寄存器數(shù)量 寄存器值字節(jié)數(shù) 寄存器值][LRC 校驗][rn]
舉例::0110000000020400010005D2rn
‘:’ :起始符,HEX 值為 3A
‘0’ ‘1’ :從站地址,HEX 值為 30 31
‘1’ ‘0’ :寫多個寄存器功能碼,HEX 值為 31 30
‘0’ ‘0’ ‘0’ ‘0’ :寄存器起始地址,HEX 值為 30 30 30 30
‘0’ ‘0’ ‘0’ ‘2’ :要寫入的寄存器數(shù)量,HEX 值為 30 30 30 32
‘0’ ‘4’ :寄存器值的字節(jié)數(shù),HEX 值為 30 34
‘0’ ‘0’ ‘0’ ‘1’ :寫入的第一個寄存器值,HEX 值為 30 30 30 31
‘0’ ‘0’ ‘0’ ‘5’ :寫入的第二個寄存器值,HEX 值為 30 30 30 35
‘D’ ‘2’ :LRC 校驗值,HEX 值為 44 32
‘r’ ‘n’ :結(jié)束符,HEX 值為 0D 0A
響應(yīng)報文格式:[:][從站地址][功能碼][寄存器起始地址 寄存器數(shù)量][LRC 校驗][rn]
舉例::011000000002BCrn
‘:’ :起始符,HEX 值為 3A
‘0’ ‘1’ :從站地址,HEX 值為 30 31
‘1’ ‘0’ :寫多個寄存器功能碼,HEX 值為 31 30
‘0’ ‘0’ ‘0’ ‘0’ :寄存器起始地址,HEX 值為 30 30 30 30
‘0’ ‘0’ ‘0’ ‘2’ :要寫入的寄存器數(shù)量,HEX 值為 30 30 30 32
‘B’ ‘C’ :LRC 校驗值,HEX 值為 42 43
‘r’ ‘n’ :結(jié)束符,HEX 值為 0D 0A
異常響應(yīng)報文格式:[:][從站地址][功能碼][異常碼][LRC 校驗][rn]
舉例::019002D4rn
‘:’ :起始符,HEX 值為 3A
‘0’ ‘1’ :從站地址,HEX 值為 30 31
‘9’ ‘0’ :原功能碼為 10,最高位為 1 表示異常響應(yīng),HEX 值為 39 30
‘0’ ‘2’ :非法數(shù)據(jù)地址(請求中指定的數(shù)據(jù)地址是從站設(shè)備不允許的或不存在的),HEX 值為 30 36
‘D’ ‘4’ :LRC 校驗值,HEX 值為 44 34
‘r’ ‘n’ :結(jié)束符,HEX 值為 0D 0A
讀取保持寄存器數(shù)據(jù):
請求報文格式:[:][從站地址][功能碼][寄存器起始地址 寄存器數(shù)量][LRC 校驗][rn]
舉例::010300000002BArn
‘:’ :起始符,HEX 值為 3A
‘0’ ‘1’ :從站地址,HEX 值為 30 31
‘0’ ‘3’ :讀單/多個保持寄存器功能碼,HEX 值為 30 33
‘0’ ‘0’ ‘0’ ‘0’ :寄存器起始地址,HEX 值為 30 30 30 30
‘0’ ‘0’ ‘0’ ‘2’ :要讀取的寄存器數(shù)量,HEX 值為 30 30 30 32
‘B’ ‘A’ :LRC 校驗值,HEX 值為 42 41
‘r’ ‘n’ :結(jié)束符,HEX 值為 0D 0A
響應(yīng)報文格式:[:][從站地址][功能碼][寄存器值字節(jié)數(shù) 寄存器值][LRC 校驗][rn]
舉例::0103040001000552rn
‘:’ :起始符,HEX 值為 3A
‘0’ ‘1’ :從站地址,HEX 值為 30 31
‘0’ ‘3’ :讀單/多個保持寄存器功能碼,HEX 值為 30 33
‘0’ ‘4’ :寄存器值字節(jié)數(shù),HEX 值為 30 34
‘0’ ‘0’ ‘0’ ‘1’ :讀取的第一個寄存器值,HEX 值為 30 30 30 31
‘0’ ‘0’ ‘0’ ‘5’ :讀取的第二個寄存器值,HEX 值為 30 30 30 35
‘5’ ‘2’ :LRC 校驗值,HEX 值為 35 32
‘r’ ‘n’ :結(jié)束符,HEX 值為 0D 0A
異常響應(yīng)報文格式:[:][從站地址][功能碼][異常碼][LRC 校驗][rn]
舉例::018302D2rn
‘:’ :起始符,HEX 值為 3A
‘0’ ‘1’ :從站地址,HEX 值為 30 31
‘8’ ‘3’ :原功能碼為 03,最高位為 1 表示異常響應(yīng),HEX 值為 38 33
‘0’ ‘2’ :非法數(shù)據(jù)地址(請求中指定的數(shù)據(jù)地址是從站設(shè)備不允許的或不存在的),HEX 值為 30 36
‘D’ ‘2’ :LRC 校驗值,HEX 值為 44 32
‘r’ ‘n’ :結(jié)束符,HEX 值為 0D 0A
5.2.3 傳輸特點
1.ASCII 字符傳輸
所有數(shù)據(jù),包括地址、命令和校驗值,都以可打印的 ASCII 字符(0-9, A-F)形式在網(wǎng)絡(luò)上傳輸。
這使得任何能夠顯示 ASCII 碼的終端軟件或簡單的調(diào)試工具都可以直接監(jiān)控、解析和調(diào)試通信過程,數(shù)據(jù)一目了然。
2.效率低但可讀性強
效率低:這是 ASCII 模式最大的缺點。因為每個信息字節(jié)都需要用兩個 ASCII 字符來傳輸,有效數(shù)據(jù)的吞吐量僅為 RTU 模式的一半。例如,傳輸一個二進制值0xFE,RTU 只需傳 1 個字節(jié)(0xFE),而 ASCII 需要傳'F''E'這 2 個字節(jié)(0x46,0x45)。
可讀性強:這是其最大優(yōu)點。人類可以直接讀懂線上的數(shù)據(jù)。一個典型的 ASCII 幀看起來像::1103006B0003E9,很容易識別出地址、功能碼和數(shù)據(jù)。
5.2.4 參數(shù)配置
在一個 Modbus ASCII 模式中,所有設(shè)備的串行通信參數(shù)必須完全一致,否則無法通信。主要參數(shù)配置包括:
注:以下為官方文檔描述,在實際使用時需要查閱設(shè)備手冊,與設(shè)備手冊中規(guī)定的參數(shù)一致。
1.波特率 (Baud Rate)- 定義通信速度(比特每秒)。常見值有:9600、19200、38400 等。9600 是最常用的默認值。
2.數(shù)據(jù)位 (Data Bits)- 固定為 7 位,最低有效位最先發(fā)送。這是 Modbus ASCII 標準的規(guī)定。
3.停止位 (Stop Bits)- 可以是 1 位 或 2 位。該設(shè)置與校驗位的選擇直接相關(guān)。
4.校驗位 (Parity)
無 (None):無奇偶校驗。此時停止位必須設(shè)置為 2 位。
奇 (Odd):奇校驗。
偶 (Even):偶校驗。這是 Modbus 協(xié)議規(guī)定的默認和首選模式。當使用奇校驗或偶校驗時,停止位設(shè)置為 1 位。
5.3 Modbus TCP(Transmission Control Protocol)
Modbus TCP 是 Modbus 協(xié)議家族中為適應(yīng)現(xiàn)代工業(yè)以太網(wǎng)環(huán)境而發(fā)展的變種。它將傳統(tǒng)的 Modbus 應(yīng)用層協(xié)議封裝在標準的 TCP/IP 協(xié)議棧中,使其能夠通過以太網(wǎng)進行通信,從而實現(xiàn)了高速、遠距離、多設(shè)備的網(wǎng)絡(luò)化集成。
5.3.1 物理層與網(wǎng)絡(luò)基礎(chǔ)
Modbus TCP 運行在完整的 TCP/IP 協(xié)議棧之上,其物理層依賴于標準的以太網(wǎng)技術(shù)。
物理介質(zhì):
雙絞線(如 CAT5e、CAT6):最常見的選擇,通信距離約 100 米。
光纖:用于長距離通信(可達數(shù)公里)和高電磁干擾環(huán)境。
無線:通過 Wi-Fi 等無線以太網(wǎng)技術(shù)實現(xiàn)靈活部署。
網(wǎng)絡(luò)拓撲:
支持星型、環(huán)型(需配合交換機協(xié)議)等復(fù)雜拓撲。
通過交換機和路由器可以輕松組建大規(guī)模、分層級的網(wǎng)絡(luò)。
協(xié)議棧關(guān)系:
應(yīng)用層:Modbus 協(xié)議
傳輸層:TCP(提供可靠連接)
網(wǎng)絡(luò)層:IP(處理尋址和路由)
數(shù)據(jù)鏈路層/物理層:以太網(wǎng)(如 IEEE 802.3 標準)
5.3.2 幀格式
Modbus TCP 協(xié)議報文在標準的 Modbus 協(xié)議數(shù)據(jù)單元(PDU)前添加了 MBAP 頭,形成完整的應(yīng)用數(shù)據(jù)單元(ADU)。其幀結(jié)構(gòu)如下:

1.MBAP 頭 (MBAP Header - Modbus Application Protocol Header)
共 7 字節(jié),專門為 TCP/IP 傳輸設(shè)計,包含路由和管理信息。
事務(wù)標識符 (Transaction Identifier)
該字段占 2 個字節(jié)。由客戶端(主站)生成,用于將請求與響應(yīng)配對。服務(wù)器(從站)在回應(yīng)中必須復(fù)制相同的事務(wù)標識符。這在異步通信中尤為重要,可以區(qū)分多個并發(fā)請求的響應(yīng)。
協(xié)議標識符 (Protocol Identifier)
該字段占 2 個字節(jié)。對于 Modbus TCP,此值固定為0x0000。其他值保留用于未來擴展。
長度 (Length)
該字段占 2 個字節(jié)。表示其后所有字節(jié)的數(shù)量,包括單元標識符(1 個字節(jié))、功能碼(1 個字節(jié)) 和數(shù)據(jù)域(0 ~ 252 個字節(jié))。
計算公式:長度 = 1 (單元標識符) + 1 (功能碼) + N (數(shù)據(jù)長度)
單元標識符 (Unit Identifier)
該字段占 1 個字節(jié)。用于標識連接在網(wǎng)關(guān)后面的子設(shè)備。在簡單的單設(shè)備網(wǎng)絡(luò)中,此字段常被用作從站地址,功能與 Modbus RTU/ASCII 中的從站地址相同。如果不需要網(wǎng)關(guān)路由,通常設(shè)置為0x00或0xFF,或者直接使用從站地址(如0x01)。
2.功能碼 (Function Code)- 該字段占 1 個字節(jié)。與 Modbus RTU/ASCII 中的功能碼完全一致。例如:01(讀線圈)、03(讀保持寄存器)、05(寫單個線圈)、06(寫單個寄存器)等。
3.數(shù)據(jù) (Data)- 該字段占 0 ~ 252 個字節(jié)。含義和內(nèi)容與 Modbus RTU 完全相同,由功能碼決定。包含請求或響應(yīng)的具體參數(shù)或數(shù)值。
示例:
向單個保持寄存器寫入數(shù)據(jù):
請求報文格式:[事務(wù)標識符 協(xié)議標識符 后續(xù)字節(jié)數(shù) 從站地址][功能碼][寄存器起始地址 寄存器值]
舉例:00 01 00 00 00 06 01 06 00 00 00 01
00 01 :事務(wù)標識符
00 00 :協(xié)議標識符(modbus 固定為 00 00)
00 06 :后續(xù)字節(jié)數(shù)
01 :從站地址
06 :向單個保持寄存器寫入數(shù)據(jù)功能碼
00 00 :寄存器起始地址
00 01 :寫入的單個寄存器數(shù)據(jù)
響應(yīng)報文格式:[事務(wù)標識符 協(xié)議標識符 后續(xù)字節(jié)數(shù) 從站地址][功能碼][寄存器起始地址 寄存器值]
舉例:00 01 00 00 00 06 01 06 00 00 00 01
00 01 :事務(wù)標識符
00 00 :協(xié)議標識符(modbus 固定為 00 00)
00 06 :后續(xù)字節(jié)數(shù)
01 :從站地址
06 :向單個保持寄存器寫入數(shù)據(jù)功能碼
00 00 :寄存器起始地址
00 01 :寫入的單個寄存器數(shù)據(jù)
異常響應(yīng)報文格式:[事務(wù)標識符 協(xié)議標識符 后續(xù)字節(jié)數(shù) 從站地址][功能碼][異常碼]
舉例:00 01 00 00 00 03 01 86 02
00 01 :事務(wù)標識符
00 00 :協(xié)議標識符(modbus 固定為 00 00)
00 03 :后續(xù)字節(jié)數(shù)
01 :從站地址
86 :原功能碼為 06,最高位為 1 表示異常響應(yīng)
02 :非法數(shù)據(jù)地址(請求中指定的數(shù)據(jù)地址是從站設(shè)備不允許的或不存在的)
向多個保持寄存器寫入數(shù)據(jù):
請求報文格式:[事務(wù)標識符 協(xié)議標識符 后續(xù)字節(jié)數(shù) 從站地址][功能碼][寄存器起始地址 寄存器數(shù)量 寄存器值字節(jié)數(shù) 寄存器值]
舉例:00 01 00 00 00 0B 01 10 00 00 00 02 04 00 01 00 05
00 01 :事務(wù)標識符
00 00 :協(xié)議標識符(modbus 固定為 00 00)
00 0B :后續(xù)字節(jié)數(shù)
01 :從站地址
10 :寫多個寄存器功能碼
00 00 :寄存器起始地址
00 02 :要寫入的寄存器數(shù)量
04 :寄存器值的字節(jié)數(shù)
00 01 :寫入的第一個寄存器值
00 05 :寫入的第二個寄存器值
響應(yīng)報文格式:[事務(wù)標識符 協(xié)議標識符 后續(xù)字節(jié)數(shù) 從站地址][功能碼][寄存器起始地址 寄存器數(shù)量]
舉例:00 01 00 00 00 06 01 10 00 00 00 02
00 01 :事務(wù)標識符
00 00 :協(xié)議標識符(modbus 固定為 00 00)
00 06 :后續(xù)字節(jié)數(shù)
01 :從站地址
10 :寫多個寄存器功能碼
00 00 :寄存器起始地址
00 02 :要寫入的寄存器數(shù)量
異常響應(yīng)報文格式:[事務(wù)標識符 協(xié)議標識符 后續(xù)字節(jié)數(shù) 從站地址][功能碼][異常碼]
舉例:00 01 00 00 00 03 01 90 02
00 01 :事務(wù)標識符
00 00 :協(xié)議標識符(modbus 固定為 00 00)
00 03 :后續(xù)字節(jié)數(shù)
01 :從站地址
90 :原功能碼為 10,最高位為 1 表示異常響應(yīng)
02 :非法數(shù)據(jù)地址(請求中指定的數(shù)據(jù)地址是從站設(shè)備不允許的或不存在的)
讀取保持寄存器數(shù)據(jù):
請求報文格式:[事務(wù)標識符 協(xié)議標識符 后續(xù)字節(jié)數(shù) 從站地址][功能碼][寄存器起始地址 寄存器數(shù)量]
舉例:00 01 00 00 00 06 01 03 00 00 00 02
00 01 :事務(wù)標識符
00 00 :協(xié)議標識符(modbus 固定為 00 00)
00 06 :后續(xù)字節(jié)數(shù)
01 :從站地址
03 :讀單/多個保持寄存器功能碼
00 00 :寄存器起始地址
00 02 :要讀取的寄存器數(shù)量
響應(yīng)報文格式:[事務(wù)標識符 協(xié)議標識符 后續(xù)字節(jié)數(shù) 從站地址][功能碼][寄存器值字節(jié)數(shù) 寄存器值]
舉例:00 01 00 00 00 07 01 03 04 00 01 00 05
00 01 :事務(wù)標識符
00 00 :協(xié)議標識符(modbus 固定為 00 00)
00 07 :后續(xù)字節(jié)數(shù)
01 :從站地址
03 :讀單/多個保持寄存器功能碼
00 01 :讀取的第一個寄存器值
00 05 :讀取的第二個寄存器值
異常響應(yīng)報文格式:[事務(wù)標識符 協(xié)議標識符 后續(xù)字節(jié)數(shù) 從站地址][功能碼][異常碼]
舉例:00 01 00 00 00 03 01 83 02
00 01 :事務(wù)標識符
00 00 :協(xié)議標識符(modbus 固定為 00 00)
00 03 :后續(xù)字節(jié)數(shù)
01 :從站地址
83 :原功能碼為 03,最高位為 1 表示異常響應(yīng)
02 :非法數(shù)據(jù)地址(請求中指定的數(shù)據(jù)地址是從站設(shè)備不允許的或不存在的)
5.3.3 傳輸特點
1.基于以太網(wǎng)/TCP/IP
Modbus TCP 運行在標準的以太網(wǎng)物理層和數(shù)據(jù)鏈路層之上,使用 TCP(傳輸控制協(xié)議)作為傳輸層協(xié)議。
這使得它可以利用現(xiàn)有的企業(yè)局域網(wǎng)(LAN)和互聯(lián)網(wǎng)基礎(chǔ)設(shè)施進行通信,傳輸距離遠,布線方便。
2.端口 502
雖然標準規(guī)定使用 502 端口,但許多設(shè)備允許用戶自定義其他端口號以適應(yīng)特定的網(wǎng)絡(luò)安全策略(如防火墻規(guī)則)。然而,502 端口是 Modbus TCP 的默認和標準端口,在未明確指定的情況下應(yīng)使用此端口。
3.無校驗(依賴 TCP)
取消了 CRC 校驗。這是因為 TCP 協(xié)議本身已經(jīng)提供了連接導(dǎo)向、數(shù)據(jù)包排序、重傳機制和錯誤校驗,確保了數(shù)據(jù)的可靠、有序和無誤傳輸。在可靠的 TCP 連接上增加 CRC 校驗是冗余的。
因此,Modbus TCP 幀結(jié)構(gòu)比 RTU 幀更簡潔,效率更高。
4.客戶端/服務(wù)器模型
Modbus TCP 將傳統(tǒng)的主站(Master)改稱為客戶端(Client),從站(Slave)改稱為服務(wù)器(Server)。
客戶端主動向服務(wù)器發(fā)起 TCP 連接并發(fā)送請求,服務(wù)器被動監(jiān)聽并響應(yīng)請求。一個服務(wù)器可以同時處理多個客戶端的連接。
5.3.4 參數(shù)配置
在 Modbus TCP 模式中,通信雙方需要配置正確的網(wǎng)絡(luò)參數(shù)才能建立連接。主要參數(shù)包括:
1.IP 地址 (IP Address)
每個設(shè)備(客戶端和服務(wù)器)必須在網(wǎng)絡(luò)中擁有唯一的 IP 地址。
2.子網(wǎng)掩碼 (Subnet Mask)
用于判斷設(shè)備是否位于同一局域網(wǎng)內(nèi)。
3.網(wǎng)關(guān) (Gateway)
當需要與不同網(wǎng)段的設(shè)備通信時,需要設(shè)置網(wǎng)關(guān)地址。
4.TCP 端口號 (TCP Port)
服務(wù)器監(jiān)聽的端口號,默認為 502??蛻舳诵枰蚍?wù)器的 IP 地址和此端口發(fā)起連接。
5.連接超時 (Connection Timeout)
客戶端等待服務(wù)器建立連接或響應(yīng)的最長時間。
5.4 擴展協(xié)議模式
除了最常見的 Modbus RTU、Modbus ASCII 和 Modbus TCP 之外,還存在其他一些協(xié)議形式或變種。 它們主要是為了適應(yīng)不同的物理介質(zhì)或滿足特定的行業(yè)需求。

六、LuatOS 上的 exmodbus 擴展庫
6.1 常量詳解
6.1.1 通信模式常量
6.1.1.1 exmodbus.RTU_MASTER

6.1.1.2 exmodbus.RTU_SLAVE

6.1.1.3 exmodbus.ASCII_MASTER

6.1.1.4 exmodbus.ASCII_SLAVE

6.1.1.5 exmodbus.TCP_MASTER

6.1.1.6 exmodbus.TCP_SLAVE

6.1.2 數(shù)據(jù)類型常量
6.1.2.1 exmodbus.COIL_STATUS

6.1.2.2 exmodbus.INPUT_STATUS

6.1.2.3 exmodbus.INPUT_REGISTER

6.1.2.4 exmodbus.HOLDING_REGISTER

6.1.3 操作類型常量
6.1.3.1 exmodbus.READ_COILS

6.1.3.2 exmodbus.READ_DISCRETE_INPUTS

6.1.3.3 exmodbus.READ_HOLDING_REGISTERS

6.1.3.4 exmodbus.READ_INPUT_REGISTERS

6.1.3.5 exmodbus.WRITE_SINGLE_COIL

6.1.3.6 exmodbus.WRITE_SINGLE_HOLDING_REGISTER

6.1.3.7 exmodbus.WRITE_MULTIPLE_HOLDING_REGISTERS

6.1.3.8 exmodbus.WRITE_MULTIPLE_COILS

6.1.4 異常碼常量
6.1.4.1 exmodbus.ILLEGAL_FUNCTION

6.1.4.2 exmodbus.ILLEGAL_DATA_ADDRESS

6.1.4.3 exmodbus.ILLEGAL_DATA_VALUE

6.1.4.4 exmodbus.SLAVE_DEVICE_FAILURE

6.1.4.5 exmodbus.ACKNOWLEDGE

6.1.4.6 exmodbus.SLAVE_DEVICE_BUSY

6.1.4.7 exmodbus.NEGATIVE_ACKNOWLEDGE

6.1.4.8 exmodbus.MEMORY_PARITY_ERROR

6.1.4.9 exmodbus.GATEWAY_PATH_UNAVAILABLE

6.1.4.10 exmodbus.GATEWAY_TARGET_NO_RESPONSE

6.1.5 響應(yīng)結(jié)果常量
6.1.5.1 exmodbus.STATUS_SUCCESS

6.1.5.2 exmodbus.STATUS_DATA_INVALID

6.1.5.3 exmodbus.STATUS_EXCEPTION

6.1.5.4 exmodbus.STATUS_TIMEOUT

6.2 函數(shù)詳解
6.2.1 exmodbus.create(config)
功能
創(chuàng)建并返回一個新的 modbus 主/從站實例;
注意事項
1、創(chuàng)建實例時需要將串口或者網(wǎng)絡(luò)參數(shù)填寫完整并且正確;
參數(shù)
由于 rtu/ascii 與 tcp 需要配置不同的 config 配置文件,因此下方將會分別進行介紹:
config(創(chuàng)建 RTU/ASCII 實例時)

config(創(chuàng)建 TCP 實例時)

返回值
local mb = exmodbus.create(config)
mb

示例

6.2.2 modbus:read(config)
功能
主站向從站發(fā)送讀取操作請求(阻塞接口);
支持通過“字段參數(shù)方式”或“原始幀方式”傳入 config 配置參數(shù),傳入格式詳見下方 config 參數(shù)示例;
如果你需要發(fā)送的請求報文是符合 modbus 標準格式,可以使用“字段參數(shù)方式”或者“原始幀方式”;
如果你需要發(fā)送的請求報文是非標準格式,必須使用“原始幀方式”,使用“字段參數(shù)方式”會導(dǎo)致解析的數(shù)據(jù)不正確;
注意事項
1、在調(diào)用此接口之前,需要先確保對應(yīng)實例對象有效;
2、請求范圍需要符合 modbus 標準協(xié)議要求;
參數(shù)
由于該接口支持通過“字段參數(shù)方式”或“原始幀方式”傳入 config 配置參數(shù),因此下方將會分別進行介紹:
config(字段參數(shù)方式傳入時)

config(原始幀方式傳入時)

返回值
local result = modbus:read(config)
result

示例

6.2.3 modbus:write(config)
功能
主站向從站發(fā)送寫入操作請求(阻塞接口);
支持通過“字段參數(shù)方式”或“原始幀方式”傳入 config 配置參數(shù),傳入格式詳見下方 config 參數(shù)示例;
如果你需要發(fā)送的請求報文是符合 modbus 標準格式,可以使用“字段參數(shù)方式”或者“原始幀方式”;
如果你需要發(fā)送的請求報文是非標準格式,必須使用“原始幀方式”,使用“字段參數(shù)方式”會導(dǎo)致解析的數(shù)據(jù)不正確;
注意事項
1、在調(diào)用此接口之前,需要先確保對應(yīng)實例對象有效;
2、請求范圍需要符合 modbus 標準協(xié)議要求;
參數(shù)
由于該接口支持通過“字段參數(shù)方式”或“原始幀方式”傳入 config 配置參數(shù),因此下方將會分別進行介紹:
config(字段參數(shù)方式傳入時)

config(原始幀方式傳入時)

返回值
local result = modbus:write(config)
result

示例

6.2.4 modbus:destroy()
功能
銷毀已創(chuàng)建的主/從站示例對象;
注意事項
暫無;
參數(shù)
無;
返回值
無;
示例

6.2.5 modbus:on(callback)
功能
此接口僅限設(shè)備做從站時使用;
當收到主站請求數(shù)據(jù)時,通過 callback 通知應(yīng)用腳本處理;
應(yīng)用腳本處理完之后,在 callback 中通知返回值,告知 exmodbus 擴展庫返回給主站;
注意事項
1、在調(diào)用此接口之前,需要先確保對應(yīng)實例對象有效;
參數(shù)
callback

返回值
無;
示例

七、LuatOS 上的 Modbus 應(yīng)用開發(fā)流程
本部分將針對一種通信模式進行實踐:Modbus RTU 通信協(xié)議模式下的 Modbus 應(yīng)用開發(fā)。
7.1 分析項目代碼
7.1.2 Modbus RTU 主站
文件說明:
1. main.lua:主程序入口文件。
2. param_field.lua:RTU 主站應(yīng)用模塊(字段參數(shù)方式)。
3. raw_frame.lua:RTU 主站應(yīng)用模塊(原始幀方式)。
4. temp_hum_sensor.lua:485 溫濕度傳感器讀取模塊。
演示功能:
1. 將設(shè)備配置為 modbus RTU 主站模式
2. 與從站 1 和 從站 2 進行通信 - 對從站 1 進行 2 秒一次的讀取保持寄存器 0-1 操作 - 對從站 2 進行 4 秒一次的寫入保持寄存器 0-1 操作
3. 讀取溫濕度傳感器數(shù)據(jù) - 配置 modbus RTU 主站,讀取溫濕度傳感器數(shù)據(jù) - 每 2 秒讀取一次傳感器數(shù)據(jù)并解析溫度和濕度值
注意事項:
1. 該示例程序需要搭配 exmodbus 擴展庫使用。
2. 在 main.lua 中 require "param_field" 模塊,可以演示標準 modbus RTU 請求報文格式的使用方式。
3. 在 main.lua 中 require "raw_frame" 模塊,可以演示非標準 modbus RTU 請求報文格式的使用方式。
4. 在 main.lua 中 require "temp_hum_sensor" 模塊,可以演示讀取 485 溫濕度傳感器數(shù)值的使用方式。
5. require "param_field"、require "raw_frame" 和 require "temp_hum_sensor",不要同時打開,否則功能會有沖突。
特別說明:
關(guān)于 RTU 報文,exmodbus 擴展庫支持通過 字段參數(shù) 或 原始幀 兩種方式進行配置。
這兩種配置方式本質(zhì)都由用戶將其放入 table 中在調(diào)用接口時傳入,區(qū)別如下:
1. 字段參數(shù)方式
這種方式需要用戶將請求報文進行解析后,將其放入 table 中,例如:

2. 原始幀方式
這種方式只需要用戶將原始請求報文放入 table 中,例如:

如果你需要發(fā)送的請求報文是符合 modbus RTU 標準格式,可以使用 字段參數(shù) 或者 原始幀 方式。
如果你需要發(fā)送的請求報文是非標準格式,必須使用 原始幀 方式,使用 字段參數(shù) 方式會導(dǎo)致解析的數(shù)據(jù)不正確。
7.1.3 Modbus RTU 從站
文件說明:
1. main.lua:主程序入口文件。
2. rtu_slave_manage.lua:RTU 從站應(yīng)用模塊;
演示功能:
1. 將設(shè)備配置為 modbus RTU 從站模式
2. 等待并且應(yīng)答主站請求
注意事項:
1. 該示例程序需要搭配 exmodbus 擴展庫使用
2. 設(shè)備作為 modbus RTU 從站模式時,僅支持接收 modbus RTU 標準格式的請求報文
3. 進行回應(yīng)時也需要符合 modbus RTU 標準格式
今天的內(nèi)容就分享到這里了~
審核編輯 黃宇
-
通信
+關(guān)注
關(guān)注
18文章
6389瀏覽量
140036 -
MODBUS RTU
+關(guān)注
關(guān)注
0文章
140瀏覽量
3689 -
LuatOS
+關(guān)注
關(guān)注
0文章
156瀏覽量
2691
發(fā)布評論請先 登錄
《從零開始學電路基礎(chǔ)》(從零開始學電子技術(shù)叢書)
Modbus TCP轉(zhuǎn)Modbus RTU的實現(xiàn)
基于Modbus RTU的串口調(diào)試軟件的實現(xiàn)
【下載】《從零開始學電子測量技術(shù)》
《從零開始學電子》叢書全套網(wǎng)盤分享
力控modbus通信方法modbus-tcp、modbus-rtu***康通信配置步驟
從零開始學電路基礎(chǔ)
PyTorch教程之從零開始的遞歸神經(jīng)網(wǎng)絡(luò)實現(xiàn)
RS485與MODBUS RTU的區(qū)別 如何選擇合適的通信技術(shù)?
LuatOS中Modbus RTU通信開發(fā)指南
從零開始:LuatOS實現(xiàn)Modbus RTU通信的技術(shù)路徑
評論