Modbus通訊協議由Modicon公司(現已經爲施耐德公司併購,成爲其旗下的子品牌)於1979年發明的,是全球最先用於工業現場的總線規約。因爲其免費公開發行,使用該協議的廠家無需繳納任何費用,Modbus通訊協議採用的是主從通訊模式(即Master/Slave通訊模式),其在分散控制方面應用極其普遍,從而使得Modbus協議在全球獲得了普遍的應用。算法
Modbus通訊協議具備多個變種,其具備支持串口(主要是RS-485總線),以太網多個版本,其中最著名的是Modbus RTU,Modbus ASCII和Modbus TCP三種。其中Modbus RTU與Modbus ASCII均爲支持RS-485總線的通訊協議,其中Modbus RTU因爲其採用二進制表現形式以及緊湊數據結構,通訊效率較高,應用比較普遍。而Modbus ASCII因爲採用ASCII碼傳輸,而且利用特殊字符做爲其字節的開始與結束標識,其傳輸效率要遠遠低於Modbus RTU協議,通常只有在通訊數據量較小的狀況下才考慮使用Modbus ASCII通訊協議,在工業現場通常都是採用Modbus RTU協議,通常而言,你們說的基於串口通訊的Modbus通訊協議都是指Modbus RTU通訊協議。服務器
在此咱們着重討論Modbus RTU協議,而Modbus TCP協議則是在RTU協議上加一個MBAP報文頭,因爲TCP是基於可靠鏈接的服務,RTU協議中的CRC校驗碼就再也不須要,因此在Modbus TCP協議中是沒有CRC校驗碼,用一句比較通俗的話說就是:Modbus TCP協議就是Modbus RTU協議在前面加上五個0以及一個6,而後去掉兩個CRC校驗碼字節就OK.雖然這句話說得不是特別準確,可是也基本上把RTU與TCP之間的區別說得比較清楚了。數據結構
RTU協議中的指令由地址碼(一個字節),功能碼(一個字節),起始地址(兩個字節),數據(N個字節),校驗碼(兩個字節)五個部分組成,其中數據又由數據長度(兩個字節,表示的是寄存器個數,假定內容爲M)和數據正文(M乘以2個字節)組成,而RTU協議是採用3.5個字節的空閒時間做爲指令的起始和結束,通常而言,只有當從機返回數據或者主機寫操做的時候,纔會有數據正文,而其餘時候好比主機讀操做指令的時候,沒有數據正文,只須要數據長度便可。(本章的討論只涉及寄存器的讀寫,其餘好比線圈的讀寫指令咱們暫時不涉及)。在此咱們經過兩個指令(0x03H:讀多個寄存器指令以及0x10H:寫多個寄存器指令)來解釋Modbus RTU協議。在此咱們使用的RTU設備是深圳市國科偉業通訊技術有限公司的ND-1084型485總線I/O模塊。tcp
ND-1084型485總線I/O模塊採用RS-485總線通訊,支持四路開關量輸出以及八路開關量輸入,咱們只講述讀取開關量輸出的狀態以及經過寫指令控制開關量的輸出。其中儲存開關量輸出狀態的四個寄存器分別:0x18E,0x18F,0x190,0x191。在此咱們假設模塊的地址爲默認的0x01,當咱們要去讀取開關量輸出對應的四個寄存器的狀態的時候,咱們下發的十六進制的指令爲:「01 03 01 8E 00 04 25 DE」,其中「01」爲模塊的地址碼,「03」爲功能碼,即表示讀寄存器,「01 8E」爲寄存器地址,即從該寄存器地址開始讀取數據,「00 04」則表示讀取4個寄存器,而「25 DE」則爲前面「01 03 01 8E 00 04」的CRC校驗碼,該數值經過CRC16校驗算法計算出來的,咱們會在其餘文章中闡述。該指令的完整解讀就是,在地址碼爲「01」的模塊中,從「01 8E」寄存器開始,讀取4個寄存器的數據返回至主機。在此,咱們能夠看到,讀取指令中並無什麼數據正文,由於它只是讀取相應數量的寄存器,並不須要數據正文,而寫操做指令則相反,咱們會在後面講到。htm
模塊返回的指令是:「01 03 08 00 01 00 01 00 01 00 01 28 D7」,返回的指令內容解讀就是:「01」表示模塊的地址碼,「03」表示該指令是讀操做返回的指令,「08」表示數據長度,在此表示的是8個字節數據正文(即4個寄存器,每一個寄存器兩個字節表示),「00 01 00 01 00 01 00 01」是數據正文,表示四個寄存器的狀態,「28 D7」就是CRC16校驗碼。開發
一樣的當咱們執行寫操做的是,咱們舉例寫第一個開關量輸出,即寄存器「0x18E」,主機下發的指令爲:「01 10 01 8e 00 01 02 00 00 A8 7E」,該指令的解讀就是:「01」表示模塊的地址,「10」表示該指令爲寫寄存器,「01 8E」表示從該寄存器地址開始執行寫操做指令「00 01」表示寫多少個寄存器,在此爲寫1個寄存器,「02」表示數據長度,表示數據長度爲兩個字節,「00 00」表示寫入寄存器的數據,在此表示連通,「A8 7E」爲CRC校驗碼。模塊返回的指令和讀取寄存器的返回的指令相似。get
前文所述,Modbus TCP協議是在RTU協議前面添加MBAP報文頭,共七個字節長度,其分別的意義是:1.傳輸標誌,兩個字節長度,標誌Modbus詢問/應答的傳輸,通常默認是00 00。2.協議標誌,兩個字節長度,0表示是Modbus,1表示UNI-TE協議,通常默認也是00 00。3.後續字節計數,兩個字節長度,其實際意義就是後面的字節長度,具體狀況詳見下文。4.單元標誌,一個字節長度,通常默認爲00,單元標誌對應於Modbus RTU協議中的地址碼,當RTU與TCP之間進行協議轉換的時候,特別是Modbus網關轉換協議的時候,在TCP協議中,該數據就是對應RTU協議中的地址碼,具體狀況詳見下文。table
經過上面的描述咱們差很少可以理解Modbus RTU協議,咱們再說說Modbus TCP通訊協議,前面就已經說過TCP協議就是在RTU協議的基礎上去掉校驗碼以及加上五個0和一個6,當是讀取相關寄存器的時候,該說法是沒有錯的,好比上文的「01 03 01 8E 00 04 25 DE」讀取指令,用TCP協議來表述的話,指令是「00 00 00 00 00 06 00 03 01 8E 00 04」,因爲TCP是基於TCP鏈接的,不存在所謂的地址碼,因此06後面通常都是「00」(當其做爲Modbus網關服務器掛接多個RTU設備的時候,數值從01-FF).即「00 03 01 8E 00 04」對應的是RTU中去掉校驗碼的指令,前面則是五個0以及一個6。其中6表示的是數據長度,即「00 03 01 8E 00 04」有6個字節長度。而當其爲寫操做指令的時候,其指令是「00 00 00 00 00 09 01 10 01 8e 00 01 02 00 00」,其中「00 09」表示後面有9個字節。ast
Modbus RTU與Modbus TCP讀指令對比效率
MBAP報文頭
|
地址碼
|
功能碼
|
寄存器地址
|
寄存器數量
|
CRC校驗
|
|
Modbus RTU |
無
|
01
|
03
|
01 8E
|
00 04
|
25 DE
|
Modbus TCP |
00 00 00 00 00 06 00
|
無
|
03
|
01 8E
|
00 04
|
無
|
指令的涵義:從地址碼爲01(TCP協議單元標誌爲00)的模塊0x18E(01 8E)寄存器地址開始讀(03)四個(00 04)寄存器。
Modbus RTU與Modbus TCP寫指令對比
MBAP報文頭
|
地址碼
|
功能碼
|
寄存器地址
|
寄存器數量
|
數據長度
|
正文
|
CRC校驗
|
|
RTU |
無
|
01
|
10
|
01 8E
|
00 01
|
02
|
00 00
|
A8 7E
|
TCP |
00 00 00 00 00 09 00
|
無
|
10
|
01 8E
|
00 01
|
02
|
00 00
|
無
|
指令的涵義:從地址碼爲01(TCP協議單元標誌爲00)的模塊0x18E(01 8E)寄存器地址開始寫(10)一個(00 01)寄存器,具體數據長度爲2個字節(02),數據正文內容爲00 00(00 00)。