MODBUS是一種廣泛使用的工業(yè)通信協(xié)議,它允許通過串行線路在不同設(shè)備之間進(jìn)行通信和數(shù)據(jù)交換。RS485模塊是一個(gè)在ESP32上實(shí)現(xiàn)MODBUS協(xié)議的硬件。在本教程中,我們將使用RS485模塊在ESP32開發(fā)板上創(chuàng)建一個(gè)MODBUS主機(jī)和從機(jī)設(shè)備,并實(shí)現(xiàn)與MODBUS主機(jī)的通信。
實(shí)驗(yàn)效果
多個(gè)Modbus(Server)從機(jī)設(shè)備與一個(gè)Modbus主機(jī)(Client)設(shè)備進(jìn)行通信。
元件說明
- 使用工業(yè)級(jí)芯片,傳輸距離可達(dá)上千米
- 具有高達(dá)正負(fù)15KV的防靜電保護(hù)
- 芯片內(nèi)置限擺率控制,大大減少信號(hào)干擾
- 接收器輸入阻抗僅1/4單位,支持多設(shè)備連接,可連接128個(gè)設(shè)備
- 工作溫度范圍廣,-40°C到85°C正常工作
- 支持熱插拔,不會(huì)出現(xiàn)信號(hào)鎖死問題
- 使用貼片大容量電解電容進(jìn)行電源濾波
- 雙瞬態(tài)抑制二極管過壓保護(hù)
- 10歐電流保護(hù)電阻,提高信號(hào)完整性
- RS485和TTL信號(hào)單面布線,保證信號(hào)質(zhì)量
- 大面積鋪銅層,提高抗干擾能力
- 提供2.54mm間距洞洞焊接,方便二次開發(fā)
- 常用M3螺釘固定孔,安裝可靠
- 120歐端接電阻,支持自動(dòng)適配
- 提供發(fā)射/接收指示燈,方便調(diào)試
- 彎角插針設(shè)計(jì),方便測試
- 支持3.3V和5V控制,兼容性強(qiáng)
引腳說明
- RXD —— 接受數(shù)據(jù)
- TXD ——傳輸數(shù)據(jù)
- VCC —— 5V供電
- GND —— 接地
- A —— 非反相接收器輸入和非反相驅(qū)動(dòng)器輸出
- B —— 反相接收器輸入和反相驅(qū)動(dòng)器輸出
BOM表
- ESP32 N個(gè)
- RS485模塊 N個(gè)
- 跳線
- 屏蔽信號(hào)線
接線圖
ESP32 | 連接 | RS485模塊 |
---|---|---|
GND | <-> | GND |
GPIO 17 | <-> | RXD |
GPIO 16 | <-> | TXD |
5V | <-> | VCC |
把所有RS485的模塊的A和B,分別A連接A,B連接B,全部連接起來。
線圈和寄存器
在 Modbus 的內(nèi)容中多次提到線圈(coil)和寄存器(register)的概念,尤其是 Moddbus功能碼中,操作的對(duì)象基本上都是線圈和寄存器。
在 Modbus 協(xié)議中之所以仍然稱為線圈和寄存器,完全是歷史原因。在 PLC 應(yīng)用領(lǐng)域,一個(gè)線圈就代表一個(gè) PLC 輸出點(diǎn),也稱為輸出繼電器。通過控制線圈導(dǎo)通與否來改變繼電器輸出狀態(tài),實(shí)現(xiàn)弱電控制強(qiáng)電。
但實(shí)際上,在如今的 Modbus 設(shè)備中,它們都只是對(duì)應(yīng)一塊內(nèi)存區(qū)域而已。其中,線圈代表位操作(bit),表示一個(gè)布爾變量;寄存器代表字操作(word),表示一個(gè)整型變量(當(dāng)然也可以通過多個(gè)字的組合,表示浮點(diǎn)數(shù)以及其他復(fù)合數(shù)據(jù)結(jié)構(gòu))。在 Modbus 協(xié)議中,字(word)的長度是 16 位,即 2 個(gè)字節(jié)。
寄存器種類說明
在 Modbus 協(xié)議中,所有數(shù)據(jù)均存放于寄存器中。根據(jù)存放的數(shù)據(jù)類型以及各自讀寫特性,可以將寄存器分為四個(gè)部分,這四個(gè)部分可以連續(xù)也可以不連續(xù),完全由開發(fā)者決定。
下表展示了四類寄存器的含義以及與 PLC 的類比。
寄存器種類 | 含義 | PLC | 示例 |
---|---|---|---|
線圈狀態(tài) (Coil Status) | 輸出端口(可讀可寫) | DO(數(shù)字量輸出) | 電磁閥輸出、LED 顯示 |
離散輸入狀態(tài) (Input Status) | 輸入端口(只讀) | DI(數(shù)字量輸入) | 撥碼開關(guān)、微動(dòng)開關(guān) |
保持寄存器 (Holding Register) | 輸出參數(shù)(可讀可寫) | AO(模擬量輸出) | PID 運(yùn)行參數(shù)、閾值上下限 |
輸入寄存器 (Input Register) | 輸入?yún)?shù)(只讀) | AI(模擬量輸入) | 傳感器數(shù)據(jù)輸入 |
寄存器地址分配
Modbus 寄存器地址分配如下表所示,同樣參照了 PLC 寄存器地址的分配方法。
寄存器種類 | 寄存器PLC地址 | 寄存器Modbus協(xié)議地址 | 簡稱 |
---|---|---|---|
線圈狀態(tài) | 00001~09999 | 0000H~FFFFH | 0x |
離散輸入狀態(tài) | 10001~19999 | 0000H~FFFFH | 1x |
保持寄存器 | 40001~49999 | 0000H~FFFFH | 4x |
輸入寄存器 | 30001~39999 | 0000H~FFFFH | 3x |
該表中的 PLC 地址可以理解為 Modbus 協(xié)議地址的變種,在觸摸屏和 PLC 編程中應(yīng)用較為廣泛。
- 寄存器 PLC 地址指存放于控制器中的地址,這些控制器可以是 PLC,也可以是觸摸屏,或者文本顯示器。PLC 地址一般采用十進(jìn)制描述,共有 5 位,其中第一位數(shù)字代表寄存器類型。
- 寄存器 Modbus 協(xié)議地址指的是通信時(shí)使用的寄存器尋址地址,例如 PLC 地址 40001 對(duì)應(yīng)尋址地址 0x0000,40002 對(duì)應(yīng)尋址地址 0x0001。寄存器尋址地址一般使用十六進(jìn)制描述。
細(xì)心的你會(huì)發(fā)現(xiàn),PLC 寄存器地址 40003 對(duì)應(yīng)的協(xié)議地址是 0x0002,PLC 寄存器地址 30003 對(duì)應(yīng)的協(xié)議地址也是 0x0002,雖然通信時(shí)使用兩個(gè)相同的 Modbus 協(xié)議地址,但是因?yàn)椴煌拇嫫鞯墓δ艽a是不相同的,因此并不存在訪問沖突。
Modbus 功能碼
Modbus 功能碼是 Modbus 消息幀(報(bào)文)的重要組成部分,是 Modbus 協(xié)議中通信事務(wù)處理的基礎(chǔ)。
Modbus 功能碼占用一個(gè)字節(jié),取值范圍是 1~127(即 0x01~0x7F)。同時(shí),使用功能碼 + 0x80 表示異常狀態(tài),即 129~255 代表異常碼。
在 Modbus 標(biāo)準(zhǔn)協(xié)議中,一共規(guī)定了三類 Modbus 功能碼。
- 公共功能碼
- 被明確定義的功能碼;
- 保證唯一性;
- 由 Modbus 協(xié)會(huì)確認(rèn),并提供公開的文檔;
- 可進(jìn)行一致性測試;
- 包括協(xié)議定義的功能碼和保留將來使用的功能碼。
- 用戶自定義功能碼
- 有兩個(gè)用戶自定義功能碼區(qū)域,分別是 65~72 和 100~110;
- 用戶自定義,不保證唯一性。
- 保留功能碼
- 保留功能碼是因?yàn)闅v史遺留原因,某些公司的傳統(tǒng)產(chǎn)品上現(xiàn)行使用的功能碼不作為公共使用。
本教程主要介紹公共功能碼,下表展示了 Modbus 協(xié)議中的部分公共功能碼。
代碼 | 名稱 | 英文 | 寄存器 PLC 地址 | 位/字操作 | 操作數(shù)量 |
---|---|---|---|---|---|
01 | 讀線圈狀態(tài) | Read Coils | 00001~09999 | 位操作 | 單個(gè)或多個(gè) |
02 | 讀離散輸入狀態(tài) | Read Discrete Inputs | 10001~19999 | 位操作 | 單個(gè)或多個(gè) |
03 | 讀保持寄存器 | Read Holding Registers | 40001~49999 | 字操作 | 單個(gè)或多個(gè) |
04 | 讀輸入寄存器 | Read Input Registers | 30001~39999 | 字操作 | 單個(gè)或多個(gè) |
05 | 寫單個(gè)線圈 | Write Single Coil | 00001~09999 | 位操作 | 單個(gè) |
06 | 寫單個(gè)保持寄存器 | Write Single Register | 40001~49999 | 字操作 | 單個(gè) |
15 | 寫多個(gè)線圈 | Write Multiple Coils | 00001~09999 | 位操作 | 多個(gè) |
16 | 寫多個(gè)保持寄存器 | Write Multiple Registers | 40001~49999 | 字操作 | 多個(gè) |
功能碼的操作可分為兩種:
- 位操作 —— 最小單位為一位(bit),包括讀線圈狀態(tài)功能碼 01、讀離散輸入狀態(tài)功能碼 02、寫單個(gè)線圈功能碼 05 和寫多個(gè)線圈功能碼 15;
- 字操作 —— 最小單位為兩個(gè)字節(jié),包括讀保持寄存器功能碼 03、讀輸入寄存器功能碼 04、寫單個(gè)保持寄存器功能碼 06 和寫多個(gè)保持寄存器功能碼 16。
功能碼詳解
0x01 讀取線圈/離散量輸出值
- 該功能碼用于讀取從設(shè)備的線圈或離散量輸出的狀態(tài),即各 DO(Discrete Output,離散輸出)的 ON/OFF 狀態(tài)。
- 消息幀中指定了需讀取的線圈起始地址和線圈數(shù)目。
- 起始地址由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0000 到 0xFFFF。
- 線圈數(shù)量由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0001 到 0x07D0(即十進(jìn)制 1~2000)。
- 需要注意,在 Modbus 協(xié)議規(guī)定的 PDU 中,規(guī)定所有線圈或寄存器地址從 0 開始計(jì)算。
0x02 讀取離散量輸入值
- 該功能碼用于讀取從設(shè)備的離散輸入,即 DI(Discrete Input)的 ON/OFF 狀態(tài)。
- 消息幀中指定了需讀取的離散輸入寄存器起始地址和數(shù)目,可讀取 1~2000 個(gè)連續(xù)的離散量輸入狀態(tài)。
- 如果從設(shè)備接受主設(shè)備的請(qǐng)求則回復(fù)功能碼 02,并返回離散量輸入各變量的當(dāng)前狀態(tài)(如果返回的 DI 數(shù)量不是 8 的整數(shù)倍,將用 0 填充最后數(shù)據(jù)字節(jié)的剩余位)。
- 起始地址由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0000 到 0xFFFF。
- 離散量數(shù)量由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0001 到 0x07D0(即十進(jìn)制 1~2000),最多一次可讀取 2000 個(gè)離散輸入狀態(tài)值。
0x03 讀取保持寄存器值
- 該功能碼用于讀取從設(shè)備保持寄存器的內(nèi)容,不支持廣播模式。
- 消息幀中指定了需讀取的保持寄存器的起始地址和數(shù)目,而保持寄存器中各地址的具體內(nèi)容和意義則由設(shè)備開發(fā)者自行規(guī)定。
- 起始地址由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0000 到 0xFFFF。
- 寄存器數(shù)量由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0001 到 0x007D(即十進(jìn)制 1~125),最多一次可連續(xù)讀取 125 個(gè)寄存器值。
- 需要注意,Modbus 的保持寄存器和輸入寄存器是以字(Word)為基本單位的(1Word 等于 2Bytes)。因此,在讀取時(shí)需要注意字節(jié)序(大小端)問題。
0x04 讀取輸入寄存器值
- 該功能碼用于讀取從設(shè)備輸入寄存器的內(nèi)容,不支持廣播模式。(與 03 功能碼類似)
- 消息幀中指定了需讀取的輸入寄存器的起始地址和數(shù)目,而輸入寄存器中各地址的具體內(nèi)容和意義則由設(shè)備開發(fā)者自行規(guī)定。
- 起始地址由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0000 到 0xFFFF。
- 寄存器數(shù)量由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0001 到 0x007D(即十進(jìn)制 1~125),最多一次可連續(xù)讀取 125 個(gè)寄存器值。
- 同樣需要注意字節(jié)序問題。
0x05 寫單個(gè)線圈/單個(gè)離散輸出
- 該功能碼用于將單個(gè)線圈寄存器(或離散輸出)設(shè)置為 ON 或 OFF,支持廣播模式。
- 在廣播模式下,所有從站設(shè)備的同一地址的值將被統(tǒng)一修改。
- 消息幀中指定了需要變更的線圈地址和設(shè)定的狀態(tài)值。
- 起始地址由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0000 到 0xFFFF。
- 目標(biāo)數(shù)據(jù)(即查詢報(bào)文中的 ON/OFF 狀態(tài))由報(bào)文數(shù)據(jù)字段的常數(shù)指定,0xFF00 表示 ON 狀態(tài),0x0000 表示 OFF 狀態(tài),其余所有值均是非法的。
- 需要注意,在 Modbus 協(xié)議規(guī)定的 PDU 中,規(guī)定所有線圈或寄存器地址從 0 開始計(jì)算。
0x06 寫單個(gè)保持寄存器
- 該功能碼用于更新從設(shè)備的單個(gè)保持寄存器的值,支持廣播模式。
- 在廣播模式下,所有從站設(shè)備的同一地址的值將被統(tǒng)一修改。
- 消息幀中需要指定從設(shè)備地址以及需要變更的保持寄存器地址和設(shè)定值。
- 起始地址由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0000 到 0xFFFF。
- 變更目標(biāo)數(shù)據(jù)由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0000 到 0xFFFF。
- 保持寄存器以字(Word)為基本單位,寫入時(shí)需要注意目標(biāo)數(shù)據(jù)的字節(jié)序問題。
0x08 診斷功能
- 該功能碼僅用于串行鏈路,主要用于檢測主設(shè)備和從設(shè)備之間的通信故障,或檢測從設(shè)備的各種內(nèi)部故障,該功能不支持廣播。
- 查詢報(bào)文中需要指定從設(shè)備地址、功能碼(Modbus Command)以及子功能碼(Diagnostic Sub-function)。其中,子功能碼字段為 2 個(gè)字節(jié),用于區(qū)別各診斷類型。
- 在正常的響應(yīng)報(bào)文中,從設(shè)備將原樣回復(fù)功能碼和子功能碼。
常用的 Modbus 診斷子功能碼定義如下:
功能碼 | 子功能碼 | 描述 | 說明 |
---|---|---|---|
08 | 00(0x00) | Return Data Query (Loop-back) | 原樣返回查詢報(bào)文 |
08 | 01(0x01) | Restart Communications | 用于初始化并重新啟動(dòng)從站設(shè)備 其中,報(bào)文字段 0x00, 0x00 表示保持事件記錄 0xFF, 0x00 表示清除事件記錄 |
08 | 02(0x02) | Return Diagnostic Register | 返回診斷寄存器內(nèi)容 |
08 | 03(0x03) | Change ASCII Input Delimiter | |
08 | 04(0x04) | Force Listen Only Mode | 強(qiáng)制被尋址的從站設(shè)備進(jìn)入只聽模式 使其與網(wǎng)絡(luò)中的其他設(shè)備斷開,不返回響應(yīng) |
08 | 10(0x0A) | Clear Counters and Diagnostic Registers | 清除計(jì)數(shù)器和診斷寄存器 |
08 | 11(0x0B) | Return Bus Message Count | 返回總線報(bào)文計(jì)數(shù)值 |
08 | 12(0x0C) | Return Bus Communication Error Count | 返回總線通信 CRC 出錯(cuò)計(jì)數(shù) |
08 | 13(0x0D) | Return Bus Exception Error Count | 返回總線異常計(jì)數(shù) |
08 | 14(0x0E) | Return Slave Message Count | 返回從站設(shè)備接收的報(bào)文數(shù)量 |
08 | 15(0x0F) | Return Slave No Response Count | 返回從站設(shè)備沒有返回響應(yīng)的報(bào)文數(shù)量 |
08 | 16(0x10) | Return Slave NAK Count | |
08 | 17(0x11) | Return Slave Busy Count | 返回從站設(shè)備響應(yīng)忙的報(bào)文數(shù)量 |
08 | 18(0x12) | Return Bus Character Overrun Count | 返回總線字符超限的報(bào)文數(shù)量 |
08 | 19(0x13) | Return IOP Overrun Count (884) | |
08 | 20(0x14) | Clear Overrun Counter and Flag (884) |
0x0B 獲取通信事件計(jì)數(shù)器
- 該功能碼主要用于獲取從設(shè)備通信計(jì)數(shù)器中的狀態(tài)字和事件計(jì)數(shù)的值,不支持廣播模式。
- 可以通過在通信報(bào)文之前和之后讀取通信事件計(jì)數(shù)值,來確定從設(shè)備是否正常處理報(bào)文。
- 對(duì)于正常完成報(bào)文處理和傳輸?shù)膱龊?,事件?jì)數(shù)器增加 1;而對(duì)于異常響應(yīng)、輪詢命令或讀事件計(jì)數(shù)器(即 0x0B 功能碼)的場合,則計(jì)數(shù)器不變。
- 通過 0x08 診斷功能中的 0x01 子功能和 0x0A 子功能,可以復(fù)位事件寄存器。
0x0C 獲取通信事件記錄
- 該功能碼主要用于從從設(shè)備獲取狀態(tài)字、事件計(jì)數(shù)、報(bào)文計(jì)數(shù)以及事件字節(jié)字段。
- 其中狀態(tài)字和事件計(jì)數(shù)與功能碼 0x0B 獲取的值一致。
- 報(bào)文計(jì)數(shù)器包含了加電重啟、清除計(jì)數(shù)器之后的報(bào)文數(shù)量,報(bào)文計(jì)數(shù)與通過 0x08 診斷功能中的 0x0B 子功能碼獲取的值一致。
- 事件字節(jié)字段包含 0~64 個(gè)字節(jié),定義各種事件。
- 正常情況下響應(yīng)報(bào)文包括一個(gè) 2 Bytes 狀態(tài)字字段、一個(gè) 2 Bytes 事件計(jì)數(shù)字段、一個(gè) 2 Bytes 消息計(jì)數(shù)字段以及 0~64 個(gè)字節(jié)的事件字段。
- 由于事件字段是變長的,因此增加了一個(gè) 1 Byte 的數(shù)據(jù)長度字段,以方便讀取響應(yīng)數(shù)據(jù)。
0x0F 寫多個(gè)線圈
- 該功能碼用于將連續(xù)的多個(gè)線圈(或離散輸出)設(shè)置為 ON 或 OFF,支持廣播模式。
- 在廣播模式下,所有從站設(shè)備的同一地址的值將被統(tǒng)一修改。
- 消息幀中指定了需要變更的線圈起始地址和線圈數(shù)目。
- 起始地址由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0000 到 0xFFFF。
- 寄存器數(shù)量字段由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0001 到 0x07B0。
- 數(shù)據(jù)字段中為邏輯 1 的位對(duì)應(yīng) ON,邏輯 0 的位對(duì)應(yīng) OFF。
0x10 寫多個(gè)保持寄存器
- 該功能碼用于設(shè)置或?qū)懭霃脑O(shè)備保持寄存器的多個(gè)連續(xù)的地址塊(1~123個(gè)寄存器),支持廣播模式。
- 在廣播模式下,所有從站設(shè)備的同一地址的值將被統(tǒng)一修改。
- 消息幀中需要指定從設(shè)備地址以及需要變更的保持寄存器地址和數(shù)量。
- 起始地址由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0000 到 0xFFFF。
- 寄存器數(shù)量字段由 2 個(gè)字節(jié)構(gòu)成,取值范圍為 0x0001 到 0x007B(即十進(jìn)制 1~123)。
- 在實(shí)際開發(fā)中,該功能碼常用于方便用戶寫入多字節(jié)類型的數(shù)據(jù),例如浮點(diǎn)數(shù)值。因此,需要注意字節(jié)序問題。
0x11 報(bào)告從站 ID
- 該功能碼僅適用于串行鏈路,用于讀取從站設(shè)備的 ID、類型描述、當(dāng)前狀態(tài)以及其他信息,不支持廣播模式。
- 查詢報(bào)文中沒有數(shù)據(jù)字段。
- 響應(yīng)消息的構(gòu)成由從站設(shè)備決定。
總結(jié)
常用 Modbus 公共功能碼下表所示。
其中,支持廣播模式的功能碼有:
- 0x05 寫單個(gè)線圈
- 0x06 寫單個(gè)保持寄存器
- 0x0F 寫多個(gè)線圈
- 0x10 寫多個(gè)保持寄存器
除了廣播模式的報(bào)文以外,其他所有查詢報(bào)文都希望能夠獲取一個(gè)正常的響應(yīng)報(bào)文。如果一切正常,則從站設(shè)備將返回一個(gè)正常響應(yīng)報(bào)文,該響應(yīng)報(bào)文的功能碼與請(qǐng)求報(bào)文的功能碼一致。文章來源:http://www.zghlxwxcb.cn/news/detail-807869.html
另外,對(duì)于字操作的功能碼,存在多字節(jié)存儲(chǔ)的大小端問題,因此主站設(shè)備和從站設(shè)備必須保持一致的規(guī)則處理,約定 Modbus 傳輸中的數(shù)據(jù)字段的字節(jié)序。文章來源地址http://www.zghlxwxcb.cn/news/detail-807869.html
到了這里,關(guān)于ESP32 使用RS485模塊實(shí)現(xiàn)Modbus通信(二)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!