干貨福利,第一時間送達!
摘要:昨天有小伙伴在群里問關于Modbus通信協(xié)議的,大家都比較積極地解答,所以今天果子哥總結一下關于Modbus相關的知識,適合正在入門的小伙伴“食用”。同樣還是理論 實戰(zhàn)的方式,歡迎留言區(qū)評論。1.什么是Modbus?
顧名思義,它是一個Bus,即總線協(xié)議。比如串口協(xié)議、IIC協(xié)議、SPI都是通信協(xié)議。你接觸到這種協(xié)議,相信你所處的行業(yè)是工業(yè)電子方面或者你的產品用于工業(yè)。好了,現在知道了大概知道了,這是一個總線協(xié)議,是一個Mod什么的公司發(fā)表的一個通信協(xié)議。那為什么要用這個呢? 答案就是他們都在用,你就得學,啊哈哈!正經的說,它被工業(yè)領域所接受的原因是它具備一下三個優(yōu)點- 公開發(fā)表并且無版權要求
- 易于部署和維護
- 對供應商來說,修改移動本地的比特或字節(jié)沒有很多限制
2.Modbus用來干什么?
用兩個字概括:通信是的,所有協(xié)議都是用來通信的,協(xié)議的制定就是讓兩個人根據這個協(xié)議看懂傳來的一組數據。比如我給你一個6666,你要是沒有協(xié)議,就只知道這是6666,而有了協(xié)議,你就知道了這是在問我是不是大佬?當然,也可以表示其他意思,具體什么意思就看你協(xié)議怎么制定!歸納:Modbus用來通信嘍,是個人都知道!3.Modbus的內容是什么?
大致分為以下幾種:- Modbus-RTU
- Modbus-ASCII
- Modbus-TCP
4.通訊過程
Modbus是主從方式通信,也就是說,不能同步進行通信,總線上每次只有一個數據進行傳輸,即主機發(fā)送,從機應答,主機不發(fā)送,總線上就沒有數據通信。(所以說,這也算是一個缺點了)舉例1: 一個總線上有一個主機,多個從機,主機查詢其中一個從機,首先你必須得這些從機分配地址(這樣才能知道哪個從機,而且每個地址必須唯一),分配好地址后,主機要查詢,然后數據下發(fā)(數據內容下面會介紹),從機得到主機發(fā)送的數據,然后對應地址的從機回復,主機得到從機數據,這樣就是一個主機到從機的通信過程,是不是很簡單呢?舉例2: 就像打電話,你得知道對方的電話(這就是唯一地址),然后你打電話過去,相當于主機查找從機,然后對方接通電話,給你回復(返回數據),正常是這樣的。如果這時候,對方正在打電話,你應該聽到的是"sorry,you…"這一串英文,說明對方忙,但是Modbus總線不能判斷對方是否忙,也沒有對應的仲裁機制,好了你又知道了一個缺點了!但是,你可以用軟件的辦法進行適當的處理數據!5 Modbus-RTU協(xié)議
設備必須要有RTU協(xié)議!這是Modbus協(xié)議上規(guī)定的,且默認模式必須是RTU,ASCII作為選項。(也就是說,一般的設備只有RTU這個協(xié)議,ASCII一般很少)所以說,一般學習Modbus協(xié)議,只需要了解RTU的協(xié)議,ASCII作為學習的了解就足夠了。1、幀結構
幀結構 = 地址 功能碼 數據 校驗- 地址: 占用一個字節(jié),范圍0-255,其中有效范圍是1-247,其他有特殊用途,比如255是廣播地址(廣播地址就是應答所有地址,正常的需要兩個設備的地址一樣才能進行查詢和回復)。
- 功能碼:占用一個字節(jié),功能碼的意義就是,知道這個指令是干啥的,比如你可以查詢從機的數據,也可以修改數據,所以不同功能碼對應不同功能。
- 數據:根據功能碼不同,有不同結構,在下面的實例中有說明。
- 校驗:為了保證數據不錯誤,增加這個,然后再把前面的數據進行計算看數據是否一致,如果一致,就說明這幀數據是正確的,我再回復;如果不一樣,說明你這個數據在傳輸的時候出了問題,數據不對的,所以就拋棄了。
2、實戰(zhàn)
只談理論大家可能不太明白,下面舉一個例子。Modbus-RTU協(xié)議一般我們用的最多功能碼就是03和06,大部分都是用modbus來查詢傳感器上的信息用03查詢功能碼,如果需要修改傳感器寄存器的值就用06修改功能碼,其他的不需要過多關注,學多了你也記不住,哈哈哈!2.1 查詢功能碼0x03
功能描述:現在我是主機,我要查詢從機地址為01的數據。我現在用電腦的modbus調試助手來代替主機,stm32來代替從機。主機發(fā)送:?01?03?00?00?00?01?84?0A
從機回復:?01?03?02?19?98?B2?7E
那么這一組數據是什么意思呢?從上面的結構圖中,可以看出,主機發(fā)送的數據大致是?地址 功能碼 數據 校驗;所以解析如下:發(fā)送數據解析
01-地址,也就是你傳感器的地址
03-功功能碼,03代表查詢功能,查詢傳感器的數據
00?00-代表查詢的起始寄存器地址.說明從0x0000開始查詢。這里需要說明以下,Modbus把數據存放在寄存器中,通過查詢寄存器來得到不同變量的值,一個寄存器地址對應2字節(jié)數據
00?01-代表查詢了一個寄存器.結合前面的00?00,意思就是查詢從0開始的1個寄存器值
84?0A-循環(huán)冗余校驗,是modbus的校驗公式,從首個字節(jié)開始到84前面為止;
回復數據解析
01-地址,也就是你傳感器的地址
03-功功能碼,03代表查詢功能,查詢傳感器的數據。這里要注意的是注意發(fā)給從機的功能碼是啥,從機就要回復同樣的功能碼,如果不一樣說明這一幀數據有錯誤
02-代表后面數據的字節(jié)數,因為上面說到,一個寄存器有2個字節(jié),所以后面的字節(jié)數肯定是2*查詢的寄存器個數;
19?98-寄存器的值是19?98,結合發(fā)送的數據看出,01這個寄存器的值為19?98
B2?7E-循環(huán)冗余校驗
好了,是不是很簡單呢?基本流程就是:- 發(fā)送:從機的地址 我要干嘛的功能碼 我要查的寄存器的地址 我要查的寄存器地址的個數 校驗碼
- 回復:從機的地址 主機發(fā)我的功能碼 要發(fā)送給主機數據的字節(jié)數 數據 校驗碼
2.2 修改功能碼0x06
如果我要修改從機的數據呢?那么這個協(xié)議有嗎?當然有,那就是0x061、修改—0x06功能碼主機發(fā)送:?01?06?00?00?00?01?48?0A
從機回復:?01?06?00?00?00?01?48?0A
誒,看上去怎么一樣的啊?是不是錯了?答案是這是正確的;發(fā)送數據解析
01-主機要查詢的從機地址
06-功能碼,06代表修改單個寄存器功能,修改有些不同,有修改一個寄存器和修改多個寄存器;
00?00-代表修改的起始寄存器地址.說明從0x0000開始.
00?01-代表修改的值為00?01.結合前面的00?00,意思就是修改0號寄存器值為00?01;
48?0A-循環(huán)冗余校驗,是modbus的校驗公式,從首個字節(jié)開始到48前面為止;
回復數據解析
01-從機返回給主機自己的地址,說明這就是主機查的從機
06-功能碼,代表修改單個寄存器功能,主機發(fā)啥功能碼,從機就必須回什么功能碼;
00?00-代表修改的起始寄存器地址.說明是0x0000.
00?01-代表修改的值為00?01.結合前面的00?00,意思就是修改0號寄存器值為00?01;
48?0A-循環(huán)冗余校驗,是modbus的校驗公式,從首個字節(jié)開始到48前面為止;
如果回復的一樣,說明這個數據是修改成功的;如果功能碼不是06,而是別的,說明從機回復的數據有誤,主機可以做相應的處理。2、修改-0x10功能碼如果我要修改多個寄存器,難道用06發(fā)好幾次,這樣不會太傻了嗎?所以Modbus RTU協(xié)議包含了修改連續(xù)多個寄存器的方法,就是功能碼為0x10;這個大家自己去查詢,基本和上面的數據格式差不多。歸納
Modbus-RTU協(xié)議只需要看懂功能碼0x03、0x06、0x10這三個基本的就已經足夠了,分別回想下其數據域部分:0x03—主機需要發(fā)送起始地址 寄存器數量,從機回復總字節(jié)數 數據;0x06—主機發(fā)送起始地址 數據內容(因為你只需要修改一個,所以起始地址就是所要修改的地址),從機返回起始地址 數據內容(發(fā)現居然一樣?。?/p>0x10—主機發(fā)送起始地址 寄存器個數 總字節(jié)數 數據,從機返回起始地址 寄存器數量6 Modbus-ACSII協(xié)議
一般只需要了解RTU協(xié)議,因為前面有說過,必須要有RTU協(xié)議的,所以只需要了解了RTU協(xié)議,就可以讀出設備信息了,至于ACSII協(xié)議,做個大概了解即可。1.幀形式
對于RTU協(xié)議,比如RTU發(fā)送一個字節(jié):0x12;ASCII協(xié)議則需要發(fā)送2個字節(jié):一個字節(jié)代表ASCII碼1,一個代表ASCII碼2,即0x31和0x32,才能代表0x12。所以,ASCII協(xié)議的效率比較低。但是ASCII更符合串口打印查看,因為串口發(fā)送的數據一般都是文本模式(ASCII)。比如用RTU方式,也叫16進制方式,要發(fā)0x03數據,RTU方式就發(fā)送00000011。用ASCII發(fā)送0x03,就要發(fā)送0的ASCII碼0x30和3的ASCII碼0x33,對應到2進制也就是發(fā)送00110000和00110011。很顯然RTU方式只需要發(fā)送8位就可以了(加上起始位和停止位就是10位數據)。那么ASCII碼方式發(fā)送就需要兩個8位(每個8位分別加上起始位和停止位就是20位數據)。也就是說ASCII碼發(fā)送數據量是RTU方式的2倍,所以ASCII碼效率更低。那么ASCII碼效率更低,數據發(fā)送量大為啥還采用這種方式呢?因為假如你要發(fā)送數據0x03,采用RTU方式(16進制發(fā)送),計算機中端設備接收到0x03后是不可以顯示的,就是不能把0x03打印出來。因為可見字符的ASCII碼是從32—126,不是這個范圍以外的顯示屏上都看不到,會出現亂碼,如果是串口助手的話就會顯示□□□□。如果采用ASCII方式(文本模式發(fā)送),就不會出現不可顯示和亂碼的情況,因為文本模式發(fā)送0x03,就是發(fā)送ASCII碼0和ASCII碼3,也就是0x30和0x33,是可以正常顯示在計算機中端的。所以現在知道為什么還要使用ASCII效率比較低的方式發(fā)送了吧,只是為了方便調試顯示而已。從上面的圖中,看出:1)比RTU多了起始段
:,多個結束符CR,LF2)地址和功能都變成了2個字節(jié);3)數據部分更加繁瑣,但是更符合人們的查看;




