MODBUS_RTU協(xié)議:是指國際上通用的 MODBUS_RTU議。以后簡稱MODBUS協(xié)議。詳見《MODBUS協(xié)議中文版》官方文檔。
JM_MOD協(xié)議:是指完全在遵循MODBUS_RTU 協(xié)議的規(guī)則下,為了適應某些捷麥公司的設備和應用場景對MODBUS_RTU協(xié)議做了更細致定義的協(xié)議。 支持JM_MOD協(xié)議的設備或軟件接口可與任何標準MODBUS主機或設備直接通信。
JM_BUS協(xié)議:是指基于JM_MOD協(xié)議,為了 適應遠程測控一個站點的各種數(shù)據(jù)一次采集的特性做了相應改動的協(xié)議。此協(xié)議不遵循MODBUS_RTU, 不能與標準MODBUS主機或設備直接通信。詳見《JMBUS協(xié)議說明》。
本協(xié)議適用于JM公司所有標明“支持MODBUS協(xié)議”的硬件設 備和應用軟件。例如T40S無線PLC、KZ04擴展模塊、遠程通PC組態(tài)和遠程通手機組態(tài)等。
JM_MOD的數(shù)據(jù)通信指令為標準的MODBUS_RTU協(xié)議,以下為 MODBUS的基本協(xié)議規(guī)范。
圖1. 通用的MODBUS幀
圖2:MODBUS事務處理(無差錯)
圖3:MODBUS事務處理(異常響應)
下文中,講接收數(shù)據(jù)并處理響應的“服務器”稱之 為“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ù)內容是小端模式,組態(tài)軟件中的HV4 HV3 HV2 HV1。
JM_MOD以一系列具有不同特征的數(shù)據(jù)模型為基礎。幾個基本數(shù)據(jù)模型為:
基本類型 | 對象類型 | 屬性 | 內容 | 常用符號 |
離散量輸入 | 單個bit | 只讀 | I/O 系統(tǒng)提供數(shù)據(jù) | DI、I*.* |
線圈 | 單個bit | 讀寫 | 通過應用程序改變數(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 | 讀寫 | 通過應用程序改變數(shù)據(jù) | -- |
字節(jié)保持存儲區(qū) | 8bit | 讀寫 | 通過應用程序改變數(shù)據(jù) | V |
實數(shù)保持存儲區(qū) | 32bit | 讀寫 | 通過應用程序改變數(shù)據(jù) | AQ |
由于MODBUS協(xié)議中沒有所有的字節(jié)和實數(shù)的定義,而只有一個籠統(tǒng)的“04輸入寄存器和03/06/10保持寄存器”的說法。在JM_MOD協(xié)議中需要在借用MODBUS協(xié)議中的偏移地址的最高位的值和命令碼來區(qū)分設備中的不同存儲區(qū),詳見下一章節(jié)。
定義匯總,字節(jié)和實數(shù)部分本文說明,離散和整數(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 |
這個功能代碼是用來讀MODBUS從機相鄰的字節(jié)(8bit)輸入 存儲區(qū)單元。請求協(xié)議數(shù)據(jù)單元詳細說明了寄存器的起始地址和讀出數(shù)量。每個存儲區(qū)單元占1個字 節(jié)。正常的響應會返回功能代碼,讀出的寄存器的數(shù)量及內容。
字節(jié)輸入存儲區(qū)的開始偏移地址:10000 (1388H)
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 04H |
起始地址 | 2字節(jié) | 2710H到7530H |
*寄存器個數(shù) (字節(jié)存儲區(qū)2倍) | 2字節(jié) | 0001H-007DH |
*寄存器個數(shù):由于字節(jié)輸入存儲區(qū)單元占1個字節(jié),而標準 MODBUS協(xié)議中讀輸入寄存器采用2個字節(jié),因此此處的寄存器個數(shù)是指是讀取了兩倍的字節(jié)寄存器數(shù) 量。例如在協(xié)議中寄存器個數(shù)為2,表示要讀取4個字節(jié)存儲區(qū)單元。
響應協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 04H |
字節(jié)數(shù) | 1 個字節(jié) | *N |
寄存器的內容 | *N 個字節(jié) |
*N=輸入字節(jié)寄存器的數(shù)量
注意:由于每個字節(jié)存儲區(qū)單元占用一個字節(jié),而MODBUS讀輸入寄存器是兩個字節(jié),因此,每一個 偏移地址對應著兩個字節(jié)存儲區(qū)單元,由于字節(jié)存儲區(qū)的開始偏移地址是從10000(2710H)開始的, 因此偏移地址10000就是字節(jié)存儲區(qū)的1和2,偏移地址N就是字節(jié)存儲區(qū)(N-10000)*2+1和字節(jié)存儲區(qū) (N-10000)*2+2。從這個定于可以看出,一次至少可讀取兩個字節(jié)存儲區(qū)單元。
下例是從字節(jié)輸入存儲區(qū)3開始讀4個存儲區(qū)單元,讀取的內 容為00 0A和01 02。
請求 | 響應 | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 | 04 | 功能 | 04 |
起始地址高位 | 27 | 字節(jié)數(shù) | 04 |
起始地址低位 | 11 | 單元3 | 00 |
寄存器個數(shù)高位 | 00 | 單元4 | 0A |
寄存器個數(shù)低位 | 02 | 單元5 | 01 |
單元6 | 02 |
這個功能代碼是用來讀MODBUS從機相鄰的字節(jié)(8bit)輸出 存儲區(qū)單元。請求協(xié)議數(shù)據(jù)單元詳細說明了寄存器的起始地址和讀出數(shù)量。每個存儲區(qū)單元占1個字 節(jié)。正常的響應會返回功能代碼,讀出的寄存器的數(shù)量及內容。
字節(jié)輸出存儲區(qū)的開始偏移地址:10000 (2710H)
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 03H |
起始地址 | 2字節(jié) | 2710H到7530H |
*寄存器個數(shù) (字節(jié)存儲區(qū)2倍) | 2字節(jié) | 0001H-007DH |
*寄存器個數(shù):由于字節(jié)輸出存儲區(qū)單元占1個字節(jié),而標準 MODBUS協(xié)議中讀輸出寄存器采用2個字節(jié),因此此處的寄存器個數(shù)是指是讀取了兩倍的字節(jié)寄存器數(shù) 量。例如在協(xié)議中寄存器個數(shù)為2,表示要讀取4個字節(jié)存儲區(qū)單元。
響應協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 03H |
字節(jié)數(shù) | 1 個字節(jié) | *N |
寄存器的內容 | *N 個字節(jié) |
*N=輸出字節(jié)寄存器的數(shù)量
注意:由于每個字節(jié)存儲區(qū)單元占用一個字節(jié),而MODBUS讀輸出寄存器是兩個字節(jié),因此,每一個 偏移地址對應著兩個字節(jié)存儲區(qū)單元,由于字節(jié)存儲區(qū)的開始偏移地址是從10000(2710H)開始的, 因此偏移地址10000就是字節(jié)存儲區(qū)的1和2,偏移地址N就是字節(jié)存儲區(qū)(N-10000)*2+1和字節(jié)存儲區(qū) (N-10000)*2+2。從這個定義可以看出,一次至少可讀取兩個字節(jié)存儲區(qū)單元。
下例是從字節(jié)輸出存儲區(qū)3開始讀4個存儲區(qū)單元,讀取的內 容為00 0A和01 02。
請求 | 響應 | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 | 03 | 功能 | 03 |
起始地址高位 | 27 | 字節(jié)數(shù) | 04 |
起始地址低位 | 11 | 單元3 | 00 |
寄存器個數(shù)高位 | 00 | 單元4 | 0A |
寄存器個數(shù)低位 | 02 | 單元5 | 01 |
單元6 | 02 |
這個功能代碼是用來寫MODBUS從機兩個字節(jié)(8bit)輸出存 儲區(qū)單元。請求協(xié)議數(shù)據(jù)單元詳細說明了寄存器的起始地址、數(shù)值。每個存儲區(qū)單元占1個字節(jié)。正 常的響應會返回功能代碼、起始地址和寄存器數(shù)值。
*兩個字節(jié)輸出存儲單元:由于字節(jié)輸出存儲區(qū)單元占1個字 節(jié),而標準MODBUS協(xié)議中寫輸出寄存器采用2個字節(jié)。所以對于MOD-BUS06指令為寫單個寄存器,到這 里就成了寫兩個字節(jié)輸出寄存器。
字節(jié)輸出存儲區(qū)的開始偏移地址:10000(2710H)
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 06H |
起始地址 | 2字節(jié) | 2710H到7530H |
數(shù)據(jù) | 2字節(jié) | 0-FFFFH值 |
響應協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 06H |
起始地址 | 2字節(jié) | 2710H到7530H |
數(shù)據(jù) | 2字節(jié) | 0-FFFFH值 |
注意:由于每個整數(shù)存儲區(qū)單元占用兩個字節(jié),而MODBUS讀輸出寄存器也是兩個字節(jié),因此,每一 個偏移地址正好一一對應著每個整數(shù)存儲區(qū)單元,由于整數(shù)存儲區(qū)的開始偏移地址是從0000H開始的 ,因此偏移地址00就是整數(shù)存儲區(qū)單元1,偏移地址N就是整數(shù)存儲區(qū)單元N+1。
下面這個例子是寫從字節(jié)輸出寄存器3開始的內容為00、 03 :
請求 | 響應 | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 | 06 | 功能 | 06 |
起始地址高位 | 27 | 起始地址高位 | 13 |
起始地址低位 | 11 | 起始地址低位 | 89 |
寄存器值高位 | 00 | 寄存器值高位 | 00 |
寄存器值低位 | 03 | 寄存器值低位 | 03 |
這個功能代碼是用來寫MODBUS從機相鄰的字節(jié)(8bit)輸出 存儲區(qū)單元。請求協(xié)議數(shù)據(jù)單元詳細說明了寄存器的起始地址、數(shù)量和內容。每個存儲區(qū)單元占1個 字節(jié)。正常的響應會返回功能代碼和起始地址。
字節(jié)輸出存儲區(qū)的開始偏移地址:10000 (2710H)
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 10H |
起始地址 | 2字節(jié) | 2710H到7530H |
寄存器個數(shù) (字節(jié)存儲區(qū)2倍) | 2字節(jié) | 0001H-007DH |
字節(jié)數(shù) | 1字節(jié) | *N |
數(shù)據(jù) | *N | 值 |
*N=輸出字節(jié)寄存器的數(shù)量
響應協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 10H |
起始地址 | 2字節(jié) | 2710H到7530H |
寄存器個數(shù) | 2字節(jié) | 0001H-007DH |
注意:由于字節(jié)寄存器占用一個字節(jié),而MODBUS寫輸出寄存器是兩個字節(jié),因此,每一個偏移地址 對應著兩個字節(jié)寄存器,由于整數(shù)存儲區(qū)的開始偏移地址區(qū)從10000(2710H)開始的,因此偏移地址 10000就是字節(jié)寄存器1和2,偏移地址N就是字節(jié)存儲區(qū)(N-10000)*2+1和字節(jié)存儲區(qū)(N-10000)*2+2。 從這個定于可以看出,寫字節(jié)輸出存儲區(qū)一次至少寫兩個。
下面這個例子是寫從字節(jié)輸出寄存器3開始的內容為00、 0A 、01和 02到存儲區(qū)中:
請求 | 響應 | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 | 10 | 功能 | 10 |
起始地址高位 | 27 | 起始地址高位 | 00 |
起始地址低位 | 11 | 起始地址低位 | 01 |
寄存器個數(shù)高位 | 00 | 寄存器個數(shù)高位 | 00 |
寄存器個數(shù)低位 | 02 | 寄存器個數(shù)低位 | 02 |
字節(jié)數(shù) | 04 | ||
單元3 | 00 | ||
單元4 | 0A | ||
單元5 | 01 | ||
單元6 | 02 |
這個功能代碼是用來讀MODBUS從機相鄰的實數(shù)(32bit)輸入 存儲區(qū)單元。請求協(xié)議數(shù)據(jù)單元詳細說明了寄存器的起始地址和讀出數(shù)量。每個寄存器為4個字節(jié)。 正常的響應會返回功能代碼,讀出的寄存器的數(shù)量及內容。
實數(shù)輸入存儲區(qū)的開始偏移地址:30000 (7530H)
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 04H |
起始地址 | 2字節(jié) | 7530H到9C40H |
*寄存器個數(shù) (實數(shù)存儲區(qū)單元個數(shù)1/2) | *2字節(jié) | 0001H-007DH |
*寄存器個數(shù):由于每個實數(shù)輸入存儲區(qū)單元占4個字節(jié),而 標準MODBUS協(xié)議中讀輸入寄存器采用2個字節(jié),因此此處的每一個寄存器個數(shù)是指是讀取半個實數(shù)存 儲區(qū)單元的數(shù)量。例如在協(xié)議中寄存器個數(shù)為2,表示要讀取1個實數(shù)存儲區(qū)單元。
響應協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 04H |
字節(jié)數(shù) | 1 個字節(jié) | *N ×4 |
寄存器的內容 | *N×4 個字節(jié) |
*N=輸入實數(shù)寄存器的數(shù)量
注意:由于每個實數(shù)儲存單元占用4個字節(jié),而MODBUS讀輸入寄存器是兩個字節(jié),因此,每兩個偏 移地址對應著一個實數(shù)存儲區(qū)單元,由于實數(shù)存儲區(qū)的開始偏移地址從30000(7530H)開始的,因此 偏移地址30000和30001就是實數(shù)存儲區(qū)0,偏移地址N(N為偶數(shù))就是實數(shù)存儲區(qū)(N-30000)/2+1。從 這個定于可以看出,讀實數(shù)輸入存儲區(qū)必須是從偏移地址是偶數(shù)位置開始的(0,2,4,6…)。
下例是從實數(shù)輸入存儲區(qū)單元2開始讀1個單元,值內容為 3.14(C3 F5 48 40) ( 40 48 F5 C3)
請求 | 響應 | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 | 04 | 功能 | 04 |
起始地址高位 | 75 | 字節(jié)數(shù) | 04 |
起始地址低位 | 34 | 單元2-1/4 | C3 |
寄存器個數(shù)高位 | 00 | 單元2-2/4 | F5 |
寄存器個數(shù)低位 | 02 | 單元2-3/4 | 48 |
單元2-4/4 | 40 |
這個功能代碼是用來讀MODBUS從機相鄰的實數(shù)(32bit)輸出 存儲區(qū)單元。請求協(xié)議數(shù)據(jù)單元詳細說明了寄存器的起始地址和讀出數(shù)量。每個寄存器為4個字節(jié)。 正常的響應會返回功能代碼,讀出的寄存器的數(shù)量及內容。
實數(shù)輸出存儲區(qū)的開始偏移地址:30000 (7530H)
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 03H |
起始地址 | 2字節(jié) | 7530H到9C40H |
*寄存器個數(shù) (實數(shù)存儲單元個數(shù)1/2) | *2字節(jié) | 0001H-007DH |
*寄存器個數(shù):由于每個實數(shù)輸出存儲區(qū)單元占4個字節(jié),而 標準MODBUS協(xié)議中讀輸出寄存器采用2個字節(jié),因此此處的每一個寄存器個數(shù)是指是讀取半個實數(shù)存 儲區(qū)單元的數(shù)量。例如在協(xié)議中寄存器個數(shù)為2,表示要讀取1個實數(shù)存儲區(qū)單元。
響應協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 03H |
字節(jié)數(shù) | 1 個字節(jié) | *N ×4 |
寄存器的內容 | *NX4個字節(jié) |
*N=輸出實數(shù)寄存器的數(shù)量
注意:由于每個實數(shù)儲存單元占用4個字節(jié),而MODBUS讀輸出寄存器是兩個字節(jié),因此,每兩個偏 移地址對應著一個實數(shù)存儲區(qū)單元,由于實數(shù)存儲區(qū)的開始偏移地址從30000(7530H)開始的,因此 偏移地址30000和30001就是實數(shù)存儲區(qū)0,偏移地址N(N為偶數(shù))就是實數(shù)存儲區(qū)(N-30000)/2+1。從 這個定于可以看出,讀實數(shù)輸出存儲區(qū)必須是從偏移地址是偶數(shù)位置開始的(0,2,4,6…)。
下例是從實數(shù)輸出存儲區(qū)單元2開始讀1個單元,值內容為 3.14(C3 F5 48 40)
請求 | 響應 | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 | 03 | 功能 | 03 |
起始地址高位 | 75 | 字節(jié)數(shù) | 04 |
起始地址低位 | 34 | 單元2-1/4 | C3 |
寄存器個數(shù)高位 | 00 | 單元2-2/4 | F5 |
寄存器個數(shù)低位 | 02 | 單元2-3/4 | 48 |
單元2-4/4 | 40 |
這個功能代碼是用來寫MODBUS從機相鄰的實數(shù)(32bit)輸出 存儲區(qū)單元。請求協(xié)議數(shù)據(jù)單元詳細說明了寄存器的起始地址、數(shù)量和內容。每個寄存器為4個字節(jié) 。正常的響應會返回功能代碼和起始地址。
實數(shù)輸出存儲區(qū)的開始偏移地址:30000 (7530H)
請求協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 10H |
起始地址 | 2字節(jié) | 7530H到9C40H |
寄存器個數(shù) (實數(shù)存儲單元個數(shù)1/2) | 2字節(jié) | 0001H-007DH |
字節(jié)數(shù) | 1字節(jié) | *N×4 |
數(shù)據(jù) | *N | 值 |
*寄存器個數(shù):由于每個實數(shù)輸出存儲區(qū)單元占4個字節(jié),而 標準MODBUS協(xié)議中寫輸出寄存器采用2個字節(jié),因此此處的每一個寄存器個數(shù)是指是寫半個實數(shù)存儲 區(qū)單元的數(shù)量。例如在協(xié)議中寄存器個數(shù)為2,表示要寫1個實數(shù)存儲區(qū)單元。
響應協(xié)議數(shù)據(jù)單元
功能代碼 | 1字節(jié) | 10H |
起始地址 | 2字節(jié) | 7530H到9C40H |
寄存器個數(shù) | 2字節(jié) | 0001H-007DH |
注意:由于每個實數(shù)儲存單元占用4個字節(jié),而MODBUS寫輸出寄存器是兩個字節(jié),因此,每兩個偏 移地址對應著一個實數(shù)存儲區(qū)單元,由于實數(shù)存儲區(qū)的開始偏移地址從30000(7530H)開始的,因此 偏移地址30000和30001就是實數(shù)存儲區(qū)0,偏移地址N(N為偶數(shù))就是實數(shù)存儲區(qū)(N-30000)/2+1。從 這個定于可以看出,讀實數(shù)輸出存儲區(qū)必須是從偏移地址是偶數(shù)位置開始的(0,2,4,6…)。
下例是寫內容為3.14(C3 F5 48 40)到實數(shù)輸出存儲區(qū)單元 2開始的存儲區(qū)中:
請求 | 響應 | ||
字段名稱 | (Hex) | 字段名稱 | (Hex) |
功能 | 10 | 功能 | 10 |
起始地址高位 | 75 | 起始地址高位 | 75 |
起始地址低位 | 32 | 起始地址低位 | 32 |
寄存器個數(shù)高位 | 00 | 寄存器個數(shù)高位 | 00 |
寄存器個數(shù)低位 | 02 | 寄存器個數(shù)低位 | 02 |
字節(jié)數(shù) | 04 | ||
數(shù)據(jù)值VOD2高字節(jié) | C3 | ||
數(shù)據(jù)值VOD2低字節(jié) | F5 | ||
數(shù)據(jù)值VOD3高字節(jié) | 48 | ||
數(shù)據(jù)值VOD3低字節(jié) | 40 |