亚洲乱色熟女一区二区三区丝袜,天堂√中文最新版在线,亚洲精品乱码久久久久久蜜桃图片,香蕉久久久久久av成人,欧美丰满熟妇bbb久久久

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

網(wǎng)絡(luò)基礎(chǔ) Modbus協(xié)議學(xué)習(xí)總結(jié)

freeflydom
2024年10月14日 10:2 本文熱度 2117

協(xié)議簡(jiǎn)介

Modbus協(xié)議,首先從字面理解它包括Mod和Bus兩部分,首先它是一種bus,即總線(xiàn)協(xié)議,總線(xiàn)就意味著有主機(jī),有從機(jī),這些設(shè)備在同一條總線(xiàn)上。

Modbus支持單主機(jī),多個(gè)從機(jī),最多支持247個(gè)從機(jī)設(shè)備。關(guān)于Mod,因?yàn)檫@種協(xié)議最早被用在PLC控制器中,準(zhǔn)確的說(shuō)是Modicon公司的PLC控制器,這也是Modbus名稱(chēng)的由來(lái)。后來(lái)Modicon被施耐德電器收購(gòu),Modbus協(xié)議廣泛應(yīng)用在工業(yè)控制器、HMI和傳感器上,逐漸被其他廠(chǎng)商所接受,成為工業(yè)領(lǐng)域通信協(xié)議的業(yè)界標(biāo)準(zhǔn),并且現(xiàn)在是工業(yè)電子設(shè)備之間常用的連接方式。

  • 每種設(shè)備(PLC、HMI、控制面板、驅(qū)動(dòng)程序、動(dòng)作控制、輸入/輸出設(shè)備)都能使用 Modbus協(xié)議來(lái)啟動(dòng)遠(yuǎn)程操作。

  • 在基于串行鏈路和以太 TCP/IP 網(wǎng)絡(luò)的 Modbus 上可以進(jìn)行相互通信。

  • 一些網(wǎng)關(guān)允許在幾種使用 Modbus 協(xié)議的總線(xiàn)或網(wǎng)絡(luò)之間進(jìn)行通信

術(shù)語(yǔ)說(shuō)明

HDLC 高級(jí)數(shù)據(jù)鏈路控制
HMI 人機(jī)界面
IETF 因特網(wǎng)工程工作組
I/O 輸入/輸出設(shè)備
IP 互連網(wǎng)協(xié)議
MAC 介質(zhì)訪(fǎng)問(wèn)控制
MB Modbus 協(xié)議
MBAP Modbus 協(xié)議

關(guān)于總線(xiàn)補(bǔ)充說(shuō)明

總線(xiàn)(Bus)是計(jì)算機(jī)各種功能部件之間傳送信息的公共通信干線(xiàn),它是由導(dǎo)線(xiàn)組成的傳輸線(xiàn)束, 按照計(jì)算機(jī)所傳輸?shù)男畔⒎N類(lèi),計(jì)算機(jī)的總線(xiàn)可以劃分為數(shù)據(jù)總線(xiàn)、地址總線(xiàn)控制總線(xiàn),分別用來(lái)傳輸數(shù)據(jù)、數(shù)據(jù)地址和控制信號(hào)。總線(xiàn)是一種內(nèi)部結(jié)構(gòu),它是cpu、內(nèi)存、輸入、輸出設(shè)備傳遞信息的公用通道,主機(jī)的各個(gè)部件通過(guò)總線(xiàn)相連接,外部設(shè)備通過(guò)相應(yīng)的接口電路再與總線(xiàn)相連接,從而形成了計(jì)算機(jī)硬件系統(tǒng)。在計(jì)算機(jī)系統(tǒng)中,各個(gè)部件之間傳送信息的公共通路叫總線(xiàn),微型計(jì)算機(jī)是以總線(xiàn)結(jié)構(gòu)來(lái)連接各個(gè)功能部件的。

Modbus被廣泛使用主要原因

  1. 標(biāo)準(zhǔn)、開(kāi)放,用戶(hù)可以免費(fèi)、放心地使用Modbus協(xié)議,不需要交納許可證費(fèi),也不會(huì)侵犯知識(shí)產(chǎn)權(quán)
  2. Modbus可以支持多種電氣接口,如RS-232、RS-485等,還可以在各種介質(zhì)上傳送,如雙絞線(xiàn)、光纖、無(wú)線(xiàn)等。  
  3. Modbus的幀格式簡(jiǎn)單、緊湊,通俗易懂。用戶(hù)使用容易,廠(chǎng)商開(kāi)發(fā)簡(jiǎn)單。

協(xié)議版本

Modbus 協(xié)議目前分別定義了基于串口()和以太網(wǎng)傳輸數(shù)據(jù)的協(xié)議,其中串口(RS232,RS485,RS422,光纖,無(wú)線(xiàn)等)數(shù)據(jù)傳輸協(xié)議分為 Modbus RTU 和 Modbus ASCII串行鏈路協(xié)議,以太網(wǎng)數(shù)據(jù)傳輸協(xié)議一種 Modbus TCP/IP協(xié)議。

其中,Modbus RTU是一種緊湊的,采用二進(jìn)制表示數(shù)據(jù)的方式,Modbus ASCII是一種人類(lèi)可讀的,冗長(zhǎng)的表示方式。

工作模式

Modbus 協(xié)議采用主從(Master/Salve)通信方式,TCP/IP傳輸模式下,主節(jié)點(diǎn)也叫客戶(hù)機(jī),從節(jié)點(diǎn)也叫服務(wù)器。連接到總線(xiàn)上的所有主機(jī)節(jié)點(diǎn)中有且只有一個(gè) Master 節(jié)點(diǎn)(主節(jié)點(diǎn)),其余為 Slave 節(jié)點(diǎn)(從節(jié)點(diǎn),可選地址為1~247,每個(gè)Slave節(jié)點(diǎn)的地址必須唯一)。

主從通信以 請(qǐng)求/應(yīng)答 為主,每次通訊都是主節(jié)點(diǎn)先發(fā)送請(qǐng)求(采用廣播模式、單播模式),從節(jié)點(diǎn)響應(yīng)指令,并按要求應(yīng)答,或者報(bào)告異常。當(dāng)主節(jié)不發(fā)送請(qǐng)求時(shí),從節(jié)不會(huì)自己發(fā)出數(shù)據(jù),從節(jié)點(diǎn)之間不能相互通訊(也就是說(shuō)從節(jié)點(diǎn)之間不能相互發(fā)送請(qǐng)求)。

無(wú)論主節(jié)點(diǎn)發(fā)送的是廣播指令還是單播指令,實(shí)際上所有從節(jié)點(diǎn)都會(huì)完整接收指令。但發(fā)送單播指令時(shí),只有地址和指令中中指定地址相同的從節(jié)點(diǎn)才會(huì)執(zhí)行及回應(yīng)指令,其它從節(jié)點(diǎn)將忽略收到的指令,而廣播請(qǐng)求所有收到指令的設(shè)備都會(huì)執(zhí)行指令,但不會(huì)給主機(jī)回應(yīng)指令。

半雙工通信

Modbus 由于請(qǐng)求/應(yīng)答機(jī)制所以不能同步通信(同步通信需要收發(fā)雙方以相同的節(jié)奏發(fā)送和接收數(shù)據(jù)),總線(xiàn)上每次只有一幀數(shù)據(jù)進(jìn)行傳輸,屬于半雙工通信。

Modbus 沒(méi)有支持繁忙機(jī)制處理,例如主機(jī)給從機(jī)發(fā)送命令, 如果從機(jī)正在處理其他任務(wù),此時(shí)從機(jī)將無(wú)法響應(yīng)主機(jī),所以需要通過(guò)軟件的方式來(lái)判斷是否正常接收。

Modbus消息幀

Modbus 協(xié)議定義了一個(gè)與基礎(chǔ)通信層無(wú)關(guān)的簡(jiǎn)單協(xié)議數(shù)據(jù)單元(PDU -> 功能碼 + 數(shù)據(jù) 部分)。特定總線(xiàn)或網(wǎng)絡(luò)上
的 MODBUS 協(xié)議映射能夠在應(yīng)用數(shù)據(jù)單元(ADU -> 地址域 + 功能碼 + 數(shù)據(jù) + 差錯(cuò)校驗(yàn))上引入一些附加域

通用數(shù)據(jù)幀

地址域功能碼數(shù)據(jù)差錯(cuò)校驗(yàn)碼
1字節(jié)1字節(jié)N字節(jié)CRC: 16字節(jié) LRC: 1字節(jié)

說(shuō)明:每個(gè)劃分字段都用16進(jìn)制表示

  • 地址域

    從機(jī)設(shè)備地址,通常1-247為有效地址,0為廣播地址(用于接收主機(jī)的廣播數(shù)據(jù)),每個(gè)從機(jī)在總線(xiàn)上地址必須唯一,只有與主機(jī)發(fā)送的地址碼相符的從機(jī)才能響應(yīng)返回?cái)?shù)據(jù)

    主節(jié)點(diǎn)通過(guò)將要聯(lián)絡(luò)的從節(jié)點(diǎn)的地址放入消息中的地址域來(lái)選取需要通信的從設(shè)備。當(dāng)從節(jié)點(diǎn)發(fā)送回應(yīng)消息時(shí),需要把自己的地址放入回應(yīng)的地址域中,以便主節(jié)點(diǎn)知道是哪一個(gè)設(shè)備作出的回應(yīng)。

  • 功能碼

    表明主節(jié)點(diǎn)請(qǐng)求數(shù)據(jù)的類(lèi)型。

    當(dāng)主節(jié)點(diǎn)向從設(shè)備發(fā)送消息時(shí),功能碼將告訴從設(shè)備需要執(zhí)行哪些行為。例如去讀取輸入的開(kāi)關(guān)狀態(tài),讀一組寄存器的數(shù)據(jù)內(nèi)容等。

  • 數(shù)據(jù)

    包含寄存器地址寄存器數(shù)據(jù)

  • 差錯(cuò)校驗(yàn)

    對(duì)數(shù)據(jù)進(jìn)行冗余校驗(yàn)的結(jié)果,CRC、LRC

其中事務(wù)處理正常時(shí),客戶(hù)機(jī)向服務(wù)器發(fā)送請(qǐng)求,在功能碼中填充功能碼代號(hào),說(shuō)明服務(wù)器需要執(zhí)行的動(dòng)作,在數(shù)據(jù)碼區(qū)填充具體的要求,比如讀寄存器的地址和數(shù)量,通信正常時(shí)服務(wù)器會(huì)在返回的通信幀的功能碼區(qū)中填充一個(gè)操作碼,該操作碼=功能碼,在通訊幀的數(shù)據(jù)區(qū)填充返回的采樣數(shù)據(jù)。

當(dāng)出現(xiàn)事務(wù)處理異常時(shí),服務(wù)器會(huì)在返回的通訊幀的功能碼中填充一個(gè)差錯(cuò)碼,該差錯(cuò)碼 = 功能碼 + 0x80,即將功能碼的最高位置1代表出現(xiàn)錯(cuò)誤。并在后面的數(shù)據(jù)段中填充錯(cuò)誤碼,用來(lái)指示本次通信的錯(cuò)誤具體內(nèi)容。

Modbus ASCII消息幀

起始位(?? + ADU + 結(jié)束符

起始位地址域功能碼數(shù)據(jù)LRC結(jié)束符
:1字節(jié)1字節(jié)N字節(jié)1字節(jié)2個(gè)字符

說(shuō)明:消息以 : 冒號(hào)字符(ASCII 碼16進(jìn)制表示 3A)開(kāi)始,以回車(chē)換行符(CR LF, ASCII 碼16進(jìn)制表示 0D,0A)結(jié)束。

一個(gè)典型 ASCII 消息幀如下

起始位地址域功能碼數(shù)據(jù)LRC結(jié)束符
:2個(gè)字符2個(gè)字符0 到 2x252 字符2個(gè)字符2個(gè)字符

Modbus RTU 消息幀

地址域功能碼數(shù)據(jù)CRC低字節(jié)CRC高字節(jié)
1字節(jié)1字節(jié)0 到 252 字節(jié)1字節(jié)1字節(jié)

說(shuō)明:RTU 通信模式下,其發(fā)送的字節(jié)數(shù)據(jù)即為原始字節(jié)數(shù)據(jù),接收端接收后無(wú)需再次轉(zhuǎn)換。

注意:

  1. RTU 模式,數(shù)據(jù)幀之間必須至少間隔 3.5 個(gè)字符時(shí)間,通過(guò)時(shí)間區(qū)間來(lái)區(qū)分報(bào)文,如下:

  1. RTU 模式下,整個(gè)報(bào)文幀必須以連續(xù)的字符流發(fā)送,如果兩個(gè)字符之間的空閑間隔大于 1.5 個(gè)字符時(shí)間,則報(bào)文幀被認(rèn)為不完整應(yīng)該被接收節(jié)點(diǎn)丟棄

  1. 字符時(shí)間
    所謂字符時(shí)間指的是傳輸一個(gè) ASCII 字符需要花費(fèi)的時(shí)間,一個(gè) ASCII 字符包含 1 個(gè)字節(jié)(8 bits),所以傳輸一個(gè)字符需要花費(fèi)傳輸 8 個(gè)數(shù)據(jù)位的時(shí)間(所以這里字符傳輸時(shí)間指代傳輸1字節(jié)數(shù)據(jù)消耗的時(shí)間)。

    然而實(shí)際上傳輸 1 個(gè)字節(jié)數(shù)據(jù)需要花費(fèi)的時(shí)間并不只 8 個(gè)位時(shí)間,因?yàn)槌藗鬏敼逃械?1 字節(jié)數(shù)據(jù),還需要傳輸一些輔助功能位。例如發(fā)送 1 個(gè)字節(jié)需要固定起始位 1 位,數(shù)據(jù)位 8 位,校驗(yàn)位 1 位(可選的),停止位 1 位,其中 8 位數(shù)據(jù)位才是真正的有效數(shù)據(jù),所以有如下公式來(lái)計(jì)算字符時(shí)間。

    字符時(shí)間=1s / 波特率 × 字符的字節(jié)總位數(shù)。

    例如:固定起始位 1 位,數(shù)據(jù)位 8 位,奇/偶校驗(yàn)位 1 位,停止位 1 位,波特率為9600 bps,計(jì)算單個(gè)字符傳輸時(shí)間為:

    字符時(shí)間 = 1000 ms / 9600 × ( 1 + 8 + 1 + 1 ) = 1.145833 ms

Modbus TCP/IP 消息幀

MBAP 報(bào)文頭 + PDU(此處PDU來(lái)自數(shù)據(jù)鏈路層的PDU)

事務(wù)元標(biāo)識(shí)符協(xié)議標(biāo)識(shí)符長(zhǎng)度單元標(biāo)識(shí)符功能碼數(shù)據(jù)
2字節(jié)2字節(jié)2字節(jié)1字節(jié)1字節(jié)N字節(jié)

MBAP 報(bào)文頭包括下列域:

  • 事務(wù)元標(biāo)識(shí)符

    Modbus 請(qǐng)求/響應(yīng)事務(wù)處理的識(shí)別,可以理解為報(bào)文的序列號(hào),一般每次通信之后就要加 1 以區(qū)別不同的通信數(shù)據(jù)報(bào)文

  • 協(xié)議標(biāo)識(shí)符

    00 00 表示Modbus 協(xié)議 客戶(hù)機(jī)啟動(dòng)

  • 長(zhǎng)度

    表示接下來(lái)的數(shù)據(jù)長(zhǎng)度,包括單元標(biāo)識(shí)符和數(shù)據(jù)域

  • 單元標(biāo)識(shí)符

    串行鏈路或其它總線(xiàn)上連接的遠(yuǎn)程從節(jié)點(diǎn)的識(shí)別碼,可以理解為從節(jié)點(diǎn)地址

數(shù)據(jù)編碼

MODBUS 使用一個(gè)Big-Endian (低地址位存放最高有效字節(jié)) 表示地址和數(shù)據(jù)項(xiàng)。這意味著當(dāng)發(fā)射多個(gè)字節(jié)時(shí),首先發(fā)送最高有效位。

例如:
寄存器大小 值

16 0x1234 發(fā)送的第一字節(jié)為 0x12, 然后 0x34

參考閱讀:Big Endian和Little Endiand的區(qū)別

數(shù)據(jù)模型

為了抽象 PLC 中可訪(fǎng)問(wèn)的數(shù)據(jù),Modbus 協(xié)議定義了 數(shù)據(jù)模型 概念,數(shù)據(jù)模型定義了四種可訪(fǎng)問(wèn)的數(shù)據(jù)類(lèi)型:

類(lèi)型大小訪(fǎng)問(wèn)權(quán)限元素地址前綴編碼元素地址范圍(0~65535)元素地址范圍(1~9999)
輸出線(xiàn)圈(Coils)1 Bit可讀可寫(xiě)0000000~06553500000~09999
輸入離散量(Discrete Input)1 Bit只讀1100000~16553510000~19999
輸入寄存器(Input Registers)16 Bit只讀3300000~36553530000~39999
保持寄存器(Holding Registers)16 Bit可讀可寫(xiě)4400000~46553540000~49999

實(shí)際上以上的數(shù)據(jù)類(lèi)型都屬于可編程邏輯控制器(PLC)中的術(shù)語(yǔ),可以簡(jiǎn)單理解為用來(lái)存放數(shù)據(jù)的容器,線(xiàn)圈通常用于表示開(kāi)關(guān)狀態(tài)(如繼電器的通或斷),而寄存器通常用于存儲(chǔ)線(xiàn)性或非線(xiàn)性的數(shù)值數(shù)據(jù)。

數(shù)據(jù)模型中的每一種數(shù)據(jù)類(lèi)型都最多允許有 65536 個(gè)元素,元素的地址編號(hào)從 0 開(kāi)始,因此地址的范圍為:0-65535。

需要說(shuō)明的是:65536 是 Modbus 協(xié)議允許的最大元素范圍,實(shí)際應(yīng)用中一般不需要這么大的存儲(chǔ)區(qū),因此 PLC 廠(chǎng)家普遍采用的是 10000 以?xún)?nèi)的地址范圍。

引入元素地址前綴編碼,是為了簡(jiǎn)化數(shù)據(jù)模型與設(shè)備存儲(chǔ)區(qū)的對(duì)應(yīng)關(guān)系。

參考鏈接:https://blog.csdn.net/jf_52001760/article/details/130192127

數(shù)據(jù)模型是一種抽象,在實(shí)際使用時(shí)必須將其映射到真實(shí)的物理存儲(chǔ)區(qū)才能被訪(fǎng)問(wèn)。

Modbus 協(xié)議允許設(shè)備將四種數(shù)據(jù)類(lèi)型分別映射到不同的存儲(chǔ)區(qū)塊中,各個(gè)區(qū)塊之間相互獨(dú)立,使用不同的功能碼可讀取到不同的數(shù)值,如下圖所示

帶有多個(gè)獨(dú)立塊的設(shè)備

僅有1個(gè)塊的設(shè)備

功能碼

功能碼整體可以分成三類(lèi):

  • 公共功能碼
  • 用戶(hù)自定義功能碼([65, 72], [100, 110])
  • 保留功能碼

常用功能碼

功能碼名稱(chēng)操作類(lèi)型功能描述
01讀線(xiàn)圈狀態(tài)位操作讀位(讀 N 個(gè) bit)讀從機(jī)線(xiàn)圈寄存器
02讀輸入離散量位操作讀位(讀 N 個(gè) bit)讀離散輸入寄存器
03讀保持寄存器字節(jié)操作讀整型,字符型,狀態(tài)字,浮點(diǎn)型(讀 N 個(gè) word)讀保持寄存器
04讀輸入寄存器字節(jié)操作讀整型,狀態(tài)字,浮點(diǎn)型(讀 N 個(gè)word)讀輸入寄存器
05寫(xiě)單個(gè)線(xiàn)圈位操作寫(xiě)位(寫(xiě) 1 個(gè) bit)寫(xiě)線(xiàn)圈寄存器
06寫(xiě)單個(gè)保持寄存器字節(jié)操作寫(xiě)整型,字符型,狀態(tài)字,浮點(diǎn)型(寫(xiě)一個(gè) word)寫(xiě)保持寄存器,
0F寫(xiě)多個(gè)線(xiàn)圈位操作寫(xiě)位(寫(xiě) N 個(gè) bit)強(qiáng)置一串連續(xù)邏輯線(xiàn)圈的通斷
10寫(xiě)多個(gè)保持寄存器位操作寫(xiě)整形,字符型,狀態(tài)字,浮點(diǎn)型(寫(xiě) N 個(gè) word)把具體的二進(jìn)制值裝入一串連續(xù)的保持寄存器

請(qǐng)求和應(yīng)答報(bào)文示例

Modbus RTU通信

示例1:寫(xiě)單個(gè)寄存器。向01地址設(shè)備0x0105保持寄存器寫(xiě)入1個(gè)數(shù)據(jù):0x0190

主機(jī)發(fā)送: 01 06 01 05 01 90 99 CB
從機(jī)回復(fù): 01 06 01 05 01 90 99 CB

說(shuō)明:01表示從機(jī)地址,06功能碼表示寫(xiě)單個(gè)保持寄存器,01 05表示寄存器地址,01 90 表示寫(xiě)入寄存器的數(shù)值,99 CB為CRC校驗(yàn)值。

可以看出,當(dāng)寫(xiě)1個(gè)寄存器數(shù)據(jù)時(shí),從機(jī)響應(yīng)的數(shù)據(jù)幀和主機(jī)發(fā)送的數(shù)據(jù)幀完成一致。

附:CRC(循環(huán)冗余校驗(yàn))在線(xiàn)計(jì)算地址:http://www.ip33.com/crc.html

CRC-16代碼實(shí)現(xiàn)

# -*- coding:utf-8 -*-
'''生成  CRC  的過(guò)程為:
1.將一個(gè) 16 位寄存器裝入十六進(jìn)制 FFFF,將之稱(chēng)作 CRC 寄存器.
2.將報(bào)文的第一個(gè)8位字節(jié)與上述 CRC 寄存器的低字節(jié)異或,結(jié)果置于 CRC 寄存器.
3.將 CRC 寄存器右移 1 位  (向 LSB(Least Significant Bit,最低有效位) 方向),  MSB(Most Significant Bit,最高有效位) 充零。提取并檢測(cè) LSB。
4.如果 LSB 為 0,則重復(fù)步驟 3 (另一次移位).
  如果 LSB 為 1: 對(duì) CRC 寄存器異或多項(xiàng)式值 0xA001 (對(duì)應(yīng)16位二進(jìn)制:1010 0000 0000 0001)
5.重復(fù)步驟 3 和 4,直到完成 8 次移位。當(dāng)做完此操作后,將完成對(duì) 8 位字節(jié)的完整操作。
6. 對(duì)報(bào)文中的下一個(gè)字節(jié)重復(fù)步驟 2 到 5,繼續(xù)此操作直至所有報(bào)文被處理完畢。
7. CRC  寄存器中的最終內(nèi)容為 CRC  值.
8. 當(dāng)放置 CRC 值于報(bào)文時(shí),需要交換CRC高低字節(jié)。
'''
def hex_char_to_int(hex_char):
    '''
    :param hex_char: 16進(jìn)制表示的字符
    :return: 字節(jié)
    '''
    return "0123456789ABCDEF".find(hex_char)
def hex_string_to_bytes(hex_string):
    '''
    16進(jìn)制字符串轉(zhuǎn)為字節(jié)數(shù)組
    :param hex_string:  16進(jìn)制表示的字符串
    :return: 字節(jié)數(shù)組
    '''
    hex_string = hex_string.strip()
    hex_string_len = len(hex_string)
    if not hex_string_len:
        return
    byte_array = [] # 存放最終結(jié)果
    hex_string = hex_string.upper()
    for i in range(int(hex_string_len/2)):
        high_digit = hex_char_to_int(hex_string[2*i]) # 獲取高4位的10進(jìn)制表示
        low_digit = hex_char_to_int(hex_string[2*i+1])  # 獲取低4位的10進(jìn)制表示
        # high_digit 左移4位,形成字節(jié)高4位
        byte_array.append(high_digit << 4 | low_digit) # 通過(guò)異或運(yùn)算,得到字節(jié)
    if hex_string_len % 2 == 1: # 不能整除時(shí),最后一個(gè)1個(gè)字符的處理
        byte_array.append(0x00 | hex_char_to_int(hex_string[hex_string_len-1]))
    return byte_array
def bytes_to_hex_string(byte_list):
    '''
    字節(jié)轉(zhuǎn)為16進(jìn)制字符串
    :param byte_list: 字節(jié)數(shù)組
    :return: 字節(jié)數(shù)組對(duì)應(yīng)的大寫(xiě)16進(jìn)制字符串表示
    '''
    hex_string = ""
    for i in range(len(byte_list)):
        # [2:] 去掉 '0x'
        # zfill(2) 1字節(jié)需要2位16進(jìn)制字符來(lái)表示,不夠時(shí)填充0
        hex_string += hex(byte_list[i] & 0xFF)[2:].zfill(2)
    return hex_string.upper()
def calculate_crc(data):
    reg_crc = 0xFFFF
    for byte in data:
        reg_crc ^= byte
        for _ in range(8):
            if reg_crc & 0x0001: # 這里直接通過(guò)與運(yùn)算,就可以判斷最低有效位是否為0,和步驟3操作等價(jià)的
                reg_crc = (reg_crc >> 1) ^ 0xA001
            else:
                reg_crc >>= 1
    return reg_crc.to_bytes(2, 'big') # 按大端模式返回代表整數(shù)的2字節(jié)數(shù)據(jù)
# 測(cè)試
string_data = '01 06 01 05 01 90'
string_data = string_data.replace(' ', '')
byte_list = bytes(string_data, encoding='utf-8')  # 注意,這里不能用代碼:實(shí)現(xiàn),這樣是錯(cuò)誤的,獲取不到正確結(jié)果
byte_list = hex_string_to_bytes(string_data)
crc_value  = calculate_crc(byte_list)
print(crc_value, bytes_to_hex_string(crc_value)) # 輸出:b'\xcb\x99' CB99
final_crc = ''
for byte in crc_value:
    final_crc = str(hex(byte)).lstrip('0x') +  ' ' + final_crc
print(final_crc.upper()) # 輸出:99 CB

示例2:寫(xiě)多個(gè)寄存器。向01地址設(shè)備0x0105、0x0106、0x0107地址保持寄存器,寫(xiě)入3個(gè)寄存器數(shù)據(jù):0x1102, 0x0304, 0x0566

主機(jī)發(fā)送:01 10 01 05 00 03 06 11 02 03 04 05 66 4A 12
從機(jī)回復(fù):01 10 01 05 00 03 91 F5

說(shuō)明:01從機(jī)地址,10功能碼表示寫(xiě)多個(gè)保持寄存器,01 05表示起始地址,00 03表示寫(xiě)3個(gè)寄存器,06表示數(shù)據(jù)量為6個(gè)字節(jié),11 02/03 04/05 66分別表示寫(xiě)入3個(gè)寄存器的數(shù)值,4A 12 表示CRC校驗(yàn)數(shù)值。

示例3:讀單個(gè)寄存器。讀01地址設(shè)備0x0105保持寄存器數(shù)據(jù)。

主機(jī)發(fā)送:01 03 01 05 00 01 95 F7
從機(jī)回復(fù):01 03 02 56 78 87 C6

說(shuō)明:

03表示讀多個(gè)寄存器,0105表示起始地址,00 01表示讀1個(gè)寄存器

02表示2個(gè)字節(jié),56 78表示寄存器的數(shù)據(jù)。

示例4:讀多個(gè)寄存器。讀01地址設(shè)備0x0105、0x0106、0x0107地址保持寄存器,共3個(gè)寄存器數(shù)據(jù)。

主機(jī)發(fā)送:01 03 01 05 00 03 14 36
從機(jī)回復(fù):01 03 06 11 22 33 44 55 66 2A 18

說(shuō)明:

03表示讀多個(gè)寄存器,01 05表示起始地址,00 03 表示讀3個(gè)寄存器

06表示6個(gè)字節(jié),11 22 33 44 55 66表示寄存器的數(shù)據(jù)。

Modbus ASCII

例子:向地址為0x01的從設(shè)備的0x0405地址,寫(xiě)入數(shù)值0x1234,報(bào)文如下:

主機(jī)發(fā)送請(qǐng)求: :01 06 04 05 12 34 AA <CR><LF>

說(shuō)明:01表示設(shè)備地址,06表示寫(xiě)單個(gè)保持寄存器。04 05 表示寄存器地址,12 34 表示數(shù)據(jù),AA 表示LRC校驗(yàn)值。實(shí)際進(jìn)行校驗(yàn)的數(shù)據(jù)不包含起始符(:)和結(jié)束符(<CR><LF>)。

附:LRC校驗(yàn)(縱向冗余校驗(yàn))在線(xiàn)計(jì)算地址:http://www.ip33.com/lrc.html

LRC代碼實(shí)現(xiàn)

string  = '01 06 04 05 12 34'
total = 0
for item in string.split(' '):
    total += int(item, 16)
result = total % 256
hex_lrc_vale = hex(256 - result)

錯(cuò)誤碼

常用錯(cuò)誤碼如下表所示。

異常碼名稱(chēng)描述
01 (01H)非法功能在請(qǐng)求中接收的功能代碼不是從設(shè)備的一個(gè)授權(quán)操作。從設(shè)備可能處于錯(cuò)誤狀態(tài),無(wú)法處理特定請(qǐng)求。
02 (02H)非法數(shù)據(jù)地址從設(shè)備接收的數(shù)據(jù)地址不是從設(shè)備的一個(gè)授權(quán)地址
03 (03H)非法數(shù)據(jù)值指定的數(shù)據(jù)超過(guò)范圍或者不允許使用。
04 (04H)從站設(shè)備故障從設(shè)備未能執(zhí)行一個(gè)請(qǐng)求的操作,因?yàn)槌霈F(xiàn)了一個(gè)無(wú)法修復(fù)的錯(cuò)誤
05 (05H)確認(rèn)確認(rèn) 從站設(shè)備已經(jīng)接受請(qǐng)求,并且正在處理這個(gè)請(qǐng)求,但是需要長(zhǎng)持續(xù)時(shí)間進(jìn)行這些操作,返回這個(gè)響應(yīng)防止在客戶(hù)機(jī)(或主站)中發(fā)生超時(shí)錯(cuò)誤,客戶(hù)機(jī)(或主機(jī))可以繼續(xù)發(fā)送輪詢(xún)程序完成報(bào)文來(lái)確認(rèn)是否完成處理
06 (06H)從站設(shè)備忙從設(shè)備忙于處理另一個(gè)命令。主設(shè)備必須在從設(shè)備空閑后發(fā)送請(qǐng)求
07 (07H)否定確認(rèn)從站設(shè)備無(wú)法執(zhí)行主站設(shè)備發(fā)送的請(qǐng)求
08 (08H)存儲(chǔ)奇偶性差錯(cuò)從設(shè)備在嘗試讀取擴(kuò)展存儲(chǔ)器的時(shí)候從存儲(chǔ)器中檢測(cè)到一個(gè)奇偶校驗(yàn)錯(cuò)誤
10 (0AH)不可用的網(wǎng)關(guān)路徑與網(wǎng)關(guān)一起使用,指示網(wǎng)關(guān)不能為處理請(qǐng)求分配輸入端口值輸出端口的內(nèi)部通信路徑。通常意味著網(wǎng)關(guān)是錯(cuò)誤配置的或過(guò)載的
11 (0BH)網(wǎng)關(guān)目標(biāo)設(shè)備響應(yīng)失敗與網(wǎng)關(guān)一起使用,指示沒(méi)有從目標(biāo)設(shè)備中獲得響應(yīng),通常意味著設(shè)備不在網(wǎng)絡(luò)中

?轉(zhuǎn)自https://www.cnblogs.com/shouke/p/18315015


該文章在 2024/10/14 10:02:26 編輯過(guò)
關(guān)鍵字查詢(xún)
相關(guān)文章
正在查詢(xún)...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專(zhuān)業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車(chē)隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類(lèi)企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷(xiāo)售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶(hù)的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved