接觸到MODBUS通信協(xié)議是在畢業(yè)設(shè)計(jì)(觸摸屏與STM32單片機(jī)的通信)中,在畢業(yè)設(shè)計(jì)中使用的485總線,數(shù)據(jù)通信則是使用MODBUS通信協(xié)議,網(wǎng)上有很多MODBUS的教程,但是內(nèi)容很多都是大同小異,對(duì)初學(xué)者來(lái)說(shuō)就是在浪費(fèi)自己的學(xué)習(xí)時(shí)間,這篇文章就簡(jiǎn)單地談?wù)凪ODBUS通信協(xié)議在STM32中的應(yīng)用。
此次內(nèi)容大概分為以下幾個(gè)部分:
1. MODBUS的簡(jiǎn)單介紹。
2. ASCII傳輸模式與RTU傳輸模式
3. LRC與CRC校驗(yàn)碼的計(jì)算方式
4. MODBUS通信協(xié)議的功能碼
5. MODBUS在STM32中的簡(jiǎn)單介紹
1. MODBUS的簡(jiǎn)單介紹
MODBUS通信協(xié)議是一個(gè)主從協(xié)議,只能有一臺(tái)主機(jī),多臺(tái)從機(jī),最多允許247臺(tái)從機(jī)。在通信過(guò)程中,只能由主機(jī)向從機(jī)發(fā)送報(bào)文幀,從機(jī)只能響應(yīng)主機(jī)的報(bào)文幀,不能主動(dòng)向主機(jī)發(fā)送數(shù)據(jù),并且從機(jī)之間是不能夠進(jìn)行通信的。主機(jī)向從機(jī)發(fā)送報(bào)文幀的方式有兩種,一種是單播模式,另一種是廣播模式。簡(jiǎn)單點(diǎn)說(shuō),對(duì)于主機(jī),單播模式就是主機(jī)只向一臺(tái)從機(jī)發(fā)送報(bào)文,廣播模式就是主機(jī)向所有從機(jī)發(fā)送報(bào)文,對(duì)于從機(jī),單播模式中從機(jī)要對(duì)主機(jī)發(fā)送的報(bào)文進(jìn)行響應(yīng),廣播模式不需要響應(yīng)。而且廣播模式只能進(jìn)行寫(xiě)操作,不能進(jìn)行讀操作,讀操作是要從機(jī)將主機(jī)需要讀的數(shù)據(jù)放到響應(yīng)中響應(yīng)給主機(jī),廣播模式不需要響應(yīng)是不能進(jìn)行讀操作的根本原因,為什么廣播模式不需要響應(yīng)????若是多個(gè)從機(jī)都響應(yīng)了主機(jī),主機(jī)如何處理數(shù)據(jù)?這便是原因。
2. ASCII傳輸模式與RTU傳輸模式
MODBUS其實(shí)有四種傳輸模式,但是為什么說(shuō)這兩種呢?首先我使用的是485總線,屬于串行通信,通信是在串行鏈路上進(jìn)行的,MODBUS在串行鏈路上傳輸模式只有ASCII和RTU兩種。
協(xié)議
開(kāi)始標(biāo)記
結(jié)束標(biāo)記
校驗(yàn)
ASCII
:
CR,LF
LRC
RTU
無(wú)
無(wú)
CRC
ASCII傳輸模式就是將十六進(jìn)制數(shù)據(jù)當(dāng)作ASCII字符進(jìn)行傳輸。文字上可能不太容易理解,通過(guò)圖一可以了解ASCII是怎么進(jìn)行傳輸?shù)摹?div style="height:15px;">
圖1 ASCII包裝數(shù)據(jù)分析
在圖一中,需要傳輸?shù)臄?shù)據(jù)是0XE8,其中E和8被當(dāng)作了ASCII字符,在ASCII表中E是0X45,8是0X38,實(shí)際傳輸?shù)臄?shù)據(jù)是0X4538,結(jié)果顯而易見(jiàn),之前兩個(gè)字節(jié)的數(shù)據(jù)實(shí)際發(fā)送的是四個(gè)字節(jié),這樣的好處就是通過(guò)串口助手調(diào)試的時(shí)候,打印出來(lái)的是字符,結(jié)果正確與否可以直接看出來(lái),在傳輸?shù)倪^(guò)程中每次發(fā)送字節(jié)的時(shí)間間隔有1S之長(zhǎng),在早期硬件可靠性不是很高的時(shí)候,這起到很大的作用。
RTU傳輸模式不對(duì)數(shù)據(jù)處理,直接將數(shù)據(jù)放到串口發(fā)送,發(fā)送的數(shù)據(jù)是幾個(gè)字節(jié),串口實(shí)際發(fā)送的數(shù)據(jù)就是幾個(gè)字節(jié),與ASCII相比傳輸速率高了很多,相應(yīng)的對(duì)時(shí)間的要求就很高了。
圖2 RTU兩幀報(bào)文之間的時(shí)間要求
圖3 每幀報(bào)文中每個(gè)字節(jié)之間的時(shí)間要求
圖二和圖三可以看出RTU傳輸對(duì)時(shí)間的要求是有多高了,但是現(xiàn)在都是在使用這種傳輸模式。
1. LRC與CRC校驗(yàn)碼的計(jì)算方式
兩種校驗(yàn)碼對(duì)應(yīng)不同的傳輸模式,但是校驗(yàn)碼都是放在報(bào)文幀的最后。LRC的計(jì)算相對(duì)簡(jiǎn)單,CRC的計(jì)算很復(fù)雜,當(dāng)然也可以進(jìn)行STM32使用查表得出校驗(yàn)碼,一般的例程中都會(huì)有。
LRC的計(jì)算:
對(duì)報(bào)文中所有的連續(xù)8位字節(jié)相加,忽略進(jìn)位,然后求出其二進(jìn)制補(bǔ)碼,執(zhí)行檢驗(yàn)針對(duì)不包括起始“:”和結(jié)尾CRLF對(duì)整個(gè)ASCII報(bào)文域的內(nèi)容。
CRC的計(jì)算:
在報(bào)文幀中的只有地址編號(hào),功能碼和傳輸數(shù)據(jù)參與計(jì)算,先定義一個(gè)十六進(jìn)制變量A并賦初始值0XFF,參與計(jì)算的數(shù)據(jù)中取一個(gè)8位字節(jié)數(shù)與A進(jìn)行異或運(yùn)算,將運(yùn)算的結(jié)果賦值給A,然后將A右移一位,檢查移出位的值,如果移出位的值為”1”,則A中的值與0XA001進(jìn)行異或運(yùn)算,如果移出位的值為”0”,則A再次右移一位,并再次判斷移出位的值。如此移動(dòng)8次之后,這個(gè)8位字節(jié)數(shù)據(jù)就計(jì)算完了,取下個(gè)字節(jié)繼續(xù)計(jì)算,直至需要計(jì)算的字節(jié)計(jì)算完為止,最終得到的結(jié)果為CRC校驗(yàn)碼,將這個(gè)校驗(yàn)碼放入報(bào)文幀中時(shí),需要把CRC校驗(yàn)碼的高8位和低8位順序交換。
2. MODBUS通信協(xié)議的功能碼
MODBUS的公共功能碼很多,這些是由官方定義好的,比較常用的功能碼主要是:01,02,03,04,05,15,16,如表4-1所示,MODBUS數(shù)據(jù)模型分為四種,訪問(wèn)不同的數(shù)據(jù)模型需要使用不同的功能碼。其中01到04都是用于讀,其他常用的功能碼都是執(zhí)行寫(xiě)操作,改變相應(yīng)地址的數(shù)據(jù)。
表2 MODBUS數(shù)據(jù)模型
對(duì)象類別
對(duì)象類型
訪問(wèn)類型
內(nèi)容
離散量輸入
單個(gè)比特
只讀
I/O系統(tǒng)提供這種類型數(shù)據(jù)
線圈
單個(gè)比特
讀寫(xiě)
通過(guò)應(yīng)用程序改變這種類型數(shù)據(jù)
輸入寄存器
16-比特字
只讀
I/O系統(tǒng)提供這種類型數(shù)據(jù)
保持寄存器
16-比特字
讀寫(xiě)
通過(guò)應(yīng)用程序改變這種類型數(shù)據(jù)
這里只簡(jiǎn)單地介紹其中的01功能碼和05功能碼,01功能碼是用于讀命令的,05是用作寫(xiě)命令,其他大同小異。表3 是01功能碼主機(jī)發(fā)送的報(bào)文示例,表4是從機(jī)響應(yīng)主機(jī)的報(bào)文示例,表5是05功能主機(jī)發(fā)送與響應(yīng)的報(bào)文示例,只要是寫(xiě)命令的功能碼,主機(jī)發(fā)送的與從機(jī)響應(yīng)的是一樣的(表中的數(shù)據(jù)只是簡(jiǎn)單例子,需根據(jù)自己需求修改)。
表3 01功能碼發(fā)送信息
從機(jī)地址
功能碼
寄存器起始地址高字節(jié)
寄存器起始地址低字節(jié)
寄存器數(shù)量高字節(jié)
寄存器數(shù)量低字節(jié)
CRC校驗(yàn)高字節(jié)
CRC校驗(yàn)低字節(jié)
11
01
00
13
00
25
0E
84
表4 01功能碼響應(yīng)
從機(jī)地址
功能碼
返回字節(jié)數(shù)
狀態(tài)信息1
狀態(tài)信息2
狀態(tài)信息3
狀態(tài)信息4
狀態(tài)信息5
CRC校驗(yàn)高字節(jié)
CRC校驗(yàn)低字節(jié)
11
01
05
CD
6B
B2
0E
1B
45
E6
表5 主機(jī)寫(xiě)單線圈發(fā)送與響應(yīng)
從機(jī)地址
功能碼
寄存器地址高字節(jié)
寄存器地址低地址
數(shù)據(jù)高字節(jié)
數(shù)據(jù)低字節(jié)
CRC校驗(yàn)高字節(jié)
CRC校驗(yàn)低字節(jié)
11
05
00
AC
FF
00
4E
8B
3. MODBUS在STM32中的簡(jiǎn)單介紹
在MODBUS實(shí)際應(yīng)用中有很多細(xì)節(jié)問(wèn)題可能是大多數(shù)人都會(huì)遇到的,主機(jī)是從機(jī)的地址問(wèn)題,從機(jī)的地址是怎么確定的呢?這問(wèn)題感覺(jué)很是高深,但是實(shí)際上用一句話來(lái)說(shuō)就是自己設(shè)置的,編寫(xiě)從機(jī)程序的時(shí)候自己設(shè)置一個(gè)地址全局變量,收到報(bào)文時(shí)先確定報(bào)文中的地址是否與從機(jī)自己設(shè)置的相同,如果相同才開(kāi)始接收整個(gè)報(bào)文幀的數(shù)據(jù),注意的是從機(jī)的地址不能相同。當(dāng)主機(jī)發(fā)送數(shù)據(jù)時(shí),由我們的程序或者是組態(tài)環(huán)境中來(lái)寫(xiě)入需要接收?qǐng)?bào)文幀從機(jī)的地址號(hào)。圖4是STM32使用RTU傳輸模式的簡(jiǎn)單應(yīng)用框架,串口中斷程序執(zhí)行的是接收主機(jī)報(bào)文幀,這個(gè)過(guò)程中設(shè)置定時(shí)器,接收完之后會(huì)進(jìn)入定時(shí)器中斷程序,進(jìn)行數(shù)據(jù)處理,根據(jù)命令不同來(lái)進(jìn)行操作。操作結(jié)束之后等待下次數(shù)據(jù)的輸入。
圖 4 STM32應(yīng)用MODBUS通信協(xié)議的框架
原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處。
關(guān)注我們吧
日常技術(shù)分享