天天看點

詳細聊聊Modbus通信協定

作者:沃愛單片機

什麼是協定

在了解什麼是Modbus之前,我們先來看下什麼是協定

協定是一個漢語詞彙,讀音為xié yì,意思是共同計議,協商;經過談判、協商而制定的共同承認、共同遵守的檔案。

簡單地說,在我們的單片機之間互相通信,以及單片機和上位機通信中,規定了不同的内容規範,這個規範是通信的雙方都需要遵守的,這樣就可以實作兩者的通信。

而這個協定規範可以有很多種,來适應不同的裝置以及通信要求等,我們常見的就有IIC SPI UART序列槽通信協定等等。而Modbus也是一個串行通信協定。

詳細聊聊Modbus通信協定

什麼是RS-485 RS-232

我們在看Modbus的時候,經常會看到485序列槽,232序列槽,這些是什麼呢?

RS232,RS485是一種電平标準

資料在通信雙方之間傳輸,本質是傳輸實體的電平 比方說傳輸5V的電壓 -1V的電壓信号,這些實體信号在傳輸過程中會受到很多幹擾,比方說你傳輸一個5V的電壓,到了接收端可能就變成了4.8V,并且通信的雙方高低電平的參考電壓可能不同。

那麼這個時候就需要一個電平标準,來判斷多少V的電壓是高電平 1,多少V的電壓是低電平 0 這就誕生了 RS-485 RS-232

RS232:是電子工業協會(Electronic Industries Association,EIA) 制定的異步傳輸标準接口,同時對應着電平标準和通信協定(時序),其電平标準:+3V~+15V對應0,-3V~-15V對應1。

  • 全雙工
  • 邏輯1:-15V–5V
  • 邏輯0:+3V–+15V

RS485:RS485是一種序列槽接口标準,為了長距離傳輸采用差分方式傳輸,傳輸的是差分信号,抗幹擾能力比RS232強很多。兩線壓差為-2~-6V表示0,兩線壓差為+2~+6V表示1

  • 半雙工
  • 邏輯1:+2V~+6V
  • 邏輯0: -2V~ -6V
  • 注意485的電平指的是485-A和485-B兩根傳輸線,兩線間的電壓差。而不是傳輸線上的電壓
詳細聊聊Modbus通信協定

如果還想繼續了解可以看部落客的這個博文:

USB轉序列槽 TTL RS-232 RS-485 COM口 UART差別

也就是RS-485電平标準确定傳輸過來的資料是0還是1,在此基礎上,這些位元組資料根據modbus通信協定來進行資料的互動傳輸。

硬體層協定:解決0和1的可靠傳輸,常有RS232、RS485、CAN、IIC、SPI …

軟體層協定:解決傳輸目的,常有Modbus、TCP/IP、CANopen …

詳細聊聊Modbus通信協定

Modbus協定說明

Modbus誕生于1979年 莫迪康公司 後來被施耐德電氣公司收購。Modbus提供通用語言用于彼此通信的裝置和裝置。

Modbus已經成為工業領域通信協定的業界标準,并且現在是工業電子裝置之間常用的連接配接方式。Modbus作為目前工業領域應用最廣泛的協定

最簡單的說,Modbus就是一個總線通信協定,像IIC SPI這種,但是他不依賴于硬體總線

Modbus之是以使用廣泛,是有他的優點的

  • Modbus協定标準開放、公開發表且無版權要求
  • Modbus協定支援多種電氣接口,包括RS232、RS485、TCP/IP等,還可以在各種媒體上傳輸,如雙絞線、光纖、紅外、無線等
  • Modbus協定消息幀格式簡單、緊湊、通俗易懂。使用者了解和使用簡單,廠商容易開發和內建,友善形成工業控制網絡

舉一個簡單的例子,我們常用的IIC通信協定,需要在實體上連接配接iic總線,然後加上拉電阻,規定好實體層的高低電平。

詳細聊聊Modbus通信協定

而 Modbus協定是一種應用層封包傳輸協定,協定本身并沒有定義實體層,定義了控制器能夠認識和使用的消息結構,不管它們是經過何種網絡進行通信的。 是以能夠适應多種電氣接口,是以使用非常廣泛。

Modebus通信過程

注意Modbus是一主多從的通信協定

Modbus通信中隻有一個裝置可以發送請求。其他從裝置接收主機發送的資料來進行響應,從機是任何外圍裝置,如I/O傳感器,閥門,網絡驅動器,或其他測量類型的裝置。從站處理資訊和使用Modbus将其資料發送給主站。

也就是說,不能Modbus同步進行通信,主機在同一時間内隻能向一個從機發送請求,總線上每次隻有一個資料進行傳輸,即主機發送,從機應答,主機不發送,總線上就沒有資料通信。

從機不會自己發送消息給主站,隻能回複從主機發送的消息請求。

詳細聊聊Modbus通信協定

并且,Modbus并沒有忙機制判斷,比方說主機給從機發送指令, 從機沒有收到或者正在處理其他東西,這時候就不能響應主機,因為modbus的總線隻是傳輸資料,沒有其他仲裁機制,是以需要通過軟體的方式來判斷是否正常接收。

舉例

現在,我們來探讨Modbus資料傳輸的方式,可以簡單地了解成打電話。并且是單向通信的打電話

主機發送資料,首先需要從機的電話号碼(區分每個從機,每個位址必須唯一),告訴從機打電話要幹什麼事情,然後是需要發送的内容,最後再問問從機,我說的話你都聽清楚了沒有呀,沒有聽錯吧?

然後從機這裡,得到了主機打過來的電話,從機回複主機需要的内容,主機得到從機資料,這樣就是一個主機到從機的通信過程

就好比老師和你打電話,老師撥通了你的電話号,然後老師跟你說,小王呀,我這裡需要你給我發東西,發的内容是上周的一周總結,你說好的,然後打開你電腦的檔案夾,把你的周報發給老師,這就是一個通信過程。

Modbus存儲區

既然從機存儲資料,那麼肯定要有一個存儲區,那就需要檔案操作,我們都知道這檔案可以分為隻讀(-r)和讀寫(-wr)兩種類型

并且存儲的資料類型可以分為 :布爾量 和 16位寄存器

  • 布爾量比如IO口的電平高低,燈的開關狀态等。
  • 16位寄存器比如 傳感器的溫度資料,存儲的密碼等。

Modbus協定規定了4個存儲區 分别是0 1 3 4區 其中1區和4區是可讀可寫,1區和3區是隻讀。

區号 名稱 讀寫 位址範圍
0區 輸出線圈 可讀可寫布爾量 00001-09999
1區 輸入線圈 隻讀布爾量 10001-19999
3區 輸入寄存器 隻讀寄存器 30001-39999
4區 保持寄存器 可讀可寫寄存器 40001-49999

并且Modbus還給每個區都劃分了位址範圍 主機向從機擷取資料時,隻需要告訴從機資料的起始位址,還有擷取多少位元組的資料,從機就可以發送資料給主機

Modbus資料模型規定了具體的位址範圍,每一個從機,都有實際的實體存儲,跟modbus的存儲區相對應,主機讀寫從機的存儲區,實際上就是對從機裝置對應的實際存儲空間進行讀寫。

詳細聊聊Modbus通信協定

Modbus協定類型

在上面我們已經說明了Modbus可以在各種媒體上傳輸,那麼他的傳輸模式也分為三種。包括ASCII、RTU(遠端終端控制系統)、TCP三種封包類型

串行端口存在多個版本的Modbus協定,而最常見的是下面四種:

  • Modbus-Rtu
  • Modbus-Ascii
  • Modbus-Tcp
  • ModbusPlus

Modbus RTU是一種緊湊的,十六進制表示資料的方式,Modbus ASCII是一種采用Ascii碼表示資料,并且每個8Bit 位元組都作為兩個ASCII字元發送的表示方式。

RTU格式後續的指令/資料帶有循環備援校驗的校驗和,而ASCII格式采用縱向備援校驗的校驗和。

Modbus協定使用序列槽傳輸時可以選擇RTU或ASCII模式,并規定了消息、資料結構、指令和應答方式并需要對資料進行校驗。ASCII 模式采用LRC校驗,RTU模式采用16 位CRC校驗。通過以太網傳輸時使用TCP,這種模式不使用校驗,因為TCP協定是一個面向連接配接的可靠協定。

詳細聊聊Modbus通信協定

當然常用的就是RTU模式,ASCII一般很少

舉一個簡單的例子,如果我們需要發送一個數字10 那麼RTU模式下,隻需要發送 0x0A 總線上傳輸資料形式為: 0000 1010

而ASCII碼模式則将資料1和0轉為’1’和’0’,需要發送0x31(1) 0x30(0)兩個位元組資料。總線上傳輸資料形式為: 0011 0001 0011 0000

詳細的我們等下再闡述

Modbus-RTU協定

Modbus封包幀結構

一個封包就是一幀資料,一個資料幀就一個封包: 指的是一串完整的指令資料,本質就是一串資料。

Modbus封包是指主機發送給從機的一幀資料,其中包含着從機的位址,主機想執行的操作,校驗碼等内容

Modbus協定在串行鍊路上的封包格式如下所示:

詳細聊聊Modbus通信協定
從站位址 功能碼 資料 CRC/LRC
1 byte 1 byte N bytes 2 bytes
幀結構 = 從機位址 + 功能嗎 + 資料 + 校驗
  • 從機位址: 每個從機都有唯一位址,占用一個位元組,範圍0-255,其中有效範圍是1-247,其中255是廣播位址(廣播就是對所有從機發送應答)
  • 功能碼: 占用一個位元組,功能碼的意義就是,知道這個指令是幹啥的,比如你可以查詢從機的資料,也可以修改從機的資料,是以不同功能碼對應不同功能.
  • 資料: 根據功能碼不同,有不同功能,比方說功能碼是查詢從機的資料,這裡就是查詢資料的位址和查詢位元組數等。
  • 校驗: 在資料傳輸過程中可能資料會發生錯誤,CRC檢驗檢測接收的資料是否正确

Modbus功能碼

Modbus規定了多個功能,那麼為了友善的使用這些功能,我們給每個功能都設定一個功能碼,也就是指代碼。

Modbus協定同時規定了二十幾種功能碼,但是常用的隻有8種,用于對存儲區的讀寫,如下表所示:

功能碼 功能說明
01H 讀取輸出線圈
02H 讀取輸入線圈
03H 讀取保持寄存器
04H 讀取輸入寄存器
05H 寫入單線圈
06H 寫入單寄存器
0FH 寫入多線圈
10H 寫入多寄存器

當然我們用的最多的就是03和06 一個是讀取資料,一個是修改資料。

CRC校驗

錯誤校驗(CRC)域占用兩個位元組包含了一個16位的二進制值。CRC值由傳輸裝置計算出來,然後附加到資料幀上,接收裝置在接收資料時重新計算CRC值,然後與接收到的CRC域中的值進行比較,如果這兩個值不相等,就發生了錯誤。

比如主機發出01 06 00 01 00 17 98 04, 98 04 兩個位元組是校驗位,那麼從機接收到後要根據01 06 00 01 00 17 再計算CRC校驗值,從機判斷自己計算出來的CRC校驗是否與接收的CRC校驗(98 04主機計算的)相等,如果不相等那麼說明資料傳輸有錯誤,這些資料就不能要。

CRC校驗流程:

1、預置一個16位寄存器為0FFFFH(全1),稱之為CRC寄存器。

2 、把資料幀中的第一個位元組的8位與CRC寄存器中的低位元組進行異或運算,結果存回CRC寄存器。

3、将CRC寄存器向右移一位,最高位填以0,最低位移出并檢測。

4 、如果最低位為0:重複第三步(下一次移位);如果最低位為1:将CRC寄存器與一個預設的固定值(0A001H)進行異或運算。

5、重複第三步和第四步直到8次移位。這樣處理完了一個完整的八位。

6 、重複第2步到第5步來處理下一個八位,直到所有的位元組處理結束。

7、最終CRC寄存器的值就是CRC的值。

此外還有一種利用預設的表格計算CRC的方法,它的主要特點是計算速度快,但是表格需要較大的存儲空間,該方法此處不在闡述

詳細聊聊Modbus通信協定

下面我們來看詳細的發送和接收資料:

1、主機對從機讀資料操作

主機發送封包格式如下:

從站位址 功能碼 起始(高) 起始(低) 數量(高) 數量(低) 校驗
0x01 0x03 0x00 0x01 0x00 0x01 0xD5 0xCA

含義:

0x01:從機的位址

0x03:查詢功能,讀取從機寄存器的資料

0x00 0x01: 代表讀取的起始寄存器位址.說明從0x0001開始讀取.

0x00 0x01: 查詢的寄存器數量為0x0001個 Modbus把資料存放在寄存器中,通過查詢寄存器來得到不同變量的值,一個寄存器位址對應2位元組資料; 寄存器位址對應着從機實際的存儲位址

0xD5 0xCA: 循環備援校驗 CRC

從機回複封包格式如下:

| 從站位址 | 功能碼 | 位元組計數 | 位元組1 |位元組2 | 校驗 |

|–|–|-|-|-|-|-|

| 0x01 | 0x03| 0x02| 0x01 | 0x00| 0x17| 0xF8 0x4A |

含義:

0x01:從機的位址

0x03:查詢功能,讀取從機寄存器的資料

0x02: 傳回位元組數為2個 一個寄存器2個位元組

0x00 0x17:寄存器的值是0017

0xF8 0x4A: 循環備援校驗 CRC

2、主機對從機寫資料操作

主機發送封包格式如下:

從站位址 功能碼 資料位址(高) 資料位址(低) 資料(高) 資料(低) 校驗
0x01 0x06 0x00 0x01 0x00 0x17 0x98 0x04

含義:

0x01:從機的位址

0x06:修改功能,修改從機寄存器的資料

0x00 0x01: 代表修改的起始寄存器位址.說明修改0x0000-0x0001的存儲内容

0x00 0x17: 要修改的資料值為0017

0x98 0x04: 循環備援校驗 CRC

從機回複封包格式如下:

從站位址 功能碼 資料位址(高) 資料位址(低) 資料(高) 資料(低) 校驗
0x01 0x06 0x00 0x01 0x00 0x17 0x98 0x04

含義:

0x01:從機的位址

0x06:修改功能,修改從機寄存器的資料

0x00 0x01: 代表修改的起始寄存器位址.說明是0x0000

0x00 0x17:修改的值為0017

0x98 0x04: 循環備援校驗 CRC

從機的回複和主機的發送是一樣的,如果不一樣說明出現了錯誤

Modbus-ACSII協定

在消息中的每個位元組都作為兩個ASCII字元發送

十六進制的0-F 分别對應ASCII字元的0…9,A…F

也就是0x30~0x3A 0x41~0x46

詳細聊聊Modbus通信協定

下方是ascii的封包幀

  • 1個位元組起始位
  • 2個位元組位址位
  • 2個位元組功能位
  • n個資料位,最小的有效位先發送
  • LRC(縱向冗長檢測) 注意校驗方式不同
  • 結束符 \r \n

可以看到資料部分更加繁瑣,正常我們使用都是用RTU格式,ASCII碼格式有了解即可。

詳細聊聊Modbus通信協定

總結:

ModbusASCII有開始字元(和結束字元(CR LF),可以作為一幀資料開始和結束的标志,而ModbusRTU沒有這樣的标志,需要用時間間隔來判斷一幀封包的開始和結束,協定規定的時間為3.5個字元周期,就是說一幀封包開始前,必須有大于3.5個字元周期的空閑時間,一幀封包結束後,也必須要有3.5個字元周期的空閑時間否則就會出現粘包的情況。

注意:針對3.5個字元周期,其實是一個具體時間,但是這個時間跟波特率相關。

在序列槽通信中,1個字元包括1位起始位、8位資料位(一般情況)、1位校驗位(或者沒有)、1位停止位(一般情況下),是以1個字元包括11個位,那麼3.5個字元就是38.5個位,波特率表示的含義是每秒傳輸的二進制位的個位,是以如果是9600波特率,3.5個字元周期=/960038.5=0.00401s1000=4.01ms

Modbus-TCP協定

我們首先看下Modbus-TCP和Modbus-ACSII的差別

Modbus-TCP并不需要從從機位址,而是需要MBAP封包頭

并且不需要差錯校驗,因為TCP本身就具有校驗差錯的能力

詳細聊聊Modbus通信協定

MBAP封包頭格式如下:

詳細聊聊Modbus通信協定

其中事務處理表示符合協定辨別符我們正常使用設定為0即可 長度為6個位元組 0x0006

簡單來說,也就是Modbus-TCP是在Modbus-ACSII的基礎上,去掉校驗,然後加上五個位元組的0和一個06

最後附上 Modbus标準協定手冊連結

Modbus标準協定手冊

繼續閱讀