1、Modbus 協(xié)議簡介
Modbus協(xié)議是一種已廣泛應用于當今工業(yè)控制領域的通用通訊協(xié)議。通過此協(xié)議,控制器相互之間、或控制器經(jīng)由網(wǎng)絡(如以太網(wǎng))可以和其它設備之間進行通信。Modbus協(xié)議使用的是主從通訊技術,即由主設備主動查詢和操作從設備。一般將主控設備方所使用的協(xié)議稱為Modbus Master,從設備方使用的協(xié)議稱為Modbus Slave。典型的主設備包括工控機和工業(yè)控制器等;典型的從設備如PLC可編程控制器等。
Modbus通訊物理接口可以選用串口(包括RS232、RS485和RS422),也可以選擇以太網(wǎng)口。其通信遵循以下的過程:
主設備向從設備發(fā)送請求
從設備分析并處理主設備的請求,然后向主設備發(fā)送結(jié)果
如果出現(xiàn)任何差錯,從設備將返回一個異常功能碼
此協(xié)議定義了一個控制器能認識使用的消息結(jié)構(gòu),而不管它們是經(jīng)過何種網(wǎng)絡進行通信的。它描述了一控制器請求訪問其它設備的過程,如何回應來自其它設備的請求,以及怎樣偵測錯誤并記錄。它制定了消息域格局和內(nèi)容的公共格式。
當在Modbus網(wǎng)絡上通信時,此協(xié)議決定了每個控制器須要知道它們的設備地址,識別按地址發(fā)來的消息,決定要產(chǎn)生何種行動。如果需要回應,控制器將生成反饋信息并用Modbus協(xié)議發(fā)出。在其它網(wǎng)絡上,包含了Modbus協(xié)議的消息轉(zhuǎn)換為在此網(wǎng)絡上使用的幀或包結(jié)構(gòu)。這種轉(zhuǎn)換也擴展了根據(jù)具體的網(wǎng)絡解決節(jié)地址、路由路徑及錯誤檢測的方法。
Modbus的工作方式是請求/應答,每次通訊都是主站先發(fā)送指令,可以是廣播,或是向特定從站的單播;從站響應指令,并按要求應答,或者報告異常。當主站不發(fā)送請求時,從站不會自己發(fā)出數(shù)據(jù),從站和從站之間不能直接通訊。
Modbus協(xié)議是應用層(協(xié)議層)報文傳輸協(xié)議,它定義了一個與物理層無關的協(xié)議數(shù)據(jù)單元(PDU),即PDU=功能碼+數(shù)據(jù)域,功能碼1byte,數(shù)據(jù)域不確定。
Modbus協(xié)議能夠應用在不同類型的總線或網(wǎng)絡。對應不同的總線或網(wǎng)絡,Modbus協(xié)議引入一些附加域映射成應用數(shù)據(jù)單元(ADU),即ADU=附加域+PDU,例如modbus tcp/ip------ ADU=MBAP+ADU。
2、Modbus 通訊方式
2.1、Modbus三種通訊方式
Modbus有下列三種通信方式:
(1)、以太網(wǎng):對應的通信模式是Modbus TCP/IP
(2)、異步串行傳輸(各種介質(zhì)如有線RS-232-/422/485/;光纖、無線等):對應的通信模式是Modbus RTU或Modbus ASCII
(3)、高速令牌傳遞網(wǎng)絡:對應的通信模式是Modbus PLUS
Modbus RTU和Modbus ASCII協(xié)議應用于串口鏈接(RS232、RS485、RS422),Modbus tcp/ip協(xié)議應用于以太網(wǎng)鏈接。
2.2、在Modbus網(wǎng)絡上傳輸
標準的Modbus口是使用RS-232C兼容串行接口,它定義了連接口的針腳、電纜、信號位、傳輸波特率、奇偶校驗??刂破髂苤苯踊蚪?jīng)由Modem組網(wǎng)。
控制器通信使用主/從技術,即僅一設備(主設備)能初始化傳輸(查詢)。其它設備(從設備)根據(jù)主設備查詢提供的數(shù)據(jù)作出相應反應。
典型的主設備:主機和可編程儀表。
典型的從設備:可編程控制器。
主設備可單獨和從設備通信,也能以廣播方式和所有從設備通信。如果單獨通信,從設備返回一消息作為回應,如果是以廣播方式查詢的,則不作任何回應。
Modbus協(xié)議建立了主設備查詢的格式:設備(或廣播)地址、功能代碼、所有要發(fā)送的數(shù)據(jù)、一錯誤檢測域。
從設備回應消息也由Modbus協(xié)議構(gòu)成,包括確認要行動的域、任何要返回的數(shù)據(jù)、和一錯誤檢測域。如果在消息接收過程中發(fā)生一錯誤,或從設備不能執(zhí)行其命令,從設備將建立一錯誤消息并把它作為回應發(fā)送出去。
2.3、在其它類型網(wǎng)絡上轉(zhuǎn)輸
在其它網(wǎng)絡上,控制器使用對等技術通信,故任何控制都能初始和其它控制器的通信。這樣在單獨的通信過程中,控制器既可作為主設備也可作為從設備。提供的多個內(nèi)部通道可允許同時發(fā)生的傳輸進程。
在消息位,Modbus協(xié)議仍提供了主/從原則,盡管網(wǎng)絡通信方法是“對等”。如果一控制器發(fā)送一消息,它只是作為主設備,并期望從從設備得到回應。同樣,當控制器接收到一消息,它將建立一從設備回應格式并返回給發(fā)送的控制器。
2.4、查詢---回應
?。?)、查詢
查詢消息中的功能代碼告之被選中的從設備要執(zhí)行何種功能。數(shù)據(jù)段包含了從設備要執(zhí)行功能的任何附加信息。例如功能代碼03是要求從設備讀保持寄存器并返回它們的內(nèi)容。數(shù)據(jù)段必須包含要告之從設備的信息:從何寄存器開始讀及要讀的寄存器數(shù)量。錯誤檢測域為從設備提供了一種驗證消息內(nèi)容是否正確的方法。
?。?)、回應
如果從設備產(chǎn)生正常的回應,在回應消息中的功能代碼是在查詢消息中的功能代碼的回應。數(shù)據(jù)段包括了從設備收集的數(shù)據(jù):象寄存器值或狀態(tài)。如果有錯誤發(fā)生,功能代碼將被修改以用于指出回應消息是錯誤的,同時數(shù)據(jù)段包含了描述此錯誤信息的代碼。錯誤檢測域允許主設備確認消息內(nèi)容是否可用。
3、三種通訊方式的報文格式
Modbus協(xié)議的報文(或幀)的基本格式是:表頭 + 功能碼 + 數(shù)據(jù)區(qū) + 校驗碼
功能碼和數(shù)據(jù)區(qū)在不同類型的網(wǎng)絡都是固定不變的,表頭和校驗碼則因網(wǎng)絡底層的實現(xiàn)方式不同而有所區(qū)別。表頭包含了從站的地址,功能碼告訴從站要執(zhí)行何種功能,數(shù)據(jù)區(qū)是具體的信息。
對于不同類型的網(wǎng)絡,Modbus的協(xié)議層實現(xiàn)是一樣的,區(qū)別在于下層的實現(xiàn)方式,常見的有TCP/IP和串行通訊兩種。
Modbus TCP基于以太網(wǎng)和TCP/IP協(xié)議,Modbus RTU和Modbus ASCII則是使用異步串行傳輸(通常是RS-232/422/485)。
如圖所示,串行傳輸的物理層是RS-485或RS-232,數(shù)據(jù)鏈路層是Modbus的串行傳輸協(xié)議;Modbus TCP傳輸的1、2、3、4層實現(xiàn)和日常所見的以太網(wǎng)、因特網(wǎng)一樣,Modbus默認采用的TCP端口號是502。
3.1、以太網(wǎng)(modbus tcp/ip)
對于Modbus TCP而言,主站通常稱為Client,從站稱為Server;而對于Modbus RTU和Modbus ASCII來說,主站是Master,從站是Slave。
ModbusTCP的數(shù)據(jù)幀可分為兩部分:ADU=MBAP+PDU = MBAP + 功能碼 + 數(shù)據(jù)域,MBAP 7byte,功能碼1byte,數(shù)據(jù)域不確定,由具體功能決定。
MBAP為報文頭,長度為7字節(jié),組成如下:
事務處理標識 | 協(xié)議標識 | 長度 | 單元標識符 |
2byte | 2byte | 2byte | 1byte |
事務處理標識 | 可以理解為報文的序列號,一般每次通信之后就要加1以區(qū)別不同的通信數(shù)據(jù)報文 |
協(xié)議標識符 | 00 00表示ModbusTCP協(xié)議 |
長度 | 表示接下來的數(shù)據(jù)長度,單位為字節(jié) |
單元標識符 | 可以理解為設備地址 |
下圖說明了Modbus TCP的改動:
(1)、取消了校驗位。數(shù)據(jù)鏈路層上就進行了CRC-32的校驗,TCP/IP是面向連接的可靠性的協(xié)議,因此沒必要再加上校驗位。
?。?)、Slave地址換成了Unit Identifier。當網(wǎng)絡里的設備全是使用TCP/IP,這個地址是沒有意義的,因為IP就能進行路由尋址。如果網(wǎng)絡里還有串行通訊的設備,則需要網(wǎng)關來實現(xiàn)Modbus TCP到Modbus RTU或ASCII之間的協(xié)議轉(zhuǎn)換,這時用Unit Identifier來標識網(wǎng)關后面的每個串行通訊設備。
?。?)、Length是指后面的字節(jié)總數(shù)。實際上數(shù)據(jù)區(qū)的長度是能確定的,有的功能碼就可以確定數(shù)據(jù)區(qū)的長度,有的功能碼雖不能確定數(shù)據(jù)區(qū)長度,但是數(shù)據(jù)區(qū)有字節(jié)計數(shù),參見上文舉的從站應答的例子。表頭增加的Length是為了應對有些情況下TCP/IP協(xié)議會將應用層的數(shù)據(jù)拆包傳輸。
?。?)、Transaction Identifier和Protocol Identifier由Client生成,Server的響應將復制這些參數(shù)。
3.1.1、modbus tcp/ip通信方式
Modbus設備可分為主站(poll)和從站(slave)。主站只有一個,從站有多個,主站向各從站發(fā)送請求幀,從站給予響應。在使用TCP通信時,主站為client端,主動建立連接;從站為server端,等待連接。
主站請求:功能碼+數(shù)據(jù)
從站正常響應:請求功能碼+響應數(shù)據(jù)
從站異常響應:異常功能碼+異常碼,其中異常功能碼即將請求功能碼的最高有效位置1,異常碼指示差錯類型
注意:需要超時管理機制,避免無期限的等待可能不出現(xiàn)的應答
IANA(Internet Assigned Numbers Authority,互聯(lián)網(wǎng)編號分配管理機構(gòu))給Modbus協(xié)議賦予TCP端口號為502,這是目前在儀表與自動化行業(yè)中唯一分配到的端口號。
3.1.2、通信過程
A、connect 建立TCP連接
B、準備Modbus報文
C、使用send命令發(fā)送報文
D、在同一連接下等待應答
E、使用recv命令讀取報文,完成一次數(shù)據(jù)交換
F、通信任務結(jié)束時,關閉TCP連接
3.2、異步串行傳輸?shù)膬煞N傳輸方式(modbus RTU和modbus ASCII)
異步串行傳輸時, 控制器可以設置為兩種傳輸模式(ASCII或RTU)中的任何一種在標準的Modbus網(wǎng)絡通信。用戶選擇想要的模式,包括串口通信參數(shù)(波特率、校驗方式等),在配置每個控制器的時候,在一個Modbus網(wǎng)絡上的所有設備都必須選擇相同的傳輸模式和串口參數(shù)。
ASCII模式:
起始位 | 設備地址 | 功能代碼 | 數(shù)據(jù)數(shù)量 | 數(shù)據(jù) | LRC高字節(jié) | LRC低字節(jié) | 結(jié)束符 |
: | 2*8bit | 2*8bit | n | n*8bit | 8bit | 8bit | CR、LF(回車、換行) |
RTU模式:
起始位 | 設備地址 | 功能代碼 | 數(shù)據(jù)數(shù)量 | 數(shù)據(jù) | CRC低字節(jié) | CRC高字節(jié) | 結(jié)束符 |
無 | 8bit | 8bit | n | n*8bit | 8bit | 8bit | 無 |
3.2.1、ASCII模式
當控制器設為在Modbus網(wǎng)絡上以ASCII(美國標準信息交換代碼)模式通信,在消息中的每個8Bit字節(jié)都作為兩個ASCII字符發(fā)送。這種方式的主要優(yōu)點是字符發(fā)送的時間間隔可達到1秒而不產(chǎn)生錯誤。
代碼系統(tǒng):
十六進制,ASCII字符0...9,A...F
消息中的每個ASCII字符都是一個十六進制字符組成
每個字節(jié)的位:1個起始位、7個數(shù)據(jù)位(最小的有效位先發(fā)送)、1個奇偶校驗位(無校驗則無)、1個停止位(有校驗時)、2個Bit(無校驗時)
錯誤檢測域:LRC(縱向冗長檢測)
3.2.2、RTU模式
當控制器設為在Modbus網(wǎng)絡上以RTU(遠程終端單元)模式通信,在消息中的每個8Bit字節(jié)包含兩個4Bit的十六進制字符。這種方式的主要優(yōu)點是:在同樣的波特率下,可比ASCII方式傳送更多的數(shù)據(jù)。
代碼系統(tǒng):
8位二進制,十六進制數(shù)0...9,A...F
消息中的每個8位域都是兩個十六進制字符組成
每個字節(jié)的位:1個起始位、8個數(shù)據(jù)位(最小的有效位先發(fā)送)、1個奇偶校驗位(無校驗則無)、1個停止位(有校驗時),2個Bit(無校驗時)
錯誤檢測域:CRC(循環(huán)冗長檢測)
3.2.3、RTU和ASCII的區(qū)別
?。?)、RTU模式下,一個字節(jié)的數(shù)據(jù),傳輸?shù)木褪且粋€字節(jié)。ASCII模式下,同樣一個字節(jié)數(shù)據(jù)用了兩個字節(jié)來傳輸。例如,要傳輸數(shù)字0x5B,RTU傳輸?shù)氖?101 1011(二進制),而ASCII傳輸?shù)氖?0110101和01000010。可見,ASCII傳輸?shù)乃俾适荝TU的一半?! ?/p>
?。?)、ASCII模式采用LRC校驗,RTU模式采用16位CRC校驗。
?。?)、ASCII有開始標記和結(jié)束標記,RTU沒有
4、Modbus RTU和Modbus ASCII消息幀
兩種傳輸模式中(ASCII或RTU),傳輸設備以將Modbus消息轉(zhuǎn)為有起點和終點的幀,這就允許接收的設備在消息起始處開始工作,讀地址分配信息,判斷哪一個設備被選中(廣播方式則傳給所有設備),判知何時信息已完成。部分的消息也能偵測到并且錯誤能設置為返回結(jié)果。
4.1、ASCII幀
使用ASCII模式,消息以冒號(:)字符(ASCII碼 3AH)開始,以回車換行符結(jié)束(ASCII碼 0DH,0AH)。
其它域可以使用的傳輸字符是十六進制的0...9,A...F。網(wǎng)絡上的設備不斷偵測“:”字符,當有一個冒號接收到時,每個設備都解碼下個域(地址域)來判斷是否發(fā)給自己的。
消息中字符間發(fā)送的時間間隔最長不能超過1秒,否則接收的設備將認為傳輸錯誤。一個典型消息幀如下所示:
起始位 | 設備地址 | 功能代碼 | 數(shù)據(jù) | LRC校驗 | 結(jié)束符 |
1個字符 | 2個字符 | 2個字符 | n個字符 | 2個字符 | 2個字符 |
4.2、RTU幀
使用RTU模式,消息發(fā)送至少要以3.5個字符時間的停頓間隔開始。在網(wǎng)絡波特率下多樣的字符時間,這是最容易實現(xiàn)的(如下圖的T1-T2-T3-T4所示)。傳輸?shù)牡谝粋€域是設備地址??梢允褂玫膫鬏斪址鞘M制的0...9,A...F。網(wǎng)絡設備不斷偵測網(wǎng)絡總線,包括停頓間隔時間內(nèi)。當?shù)谝粋€域(地址域)接收到,每個設備都進行解碼以判斷是否發(fā)往自己的。在最后一個傳輸字符之后,一個至少3.5個字符時間的停頓標定了消息的結(jié)束。一個新的消息可在此停頓后開始。
整個消息幀必須作為一連續(xù)的流轉(zhuǎn)輸。如果在幀完成之前有超過1.5個字符時間的停頓時間,接收設備將刷新不完整的消息并假定下一字節(jié)是一個新消息的地址域。同樣地,如果一個新消息在小于3.5個字符時間內(nèi)接著前個消息開始,接收的設備將認為它是前一消息的延續(xù)。這將導致一個錯誤,因為在最后的CRC域的值不可能是正確的。一典型的消息幀如下所示:
起始位 | 設備地址 | 功能代碼 | 數(shù)據(jù) | CRC校驗 | 結(jié)束符 |
T1-T2-T3-T4 | 8Bit | 8Bit | n個8Bit | 16Bit | T1-T2-T3-T4 |
4.3、兩種幀的分析
?。?)、地址域
消息幀的地址域包含兩個字節(jié)(ASCII)或一個字節(jié)(RTU)??赡艿膹脑O備地址是0...247 (十進制)。單個設備的地址范圍是1...247。主設備通過將要聯(lián)絡的從設備的地址放入消息中的地址域來選通從設備。當從設備發(fā)送回應消息時,它把自己的地址放入回應的地址域中,以便主設備知道是哪一個設備作出回應。
地址0是用作廣播地址,以使所有的從設備都能認識。當Modbus協(xié)議用于更高水準的網(wǎng)絡,廣播可能不允許或以其它方式代替。
(2)、如何處理功能域
消息幀中的功能代碼域包含了兩個字節(jié)(ASCII)或一個字節(jié)(RTU)??赡艿拇a范圍是十進制的1...255。當然,有些代碼是適用于所有控制器,有此是應用于某種控制器,還有些保留以備后用。
當消息從主設備發(fā)往從設備時,功能代碼域?qū)⒏嬷畯脑O備需要執(zhí)行哪些行為。例如去讀取輸入的開關狀態(tài),讀一組寄存器的數(shù)據(jù)內(nèi)容,讀從設備的診斷狀態(tài),允許調(diào)入、記錄、校驗在從設備中的程序等。
當從設備回應時,它使用功能代碼域來指示是正常回應(無誤)還是有某種錯誤發(fā)生(稱作異議回應)。對正?;貞瑥脑O備僅回應相應的功能代碼。對異議回應,從設備返回一等同于正常代碼的代碼,但最重要的位置為邏輯1。
例如:一從主設備發(fā)往從設備的消息要求讀一組保持寄存器,將產(chǎn)生如下功能代碼:0 0 0 0 0 0 1 1 (十六進制03H)
對正?;貞瑥脑O備僅回應同樣的功能代碼。對異議回應,它返回:1 0 0 0 0 0 1 1 (十六進制83H)
除功能代碼因異議錯誤作了修改外,從設備將一獨特的代碼放到回應消息的數(shù)據(jù)域中,這能告訴主設備發(fā)生了什么錯誤。
主設備應用程序得到異議的回應后,典型的處理過程是重發(fā)消息,或者診斷發(fā)給從設備的消息并報告給操作員。
?。?)、數(shù)據(jù)域
數(shù)據(jù)域是由兩個十六進制數(shù)集合構(gòu)成的,范圍00...FF。根據(jù)網(wǎng)絡傳輸模式,這可以是由一對ASCII字符組成或由一RTU字符組成。
從主設備發(fā)給從設備消息的數(shù)據(jù)域包含附加的信息:從設備必須用于進行執(zhí)行由功能代碼所定義的所為。這包括了象不連續(xù)的寄存器地址,要處理項的數(shù)目,域中實際數(shù)據(jù)字節(jié)數(shù)。
例如,如果主設備需要從設備讀取一組保持寄存器(功能代碼03),數(shù)據(jù)域指定了起始寄存器以及要讀的寄存器數(shù)量。如果主設備寫一組從設備的寄存器(功能代碼10十六進制),數(shù)據(jù)域則指明了要寫的起始寄存器以及要寫的寄存器數(shù)量,數(shù)據(jù)域的數(shù)據(jù)字節(jié)數(shù),要寫入寄存器的數(shù)據(jù)。
如果沒有錯誤發(fā)生,從從設備返回的數(shù)據(jù)域包含請求的數(shù)據(jù)。如果有錯誤發(fā)生,此域包含一異議代碼,主設備應用程序可以用來判斷采取下一步行動。
在某種消息中數(shù)據(jù)域可以是不存在的(0長度)。例如,主設備要求從設備回應通信事件記錄(功能代碼0B十六進制),從設備不需任何附加的信息。
?。?)、錯誤檢測域
標準的Modbus網(wǎng)絡有兩種錯誤檢測方法。錯誤檢測域的內(nèi)容視所選的檢測方法而定。
ASCII:當選用ASCII模式作字符幀,錯誤檢測域包含兩個ASCII字符。這是使用LRC(縱向冗長檢測)方法對消息內(nèi)容計算得出的,不包括開始的冒號符及回車換行符。LRC字符附加在回車換行符前面。
RTU: 當選用RTU模式作字符幀,錯誤檢測域包含一16Bits值(用兩個8位的字符來實現(xiàn))。錯誤檢測域的內(nèi)容是通過對消息內(nèi)容進行循環(huán)冗長檢測方法得出的。CRC域附加在消息的最后,添加時先是低字節(jié)然后是高字節(jié)。故CRC的高位字節(jié)是發(fā)送消息的最后一個字節(jié)。
?。?)、字符的連續(xù)傳輸
當消息在標準的Modbus系列網(wǎng)絡傳輸時,每個字符或字節(jié)以如下方式發(fā)送(從左到右):
最低有效位...最高有效位
使用ASCII字符幀時,位的序列是:
有奇偶校驗
啟始位 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 奇偶位 | 停止位 |
無奇偶校驗:
啟始位 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 停止位 | 停止位 |
使用RTU字符幀時,位的序列是:
有奇偶校驗
啟始位 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 奇偶位 | 停止位 |
無奇偶校驗
啟始位 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 停止位 | 停止位 |
5、錯誤檢測方法
標準的Modbus串行網(wǎng)絡采用兩種錯誤檢測方法。奇偶校驗對每個字符都可用,幀檢測(LRC或CRC)應用于整個消息。它們都是在消息發(fā)送前由主設備產(chǎn)生的,從設備在接收過程中檢測每個字符和整個消息幀。
用戶要給主設備配置一預先定義的超時時間間隔,這個時間間隔要足夠長,以使任何從設備都能作為正常反應。如果從設備測到一傳輸錯誤,消息將不會接收,也不會向主設備作出回應。這樣超時事件將觸發(fā)主設備來處理錯誤。發(fā)往不存在的從設備的地址也會產(chǎn)生超時。
5.1、奇偶校驗
用戶可以配置控制器是奇或偶校驗,或無校驗。這將決定了每個字符中的奇偶校驗位是如何設置的。
如果指定了奇或偶校驗,“1”的位數(shù)將算到每個字符的位數(shù)中(ASCII模式7個數(shù)據(jù)位,RTU中8個數(shù)據(jù)位)。例如RTU字符幀中包含以下8個數(shù)據(jù)位:1 1 0 0 0 1 0 1
整個“1”的數(shù)目是4個。如果便用了偶校驗,幀的奇偶校驗位將是0,便得整個“1”的個數(shù)仍是4個。如果便用了奇校驗,幀的奇偶校驗位將是1,便得整個“1”的個數(shù)是5個。
如果沒有指定奇偶校驗位,傳輸時就沒有校驗位,也不進行校驗檢測。代替一附加的停止位填充至要傳輸?shù)淖址麕小?/p>
5.2、LRC檢測
使用ASCII模式,消息包括了一基于LRC方法的錯誤檢測域。LRC域檢測了消息域中除開始的冒號及結(jié)束的回車換行號外的內(nèi)容。
LRC域是一個包含一個8位二進制值的字節(jié)。LRC值由傳輸設備來計算并放到消息幀中,接收設備在接收消息的過程中計算LRC,并將它和接收到消息中LRC域中的值比較,如果兩值不等,說明有錯誤。
LRC方法是將消息中的8Bit的字節(jié)連續(xù)累加,丟棄了進位。
LRC簡單函數(shù)如下:
1 ///C代碼 2 static unsigned char LRC(auchMsg,usDataLen) 3 4 unsigned char *auchMsg ; /* 要進行計算的消息 */ 5 unsigned short usDataLen ; /* LRC 要處理的字節(jié)的數(shù)量*/ 6 7 { 8 unsigned char uchLRC = 0 ; /* LRC 字節(jié)初始化 */ 9 while (usDataLen--) /* 傳送消息 */ 10 uchLRC += *auchMsg++ ; /* 累加*/ 11 12 return ((unsigned char)(-((char_uchLRC))) ; 13 }
5.3、CRC檢測
使用RTU模式,消息包括了一基于CRC方法的錯誤檢測域。CRC域檢測了整個消息的內(nèi)容。
CRC域是兩個字節(jié),包含一16位的二進制值。它由傳輸設備計算后加入到消息中。接收設備重新計算收到消息的CRC,并與接收到的CRC域中的值比較,如果兩值不同,則有誤。
CRC是先調(diào)入一值是全“1”的16位寄存器,然后調(diào)用一過程將消息中連續(xù)的8位字節(jié)各當前寄存器中的值進行處理。僅每個字符中的8Bit數(shù)據(jù)對CRC有效,起始位和停止位以及奇偶校驗位均無效。
CRC產(chǎn)生過程中,每個8位字符都單獨和寄存器內(nèi)容相或(OR),結(jié)果向最低有效位方向移動,最高有效位以0填充。LSB被提取出來檢測,如果LSB為1,寄存器單獨和預置的值或一下,如果LSB為0,則不進行。整個過程要重復8次。在最后一位(第8位)完成后,下一個8位字節(jié)又單獨和寄存器的當前值相或。最終寄存器中的值,是消息中所有的字節(jié)都執(zhí)行之后的CRC值。
CRC添加到消息中時,低字節(jié)先加入,然后高字節(jié)。
計算CRC碼的步驟為:
預置16位寄存器為十六進制FFFF(即全為1)。稱此寄存器為CRC寄存器;
把第一個8位數(shù)據(jù)與16位CRC寄存器的低位相異或,把結(jié)果放于CRC寄存器;
把寄存器的內(nèi)容右移一位(朝低位),用0填補最高位,檢查最低位;
如果最低位為0:重復第3步(再次移位); 如果最低位為1:CRC寄存器與多項式A001(1010 0000 0000 0001)進行異或;
重復步驟3和4,直到右移8次,這樣整個8位數(shù)據(jù)全部進行了處理;
重復步驟2到步驟5,進行下一個8位數(shù)據(jù)的處理;
最后得到的CRC寄存器即為CRC碼。
1 /** 2 * @brief modbus rtu校驗 3 * @param p_data:要校驗的數(shù)據(jù)的地址 4 * data_len:要校驗數(shù)據(jù)的長度(字節(jié)) 5 * data_crc:數(shù)據(jù)的校驗碼 6 * @retval 無 7 */ 8 void CRC_Checkout_16(uint8_t *p_data,uint32_t data_ len,uint8_t *data_crc) 9 {10 uint16_t wcrc = 0xFFFF; 11 uint8_t temp; 12 uint32_t i=0,j=0; 13 for(i=0;i<data_len;i++) 14 {15 temp = *p_data & 0X00FF; 16 p_data++; 17 wcrc = wcrc^temp; 18 for(j=0;j<8;j++) 19 {20 if(wcrc & 0X0001) 21 {22 wcrc>>=1; 23 wcrc^=0XA001; 24 }25 else 26 {27 wcrc>>=1; 28 }29 }30 }31 temp=wcrc;32 33 data_crc[0]=wcrc; 34 data_crc[1]=wcrc>>8; 35 36 return ;37 }
1 /* CRC 高位字節(jié)值表 */ 2 static unsigned char auchCRCHi[] = 3 { 4 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 5 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 6 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 7 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 8 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 9 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,10 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,11 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,12 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,13 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,14 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,15 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,16 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,17 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,18 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,19 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,20 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,21 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,22 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,23 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,24 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,25 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,26 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,27 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,28 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,29 0x80, 0x41, 0x00, 0xC1, 0x81, 0x4030 } ;31 32 /* CRC低位字節(jié)值表*/33 static char auchCRCLo[] =34 {35 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,36 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,37 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,38 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,39 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,40 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,41 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,42 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,43 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,44 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,45 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,46 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,47 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,48 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,49 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,50 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,51 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,52 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,53 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,54 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,55 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,56 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,57 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,58 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,59 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,60 0x43, 0x83, 0x41, 0x81, 0x80, 0x4061 } ;
CRC冗余碼在線計算****: http://www.ip33.com/crc.html
6、Modbus的四種數(shù)據(jù)類型
輸出線圈:大小只有1bit,ON或OFF,可讀可寫,既可以是一個輸出量輸出點,也可以是數(shù)字量輸入點,有效的地址范圍是1-9999。
輸入離散量:大小只有1bit,ON或OFF,只讀,即數(shù)字量輸出點,有效地址范圍是10001-19999。
輸入寄存器:16bit的寄存器,只讀,可以用作模擬量或16位打包輸入點,有效地址范圍是30001-39999。
保持寄存器:16bit的寄存器,可讀可寫,既可以是一個模擬量或16位打包輸入點,也可以是模擬量或16位打包輸出點,有效地址范圍是40001-49999。
在PLC或DCS上用點名標記不同的變量,在Modbus則以數(shù)據(jù)地址來標記每個點。以上所說的地址都是參考地址,而不是實際的物理地址。上述的地址是在設備中的地址,按照PLC的習慣從1開始遞增,而Modbus報文中是從0開始遞增。例如地址偏移為4、5、6的Holding Register,其實是指參考地址是40005、40006、40007的寄存器。
?。?)、Coil和Register
Modbus中定義的兩種數(shù)據(jù)類型:Coil是位(bit)變量;Register是整型(Word,即16-bit)變量。
(2)、Slave和Master與Server和Client
同一種設備在不同領域的不同叫法。
Slave: 工業(yè)自動化用語;響應請求;
Master:工業(yè)自動化用語;發(fā)送請求;
Server:IT用語;響應請求;
Client:IT用語;發(fā)送請求;
在Modbus中,Slave和Server意思相同,Master和Client意思相同。
?。?)Modbus數(shù)據(jù)模型
Modbus中,數(shù)據(jù)可以分為兩大類,分別為位變量(Coil)和整形變量(Register),每一種數(shù)據(jù),根據(jù)讀寫方式的不同,又可細分為兩種(只讀,讀寫)。
Modbus四種數(shù)據(jù)類型:
Discretes Input | 位變量 | 只讀 |
Coils | 位變量 | 讀寫 |
Input Registers | 16-bit整型 | 只讀 |
Holding Registers | 16-bit整型 | 讀寫 |
?。?)、Modbus地址范圍對應表
設備地址 | Modbus地址 | 描述 | 功能 | R/W |
1~10000 | address-1 | Coils(Output) | 0 | R/W |
10001~20000 | address-10001 | Discrete Inputs | 01 | R |
30001~40000 | address-30001 | Input Registers | 04 | R |
40001~50000 | address-40001 | Holding Registers | 03 | R/W |
?。?)、Modbus變量地址
映射地址 | Function Code | 地址類型 | R/W | 描述 |
0xxxx | 01,05,15 | Coil | R/W | --- |
1xxxx | 02 | 離散輸入 | R | --- |
2xxxx | 03,04,06,16 | 浮點寄存器 | R/W | 兩個連續(xù)16-bit寄存器表示一個浮點數(shù)(IEEE754) |
3xxxx | 04 | 輸入寄存器 | R | 每個寄存器表示一個16-bit無符號整數(shù)(0~65535) |
4xxxx | 03,06,16 | 保持寄存器 | R/W | --- |
5xxxx | 03,04,06,16 | ASCII字符 | R/W | 每個寄存器表示兩個ASCII字符 |
7、modbus協(xié)議的功能碼
地址碼 | 功能碼 | 數(shù)據(jù)區(qū) | 錯誤校驗碼 |
8bit | 8bit | n*8bit | 2*8bit |
Modbus的操作對象有四種:線圈、離散輸入、輸入寄存器、保持寄存器。
線圈 | PLC的輸出位,開關量,在Modbus中可讀可寫 |
離散量 | PLC的輸入位,開關量,在Modbus中只讀 |
輸入寄存器 | PLC中只能從模擬量輸入端改變的寄存器,在Modbus中只讀 |
保持寄存器 | PLC中用于輸出模擬量信號的寄存器,在Modbus中可讀可寫 |
根據(jù)對象的不同,Modbus的功能碼有:
功能碼 | 名稱 | 功能 |
01 | 讀線圈狀態(tài) | 讀位(讀N個bit)---讀從機線圈寄存器,位操作 |
02 | 讀輸入離散量 | 讀位(讀N個bit)---讀離散輸入寄存器,位操作 |
03 | 讀多個寄存器 | 讀整型、字符型、狀態(tài)字、浮點型(讀N個words)---讀保持寄存器,字節(jié)操作 |
04 | 讀輸入寄存器 | 讀整型、狀態(tài)字、浮點型(讀N個words)---讀輸入寄存器,字節(jié)操作 |
05 | 寫單個線圈 | 寫位(寫一個bit)---寫線圈寄存器,位操作 |
06 | 寫單個保持寄存器 | 寫整型、字符型、狀態(tài)字、浮點型(寫一個word)---寫保持寄存器,字節(jié)操作 |
07 | 讀取異常狀態(tài) | 取得8個內(nèi)部線圈的通斷狀態(tài),這8個線圈的地址由控制器決定,用戶邏輯可以將這些線圈定義,以說明從機狀態(tài),短報文適宜于迅速讀取狀態(tài) |
08 | 回送診斷校驗 | 把診斷校驗報文送從機,以對通信處理進行評鑒 |
09 | 編程(只用于484) | 使主機模擬編程器作用,修改PC從機邏輯 |
0A | 控詢(只用于484) | 可使主機與一臺正在執(zhí)行長程序任務從機通信,探詢該從機是否已完成其操作任務,僅在含有功能碼9的報文發(fā)送后,本功能碼才發(fā)送 |
0B | 讀取事件計數(shù) | 可使主機發(fā)出單詢問,并隨即判定操作是否成功,尤其是該命令或其他應答產(chǎn)生通信錯誤時 |
0C | 讀取通訊事件記錄 | 可是主機檢索每臺從機的ModBus事務處理通信事件記錄。如果某項事務處理完成,記錄會給出有關錯誤 |
0D | 編程(184/384/484/584) | 可使主機模擬編程器功能修改PC從機邏輯 |
0E | 探詢(184/384/484/584) | 可使主機與正在執(zhí)行任務的從機通信,定期控詢該從機是否已完成其程序操作,僅在含有功能13的報文發(fā)送后,本功能碼才得發(fā)送 |
0F | 寫多個線圈 | 可以寫多個線圈---強置一串連續(xù)邏輯線圈的通斷 |
10 | 寫多個保持寄存器 | 寫多個保持寄存器---把具體的二進制值裝入一串連續(xù)的保持寄存器 |
11 | 報告從機標識 | 可使主機判斷編址從機的類型及該從機運行指示燈的狀態(tài) |
12 | (884和MICRO84) | 可使主機模擬編程功能,修改PC狀態(tài)邏輯 |
13 | 重置通信鏈路 | 發(fā)生非可修改錯誤后,是從機復位于已知狀態(tài),可重置順序字節(jié) |
14 | 讀取通用參數(shù)(584L) | 顯示擴展存儲文件中的數(shù)據(jù)信息 |
15 | 寫入通用參數(shù)(584L) | 把通用參數(shù)寫入擴展存儲文件 |
16~40 | 保留做擴展功能備用 | |
41~48 | 保留以備用戶功能所用 | 留作用戶功能的擴展編碼 |
49~77 | 非法功能 | |
78~7F | 保留 | 留作內(nèi)部作用 |
80~FF | 保留 | 用于異常應答 |
常用功能碼如下:
功能碼 | 名稱 | 功能 | 對應的地址類型 |
01 | 讀線圈狀態(tài) | 讀位(讀N個bit)---讀從機線圈寄存器,位操作 | 0x |
02 | 讀輸入離散量 | 讀位(讀N個bit)---讀離散輸入寄存器,位操作 | 1x |
03 | 讀多個寄存器 | 讀整型、字符型、狀態(tài)字、浮點型(讀N個words)---讀保持寄存器,字節(jié)操作 | 4X |
04 | 讀輸入寄存器 | 讀整型、狀態(tài)字、浮點型(讀N個words)---讀輸入寄存器,字節(jié)操作 | 3x |
05 | 寫單個線圈 | 寫位(寫一個bit)---寫線圈寄存器,位操作 | 0x |
06 | 寫單個保持寄存器 | 寫整型、字符型、狀態(tài)字、浮點型(寫一個word)---寫保持寄存器,字節(jié)操作 | 4x |
0F | 寫多個線圈 | 寫位(寫n個bit)---強置一串連續(xù)邏輯線圈的通斷 | 0x |
10 | 寫多個保持寄存器 | 寫整形、字符型、狀態(tài)字、浮點型(寫n個word)---把具體的二進制值裝入一串連續(xù)的保持寄存器 | 4x |
8、PDU詳細結(jié)構(gòu)
(1)、0x01:讀線圈
在從站中讀1~2000個連續(xù)線圈狀態(tài),ON=1,OFF=0
請求:MBAP 功能碼 起始地址H 起始地址L 數(shù)量H 數(shù)量L(共12字節(jié))
響應:MBAP 功能碼 數(shù)據(jù)長度 數(shù)據(jù)(一個地址的數(shù)據(jù)為1位)
如:在從站0x01中,讀取開始地址為0x0002的線圈數(shù)據(jù),讀0x0008位------------------00 01 00 00 00 06 01 01 00 02 00 08
回:數(shù)據(jù)長度為0x01個字節(jié),數(shù)據(jù)為0x01,第一個線圈為ON,其余為OFF------------00 01 00 00 00 04 01 01 01 01
?。?)、0x05:寫單個線圈
將從站中的一個輸出寫成ON或OFF,0xFF00請求輸出為ON,0x000請求輸出為OFF
請求:MBAP 功能碼 輸出地址H 輸出地址L 輸出值H 輸出值L(共12字節(jié))
響應:MBAP 功能碼 輸出地址H 輸出地址L 輸出值H 輸出值L(共12字節(jié))
如:將地址為0x0003的線圈設為ON---------------00 01 00 00 00 06 01 05 00 03 FF 00
回:寫入成功--------------------------------------------00 01 00 00 00 06 01 05 00 03 FF 00
(3)、0x0F:寫多個線圈
將一個從站中的一個線圈序列的每個線圈都強制為ON或OFF,數(shù)據(jù)域中置1的位請求相應輸出位ON,置0的位請求響應輸出為OFF
請求:MBAP 功能碼 起始地址H 起始地址L 輸出數(shù)量H 輸出數(shù)量L 字節(jié)長度 輸出值H 輸出值L
響應:MBAP 功能碼 起始地址H 起始地址L 輸出數(shù)量H 輸出數(shù)量L
?。?)、0x02:讀離散量輸入
從一個從站中讀1~2000個連續(xù)的離散量輸入狀態(tài)
請求:MBAP 功能碼 起始地址H 起始地址L 數(shù)量H 數(shù)量L(共12字節(jié))
響應:MBAP 功能碼 數(shù)據(jù)長度 數(shù)據(jù)(長度:9+ceil(數(shù)量/8))
如:從地址0x0000開始讀0x0012個離散量輸入-------------------------------------------------------------------------------------------------00 01 00 00 00 06 01 02 00 00 00 12
回:數(shù)據(jù)長度為0x03個字節(jié),數(shù)據(jù)為0x01 04 00,表示第一個離散量輸入和第11個離散量輸入為ON,其余為OFF----------00 01 00 00 00 06 01 02 03 01 04 00
?。?)、0x04:讀輸入寄存器
從一個遠程設備中讀1~2000個連續(xù)輸入寄存器
請求:MBAP 功能碼 起始地址H 起始地址L 寄存器數(shù)量H 寄存器數(shù)量L(共12字節(jié))
響應:MBAP 功能碼 數(shù)據(jù)長度 寄存器數(shù)據(jù)(長度:9+寄存器數(shù)量×2)
如:讀起始地址為0x0002,數(shù)量為0x0005的寄存器數(shù)據(jù)----------------------------00 01 00 00 00 06 01 04 00 02 00 05
回:數(shù)據(jù)長度為0x0A,第一個寄存器的數(shù)據(jù)為0x0c,其余為0x00----------------00 01 00 00 00 0D 01 04 0A 00 0C 00 00 00 00 00 00 00 00
(6)、0x03:讀保持寄存器
從遠程設備中讀保持寄存器連續(xù)塊的內(nèi)容
請求:MBAP 功能碼 起始地址H 起始地址L 寄存器數(shù)量H 寄存器數(shù)量L(共12字節(jié))
響應:MBAP 功能碼 數(shù)據(jù)長度 寄存器數(shù)據(jù)(長度:9+寄存器數(shù)量×2)
如:起始地址是0x0000,寄存器數(shù)量是 0x0003----------------------------------00 01 00 00 00 06 01 03 00 00 00 03
回:數(shù)據(jù)長度為0x06,第一個寄存器的數(shù)據(jù)為0x21,其余為0x00-----------00 01 00 00 00 09 01 03 06 00 21 00 00 00 00
(7)、0x06:寫單個保持寄存器
在一個遠程設備中寫一個保持寄存器
請求:MBAP 功能碼 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字節(jié))
響應:MBAP 功能碼 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字節(jié))
如:向地址是0x0000的寄存器寫入數(shù)據(jù)0x000A------------------00 01 00 00 00 06 01 06 00 00 00 0A
回:寫入成功--------------------------------------------------------------00 01 00 00 00 06 01 06 00 00 00 0A
?。?)、0x10:寫多個保持寄存器
在一個遠程設備中寫連續(xù)寄存器塊(1~123個寄存器)
請求:MBAP 功能碼 起始地址H 起始地址L 寄存器數(shù)量H 寄存器數(shù)量L 字節(jié)長度 寄存器值(13+寄存器數(shù)量×2)
響應:MBAP 功能碼 起始地址H 起始地址L 寄存器數(shù)量H 寄存器數(shù)量L(共12字節(jié))
如:向起始地址為0x0000,數(shù)量為0x0001的寄存器寫入數(shù)據(jù),數(shù)據(jù)長度為0x02,數(shù)據(jù)為0x000F-----------00 01 00 00 00 09 01 10 00 00 00 01 02 00 0F
回:寫入成功------------------------------------------------------------------------------------------------------------------------00 01 00 00 00 06 01 10 00 00 00 01
9、數(shù)據(jù)解析
ModBus TCP/IP與串行鏈路Modbus的數(shù)據(jù)域是一致的,具體數(shù)據(jù)域可以參考串行modbus。這里給出幾個ModbusTcp的鏈路解析說明,輔助新人分析報文。
(1)、數(shù)據(jù)請求
97 76 00 00 00 06 04 04 00 7D 00 7D | ||||
示例 | 長度 | 說明 | 備注 | |
Map報文頭 | 0x97 | 1 | 事務處理標識符Hi | 客戶機發(fā)起,服務器復制,用于事務處理配對 |
0x96 | 1 | 事務處理標識符Lo | ||
0x0000 | 2 | 協(xié)議標識符號 | 客戶機發(fā)起,服務器復制 Modbus協(xié)議 = 0. | |
0x0006 | 2 | 長度 | 從本字節(jié)下一個到最后
| |
0x04 | 1 | 單元標識符 | 客戶機發(fā)起,服務器復制 串口鏈路或其他總線上遠程終端標識 | |
功能碼 | 0x04 | 1 | 功能碼,讀寄存器 | 參考標準modbus協(xié)議 |
數(shù)據(jù) | 0x007D | 2 | 起始地址 | |
0x 007D | 2 | 寄存器數(shù)量 | ||
校驗 |
(2)、數(shù)據(jù)請求回復
97 76 00 00 00 FD 04 04 FA AB 9E 41 18 7A E1 3F 94 7A E1 3F 94 0A 3D 3F 97 51 EC 3F 98 CC CD C0 6C 33 33 C0 E3 CC CD C0 EC EB 85 41 F1 D7 0A 41 E9 47 AE 41 ED EB 85 41 F1 19 9A 43 D0 E6 66 43 C9 4C CD 43 CF EB 85 41 F3 66 66 42 0F CC CD 41 C2 E6 66 44 0A 1E B8 41 FB A3 D7 42 0C CC CD 41 BC C0 00 44 0A B8 52 41 F6 5C 29 42 0F 47 AE 41 D1 C6 66 44 0A 00 00 00 00 C9 9E FF 7F C9 9E FF 7F C9 9E FF 7F C9 9E FF 7F C9 9E FF 7F C9 9E FF 7F C9 9E FF 7F C9 9E FF 7F C9 9E FF 7F 05 16 00 00 04 11 00 00 05 16 00 00 04 11 00 00 05 16 00 00 04 11 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0A 00 0A 00 0A 00 0A 00 04 00 04 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F | ||||
示例 | 長度 | 說明 | 備注 | |
Map報文頭 | 0x97 | 1 | 事務處理標識符Hi | 客戶機發(fā)起,服務器復制,用于事務處理配對 |
0x96 | 1 | 事務處理標識符Lo | ||
0x0000 | 2 | 協(xié)議標識符號 | 客戶機發(fā)起,服務器復制 Modbus協(xié)議 = 0. | |
0x00FD | 2 | 長度 | 從本字節(jié)下一個到最后
| |
0x04 | 1 | 單元標識符 | 客戶機發(fā)起,服務器復制 串口鏈路或其他總線上遠程終端標識 | |
功能碼 | 0x04 | 1 | 功能碼,讀寄存器 | 參考標準modbus協(xié)議 |
數(shù)據(jù) | 0x FA | 1 | 字節(jié)個數(shù) | |
0x---- | 數(shù)據(jù) | |||
校驗 |
?。?)、寫多個寄存器
97 79 00 00 00 09 04 10 00 00 00 01 02 00 01 | ||||
示例 | 長度 | 說明 | 備注 | |
Map報文頭 | 0x97 | 1 | 事務處理標識符Hi | 客戶機發(fā)起,服務器復制,用于事務處理配對 |
0x79 | 1 | 事務處理標識符Lo | ||
0x0000 | 2 | 協(xié)議標識符號 | 客戶機發(fā)起,服務器復制 Modbus協(xié)議 = 0. | |
0x0009 | 2 | 長度 | 從本字節(jié)下一個到最后
| |
0x04 | 1 | 單元標識符 | 客戶機發(fā)起,服務器復制 串口鏈路或其他總線上遠程終端標識 | |
功能碼 | 0x10 | 1 | 功能碼,讀寄存器 | 參考標準modbus協(xié)議 |
數(shù)據(jù) | 0x0000 | 2 | 起始地址 | |
0x 0001 | 2 | 寫寄存器數(shù)量 | ||
0x 02 | 1 | 寫字節(jié)的個數(shù) | ||
00 01 | 2 | 目標值 | ||
校驗 |
(4)、寫多個寄存器響應
97 79 00 00 00 06 04 10 00 00 00 01 | ||||
示例 | 長度 | 說明 | 備注 | |
Map報文頭 | 0x97 | 1 | 事務處理標識符Hi | 客戶機發(fā)起,服務器復制,用于事務處理配對 |
0x79 | 1 | 事務處理標識符Lo | ||
0x0000 | 2 | 協(xié)議標識符號 | 客戶機發(fā)起,服務器復制 Modbus協(xié)議 = 0. | |
0x0006 | 2 | 長度 | 從本字節(jié)下一個到最后
| |
0x04 | 1 | 單元標識符 | 客戶機發(fā)起,服務器復制 串口鏈路或其他總線上遠程終端標識 | |
功能碼 | 0x10 | 1 | 功能碼,讀寄存器 | 參考標準modbus協(xié)議 |
數(shù)據(jù) | 0x0000 | 2 | 起始地址 | |
0x 0001 | 2 | 寄存器個數(shù) | ||
校驗 |
10、五種量的概念
在工業(yè)自動化控制中,經(jīng)常會遇到開關量,數(shù)字量,模擬量,離散量,脈沖量等各種概念,而人們在實際應用中,對于這些概念又很容易混淆?,F(xiàn)將各種概念羅列如下:
?。?)、開關量
一般指的是觸點的“開”與“關”的狀態(tài),一般在計算機設備中也會用“0”或“1”來表示開關量的狀態(tài)。開關量分為有源開關量信號和無源開關量信號,有源開關量信號指的是“開”與“關”的狀態(tài)是帶電源的信號,專業(yè)叫法為躍階信號,可以理解為脈沖量,一般的都有220VAC,?110VAC,24VDC,12VDC等信號,無源開關量信號指的是“開”和“關”的狀態(tài)時不帶電源的信號,一般又稱之為干接點。電阻測試法為電阻0或無窮大。
(2)、數(shù)字量
很多人會將數(shù)字量與開關量混淆,也將其與模擬量混淆。數(shù)字量在時間和數(shù)量上都是離散的物理量,其表示的信號則為數(shù)字信號。數(shù)字量是由0和1組成的信號,經(jīng)過編碼形成有規(guī)律的信號,量化后的模擬量就是數(shù)字量。
?。?)、模擬量
模擬量的概念與數(shù)字量相對應,但是經(jīng)過量化之后又可以轉(zhuǎn)化為數(shù)字量。模擬量是在時間和數(shù)量上都是連續(xù)的物理量,其表示的信號則為模擬信號。模擬量在連續(xù)的變化過程中任何一個取值都是一個具體有意義的物理量,如溫度,電壓,電流等。
(4)、離散量
離散量是將模擬量離散化之后得到的物理量。即任何儀器設備對于模擬量都不可能有個完全精確的表示,因為他們都有一個采樣周期,在該采樣周期內(nèi),其物理量的數(shù)值都是不變的,而實際上的模擬量則是變化的。這樣就將模擬量離散化,成為了離散量。
?。?)、脈沖量
脈沖量就是瞬間電壓或電流由某一值躍變到另一值的信號量。在量化后,其變化持續(xù)有規(guī)律就是數(shù)字量,如果其由0變成某一固定值并保持不變,其就是開關量。
綜上所述,模擬量就是在某個過程中時間和數(shù)量連續(xù)變化的物理量,由于在實際的應用中,所有的儀器設備對于外界數(shù)據(jù)的采集都有一個采樣周期,其采集的數(shù)據(jù)只有在下一個采樣周期開始時才有變動,采樣周期內(nèi)其數(shù)值并不隨模擬量的變化而變動。
這樣就將模擬量離散化了,例如:某設備的采樣周期為1秒,其在第五秒的時間采集的溫度為35度,而第六秒的溫度為36度,該設備就只能標稱第五秒時間溫度35度,第六秒時間溫度36度,而第五點五秒的時間其標稱也只是35度,但是其實際的模擬量是35.5度。這樣就將模擬信號離散化。其采集的數(shù)據(jù)就是離散化了,不再是連續(xù)的模擬量信號。
由于計算機只識別0和1兩個信號,即開關量信號,用其來表示數(shù)值都是使用數(shù)字串來表示,由于計算能力的問題,其數(shù)字串不能無限長,即其表達的精度也是有限的,同樣的以溫度為例,由于數(shù)字串限制,其表達溫度的精度只能達到0.1度,小于該單位的數(shù)值則不能被標稱,這樣就必須將離散量進行量化,將其變?yōu)閿?shù)字量。即35.68度的溫度則表示為35.6度。
這種方式的主要優(yōu)點是字符發(fā)送的時間間隔可達到1秒而不產(chǎn)生錯誤。