MODBUS_RTU協(xié)議:是指國際上通用的 MODBUS_RTU議。以后簡稱MODBUS協(xié)議。詳見《MODBUS協(xié)議中文版》官方文檔。
JM_MOD協(xié)議:是指完全在遵循MODBUS_RTU 協(xié)議的規(guī)則下,為了適應(yīng)某些捷麥公司的設(shè)備和應(yīng)用場景對MODBUS_RTU協(xié)議做了更細致定義的協(xié)議。 支持JM_MOD協(xié)議的設(shè)備或軟件接口可與任何標準MODBUS主機或設(shè)備直接通信。
JM_BUS協(xié)議:是指基于JM_MOD協(xié)議,為了 適應(yīng)遠程測控一個站點的各種數(shù)據(jù)一次采集的特性做了相應(yīng)改動的協(xié)議。此協(xié)議不遵循MODBUS_RTU, 不能與標準MODBUS主機或設(shè)備直接通信。詳見《JMBUS協(xié)議說明》。
本協(xié)議適用于JM公司所有標明“支持MODBUS協(xié)議”的硬件設(shè) 備和應(yīng)用軟件。例如T40S無線PLC、KZ04擴展模塊、遠程通PC組態(tài)和遠程通手機組態(tài)等。
JM_MOD的數(shù)據(jù)通信指令為標準的MODBUS_RTU協(xié)議,以下為 MODBUS的基本協(xié)議規(guī)范。
圖1. 通用的MODBUS幀
圖2:MODBUS事務(wù)處理(無差錯)
圖3:MODBUS事務(wù)處理(異常響應(yīng))
下文中,講接收數(shù)據(jù)并處理響應(yīng)的“服務(wù)器”稱之 為“MODBUS從機”。
JM_MOD 使用一個‘big-Endian’ 表示地址和數(shù)據(jù)項。這意 味著當發(fā)射多個字節(jié)時,首先發(fā)送最高有效位。例如:
寄存器大小 | 值 | |
16-比特 | 0x1234 | 發(fā)送的第一字節(jié)為0x12然后0x34 |
同樣的道理,如果傳送實數(shù)數(shù)據(jù)時,首先發(fā)送最高有效位, 最后發(fā)送最低位(組態(tài)軟件中的HV1 HV2 HV3 HV4)。
特例:起始地址為330001和430001的浮點型數(shù)據(jù)內(nèi)容是小端模式,組態(tài)軟件中的HV4 HV3 HV2 HV1。
JM_MOD以一系列具有不同特征的數(shù)據(jù)模型為基礎(chǔ)。幾個基本數(shù)據(jù)模型為:
基本類型 | 對象類型 | 屬性 | 內(nèi)容 | 常用符號 |
離散量輸入 | 單個bit | 只讀 | I/O 系統(tǒng)提供數(shù)據(jù) | DI、I*.* |
線圈 | 單個bit | 讀寫 | 通過應(yīng)用程序改變數(shù)據(jù) | DO、Q*.* |
整數(shù)輸入存儲區(qū) | 16bit | 只讀 | I/O 系統(tǒng)提供數(shù)據(jù) | -- |
字節(jié)輸入存儲區(qū) | 8bit | 只讀 | I/O 系統(tǒng)提供數(shù)據(jù) | -- |
實數(shù)輸入存儲區(qū) | 32bit | 只讀 | I/O 系統(tǒng)提供數(shù)據(jù) | AI |
整數(shù)保持存儲區(qū) | 16bit | 讀寫 | 通過應(yīng)用程序改變數(shù)據(jù) | -- |
字節(jié)保持存儲區(qū) | 8bit | 讀寫 | 通過應(yīng)用程序改變數(shù)據(jù) | V |
實數(shù)保持存儲區(qū) | 32bit | 讀寫 | 通過應(yīng)用程序改變數(shù)據(jù) | AQ |
由于MODBUS協(xié)議中沒有所有的字節(jié)和實數(shù)的定義,而只有一個籠統(tǒng)的“04輸入寄存器和03/06/10保持寄存器”的說法。在JM_MOD協(xié)議中需要在借用MODBUS協(xié)議中的偏移地址的最高位的值和命令碼來區(qū)分設(shè)備中的不同存儲區(qū),詳見下一章節(jié)。
定義匯總,離散和整數(shù)部分本文說明,字節(jié)和實數(shù)部分在“下篇”中說明。
存儲區(qū)名稱 | 意義 | 功能碼 | 地址(標準表示) | 數(shù)據(jù)類型 | 傳輸形式 |
離散輸入 | 讀離散輸入 | 02 | 0 (10001) | bit | bit |
離散輸出 | 讀離散輸出 | 01 | 0 (00001) | bit | bit |
寫單個離散輸出 | 05 | 0 (00001) | bit | bit | |
寫多個離散輸出 | 0x0F | 0 (00001) | bit | bit | |
字節(jié)輸入 | 讀字節(jié)輸入 | 04 | 10000 (310001) | 16bit | 16bit |
字節(jié)輸出 | 讀字節(jié)輸出 | 03 | 10000 (410001) | 16bit | 16bit |
寫單個字節(jié)輸出 | 06 | 10000 (410001) | 16bit | 16bit | |
寫多個字節(jié)輸出 | 0x10 | 10000 (410001) | 16bit | 16bit | |
整數(shù)輸入 | 讀整數(shù)輸入 | 04 | 0 (30001) | 8bit | 16bit |
整數(shù)輸出 | 讀整數(shù)輸出 | 03 | 0 (30001) | 8bit | 16bit |
寫單個整數(shù)輸出 | 06 | 0 (30001) | 8bit | 16bit | |
寫多個整數(shù)輸出 | 0x10 | 0 (30001) | 8bit | 16bit | |
實數(shù)輸入 | 讀實數(shù)輸入 | 04 | 30000 (330001) | 32bit | 16bit |
實數(shù)輸出 | 讀實數(shù)輸出 | 03 | 30000 (430001) | 32bit | 16bit |
寫單個實數(shù)輸出 | 06 | 30000 (430001) | 32bit | 16bit | |
寫多個實數(shù)輸出 | 0x10 | 30000 (430001) | 32bit | 16bit |
此功能代碼是遠程安裝設(shè)備驅(qū)動程序用來讀取離散輸入的1~ 2000個鄰近狀態(tài)。請求PDU詳細說明了離散輸入的起始地址,第一個離散輸入的地址域和離散輸入的 個數(shù)。離散輸入的地址從0開始,因此,離散輸入感應(yīng)器1-16的地址為0-15。
響應(yīng)信息中的離散輸入被按字節(jié)打包,數(shù)據(jù)字節(jié)的每一位都 有一個離散輸入與之相對應(yīng)。狀態(tài)1=ON,0=OFF。起始地址的內(nèi)容被放入數(shù)據(jù)第一字節(jié)的最低有效位 ,依次類推。
如果返回輸出的位數(shù)不是8的倍數(shù),剩余高位用0補。 計數(shù)字節(jié)詳細記錄了完整數(shù)據(jù)字節(jié)的數(shù)量。
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 0x02 |
起始地址 | 2字節(jié) | 0x0000到0xFFFF |
輸入量 | 2字節(jié) | 1到2000(0x7D0) |
響應(yīng)協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 0x02 |
感應(yīng)器狀態(tài) | N*X1字節(jié) |
N*=輸出量/8,如果剩余量不為0,則N=N+1
下面舉一個例子是關(guān)于請求讀離散輸入(197-218):
請求 | 響應(yīng) | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 起始地址高位 起始地址低位 輸入位數(shù)的高位 輸入位數(shù)的低位 | 02 | 功能 | 02 |
00 | 03 | ||
C4 | AC | ||
00 | DB | ||
16 | 35 |
從十六進制數(shù)AC或二進制數(shù)1010 1100中可以讀出離散輸入 204-197的狀態(tài),輸入位204是這個字節(jié)最高位,197是這個字節(jié)的最低位。
從十六進制數(shù)35或二進制數(shù)0011 0101中可以讀出離散輸入 204-197的狀態(tài),輸入位218是字節(jié)從左邊數(shù)的第三位,輸入位213是這個字節(jié)的最低位
注意:剩余的兩位(高位)用0
01功能代碼是MODBUS用來讀取從機離散輸出的10001~165535 狀態(tài)。請求協(xié)議數(shù)據(jù)單元詳細說明了離散輸出的起始地址和個數(shù)。離散輸出的地址從0開始,0x0000 對應(yīng)MODBUS地址10001,0x0001對應(yīng)地址10002,依次類推。
響應(yīng)信息中的離散輸出被按字節(jié)打包,數(shù)據(jù)字節(jié)的每一位都 有一個離散輸出與之相對應(yīng)。狀態(tài)1=ON,0=OFF。起始地址的內(nèi)容被放入數(shù)據(jù)第一字節(jié)的最低有效位 ,依次類推。
如果返回輸出的位數(shù)不是8的倍數(shù),剩余高位用0補。計數(shù)字 節(jié)詳細記錄了完整數(shù)據(jù)字節(jié)的數(shù)量。
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 0x01 |
起始地址 | 2字節(jié) | 0x0000到0xFFFF |
感應(yīng)器數(shù)量 | 2字節(jié) | 1到2000(0x7D0) |
響應(yīng)協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 0x01 |
字節(jié)數(shù) | n字節(jié) | n=N或者N+1 |
N*=輸出量/8,如果剩余量不為0,則n=N*+1
下面舉一個例子是關(guān)于請求讀離散輸出(20-38):
請求 | 響應(yīng) | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 起始地址高位 起始地址低位 輸出位數(shù)的高位 輸出位數(shù)的低位 | 01 | 功能 字節(jié)數(shù) 輸出狀態(tài)27-20 輸出狀態(tài)35-28 輸出狀態(tài)38-36 | 01 |
00 | 03 | ||
13 | CD | ||
00 | 6B | ||
13 | 05 |
十六進制數(shù)CD或二進制數(shù)1100 1101包含了輸 出位27的狀態(tài)“1”。輸出位27是這個字節(jié)的最高位,輸出位20為這個字節(jié)的最低位。
在通常的情況下,一個字節(jié)的左邊是最高有效位,右邊是最 低有效位。這樣輸出的第一個字節(jié)從左邊到右邊依次是位27到20,下一個字節(jié)從左到右依次是位35到 28。當傳輸這些輸出狀態(tài)時,從最低有效位到最高有效位:20…27,28…35依次類推。
在最后一個字節(jié),十六進制數(shù)05或二進制數(shù)0000 0101 是輸出位38-36的狀態(tài)。輸出位38是從左邊開始數(shù)的第六位,輸出位36是這個字節(jié)的最低位。剩余的 五個高位用0補。
注:北京捷麥PLC離散輸出變量有256個,除了實際 硬件對應(yīng)的之外,其它的都可以做中間繼電器使用。
在一個MODBUS從機上,使用該功能碼寫單個輸出為ON 或OFF 。
請求數(shù)據(jù)域中的常量說明請求的ON/OFF狀態(tài)。十六進制值FF 00請求輸出為ON。十六進制值00 00 請求輸出為OFF。其它所有值均是非法的,并且對輸出不起作用 。
請求PDU說明了強制的線圈地址。從零開始尋址線圈。因此, 尋址線圈1 為0。線圈值域的常量說明請求的ON/OFF 狀態(tài)。十六進制值0XFF00請求線圈為ON。十六進 制值0X0000請求線圈為OFF。其它所有值均為非法的,并且對線圈不起作用。
正常響應(yīng)是請求的應(yīng)答,在寫入線圈狀態(tài)之后返回這個正常 響應(yīng)。
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 0x05 |
起始地址 | 2字節(jié) | 0x0000至0xFFFF |
輸出值 | 2字節(jié) | 0x0000 至0xFF00 |
響應(yīng)協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 0x05 |
起始地址 | 2字節(jié) | 0x0000 至0xFFFF |
輸出值 | 2字節(jié) | 0x0000 至0xFF00 |
這是一個請求寫線圈173 為ON 的實例:
請求 | 響應(yīng) | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 輸出地址Hi 輸出地址Lo 輸出值Hi 輸出值Lo | 05 | 功能 輸出地址Hi 輸出地址Lo 輸出值Hi 輸出值Lo | 05 |
00 | 00 | ||
AC | AC | ||
FF | FF | ||
00 | 00 |
這個功能代碼是MODBUS從機用來確定離散輸出序列中的離散 輸出的ON或OFF狀態(tài)。請求協(xié)議數(shù)據(jù)單元詳細說明了離散輸出的起始地址和輸出數(shù)量。離散輸出的地 址是從0開始的,因此離散輸出1的地址為0。
在請求協(xié)議數(shù)據(jù)單元詳細說明了請求狀態(tài)ON或OFF。這個區(qū)域 的相應(yīng)位為邏輯“1”時,對應(yīng)的輸出為ON,邏輯“0”對應(yīng)OFF。
正常的響應(yīng)返回功能代碼,起始地址和對應(yīng)離散輸出的數(shù)量 。
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 0FH |
起始地址 | 2字節(jié) | 0000H到007FH |
輸出數(shù)量 | 2字節(jié) | 0001H到0080H |
輸出值 | N*×1字節(jié) |
N*=輸出量/8, 如果剩余量不為0,則N=N+1
響應(yīng)協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 0FH |
起始地址 | 2字節(jié) | 0000H到007FH |
輸出數(shù)量 | 2字節(jié) | 0001H到0080H |
下面舉一個例子,寫一連串的10個離散輸出,從離散輸出20 開始
被傳輸?shù)臄?shù)據(jù)的第一字節(jié)CD是存儲器碼為27-20的狀態(tài) ,最低位表達的是離散輸出20的狀態(tài),下一字節(jié)存儲器碼為29-28的狀態(tài),最低位表達的是離散輸出 28的狀態(tài)。在最后一字節(jié)沒有用到的位用0補。
請求 | 響應(yīng) | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 起始地址Hi 起始地址Lo 輸出數(shù)量Hi 輸出數(shù)量Lo 字節(jié)數(shù) 輸出值Hi 輸出值Lo | 0F | 功功能 起始地址Hi 起始地址Lo 輸出數(shù)量Hi 輸出數(shù)量Lo | 0F |
00 | 00 | ||
13 | 13 | ||
00 | 00 | ||
0A | 0A | ||
02 | |||
CD | |||
01 |
這個功能代碼是用來讀MODBUS從機相鄰的整數(shù)(16bit)輸入 存儲區(qū)單元。請求協(xié)議數(shù)據(jù)單元詳細說明了存儲區(qū)的起始地址和讀出數(shù)量。每個存儲區(qū)單元為兩個字 節(jié)。正常的響應(yīng)會返回功能代碼,讀出的存儲區(qū)單元的數(shù)量及內(nèi)容。
整數(shù)輸入存儲區(qū)的開始偏移地址:0 (0000H)
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 04H |
起始地址 | 2字節(jié) | 0000H到2710H |
寄存器個數(shù)(*N) | 2字節(jié) | 0001H-007DH |
*N=輸入整數(shù)存儲區(qū)單元的數(shù)量
響應(yīng)協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 04H |
字節(jié)數(shù) | 1 個字節(jié) | *N ×2 |
寄存器值 | *N ×2個字節(jié) | 值 |
*N=輸入整數(shù)存儲區(qū)單元的數(shù)量
注意:由于每個整數(shù)存儲區(qū)單元占用兩個字節(jié),而MODBUS讀輸入寄存器也是兩個字節(jié),因此 ,每一個偏移地址正好一一對應(yīng)著每個整數(shù)存儲區(qū)單元,由于整數(shù)存儲區(qū)的開始偏移地址是從0000H 開始的,因此偏移地址00就是整數(shù)存儲區(qū)單元1,偏移地址N就是整數(shù)存儲區(qū)單元N+1。
下例是從整數(shù)輸入存儲區(qū)單元2開始讀兩個單元,讀出的內(nèi)容 為00 0A和01 02。
請求 | 響應(yīng) | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 | 04 | 功能 | 04 |
起始地址高位 | 00 | 字節(jié)數(shù) | 04 |
起始地址低位 | 01 | 單元2高字節(jié) | 00 |
寄存器個數(shù)高位 | 00 | 單元2低字節(jié) | 0A |
寄存器個數(shù)低位 | 02 | 單元3高字節(jié) | 01 |
單元3低字節(jié) | 02 |
這個功能代碼是用來讀MODBUS從機相鄰的整數(shù)(16bit)輸出 存儲區(qū)單元。請求協(xié)議數(shù)據(jù)單元詳細說明了存儲區(qū)的起始地址和讀出數(shù)量。每個存儲區(qū)單元為兩個字 節(jié)。正常的響應(yīng)會返回功能代碼,讀出的存儲區(qū)單元的數(shù)量及內(nèi)容。
整數(shù)輸出存儲區(qū)的開始偏移地址:0 (0000H)
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 03H |
起始地址 | 2字節(jié) | 0000H到2710H |
寄存器個數(shù)(*N) | 2字節(jié) | 0001H-007DH |
*N=輸出整數(shù)存儲區(qū)單元的數(shù)量
響應(yīng)協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 03H |
字節(jié)數(shù) | 1 個字節(jié) | *N ×2 |
寄存器值 | *N ×2個字節(jié) | 值 |
*N=輸出整數(shù)存儲區(qū)單元的數(shù)量
注意:由于每個整數(shù)存儲區(qū)單元占用兩個字節(jié),而MODBUS讀輸出寄存器也是兩個字節(jié),因此 ,每一個偏移地址正好一一對應(yīng)著每個整數(shù)存儲區(qū)單元,由于整數(shù)存儲區(qū)的開始偏移地址是從0000H 開始的,因此偏移地址00就是整數(shù)存儲區(qū)單元1,偏移地址N就是整數(shù)存儲區(qū)單元N+1。
下例是從整數(shù)輸出存儲區(qū)單元2開始讀兩個單元,讀出的內(nèi)容 為00 0A和01 02。
請求 | 響應(yīng) | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 | 03 | 功能 | 03 |
起始地址高位 | 00 | 字節(jié)數(shù) | 04 |
起始地址低位 | 01 | 單元2高字節(jié) | 00 |
寄存器個數(shù)高位 | 00 | 單元2低字節(jié) | 0A |
寄存器個數(shù)低位 | 02 | 單元3高字節(jié) | 01 |
單元3低字節(jié) | 02 |
這個功能代碼是用來寫MODBUS從機單個的整數(shù)(bit16)輸出 存儲區(qū)單元。請求協(xié)議數(shù)據(jù)單元說明了被寫入寄存器的地址。每個寄存器為兩個字節(jié)。正常的響應(yīng)會 返回功能代碼,起始地址和存儲區(qū)單元的內(nèi)容。
整數(shù)輸出存儲區(qū)的開始偏移地址:0 (0000H)
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 06H |
寄存器地址 | 2字節(jié) | 0000H到2710H |
寄存器的值 | 2字節(jié) | 0x0000 到0xFFFF |
響應(yīng)協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 06H |
寄存器地址 | 2字節(jié) | 0000H到2710H |
寄存器的值 | 2字節(jié) | 0x0000 到0xFFFF |
注意:由于每個整數(shù)存儲區(qū)單元占用兩個字節(jié),而MODBUS讀輸出寄存器也是兩個字節(jié),因此 ,每一個偏移地址正好一一對應(yīng)著每個整數(shù)存儲區(qū)單元,由于整數(shù)存儲區(qū)的開始偏移地址是從0000H 開始的,因此偏移地址00就是整數(shù)存儲區(qū)單元1,偏移地址N就是整數(shù)存儲區(qū)單元N+1。
下例是從將內(nèi)容為00 03的數(shù)據(jù)寫入整數(shù)輸出存儲區(qū)單元2中 。
請求 | 響應(yīng) | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 | 06 | 功能 | 06 |
起始地址高位 | 00 | 起始地址高位 | 00 |
起始地址低位 | 01 | 起始地址低位 | 01 |
寄存器值高位 | 00 | 寄存器值高位 | 00 |
寄存器值低位 | 03 | 寄存器值低位 | 03 |
這個功能代碼是用來寫MODBUS從機相鄰的整數(shù)(16bit)輸出 存儲區(qū)單元。請求協(xié)議數(shù)據(jù)單元詳細說明了寄存器的起始地址、數(shù)量和數(shù)據(jù)內(nèi)容。每個存儲區(qū)單元為 兩個字節(jié)。正常的響應(yīng)會返回功能代碼,起始地址和讀出的存儲區(qū)單元內(nèi)容。
整數(shù)輸出存儲區(qū)的開始偏移地址:0 (0000H)
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 10H |
起始地址 | 2字節(jié) | 0000H到2710H |
寄存器個數(shù) | 2字節(jié) | 0001H-007DH |
字節(jié)數(shù) | 1字節(jié) | *N ×2 |
數(shù)據(jù) | *N ×2 | 值 |
*N=輸出整數(shù)寄存器的數(shù)量
響應(yīng)協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 10H |
起始地址 | 2字節(jié) | 0000H到2710H |
寄存器個數(shù) | 2字節(jié) | 0001H-007DH |
注意:由于每個整數(shù)存儲區(qū)單元占用兩個字節(jié),而MODBUS讀輸出寄存器也是兩個字節(jié),因此 ,每一個偏移地址正好一一對應(yīng)著每個整數(shù)存儲區(qū)單元,由于整數(shù)存儲區(qū)的開始偏移地址是從0000H 開始的,因此偏移地址00就是整數(shù)存儲區(qū)單元1,偏移地址N就是整數(shù)存儲區(qū)單元N+1。
下例是將內(nèi)容為00 0A和01 02寫從整數(shù)輸出存儲區(qū)單元2開始 的存儲區(qū)中:
請求 | 響應(yīng) | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 | 10 | 功能 | 10 |
起始地址高位 | 00 | 起始地址高位 | 00 |
起始地址低位 | 01 | 起始地址低位 | 01 |
寄存器個數(shù)高位 | 00 | 寄存器個數(shù)高位 | 00 |
寄存器個數(shù)低位 | 02 | 寄存器個數(shù)低位 | 02 |
字節(jié)數(shù) | 04 | ||
數(shù)據(jù)值VOD2高字節(jié) | 00 0A 01 02 | ||
數(shù)據(jù)值VOD2低字節(jié) | |||
數(shù)據(jù)值VOD3高字節(jié) | |||
數(shù)據(jù)值VOD3低字節(jié) |
點擊打開北京捷麥MODBUD-RTU協(xié)議說明(下)