【1】Modbus
1. 起源
- Modbus由Modicon公司于1979年開發,是全球第一個真正用于工業現場的總線協議
- 在中國,Modbus 已經成為國家標準,并有專業的規范文檔,感興趣的可以去查閱相關的文件,詳情如下:標準編號為:GB/T19582-2008文件名稱:《基于 Modbus 協議的工業自動化網絡規范》
- Modbus通信協議具有多個變種,其中有支持串口,以太網多個版本,其中最著名的是Modbus RTU、Modbus ASCII和Modbus TCP三種,其中Modbus TCP是在施耐德收購Modicon后1997年發布的。
2.?分類
1)Modbus RTU
運行在串口上的協議,采用二進制表現形式以及緊湊的數據結構,通信效率較高,應用比較廣泛
2)Modbus ASCII
運行在串口上的協議,采用ASCII碼進行傳輸,并且每個字節的開始和結束都有特殊字符作為標志,傳輸效率遠遠低于Modbus RTU,一般只有通訊量比較少時才會考慮它。
3)Modbus TCP
是一種基于以太網的協議,使用 TCP/IP 協議棧進行通信。它使用以太網幀作為數據傳輸的封裝,通過 IP 地址和端口號來標識設備。
3. 優勢
簡單、免費、容易使用
4. 應用場景
Modbus協議是現在國內工業領域應用最多的協議,不只PLC設備,各種終端設備,比如水控機、水表、電表、工業秤、各種采集設備
問答
在面試中回答“Modbus 協議”相關問題時,可從協議定位、核心架構、傳輸方式、通信流程、實際應用、技術價值等維度組織內容,既體現全面性,又貼合工業/嵌入式場景:
一、協議定位與核心價值
Modbus 是工業自動化領域應用廣泛的開源通信協議,旨在解決工業現場不同設備(PLC、傳感器、執行器、網關等)間的“數據互通與指令協同”問題,讓分散的設備能像“統一系統”一樣工作,是工業物聯網(IIoT)底層設備互聯的核心協議之一。
二、核心架構:主從式通信
采用“一主多從”的主從架構:
- 主設備(如 PLC、工業網關、上位機)主動發起通信請求;
- 從設備(如溫濕度傳感器、電機驅動器、閥門控制器)僅響應主設備的請求,不主動發起通信。
這種架構簡化了通信沖突處理,適合工業現場“中心控制+分散設備”的管理模式。
三、主流傳輸版本與差異
Modbus 針對不同“傳輸介質”衍生出 3 類核心版本,適配從“串口總線”到“以太網”的場景:
1. Modbus RTU(串行總線,如 RS - 485/RS - 232)
- 數據格式:二進制緊湊傳輸,每個字節為 8 位,用 CRC(循環冗余校驗) 保證數據完整性;
詳述循環冗余校驗CRC
一道題帶你搞懂CRC循環冗余校驗是如何糾錯的
- 傳輸效率:適合長距離、低帶寬的工業現場(如車間產線設備互聯),但通信速率受串口波特率限制(常見 9600bps、19200bps);
- 典型場景:工廠產線的傳感器(溫濕度、壓力)與 PLC 通信,單主設備可帶最多 247 個從設備。
2. Modbus ASCII(串行總線)
- 數據格式:ASCII 字符傳輸(每個字節拆為 2 個 ASCII 字符),用 LRC(縱向冗余校驗);
- 特點:可讀性強(便于串口調試工具抓包分析),但傳輸效率低于 RTU(相同數據,ASCII 長度是 RTU 的 2 倍),多用于對“調試友好性”要求高的場景(如實驗室設備聯調)。
3. Modbus TCP(以太網)
- 傳輸層:基于 TCP/IP 協議,把 Modbus 應用數據封裝在 TCP 數據包中傳輸;
- 特點:突破串口“距離與速率”限制,支持跨網絡、高速通信(千兆以太網下可近實時傳輸);
- 典型場景:工業物聯網云平臺與邊緣網關通信、智能工廠多車間設備的跨區域集中管理。
四、通信流程(以“主設備讀從設備數據”為例)
以 Modbus RTU 為例,核心流程分“請求 - 響應 - 錯誤處理”:
- 主設備請求:主設備發送“請求幀”,包含: 從設備地址(指定和哪個從設備通信);
- 功能碼(如 0x03 表示“讀保持寄存器”,0x01 表示“讀線圈狀態”);
- 數據地址(要讀的寄存器/線圈起始地址);
- 數據長度(讀多少個寄存器/線圈);
- CRC 校驗(確保幀傳輸無錯)。
- 從設備響應:從設備收到請求后,先校驗地址和 CRC: 若匹配且能執行操作,返回“響應幀”:包含從設備地址、功能碼、實際讀取的數據、CRC 校驗;
- 若出錯(如地址不存在、功能不支持),返回“異常響應幀”:功能碼最高位設為 1(表示異常),并附帶“異常碼”(說明錯誤原因,如 0x01 表示“不支持的功能碼”)。
- 錯誤處理:主設備收到異常響應后,可根據異常碼重試、切換從設備或報警。
五、在工業/嵌入式場景的典型應用
Modbus 是工業設備互聯的“通用語言”,典型應用場景包括:
- 設備數據采集:PLC 通過 Modbus 讀取車間溫濕度傳感器、壓力變送器的實時數據,為生產決策(如空調啟停、產線速度調整)提供依據;
- 設備遠程控制:上位機通過 Modbus TCP 向邊緣網關下發指令,網關再通過 Modbus RTU 控制車間電機轉速、閥門開關;
- 多系統集成:把采用不同通信協議的設備(如老產線的 Modbus 傳感器、新系統的 Profinet 執行器)通過“Modbus 網關”橋接,實現跨協議協同。
六、技術優勢(為什么工業領域廣泛用 Modbus)
- 開源免費:無授權費用,降低工業企業/嵌入式開發者的使用成本;
- 易實現:協議格式簡單,嵌入式端(如 STM32、Arduino)可通過串口庫+CRC 校驗庫快速開發從設備/主設備;
- 兼容性強:幾乎所有工業設備廠商(西門子、施耐德、國產 PLC 等)都支持 Modbus,不同品牌設備能“即連即用”。
【2】Modbus TCP協議
1. 特點
- 遵循主從問答協議 (主機 從機 主從問答:采集信息 控制)
- (主機問---從機答247 1-247:從機 0:廣播 248-255:保留 )
- Modbus TCP協議是應用層協議,基于傳輸層TCP通信
- Modbus TCP的默認端口號是502
2.?組成
Modbus TCP協議包含三部分:報文頭、功能碼、數據
報文頭有7個字節,功能碼有1個字節,Modbus TCP協議最大數據幀長度為260個字節,數據最多為252個字節。
2.1 報文頭:7個字節
事務處理標識符:包的標識,沒有什么限制,一般主機發什么從機回什么
協議標識符:0x0000 兩個字節
長度:長度后面的字節個數,必須占2個字節
單元標識符:從機地址,從機ID
2.2?寄存器(存儲數據) ******
Modbus TCP通過寄存器的方式存儲數據。
一共有四種類型的寄存器,分別是:離散量輸入寄存器、線圈寄存器、輸入寄存器、保持寄存器。
1) 離散量和線圈其實就是位寄存器(每個寄存器數據占1字節),工業上主要用于控制IO設備。
線圈寄存器,類比為開關量,每一個bit都對應一個信號的開關狀態。所以一個byte就可以同時控制8路的信號。比如控制外部8路io的高低。 線圈寄存器支持讀也支持寫,寫在功能碼里面又分為寫單個線圈寄存器和寫多個線圈寄存器。
對應的功能碼也就是:0x01 0x05 0x0f
離散輸入寄存器,離散輸入寄存器就相當于線圈寄存器的只讀模式,他也是每個bit表示一個開關量,而他的開關量只能讀取輸入的開關信號,是不能夠寫的。比如我讀取外部按鍵的按下還是松開。
所以功能碼也簡單就一個讀的 0x02
2) 輸入和保持寄存器是字寄存器(每個寄存器數據占2個字節),工業上主要用于存儲工業設備的值。
保持寄存器,這個寄存器的單位不再是bit而是兩個byte,也就是可以存放具體的數據量的,并且是可讀寫的。比如我設置時間年月日,不但可以寫也可以讀出來現在的時間。寫也分為單個寫和多個寫
所以功能碼有對應的三個:0x03 0x06 0x10
輸入寄存器,這個和保持寄存器類似,但是也是只支持讀而不能寫。一個寄存器也是占據兩個byte的空間。類比我通過讀取輸入寄存器獲取現在的AD采集值
對應的功能碼也就一個 0x04
2.3?功能碼(記住)
寄存器PLC地址和寄存器的對應關系:
線圈: 00001-09999
離散量輸入:10001-19999
輸入寄存器:30001-39999
保持寄存器:40001-49999
開燈:05
讀溫度傳感器數據:03 04
具體協議分析:
總結
讀數據:
主機--》從機:
報文頭(7字節)+功能碼(1)+起始地址(2)+數量(2)
從機--》主機:
報文頭(7)+功能碼(1)+字節計數(1)+數據(?)
寫數據:
寫單個:
主機--》從機:
報文頭(7)+功能碼(1)+地址(2)+斷通標志/數據(2)
(線圈:斷通標志 0x0000:復位 0xff00:置位 保持寄存器:數據)
從機--》主機:
原文返回
對于讀數據和寫單個主機--》從機來說,報文頭中字節長度固定為0x0006,(1個字節的單元標識符+1個字節的功能碼+4個字節的數據)
寫多個:
主機--》從機:
報文頭(7)功能碼(2)+起始地址(2)+數量(2)+字節計數(1)+數據(?)
從機--》主機:
報文頭(7)功能碼(2)+起始地址(2)+數量(2)(原文返回)
練習
主機--》從機:
12 34 00 00 00 06 01 03 00 63 00 03
從機--》主機:
12 34 00 00 00 09 01 03 06 45 69 11 11 66 66
1.讀傳感器數據,讀1個寄存器數據,寫出主從數據收發協議。
主機--》從機:12 34 00 00 00 06 11 03 00 01 00 01
從機--》主機:12 34 00 00 00 05 11 03 02 12 34
2. 寫出控制IO設備開關的協議數據,操作1個線圈,置1。
主機--》從機:12 34 00 00 00 06 01 05 00 63 ff 00
從機--》主機:12 34 00 00 00 06 01 05 00 63 ff 00
【3】工具使用
1.Modbus Slave、Poll安裝
1)默認安裝
2)破解:點擊connection-》connect,輸入序列號(序列號在SN.txt)
3)使用:
從機:Modbus Slave
先設置:
再連接:點擊connection-》connect
主機:
先設置
再連接:(一定要先開啟從機(salve端),再開啟主機(poll端))
2. 網絡調試助手
linux下編程
在虛擬機寫程序實現poll端功能,編寫客戶端實現和Slave通信,實現03功能碼。
uint8_t data[12]={0x00,0x00,0x00,0x00,0x00,0x06,0x01....};
主機要先建立連接---》發送協議(modbus tcp協議)---》接收數據(modbus tcp協議)--》打印數據
1. 功能碼0x01(讀線圈狀態)
示例1:讀取地址0x0000的兩個線圈
主機->從機:00 01 00 00 00 06 01 01 00 00 00 02
從機->主機:00 01 00 00 00 04 01 01 01 03
# 解析:線圈0狀態為1(ON),線圈1狀態為1(ON),其余線圈狀態無效
示例2:讀取地址0x0003的四個線圈
主機->從機:00 02 00 00 00 06 01 01 00 03 00 04
從機->主機:00 02 00 00 00 04 01 01 01 0F
# 解析:二進制0F轉換為十進制為15,即00001111,線圈3至6狀態為1(ON)(有效位為1)
2. 功能碼0x02(讀離散輸入)
示例1:讀取地址0x0001的三個離散輸入
主機->從機:00 03 00 00 00 06 01 02 00 01 00 03
從機->主機:00 03 00 00 00 04 01 02 01 05
# 解析:二進制05轉換為十進制為5,即00000101,輸入1狀態為1(ON),輸入3狀態為1(ON)
示例2:讀取地址0x0005的兩個離散輸入
主機->從機:00 04 00 00 00 06 01 02 00 05 00 02
從機->主機:00 04 00 00 00 04 01 02 01 01
# 解析:二進制01轉換為十進制為1,即00000001,僅輸入5狀態為1(ON)
3. 功能碼0x03(讀保持寄存器)
示例1:讀取地址0x0002的兩個保持寄存器
主機->從機:00 05 00 00 00 06 01 03 00 02 00 02
從機->主機:00 05 00 00 00 07 01 03 04 12 34 56 78
# 解析:寄存器2的值為0x1234,寄存器3的值為0x5678
示例2:讀取地址0x000A的一個保持寄存器
主機->從機:00 06 00 00 00 06 01 03 00 0A 00 01
從機->主機:00 06 00 00 00 05 01 03 02 FF FF
# 解析:寄存器10的值為0xFFFF(典型錯誤狀態碼)
4. 功能碼0x04(讀輸入寄存器)
示例1:讀取地址0x0000的三個輸入寄存器
主機->從機:00 07 00 00 00 06 01 04 00 00 00 03
從機->主機:00 07 00 00 00 09 01 04 06 00 64 01 F4 FF FF
# 解析:寄存器0的值為100(0x0064),寄存器1的值為500(0x01F4),寄存器2的值為65535(0xFFFF)
示例2:讀取地址0x0005的兩個輸入寄存器
主機->從機:00 08 00 00 00 06 01 04 00 05 00 02
從機->主機:00 08 00 00 00 07 01 04 04 80 00 40 00
# 解析:寄存器5的值為32768(0x8000),寄存器6的值為16384(0x4000)
5. 功能碼0x05(寫單個線圈)
示例1:開啟地址0x0063的線圈
主機->從機:00 09 00 00 00 06 01 05 00 63 FF 00
從機->主機:00 09 00 00 00 06 01 05 00 63 FF 00
# 說明:0xFF00表示置ON,成功時返回相同數據
示例2:關閉地址0x001A的線圈
主機->從機:00 0A 00 00 00 06 01 05 00 1A 00 00
從機->主機:00 0A 00 00 00 06 01 05 00 1A 00 00
# 說明:0x0000表示置OFF
6. 功能碼0x06(寫單個寄存器)
示例1:寫地址0x0003的寄存器值為0x55AA
主機->從機:00 0B 00 00 00 06 01 06 00 03 55 AA
從機->主機:00 0B 00 00 00 06 01 06 00 03 55 AA
# 成功時回顯寫入值
示例2:寫地址0x0010的寄存器值為0x1234
主機->從機:00 0C 00 00 00 06 01 06 00 10 12 34
從機->主機:00 0C 00 00 00 06 01 06 00 10 12 34
7. 功能碼0x0F(寫多個線圈)
示例1:寫地址0x0010的3個線圈為ON
主機->從機:00 0D 00 00 00 08 01 0F 00 10 00 03 01 07
從機->主機:00 0D 00 00 00 06 01 0F 00 10 00 03
# 解析:二進制07轉換為十進制為7,即00000111,線圈16至18置ON
???????
示例2:寫地址0x0020的5個線圈(二進制10101)
主機->從機:00 0E 00 00 00 08 01 0F 00 20 00 05 01 15
從機->主機:00 0E 00 00 00 06 01 0F 00 20 00 05
# 解析:二進制15轉換為十進制為15,即00010101,僅偶數位生效(線圈32、34、36置ON)
8. 功能碼0x10(寫多個寄存器)
示例1:寫地址0x0004的2個寄存器(值0xAABB和0xCCDD)
主機->從機:00 0F 00 00 00 0B 01 10 00 04 00 02 04 AA BB CC DD
從機->主機:00 0F 00 00 00 06 01 10 00 04 00 02
# 數據部分以四字節表示兩個寄存器的值
示例2:寫地址0x0010的三個寄存器(十進制值100、200、300)
主機->從機:00 10 00 00 00 0D 01 10 00 10 00 03 06 00 64 00 C8 01 2C
從機->主機:00 10 00 00 00 06 01 10 00 10 00 03
# 數值轉換:100轉換為十六進制為0x0064,200轉換為十六進制為0x00C8,300轉換為十六進制為0x012C