Modbus tcp 格式說明 通訊機制 附C#測試載入器用於學習,測試

來源:互聯網
上載者:User

標籤:lan   輸入   api   strong   分享圖片   第一個   支援人員   logs   用戶端程式   

前言:

 之前的部落格介紹了如何用C#來讀寫modbus tcp伺服器的資料,文章:http://www.cnblogs.com/dathlin/p/7885368.html

當然也有如何建立一個伺服器文章:http://www.cnblogs.com/dathlin/p/7782315.html

但是上面的兩篇文章是已經封裝好的API,只要調用就可以實現功能了,對於想瞭解modbus tcp的原理的人可能就不適合了,最近有不少網友的想要瞭解這個協議,所以在這裡再寫一篇介紹Modbus tcp的文章,不過這篇文章是簡易版本的,未來我再研究深入的話,再開一篇進階版,在簡易版中,就略去了成功標誌位及其他資料標誌,這些到等到後面再說。

先分享一下,我自己學習的地址來源:http://blog.csdn.net/thebestleo/article/details/52269999  聲明:本文並非轉載,並非照搬原文章,是在我參照原部落格的基礎上,理解了基本的modbus通訊,並結合自己的理解,重新寫一篇更好入門的文章,此處貼出原作者的文章以示尊重智慧財產權,原文章有些地方有一點錯誤,而且早就停止更新了,也沒有提供方便的測試載入器,官方的modbus 測試載入器是實驗版本的,需要購買序號才可以,所以此處提供我自己的測試載入器,地址如下,下面的介紹的例子都是基於這個工具來實現的。

https://github.com/dathlin/ModBusTcpTools/raw/master/download/download.zip

關於該測試載入器也是開放原始碼的,如果想要查看原始碼:https://github.com/dathlin/ModBusTcpTools

支援人員QQ群:592132877

 

準備條件:

在上面的測試載入器下載之前,需要一些額外的知識補充,此處不管你是學習什麼語言的,對於socket通訊層來說,其實是一樣的,下面的講解的內容是直接基於底層的,無關文法的操作。

但是需要你對位元組概念非常清晰,一般都是byte數組,一個byte有8個位,這個也要非常的清晰,如果連byte是什麼都搞不清楚,那麼對本文下面的內容理解會非常的吃力,那麼還是建議你再看看電腦原理這些書,對於socket通訊,每種語言都有不同的寫法,但是所有的語言都有兩個共同點,都能實現把資料發送到socket和從socket接收資料,至於這個如果去做,就參照你自己需要使用的語言了,此處不做這方面的說明了。

關於十六進位文本,在本文的下面的內容上,所有的byte位元組數組都表示成十六進位形式,比如 FF 10 代表2個位元組,一個是255,另一個是16。

byte[] temp = new byte[2];temp[0] = 0xFF;temp[1] = 0x10;

如果將上述的temp看作是讀取到的線圈的資料,那麼轉換規則如下:

先將上述資料轉化成二進位 : 1111 1111    (第一個byte,我們從高位寫到地位)             0001 0000   (第二個byte,我們從高位寫到地位)

對應的線圈就是,線圈7-線圈0,,,,第二個byte對應的線圈是,線圈15-線圈8     這裡一定要好好理解,從byte上來說,temp[0]是地位,temp[1]是高位,深入到每個byte裡面的二進位,高位在前,低位在後。

在C#裡等同於下面的代碼,和C語言,java也是非常的相近,還算比較好理解。

如果我說,發送 00 00 00 00 00 06 FF 01 00 00 00 01 到socket上去,那麼也就是:

byte[] temp = new temp[12];temp[0] = 0x00;temp[1] = 0x00;temp[2] = 0x00;temp[3] = 0x00;temp[4] = 0x00;temp[5] = 0x06;temp[6] = 0xFF;temp[7] = 0x01;temp[8] = 0x00;temp[9] = 0x00;temp[10] = 0x00;temp[11] = 0x01;socket.Send(temp);

先不要管上面的資料是什麼含義,知道上面的代碼是啥含義就行了。接下來就是下載上面的測試載入器,開始真正的學習modbus tcp協議了!

 

測試載入器初始化

先運行Server.exe檔案,連接埠裡輸入502,然後點擊啟動服務即可,如下:

然後運行Client.exe程式,在Ip地址裡輸入127.0.0.1,連接埠裡輸入502,點擊配置即可,我們看到,如果你的伺服器程式運行在了別的電腦上,甚至是雲端,只要用戶端的ip修改成伺服器的ip,連接埠號碼對應上,就可以訪問到伺服器的資料了。

特殊測試不用去管,和我們現在學習的東西不一致。

 

功能碼詳細解釋

對於modbus來說,涉及的功能碼也就是0x01,0x02,0x03,0x05,0x06,0x0F,0x10了,其實分類來說,就只有兩種,線圈和寄存器,也就是位讀寫和字讀寫,首先需要清楚的是功能碼不一樣,對應資料的解析規則也不一樣,下面就針對不同的情況來說。

首先說明的是,modbus協議呢,最終目的還是為了實現資料互動,既然是資料互動,那就是包含了資料讀和寫,我們把我們的想法轉化成一串資料,發送給裝置(或者叫伺服器),它返回一串資料,根據規則解析出來,這樣就得到了我們真正想要的資料。下面就來第一個想法實現吧。

另外,在modbus伺服器端,資料是使用地址的方式來公開的,這很好理解,伺服器端儲存了很多資料,你想要訪問某個資料肯定需要指定唯一的身份標識,從連續的地址來區分資料是最常用的做法,不僅好理解,還便於擴充,比如你還可以讀取連續地址的資料區塊。如果採用字串名字來標識資料,就沒有這個特點。

對於位操作來說(各種線圈和離散量),一個地址代表了一個bool變數,即 0 和 1,要麼通要麼斷,就好比一些普通的開關。

對於寄存器來說,一個地址代表了2個byte,共有65536種方式,可以滿足大多數日常使用了,比如我們讀取地址0的寄存器,返回 00 00 及代表寄存器0資料為0,如果返回 01 00 ,那麼代表寄存器0資料為 256 

 

功能碼0x01:

我不直接上一串資料,這樣看著也累,我們從例子出發,現在我們需要讀取線圈(離散量)操作,我想讀取地址0的線圈是否是通還是斷的。我們有了這個功能需求後,就可以根據需求來寫出特殊的指令了。根據協議指定,需要填寫長度為12的byte數組

byte[0]    byte[1]    byte[2]   byte[3]   byte[4]   byte[5]   byte[6]   byte[7]   byte[8]   byte[9]   byte[10]   byte[11]  

byte[0]    byte[1]   : 訊息編號---------隨便指定,伺服器返回的資料的前兩個字和這個一樣

byte[2]   byte[3]   :modbus標識,強製為0即可

byte[4]   byte[5]    :指示排在byte[5]後面所有位元組的個數,也就是總長度-6

byte[6]: 站號,隨便指定,00  -- FF 都可以

byte[7] :功能碼,這裡就需要填入我們的真正的想法了

byte[8]  byte[9]  :起始地址,比如我們想讀取地址0的資料,就填 00 00 ,如果我們想讀取地址1000的資料,怎麼辦,填入 03 E8 ,也就是將1000轉化十六進位填進去。

byte[10]  byte[11] :指定想讀取的資料長度,比如我們就想讀取地址0的一個資料,這裡就寫 00 01,如果我們想讀取地址0-999共計一個資料的長度,就寫 03 E8。和起始地址是一樣的。

 

有了上面的格式之後,接下來我們就按照格式來填寫資料吧,我們需要讀取地址0的資料,那麼指定如下

00 00 00 00 00 06 FF 01 00 00 00 01

訊息編號設為0,站號FF,功能碼01,地址01,長度01:將上面的指令在用戶端程式裡進行輸入,點擊發送,這樣就在下面的響應框裡接收到伺服器反饋的資料,我們最終需要的資訊就在反饋的資料裡了。

前面是接收到資料的時間,自動忽略,那麼返回的資料就是 00 00 00 00 00 04 FF 01 01 00 共計10個位元組的資料,ok,這玩意到底是什麼意思呢,我們來分別解析下:

byte[0]  byte[1] : 訊息編號,我們之前寫發送指令的時候,是多少,這裡就是多少。

byte[2]  byte[3]:必須都為0,代表這是modbus 通訊

byte[4]  byte[5]:指示byte[5]後面的所有位元組數,你數數看是不是4個?所以這裡是00 04,如果後面共有100個,那麼這裡就是 00 64

byte[6]:站號,之前我們寫了FF,那麼這裡也就是FF

byte[7]:功能碼,我們之前寫了01的功能碼,這裡也是01,和我們發送的指令是一致的

byte[8]:指示byte[8]後面跟隨的位元組數量,因為跟在byte[8]後面的就是真實的資料,我們最終想要的結果就在byte[8]後面

byte[9]:真實的資料,哈哈,這肯定就是我們真正想要的東西了,我們知道一個byte有8位,但是我們唯讀取了一個位元據,所有這裡的有效值只是byte[9]的最低位,二進位為 0000 0000 我們看到最低位為0,所以最終我們讀取的地址0的線圈為斷。

 

假設我們讀取地址10,開始的共10個線圈呢,那麼會返回什嗎?所以我們發送 00 00 00 00 00 06 FF 01 00 0A 00 0A

我們接收到了:00 00 00 00 00 05 FF 01 02 00 00      前面的8個位元組的資訊參照上面的分析,是一致的,我們就針對後面三個位元組著重分析。我們讀取了10個位,那麼一個位元組可以表示8個位,那麼我們的結果至少需要2個byte才能表示完,所以最終的資料肯定是2個位元組,那麼02就是後面的位元組數量,也就是真實的資料長度。

最後2個位元組就是我們最終的想要的資料了!接下來就是怎麼去解析了,我們還是需要先寫成二進位先,才能一個一個分析:00 00 二進位如下

   0               0               0             0            0           0           0            0                                  0             0              0            0           0          0          0            0                       

線圈17     線圈16     線圈15    線圈14   線圈13  線圈12  線圈11    線圈10                             無效         無效          無效        無效       無效      無效     線圈19    線圈18

至此我們擷取到了我們最終的資料!因為此處伺服器都是0,所以所有的線圈都是斷,等會可以結合05功能碼寫線圈進行聯合測試。

 

功能碼0x02:

這個功能碼和上面的一致,在本伺服器裡不支援這個功能碼。發送和解析規則和上面的一致,不再贅述。

 

功能碼0x05:

我們先講解05功能碼,這個功能碼是實現資料寫入,它能實現什麼功能呢,我們可以利用這個功能碼來指定某個線圈通或斷,具體怎麼操作呢,有了之前01功能碼的經驗,下面的代碼看起來就順利多了。

比如我要指定地址0的寄存器為通: 00 00 00 00 00 06 FF 05 00 00 FF 00    前面的含義都是一致的,我們就分析 05 00 00 FF 00

05 是功能碼, 00 00 是我們指定的地址,如果我們想寫地址1000為通,那麼就為 03 E8,至於FF 00是規定的資料,如果你想地址線圈通,就填這個值,想指定線圈為斷,就填 00 00 ,其他任何的值都對結果無效。

然後我們看看寫入的動作伺服器返回了什麼 ?  我們看到也是  00 00 00 00 00 06 FF 05 00 00 FF 00   因為在你寫入的操作中,是不帶讀取資料的,所以伺服器會直接複製一遍你的指令並返回。

 

下面再舉例一些方便理解(我們只需要指定地址及是否通斷的情況即可):

寫入地址100為通: 00 00 00 00 00 06 FF 05 00 64 FF 00   

寫入地址1000為斷:00 00 00 00 00 06 FF 05 03 E8 00 00

 

功能碼0x0F:

未完待續,,,

 

Modbus tcp 格式說明 通訊機制 附C#測試載入器用於學習,測試

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.