據(jù)采集卡從入門到精通(21):Modbus協(xié)議詳解——從幀結(jié)構(gòu)到寄存器點表設計)
Modbus誕生于1979年是工業(yè)自動化領(lǐng)域最長壽、最通用的協(xié)議。任何一塊想接入PLC、組態(tài)軟件、SCADA的采集卡都必須說好這門工業(yè)普通話。本文從零講起RTU與TCP兩種形態(tài)、四大寄存器區(qū)、幀結(jié)構(gòu)逐字節(jié)解剖、CRC校驗最后設計一張完整的采集卡點表并給出Python主站實現(xiàn)。全文約4500字。一、為什么是Modbus三條硬理由免費開放無授權(quán)費、無專利墻、極簡可靠主從問答、CRC校驗30年現(xiàn)場驗證、生態(tài)通吃任何PLC/組態(tài)/SCADA都原生支持。對采集卡廠商說Modbus等于一句買我就能接進你現(xiàn)有的系統(tǒng)對用戶會Modbus等于手握打開一切工業(yè)設備的鑰匙。兩種主流形態(tài)Modbus RTU跑在RS485或RS232上二進制緊湊幀CRC16校驗——車間現(xiàn)場標準Modbus TCP跑在以太網(wǎng)上RTU幀外面包一層MBAP頭TCP端口502——遠程與組網(wǎng)標準。兩者數(shù)據(jù)語義完全同構(gòu)同樣的寄存器地址、同樣的功能碼學會一種即通兩種。二、數(shù)據(jù)模型四大寄存器區(qū)Modbus把設備數(shù)據(jù)組織成四個區(qū)每區(qū)65536個地址區(qū)名稱讀寫常用功能碼采集卡對應線圈Coils讀/寫01讀/05寫單/0F寫多DO數(shù)字輸出離散輸入Discrete Inputs只讀02讀DI數(shù)字輸入輸入寄存器Input Registers只讀04讀AI模擬輸入只讀型保持寄存器Holding Registers讀/寫03讀/06寫單/10寫多配置參數(shù)、AO輸出、可寫數(shù)據(jù)命名記憶法線圈和離散輸入是位bit輸入/保持寄存器是16位字word輸入是別人寫給我讀的保持是我存著可改的。對采集卡的典型映射0x (線圈, 00001~00016) → DO1~DO8 預留 1x (離散輸入, 10001~10016) → DI1~DI8 報警位 3x (輸入寄存器, 30001~30064)→ AI1~AI8原始碼/工程量 4x (保持寄存器, 40001~40100)→ 采樣率/量程/標定系數(shù)/AO值三、RTU幀逐字節(jié)解剖主站讀保持寄存器功能碼03請求幀[01] [03] [00C8] [0002] [CRC_L CRC_H] 從站 功能 起始地址 數(shù)量 CRC16 地址 碼 40009 2個字從站正常應答[01] [03] [04] [13 88] [0B B8] [CRC_L CRC_H] 從站 功能 字節(jié)數(shù) 寄存器值1 值2 CRC 地址 碼 2字×2B 5000 3000從站異常應答功能碼0x80標志異常[01] [83] [02] [CRC...] ↑功能碼80h ↑異常碼02非法數(shù)據(jù)地址常用異常碼01非法功能、02非法地址、03非法數(shù)據(jù)值、04從站故障、06忙。RTU幀的靜默定界RTU沒有幀頭幀尾字符靠字符間靜默≥3.5個字符時間分幀。115200bps下一個字符約87μs靜默閾值約0.3ms——這就是RTU對主站發(fā)送節(jié)拍的要求不能在幀中間插入3.5字符的停頓。CRC16算法CRC-16/MODBUS多項式0xA001反轉(zhuǎn)的0x8005初值0xFFFF低字節(jié)在前發(fā)送。接收端重算比對不一致即丟棄該幀。四、TCP幀MBAP包頭Modbus TCP把RTU的應用數(shù)據(jù)去掉CRC——TCP自己有校驗包進7字節(jié)MBAP頭[事務ID 2B][協(xié)議ID 0000][長度 2B][單元ID 1B][功能碼][數(shù)據(jù)...]事務ID主站自增序號應答原樣帶回——多請求并發(fā)時的配對鑰匙RTU做不到并發(fā)單元ID替代RTU的從站地址網(wǎng)關(guān)場景下指向網(wǎng)關(guān)后的485從站去掉CRCTCP鏈路本身有校驗和重傳應用層CRC冗余。TCP形態(tài)還帶來多主站并發(fā)多個客戶端可同時連接502端口各自讀寫寫操作需應用層協(xié)調(diào)。五、實戰(zhàn)點表設計一塊8通道采集卡好的點表設計遵循三條原則按數(shù)據(jù)性質(zhì)分區(qū)、預留擴展空間、工程量與原始碼雙軌。示例設計 線圈區(qū) 0x 00001~00008 DO1~DO8輸出狀態(tài) 00009~00016 (預留) 離散輸入?yún)^(qū) 1x 10001~10008 DI1~DI8實時狀態(tài) 10009 任意通道超量程標志 10010 標定有效標志 10011~10016 (預留) 輸入寄存器區(qū) 3x (只讀) 30001~30008 AI1~AI8 電壓×1000(有符號,單位mV) 30009 DI狀態(tài)打包(bit0~7DI1~8) 30010~30011 幀計數(shù)器32位 30012 固件版本×100 保持寄存器區(qū) 4x (讀寫) 40001 采樣率(Hz) 40002 通道使能位圖(bit0~7) 40003 量程代碼(0±5V,1±10V,24-20mA) 40004 觸發(fā)閾值×1000 40005 觸發(fā)通道號 40010~40017 AO1~AO4輸出×1000(mV) 40020~40031 標定系數(shù)M/N(每通道2字×8通道) 40090 命令寄存器(寫特定值觸發(fā)動作)設計細節(jié)解析工程量定點化浮點數(shù)Modbus也能傳兩字拼IEEE754但定點×1000更通用組態(tài)軟件整數(shù)處理無歧義5V→50001LSB1mV語義清晰DI打包8個DI可以8個離散地址組態(tài)方便1個打包字輪詢高效雙軌提供——按上位機習慣取用命令寄存器寫魔術(shù)數(shù)觸發(fā)動作如0x5A5A啟動采集、0xA5A5停止把操作也塞進寄存器模型保持協(xié)議純一幀計數(shù)器從站每次數(shù)據(jù)更新自增——主站輪詢時讀它判斷數(shù)據(jù)是否刷新避免重復處理舊值這是無時間戳環(huán)境下的輕量新鮮度方案。六、Python主站實戰(zhàn)# pip install pymodbusfrompymodbus.clientimportModbusSerialClient clientModbusSerialClient(portCOM7,baudrate9600,parityN,stopbits1,timeout1)client.connect()# 讀8路AI(30001~30008 → 功能碼04)rrclient.read_input_registers(0,8,slave1)volts[r/1000forrinrr.registers]print(AI:,[f{v:.3f}Vforvinvolts])# 讀DI狀態(tài)字(30009)rrclient.read_input_registers(8,1,slave1)dirr.registers[0]print(DI:,.join(str((dii)1)foriinrange(8)))# 寫采樣率400011000Hzclient.write_register(1000,1000,slave1)# 命令: 啟動采集(400900x5A5A)client.write_register(4089,0x5A5A,slave1)client.close()TCP版本只需換一行frompymodbus.clientimportModbusTcpClient clientModbusTcpClient(192.168.1.50,port502)# 其余代碼不變——寄存器語義跨傳輸層一致七、輪詢周期預算485輪詢的周期下限由單次往返延遲×從站數(shù)決定單次往返 ≈ 幀發(fā)送時間 從站處理 應答時間 9600bps讀8字: ≈ 8ms發(fā)3ms處理10ms答 ≈ 21ms 單從站最快輪詢: ~47Hz 16從站全輪一遍: ~3Hz(每個從站3次/秒)啟示輪詢頻率與從站數(shù)量此消彼長。要快就提波特率、減輪詢項只讀變化部分、或分散到多條總線。八、常見問題FAQQ1為什么我的讀返回異常碼02地址越界——檢查點表的協(xié)議地址與寄存器號差1問題40001對應協(xié)議地址0x0000。組態(tài)軟件與代碼里常差一位。Q2CRC錯誤頻發(fā)怎么排查按序查波特率/校驗位匹配→布線星型終端電阻→干擾源變頻器濾波→共模隔離器。Q3Modbus能主動上報嗎標準RTU/TCP不能純問答。需要主動上報用Modbus UDP變體或換MQTT類發(fā)布訂閱協(xié)議。Q4浮點數(shù)怎么傳雙寄存器拼IEEE754大端字序注意廠商字序約定AB CD還是CD AB——兩字交換錯誤是浮點讀出天文數(shù)字的頭號原因。九、總結(jié)Modbus四區(qū)四碼一CRC線圈與離散管bit輸入與保持管word功能碼03/04讀、06/10寫、01/02/05管位CRC16守住最后一道正確性。對采集卡用戶讀懂點表完全掌握設備數(shù)據(jù)主權(quán)對開發(fā)者一張設計良好的點表是產(chǎn)品易用性的隱形骨架。下一篇回到卡的功能側(cè)數(shù)字IO與編碼器接口。下一篇預告《數(shù)字IO與編碼器接口PNP/NPN、去抖與正交解碼》