STM32--MODBUS 通訊篇

2020-10-11 11:00:17

STM32–MODBUS 通訊篇




一、MODBUS簡介

①Modbus協定是一種請求/應答的序列鏈路協定,是一種工業現場匯流排協定標準。是一項應用層報文傳輸協定,用於在通過不同型別的匯流排或網路連線的裝置之間的客戶機/伺服器通訊。

②Modbus協定是一項應用層報文傳輸協定,包括ASCII、RTU、TCP三種報文型別。

③標準的Modbus協定物理層介面有RS232、RS422、RS485和乙太網介面,採用master/slave方式通訊。

④MODBUS 是一項應用層報文傳輸協定,用於在通過不同型別的匯流排或網路連線的裝置之間的客戶機/伺服器通訊。

MODBUS 通用幀如圖:在這裡插入圖片描述


二、MODBUS功能碼詳解

1. 暫存器分類

Modbus暫存器分為四種,如表

暫存器種類資料型別存取型別功能碼PLC地址暫存器地址
線圈暫存器讀寫01H 05H 0FH00001-099990000H-FFFFH
離散輸入暫存器只寫02H10001-199990000H-FFFFH
輸入暫存器只寫04H30001-399990000H-FFFFH
保持暫存器讀寫03H 06H 10H40001-499990000H-FFFFH

2. 常用功能碼

Modbus中常用功能碼有8個,可以分為位元運算和字操作兩類,如表所示:

功能碼描述PLC地址暫存器地址位/字操作運算元量
01H讀線圈暫存器00001-099990000H-FFFFH位元運算單個或多個
02H讀離散輸入暫存器10001-199990000H-FFFFH位元運算單個或多個
03H讀保持暫存器40001-499990000H-FFFFH字操作單個或多個
04H讀輸入暫存器30001-399990000H-FFFFH字操作單個或多個
05H寫單個線圈暫存器00001-099990000H-FFFFH位元運算單個
06H寫單個保持暫存器40001-499990000H-FFFFH字操作單個
0FH寫多個線圈暫存器00001-099990000H-FFFFH位元運算多個
10H寫多個保持暫存器40001-499990000H-FFFFH字操作多個

2. 常用功能碼說明

①讀線圈暫存器——01H

●功能碼01H讀取Modbus從機中線圈暫存器的狀態,可以是單個暫存器,或者多個連續的暫存器。

●假設從機地址為01H,讀取的線圈暫存器的起始地址為0017H,讀取38個暫存器,指令如表所示:
傳送讀線圈暫存器指令:

從機地址功能碼起始地址高位起始地址低位暫存器數量高位暫存器數量低位CRC高位CRC低位
0101001700260DD4

●響應:各線圈的狀態與資料內容的每個bit對應,1代表ON,0代表OFF。如果查詢的線圈數量不是8的倍數,則在最後一個位元組的高位補0。

讀線圈暫存器狀態響應:

從機地址功能碼返回位元組數資料1資料2資料3資料4資料5CRC高位CRC低位
010105CD6BB20E1B44EA

●其中,第一個位元組CDH對應線圈0017H到001E的狀態,轉為二進位制是11001101,其中bit0對應0017H,bit7對應001E,如表所示:

線圈0017H到001EH的狀態:

001EH001DH001CH001BH001AH0019H0018H0017H
ONONOFFOFFONONOFFON

●最後一個位元組為1BH,對應線圈0037H到003CH的狀態,轉為二進位制是00011011,其中bit0對應0037H,bit5對應003CH,其餘兩位用0填充,如表所示:

線圈0037H到003CH的狀態:

001EH001DH001CH001BH001AH0019H0018H0017H
ONONOFFOFFONONOFFON

②讀離散輸入暫存器——02H

●功能碼02H讀取Modbus從機中離散輸入暫存器的狀態,可以是單個暫存器,或者多個連續的暫存器。

●假設從機地址為01H,讀取的離散輸入暫存器的起始地址為00C4H,讀取22個暫存器,指令如表所示:

傳送讀離散輸入暫存器指令:

從機地址功能碼起始地址高位起始地址低位暫存器數量高位暫存器數量低位CRC高位CRC低位
010200C40016B839

●響應:各個離散輸入暫存器的狀態與資料內容的每個bit對應,1代表ON,0代表OFF。如果查詢的線圈數量不是8的倍數,則在最後一個位元組的高位補0

讀離散輸入暫存器的返回結果:

從機地址功能碼返回位元組數資料1資料2資料3CRC高位CRC低位
010203ACDB352288

●其中,第一個位元組ACH對應00C4H到00CBH暫存器的狀態,轉為二進位制是10101100,其中bit0對應00C4H,bit7對應00CB,如表所示:

暫存器00C4H到00CBH的狀態:

00CBH00CAH00C9H00C8H00C7H00C6H00C5H00C4H
10101100
ONOFFONOFFONONOFFOFF

●最後一個位元組為35H,對應暫存器00D4H到00D9H的狀態,轉為二進位制是00110101,其中bit0對應00D4H,bit5對應00D9H,其餘兩位用0填充,如表所示:

暫存器00D4H到00D9H的狀態

00DBH00DAH00D9H00D8H00D7H00D6H00D5H00D4H
00110101
ONOFFONOFFONONOFFOFF

③讀保持暫存器——03H

●功能碼03H讀取Modbus從機中保持暫存器的資料,可以是單個暫存器,或者多個連續的暫存器。
●假設從機地址為01H,讀取的保持暫存器的起始地址為006BH,讀取3個暫存器,指令如表所示:

傳送讀保持暫存器指令:

從機地址功能碼起始地址高位起始地址低位暫存器數量高位暫存器數量低位CRC高位CRC低位
0103006B00037417

●響應:每個保持暫存器的長度為2個位元組。保持暫存器之間,低地址暫存器先傳輸,高地址暫存器後傳輸。單個保持暫存器,高位元組資料先傳輸,低位元組資料後傳輸。

讀保持暫存器的返回結果:

從機地址功能碼位元組數006BH高位位元組006BH低位位元組006CH高位位元組006CH低位位元組006BH高位位元組006BH低位位元組CRC高位CRC低位
010306006B00130000F579

④讀輸入暫存器——04H

●功能碼04H讀取Modbus從機中輸入暫存器的資料,可以是單個暫存器,或者多個連續的暫存器。
●假設從機地址為01H,讀取的保持暫存器的起始地址為0008H,讀取2個暫存器,指令如表所示:

傳送讀輸入暫存器指令:

從機地址功能碼起始地址高位起始地址低位暫存器數量高位暫存器數量低位CRC高位CRC低位
0104006B00020017

●響應:每個輸入暫存器的長度為2個位元組。輸入暫存器之間,低地址暫存器先傳輸,高地址暫存器後傳輸。單個輸入暫存器,高位元組資料先傳輸,低位元組資料後傳輸。

讀輸入暫存器的返回結果:

從機地址功能碼位元組數0008H高位位元組0008H低位位元組0009H高位位元組0009H低位位元組CRC高位CRC低位
010404000A000B9A41

⑤寫單個線圈暫存器——05H

●功能碼05H寫單個線圈暫存器,FF00H請求線圈處於ON狀態,0000H請求線圈處於OFF狀態。
●假設從機地址為01H,線圈暫存器的地址為00ACH,使其處於ON狀態的指令,如表所示:

傳送寫單個線圈指令:

從機地址功能碼起始地址高位起始地址低位暫存器數量高位暫存器數量低位CRC高位CRC低位
010500ACFF004C1B

●響應:如果寫入成功,返回傳送的指令,即010500ACFF004C1B。

從機地址功能碼起始地址高位起始地址低位暫存器數量高位暫存器數量低位CRC高位CRC低位
010500ACFF004C1B

⑥寫單個保持暫存器——06H

●功能碼06H寫單個保持暫存器。
●假設從機地址為01H,保持暫存器的地址為0001H,資料位0003H,指令如表所示:

傳送寫單個保持暫存器指令:

從機地址功能碼起始地址高位起始地址低位暫存器數量高位暫存器數量低位CRC高位CRC低位
010600010003980B

●響應:如果寫入成功,返回傳送的指令,即010600010003980B。

從機地址功能碼起始地址高位起始地址低位暫存器數量高位暫存器數量低位CRC高位CRC低位
010600010003980B

⑦寫多個線圈暫存器——0FH

●功能碼0FH寫多個線圈暫存器。如果對應的資料位為1,表示線圈狀態為ON;如果對應的資料位為0,表示線圈狀態為OFF。線圈暫存器之間,低地址暫存器先傳輸,高地址暫存器後傳輸。單個線圈暫存器,高位元組資料先傳輸,低位元組資料後傳輸。如果寫入的線圈暫存器的個數不是8的倍數,則在最後一個位元組的高位補0。

●假設從機地址為01H,線圈暫存器的起始地址為0013H,寫入10個暫存器,指令如表所示:

傳送寫入多個線圈暫存器指令:

從機地址功能碼起始地址高位起始地址低位暫存器數量高位暫存器數量低位位元組數資料1資料2CRC高位CRC低位
010F0013000A02CD0172CB

●其中,CDH對應線圈0013H到001AH的內容,01H對應線圈001B到001CH的內容,未使用位用0填充。

線圈暫存器0013H到001CH的內容:

001AH0019H0018H0017H0016H0015H0014H0013H
11001101
0022H0021H0020H001FH001EH001DH001CH001BH
00000001

●響應:如果寫入成功,返回寫入的暫存器數量,如表所示

寫多個線圈暫存器的返回結果:

從機地址功能碼起始地址高位起始地址低位暫存器數量高位暫存器數量低位CRC高位CRC低位
010F0013000A2409

⑧寫多個保持暫存器——10H

●功能碼10H寫多個保持暫存器,其中每個保持暫存器的長度為兩個位元組。
●假設從機地址為01H,保持暫存器的起始地址為0001H,寫入2個暫存器,指令如表所示:

傳送寫入多個保持暫存器指令:

從機地址功能碼起始地址高位起始地址低位暫存器數量高位暫存器數量低位位元組數0001H高位0001H低位0002H高位0002H低位CRC高位CRC低位
010100001000204000A01029230

●響應:如果寫入成功,返回寫入的暫存器數量,如表所示:

從機地址功能碼起始地址高位起始地址低位暫存器數量高位暫存器數量低位CRC高位CRC低位
0110000100021008

3.小結

●功能碼詳解主要參考文獻為:
https://blog.csdn.net/lakerszhy/article/details/68927178?locationNum=4&fps=1


三、MODBUS協定詳解

1.兩種序列傳輸模式

①.ASCII模式

編碼系統:
十六進位制,ASCII 字元 0-9, A-F。報文中每個 ASCII 字元含有 1 個十六進位制字元

Bits per Byte:
1 起始位
7 資料位, 首先傳送最低有效位
1 位作為奇偶校驗
1 停止位

奇偶校驗 :
●偶校驗是要求的, 其它模式 ( 奇校驗, 無校驗 ) 也可以使用。 為了保證與其它產品的最大相容性,同時支援無校驗模式是建議的。預設校驗模式模式 必須為偶校驗。
注 : 使用無校驗要求 2 個停止位。

字序列傳送:
●每個字元或位元組均由此順序傳送(從左到右):
●最低有效位 (LSB) . . . 最高有效位 (MSB),資料傳輸如圖:
●有奇偶檢驗
在這裡插入圖片描述
●無奇偶檢驗:
在這裡插入圖片描述

Modbus ASCII 報文幀:
在 ASCII 模式, 報文用特殊的字元區分幀起始和幀結束。一個報文必須以一個‘冒號’ ( : )(ASCII 十六進位制 3A )起始,以 ‘回車-換行’ (CR LF) 對 (ASCII 十六進位制 0D 和 0A) 結束。
注 : LF 字元可以通過特定的 Modbus 應用命令 (參見 Modbus 應用協定規範) 改變。

對於所有的域,允許傳送的字元為十六進位制 0–9, A–F (ASCII 編碼)。 裝置連續的監視匯流排上的 ‘冒號’ 字元。 當收到這個字元后,每個裝置解碼後續的字元一直到幀結束。

報文幀包括:起始、地址、功能碼、資料、LRC校驗位、結束。如圖:

在這裡插入圖片描述
注:每個字元子節需要用兩個字元編碼。因此,為了確保 ASCII 模式 和 RTU 模式在 Modbus 應用級相容,ASCII
資料域最巨量資料長度為 (2x252) 是 RTU 資料域 (252) 的兩倍。
必然的, Modbus ASCII 幀的最大尺寸為 513 個字元。

ASCII 傳輸模式狀態如圖:

在這裡插入圖片描述
幀檢驗域:
①幀檢驗方式為::縱向冗餘校驗 (LRC - Longitudinal Redundancy Checking)

②LRC 域檢驗不包括起始「冒號」和結尾 CRLF 對的整個報文的內容。不管報文有無奇偶校驗,均執行此檢驗。

③LRC 域為一個子節,包含一個 8 位二進位制值。LRC 值由傳送裝置計算,然後將 LRC 附在報文後面。接收裝置在接收報文時重新計算 LRC 的值,並將計算結果於實際接收到的 LRC 值相比較。如果兩個值不相等,則為錯誤。LRC 的計算, 對報文中的所有的連續 8 位位元組相加,忽略任何進位,然後求出其二進位制二補數。執行檢驗針對不包括起始「冒號」和結尾 CRLF 對的整個 ASCII 報文域的內容。在 ASCII 模式,LRC 的結果被 ASCII 編碼為兩個位元組並放置於 ASCII 模式報文幀的結尾, CRLF 之前。


②.RTU模式

RTU模式:報文中每個 8 位位元組含有兩個 4 位十六進位制字元。這種模式的主要優點是較高的資料密度,在相同的波特率下比ASCII 模式有更高的吞吐率。每個報文必須以連續的字元流傳送。

編碼系統:

8–位二進位制報文中每個 8 位位元組含有兩個 4 位十六進位制字元(0–9, A–F)

Bits per Byte:

1 起始位
8 資料位, 首先傳送最低有效位
1 位作為奇偶校驗
1 停止位

奇偶校驗 :
●偶校驗是要求的, 其它模式 ( 奇校驗, 無校驗 ) 也可以使用。 為了保證與其它產品的最大相容性,同時支援無校驗模式是建議的。預設校驗模式模式 必須為偶校驗。
注 : 使用無校驗要求 2 個停止位。

字序列傳送:
●每個字元或位元組均由此順序傳送(從左到右):
●最低有效位 (LSB) . . . 最高有效位 (MSB),資料傳輸如圖:
●有奇偶校驗:
在這裡插入圖片描述
●無奇偶校驗:
在這裡插入圖片描述

Modbus RTU 報文幀:

RTU 報文幀描述如圖 :
在這裡插入圖片描述
注意: Modbus RTU 幀最大為 256 位元組。

●在 RTU 模式,報文幀由時長至少為 3.5 個字元時間的空閒間隔區分。在後續的部分,這個時間區間被稱作 t3.5。如果兩個字元之間的空閒間隔大於 1.5 個字元時間,則報文幀被認為不完整應該被接收節點丟棄。傳輸格式如圖:


在這裡插入圖片描述
注 :
RTU 接收驅動程式的實現,由於 t1.5 和 t3.5 的定時,隱含著大量的對中斷的管理。在高通訊速率下,這導致 CPU 負擔加重。因此,在通訊速率等於或低於 19200 Bps 時,這兩個定時必須嚴格遵守;對於波特率大於 19200 Bps 的情形,應該使用 2 個定時的固定值:建議的字元間超時時間(t1.5)為 750µs,幀間的超時時間 (t1.5) 為 1.750ms。

●下圖表示了對 RTU 傳輸模式狀態圖的描述。 「主節點」 和 「子節點」 的不同角度均在相同的圖中表示:
在這裡插入圖片描述
上面狀態圖的一些解釋:
● 從 「初始」 態到 「空閒」 態轉換需要 t3.5 定時超時: 這保證幀間延遲
● 「空閒」 態是沒有傳送和接收報文要處理的正常狀態。
●在 RTU 模式, 當沒有活動的傳輸的時間間隔達 3.5 個字元長時,通訊鏈路被認為在 「空閒」
態。
●當鏈路空閒時, 在鏈路上檢測到的任何傳輸的字元被識別為幀起始。 鏈路變為 「活動」 狀態。
然後, 當鏈路上沒有字元傳輸的時間間個達到 t3.5 後,被識別為幀結束。
● 檢測到幀結束後,完成 CRC 計算和檢驗。然後,分析地址域以確定幀是否發往此裝置,如果不是,則丟棄此幀。 為了減少接收處理時間,地址域可以在一接到就分析,而不需要等到整個幀結束。這樣,CRC 計算只需要在幀定址到該節點 (包括廣播幀) 時進行。

幀檢驗域:
①幀檢驗方式為:迴圈冗餘校驗 (CRC)

②CRC 包含由兩個 8 位位元組組成的一個 16 位值。

③CRC 域作為報文的最後的域附加在報文之後。計算後,首先附加低位元組,然後是高位元組。CRC

④高位元組為報文傳送的最後一個子節。附加在報文後面的 CRC 的值由傳送裝置計算。接收裝置在接收報文時重新計算 CRC 的值,
並將計算結果於實際接收到的 CRC 值相比較。如果兩個值不相等,則為錯誤。CRC 的計算, 開始對一個 16 位暫存器預裝全 1。 然後將報文中的連續的 8 位子節對其進行後續的計算。只有字元中的 8 個資料位參與生成 CRC 的運算,起始位,停止位和校驗位不參與 CRC計算。

⑤CRC 的生成過程中, 每個 8–位字元與暫存器中的值互斥或。然後結果向最低有效位(LSB)方向移動(Shift) 1 位,而最高有效位(MSB)位置充零。 然後提取並檢查 LSB:如果 LSB 為 1, 則暫存器中的值與一個固定的預置值互斥或;如果 LSB 為 0, 則不進行互斥或操作。
這個過程將重複直到執行完 8 次移位。完成最後一次(第 8 次)移位及相關操作後,下一個 8位元位元組與暫存器的當前值互斥或,然後又同上面描述過的一樣重複 8 次。當所有報文中子節都運算之後得到的暫存器忠的最終值,就是 CRC。


③小結

MODBUS分為兩種傳輸模式,ASCII方式、RTU方式。這兩種模式的區別在於: 1、起始符,與結束符不一樣;

●ASCII模式,起始符是一個冒號「:」 ASCII碼為3AH H是十六進位製表示結束符是「回車換行符」 ASCII碼為0DH 0AH

●RTU 模式,起始符與結束符都是至少3.5倍字元傳輸時間的停頓間隔時間標定3.5倍字元的傳輸時間的計算方法,根據「通訊格式、傳輸方式及MODBUS協定簡介」視訊中介紹的一個字元的傳輸時間的計算方法,很容易計算出來。

2、校驗和計算不一樣;

●ASCII模式,是LRC校驗
●RTU 模式,是CRC校驗
3、傳送格式不一樣;
●ASCII模式,在訊息中的每個位元組都作為兩個ASCII字元傳送
●RTU 模式,在訊息中的每個位元組包含兩個 4Bit的十六進位制字元。


2. ModbusTCP

●ModbusTCP的資料框可分為兩部分:MBAP+PDU。

①結構幀MBAP

MBAP為報文頭,長度為7位元組,組成如下:

事務緊急處理標識協定標識長度單元識別符號
2位元組2位元組2位元組1位元組

事務處理標識 : 可以理解為報文的序列號,一般每次通訊之後就要加1以區別不同的通訊資料包文。
協定識別符號 : 00 00表示ModbusTCP協定。
長度 : 表示接下來的資料長度,單位為位元組。
單元識別符號 : 可以理解為裝置地址。

②結構幀PDU

PDU由功能碼+資料組成。功能碼為1位元組,資料長度不定,由具體功能決定。該處使用的url網路請求的資料。

②小結

modbus裝置可分為主站(poll)和從站(slave)。主站只有一個,從站有多個,主站向各從站傳送請求幀,從站給予響應。在使用TCP通訊時,主站為client端,主動建立連線;從站為server端,等待連線。

●主站請求:功能碼+資料
●從站正常響應:請求功能碼+響應資料
●從站異常響應:異常功能碼+異常碼,其中異常功能碼即將請求功能碼的最高有效位置1,異常碼指示差錯型別
●注意:需要超時管理機制,避免無期限的等待可能不出現的應答

在linux下使用modbusTCP連線
IANA(Internet Assigned Numbers Authority,網際網路編號分配管理機構)給Modbus協定賦予TCP埠號為502,這是目前在儀表與自動化行業中唯一分配到的埠號。
通訊過程
1.connect 建立TCP連線
2.準備modbus報文
3.使用send命令傳送報文
4.在同一連線下等待應答
5.使用recv命令讀取報文,完成一次資料交換
6.通訊任務結束時,關閉TCP連線


四、基於STM32-MODBUS實現

有點累了,改天再寫。。。

如需要技術指導,小編QQ:271841502

如需要進入QQ技術交流群,電賽資料共用群:484040216

電賽資料共用群二維條碼如下:

在這裡插入圖片描述