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