摘要:昨天有小夥(huo) 伴在群裏問關(guan) 於(yu) Modbus通信協議的,大家都比較積極地解答,所以今天果子哥總結一下關(guan) 於(yu) Modbus相關(guan) 的知識,適合正在入門的小夥(huo) 伴“食用”。同樣還是理論+實戰的方式解答,大佬勿噴。
1.什麽是Modbus?
顧名思義(yi) ,它是一個(ge) bus,即總線協議。比如串口協議、IIC協議、SPI都是通信協議。你接觸到這種協議,相信你所處的行業(ye) 是工業(ye) 方麵或者你的產(chan) 品用於(yu) 工業(ye) 。
好了,現在知道了大概知道了,這是一個(ge) 總線協議,是一個(ge) mod什麽(me) 的公司發表的一個(ge) 通信協議。那為(wei) 什麽(me) 要用這個(ge) 呢? 答案就是他們(men) 都在用,你就得學,啊哈哈!
正經的說,它被工業(ye) 領域所接受的原因是它具備一下三個(ge) 優(you) 點
- 公開發表並且無版權要求
- 易於部署和維護
- 對供應商來說,修改移動本地的比特或字節沒有很多限製
簡單的概括,就是免費+簡單+方便修改!
歸納:Modbus就是一種用在工業(ye) 上的簡單協議!
2.Modbus用來幹什麽?
用兩(liang) 個(ge) 字概括:通信
是的,所有協議都是用來通信的,協議的製定就是讓兩(liang) 個(ge) 人根據這個(ge) 協議看懂傳(chuan) 來的一組數據。比如我給你一個(ge) 6666,你要是沒有協議,就隻知道這是6666,而有了協議,你就知道了這是在問我是不是大佬?當然,也可以表示其他意思,具體(ti) 什麽(me) 意思就看你協議怎麽(me) 製定!
歸納:Modbus用來通信嘍,是個(ge) 人都知道!
3.Modbus的內容是什麽?
大致分為(wei) 以下幾種:
- Modbus-RTU
- Modbus-ASCII
- Modbus-TCP
以上三種協議,一個(ge) 設備隻會(hui) 有一種協議,如果你的設備使用的是Modbus-RTU,隻需查看以下對應部分,一般來說大部分的設備都是Modbus-RTU協議的。
4.通訊過程
Modbus是主從(cong) 方式通信,也就是說,不能同步進行通信,總線上每次隻有一個(ge) 數據進行傳(chuan) 輸,即主機發送,從(cong) 機應答,主機不發送,總線上就沒有數據通信。(所以說,這也算是一個(ge) 缺點了)
舉(ju) 例1: 一個(ge) 總線上有一個(ge) 主機,多個(ge) 從(cong) 機,主機查詢其中一個(ge) 從(cong) 機,首先你必須得這些從(cong) 機分配地址(這樣才能知道哪個(ge) 從(cong) 機,而且每個(ge) 地址必須唯一),分配好地址後,主機要查詢,然後數據下發(數據內(nei) 容下麵會(hui) 介紹),從(cong) 機得到主機發送的數據,然後對應地址的從(cong) 機回複,主機得到從(cong) 機數據,這樣就是一個(ge) 主機到從(cong) 機的通信過程,是不是很簡單呢?
舉(ju) 例2: 就像打電話,你得知道對方的電話(這就是唯一地址),然後你打電話過去,相當於(yu) 主機查找從(cong) 機,然後對方接通電話,給你回複(返回數據);正常是這樣的。
如果這時候,對方正在打電話,你應該聽到的是"sorry,you…
"這一串英文,說明對方忙,但是Modbus總線
不能判斷對方是否忙,也沒有對應的仲裁機製,好了你又知道了一個(ge) 缺點了!但是,你可以在用軟件的辦法進行適當的處理數據!
5 Modbus-RTU協議
設備必須要有RTU協議!這是Modbus協議上規定的,且默認模式必須是RTU,ASCII作為(wei) 選項。(也就是說,一般的設備隻有RTU這個(ge) 協議,ASCII一般很少)所以說,一般學習(xi) Modbus協議,隻需要了解RTU的協議,ASCII作為(wei) 學習(xi) 的了解就足夠了。
1、幀結構
幀結構 = 地址 + 功能嗎 + 數據 + 校驗
-
地址: 占用一個(ge) 字節,範圍0-255,其中有效範圍是1-247,其他有特殊用途,比如255是廣播地址(廣播地址就是應答所有地址,正常的需要兩(liang) 個(ge) 設備的地址一樣才能進行查詢和回複)。
-
功能碼:占用一個(ge) 字節,功能碼的意義(yi) 就是,知道這個(ge) 指令是幹啥的,比如你可以查詢從(cong) 機的數據,也可以修改數據,所以不同功能碼對應不同功能。
-
數據:根據功能碼不同,有不同結構,在後續的實例中有說明。
-
校驗:為(wei) 了保證數據不錯誤,增加這個(ge) ,然後再把前麵的數據進行計算看數據是否一致,如果一致,就說明這幀數據是正確的,我再回複;如果不一樣,說明你這個(ge) 數據在傳(chuan) 輸的時候出了問題,數據不對的,所以就拋棄了。
2、實戰
隻談理論大家可能不太明白,下麵舉(ju) 一個(ge) 例子。記住Modbus-RTU協議一般我們(men) 用的最多功能碼就是03
和06
,大部分都是用modbus來查詢傳(chuan) 感器上的信息用03
查詢功能碼,如果需要修改傳(chuan) 感器寄存器的值就用06
修改功能碼,其他的不需要過多關(guan) 注,學多了你也記不住,哈哈哈!
2.1 查詢功能碼0x03
功能描述:現在我是主機,我要查詢從(cong) 機地址為(wei) 1的數據。我現在用電腦的modbus調試助手來代替注意,stm32來代替從(cong) 機。
我需要發送以下數據:
主機發送: 01 03 00 00 00 01 84 0A
從(cong) 機回複: 01 03 02 19 98 B2 7E
那麽(me) 這一組數據是什麽(me) 意思呢?
從(cong) 上麵的結構圖中,可以看出,主機發送的數據大致是 地址+功能碼+數據+校驗;
所以解析如下:
發送數據解析
01-地址,也就是你傳(chuan) 感器的地址
03-功功能碼,03代表查詢功能,查詢傳(chuan) 感器的數據
00 00-代表查詢的起始寄存器地址.說明從(cong) 0x0000開始查詢。這裏需要說明以下,Modbus把數據存放在寄存器中,通過查詢寄存器來得到不同變量的值,一個(ge) 寄存器地址對應2字節數據
00 01-代表查詢了一個(ge) 寄存器.結合前麵的00 00,意思就是查詢從(cong) 0開始的1個(ge) 寄存器值
84 0A-循環冗餘(yu) 校驗,是modbus的校驗公式,從(cong) 首個(ge) 字節開始到84前麵為(wei) 止;
回複數據解析
01-地址,也就是你傳(chuan) 感器的地址
03-功功能碼,03代表查詢功能,查詢傳(chuan) 感器的數據。這裏要注意的是注意發給從(cong) 機的功能碼是啥,從(cong) 機就要回複同樣的功能碼,如果不一樣說明這一幀數據有錯誤
02-代表後麵數據的字節數,因為(wei) 上麵說到,一個(ge) 寄存器有2個(ge) 字節,所以後麵的字節數肯定是2*查詢的寄存器個(ge) 數;
19 98-寄存器的值是19 98,結合發送的數據看出,01這個(ge) 寄存器的值為(wei) 19 98
B2 7E-循環冗餘(yu) 校驗
好了,是不是很簡單呢?基本流程就是:
-
發送:從(cong) 機的地址+我要幹嘛的功能碼+我要查的寄存器的地址+我要查的寄存器地址的個(ge) 數+校驗碼
-
回複:從(cong) 機的地址+主機發我的功能碼+要發送給主機數據的字節數+數據+校驗碼
就是這麽(me) 簡單!
2.2 修改功能碼0x06
如果我要修改從(cong) 機的數據呢?那麽(me) 這個(ge) 協議有嗎,答案是Yes!
1、修改-0x06功能碼
主機發送: 01 06 00 00 00 01 48 0A
從(cong) 機回複: 01 06 00 00 00 01 48 0A
誒,看上去怎麽(me) 一樣的啊?是不是錯了?答案是這是正確的;
發送數據解析
01-主機要查詢的從(cong) 機地址
06-功能碼,06代表修改單個(ge) 寄存器功能,修改有些不同,有修改一個(ge) 寄存器和修改多個(ge) 寄存器;
00 00-代表修改的起始寄存器地址.說明從(cong) 0x0000開始.
00 01-代表修改的值為(wei) 00 01.結合前麵的00 00,意思就是修改0號寄存器值為(wei) 00 01;
48 0A-循環冗餘(yu) 校驗,是modbus的校驗公式,從(cong) 首個(ge) 字節開始到48前麵為(wei) 止;
回複數據解析
01-從(cong) 機返回給主機自己的地址,說明這就是主機查的從(cong) 機
06-功能碼,代表修改單個(ge) 寄存器功能,主機發啥功能碼,從(cong) 機就必須回什麽(me) 功能碼;
00 00-代表修改的起始寄存器地址.說明是0x0000.
00 01-代表修改的值為(wei) 00 01.結合前麵的00 00,意思就是修改0號寄存器值為(wei) 00 01;
48 0A-循環冗餘(yu) 校驗,是modbus的校驗公式,從(cong) 首個(ge) 字節開始到48前麵為(wei) 止;
如果回複的一樣,說明這個(ge) 數據是修改成功的;如果功能碼不是06,而是別的,說明從(cong) 機回複的數據有誤,主機可以做相應的處理。
2、修改-0x10功能碼
如果我要修改多個(ge) 寄存器,難道用06發好幾次,這樣不會(hui) 太傻了嗎?所以modbus RTU協議包含了修改連續多個(ge) 寄存器的方法,就是功能碼為(wei) 0x10;這個(ge) 大家自己去查詢,基本和上麵的數據格式差不多。
歸納
Modbus-RTU協議隻需要看懂功能碼0x03
、0x06
、0x10
這三個(ge) 基本的就已經足夠了;分別回想下其數據域部分:
0x03–主機需要發送起始地址
+寄存器數量
,從(cong) 機回複總字節數
+數據
;
0x06–主機發送起始地址
+數據內(nei) 容
(因為(wei) 你隻需要修改一個(ge) ,所以起始地址就是所要修改的地址),從(cong) 機返回起始地址
+數據內(nei) 容
(發現居然一樣!)
0x10–主機發送起始地址
+寄存器個(ge) 數
+總字節數
+數據
,從(cong) 機返回起始地址
+寄存器數量
6 Modbus-ACSII協議
一般隻需要了解RTU協議,因為(wei) 前麵有說過,必須要有RTU協議的,所以隻需要了解了RTU協議,就可以讀出設備信息了,至於(yu) ACSII協議,做個(ge) 大概了解
1.幀形式
對於(yu) RTU協議,比如RTU發送一個(ge) 字節:0x12
;ASCII協議則需要發送2個(ge) 字節:一個(ge) 字節代表ASCII碼1
,一個(ge) 代表ASCII碼2
,即0x31
和0x32
,才能代表0x12
。所以,ASCII協議的效率比較低。但是ASCII更符合串口打印查看,因為(wei) 串口發送的數據一般都是文本模式(ASCII),比如用RTU協議,你發送06串口可以把06正常顯示出來,但是用ACSII協議,你發送06串口是不能正常顯示的,因為(wei) 06是不可顯示字符。
從(cong) 上麵的圖中,看出:
1)比RTU多了起始段:
,多個(ge) 結束符CR
,LF
2)地址和功能都變成了2個(ge) 字節
;
3)數據部分更加繁瑣,但是更符合人們(men) 的查看;
2.歸納
由於(yu) Modbus-RTU和Modbus-ACSII都是基於(yu) 232和485鏈路的,所以其通訊模式半雙工,一般是主機和從(cong) 機的模式。其差別就是其字節的格式不同,一個(ge) 是16進製的數據,一個(ge) 是ASCII數據。ASCII多了幀頭和幀尾,也就是說可以有用這個(ge) 頭尾判斷一幀字節來判斷是否結束;而RTU沒有幀頭和幀尾,所以協議裏明確兩(liang) 幀之間要大於(yu) 3.5個(ge) 字節時間間隔,作為(wei) 一幀結束的判斷依據。對於(yu) RS485來說,總線上一般允許最大32個(ge) 設備。
備注
最後再補充點:Modbus從(cong) 設備的回應數據格式是:1、回應的數據包與(yu) 主機查詢的數據包格式一致。從(cong) 機正常回應時:功能碼與(yu) 主機發送的功能碼一致(1-127)
如果異常回應時:功能碼要在收的主機的功能碼的基礎上加128。不要問為(wei) 啥加128,你去問造協議的那一幫人吧!
因為(wei) 電腦隻支持USB,所以我們(men) 需要把USB轉TTL串口,再轉成485接口之後與(yu) 單片機相連,這是硬件最基本的,但是也需要注意。
最後修改了一下串口調試助手,加了一個(ge) CRC校驗的功能,後台回複:Modbus-ly,就可以獲取。