modbus通訊協議詳解

、Modbus 協議簡介  

  Modbus協議是一種已廣泛應用於當今工業控制領域的通用通訊協議。通過此協議,控制器相互之間、或控制器經由網絡(如以太網)可以和其它設備之間進行通信。Modbus協議使用的是主從通訊技術,即由主設備主動查詢和操作從設備。一般將主控設備方所使用的協議稱爲Modbus Master,從設備方使用的協議稱爲Modbus Slave。典型的主設備包括工控機和工業控制器等;典型的從設備如PLC可編程控制器等。Modbus通訊物理接口可以選用串口(包括RS232、RS485和RS422),也可以選擇以太網口。其通信遵循以下的過程:

  ● 主設備向從設備發送請求

  ● 從設備分析並處理主設備的請求,然後向主設備發送結果

  ● 如果出現任何差錯,從設備將返回一個異常功能碼 

  此協議定義了一個控制器能認識使用的消息結構,而不管它們是經過何種網絡進行通信的。它描述了一控制器請求訪問其它設備的過程,如果迴應來自其它設備的請求,以及怎樣偵測錯誤並記錄。它制定了消息域格局和內容的公共格式。 

    當在一Modbus網絡上通信時,此協議決定了每個控制器須要知道它們的設備地址,識別按地址發來的消息,決定要產生何種行動。如果需要回應,控制器將生成反饋信息並用Modbus協議發出。在其它網絡上,包含了Modbus協議的消息轉換爲在此網絡上使用的幀或包結構。這種轉換也擴展了根據具體的網絡解決節地址、路由路徑及錯誤檢測的方法。

  Modbus的工作方式是請求/應答,每次通訊都是主站先發送指令,可以是廣播,或是向特定從站的單播,從站響應指令,並按要求應答,或者報告異常。當主站不發送請求時,從站不會自己發出數據,從站和從站之間不能直接通訊。

  ModBus協議是應用層報文傳輸協議(OSI模型第7層),它定義了一個與通信層無關的協議數據單元(PDU),即PDU=功能碼+數據域,功能碼1byte,數據域不確定。

  ModBus協議能夠應用在不同類型的總線或網絡。對應不同的總線或網絡,Modbus協議引入一些附加域映射成應用數據單元(ADU),即ADU=附加域+PDU,例如modbus tcp/ip ADU=MBAP+ADU。

二、Modbus 通訊方式 

  1、Modbus三種通訊方式

  Modbus有下列三種通信方式:

  (1)、以太網:對應的通信模式是MODBUS TCP/IP。

  (2)、異步串行傳輸(各種介質如有線RS-232-/422/485/;光纖、無線等):對應的通信模式是MODBUS RTU或MODBUS ASCII。

  (3)、高速令牌傳遞網絡:對應的通信模式是Modbus PLUS

  Modbus RTU和Modbus ASCII協議應用於串口鏈接(RS232、RS485、RS422),Modbus tcp/ip協議應用於以太網鏈接。

  2、在Modbus網絡上傳輸

     標準的Modbus口是使用RS-232C兼容串行接口,它定義了連接口的針腳、電纜、信號位、傳輸波特率、奇偶校驗。控制器能直接或經由Modem組網。 

     控制器通信使用主—從技術,即僅一設備(主設備)能初始化傳輸(查詢)。其它設備(從設備)根據主設備查詢提供的數據作出相應反應。

       典型的主設備:主機和可編程儀表。

       典型的從設備:可編程控制器。 

    主設備可單獨和從設備通信,也能以廣播方式和所有從設備通信。如果單獨通信,從設備返回一消息作爲迴應,如果是以廣播方式查詢的,則不作任何迴應。Modbus協議建立了主設備查詢的格式:設備(或廣播)地址、功能代碼、所有要發送的數據、一錯誤檢測域。 

    從設備迴應消息也由Modbus協議構成,包括確認要行動的域、任何要返回的數據、和一錯誤檢測域。如果在消息接收過程中發生一錯誤,或從設備不能執行其命令,從設備將建立一錯誤消息並把它作爲迴應發送出去。

  3、在其它類型網絡上轉輸

    在其它網絡上,控制器使用對等技術通信,故任何控制都能初始和其它控制器的通信。這樣在單獨的通信過程中,控制器既可作爲主設備也可作爲從設備。提供的多個內部通道可允許同時發生的傳輸進程。 

    在消息位,Modbus協議仍提供了主—從原則,儘管網絡通信方法是“對等”。如果一控制器發送一消息,它只是作爲主設備,並期望從從設備得到迴應。同樣,當控制器接收到一消息,它將建立一從設備迴應格式並返回給發送的控制器。

  4、查詢---迴應

  (1)、查詢

    查詢消息中的功能代碼告之被選中的從設備要執行何種功能。數據段包含了從設備要執行功能的任何附加信息。例如功能代碼03是要求從設備讀保持寄存器並返回它們的內容。數據段必須包含要告之從設備的信息:從何寄存器開始讀及要讀的寄存器數量。錯誤檢測域爲從設備提供了一種驗證消息內容是否正確的方法。

  (2)、迴應

     如果從設備產生一正常的迴應,在迴應消息中的功能代碼是在查詢消息中的功能代碼的迴應。數據段包括了從設備收集的數據:象寄存器值或狀態。如果有錯誤發生,功能代碼將被修改以用於指出迴應消息是錯誤的,同時數據段包含了描述此錯誤信息的代碼。錯誤檢測域允許主設備確認消息內容是否可用。

 三、三種通訊方式的報文格式

  Modbus協議的報文(或幀)的基本格式是:

    表頭 + 功能碼 + 數據區 + 校驗碼

  功能碼和數據區在不同類型的網絡都是固定不變的,表頭和校驗碼則因網絡底層的實現方式不同而有所區別。表頭包含了從站的地址,功能碼告訴從站要執行何種功能,數據區是具體的信息。

  對於不同類型的網絡,Modbus的第7層實現是一樣的,區別在於下層的實現方式,常見的有TCP/IP和串行通訊兩種。

  Modbus TCP基於以太網和TCP/IP協議,Modbus RTU和Modbus ASCII則是使用異步串行傳輸(通常是RS-232/422/485)。

  1、以太網(modbus  tcp/ip)

  對於Modbus TCP而言,主站通常稱爲Client,從站稱爲Server;而對於Modbus RTU和Modbus ASCII來說,主站是Master,從站是Slave。

  ModbusTCP的數據幀可分爲兩部分:ADU=MBAP+PDU = MBAP + 功能碼 + 數據域,MBAP 7byte,功能碼1byte,數據域不確定,由具體功能決定

  MBAP爲報文頭,長度爲7字節,組成如下:

事務處理標識 協議標識 長度 單元標識符
2byte 2byte 2byte 1byte

 

內容 解釋
事務處理標識 可以理解爲報文的序列號,一般每次通信之後就要加1以區別不同的通信數據報文。
協議標識符 00 00表示ModbusTCP協議。
長度 表示接下來的數據長度,單位爲字節。
單元標識符 可以理解爲設備地址。

   如圖所示,串行傳輸的物理層是RS-485或RS-232,數據鏈路層是Modbus的串行傳輸協議;Modbus TCP的1、2、3、4層實現和日常所見的以太網、因特網一樣。Modbus默認採用的TCP端口號是502。

 

 

 

 

 

 

 

 

 

 

  下圖說明了Modbus TCP的改動:

  (1)、取消了校驗位。數據鏈路層上就進行了CRC-32的校驗,TCP/IP是面向連接的可靠性的協議,因此沒必要再加上校驗位。

  (2)、Slave地址換成了Unit Identifier。當網絡裏的設備全是使用TCP/IP,這個地址是沒有意義的,因爲IP就能進行路由尋址。如果網絡裏還有串行通訊的設備,則需要網關來實現Modbus TCP到Modbus RTU或ASCII之間的協議轉換,這時用Unit Identifier來標識網關後面的每個串行通訊設備。

  (3)、Length是指後面的字節總數。實際上數據區的長度是能確定的,有的功能碼就可以確定數據區的長度,有的功能碼雖不能確定數據區長度,但是數據區有字節計數,參見上文舉的從站應答的例子。表頭增加的Length是爲了應對有些情況下TCP/IP協議會將應用層的數據拆包傳輸。

  (4)、Transaction Identifier和Protocol Identifier由Client生成,Server的響應將複製這些參數。

  1.1、modbus tcp/ip通信方式

  Modbus設備可分爲主站(poll)和從站(slave)。主站只有一個,從站有多個,主站向各從站發送請求幀,從站給予響應。在使用TCP通信時,主站爲client端,主動建立連接;從站爲server端,等待連接。

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

  IANA(Internet Assigned Numbers Authority,互聯網編號分配管理機構)給Modbus協議賦予TCP端口號爲502,這是目前在儀表與自動化行業中唯一分配到的端口號。

  1.2、通信過程

    A、connect 建立TCP連接

    B、準備Modbus報文

    C、使用send命令發送報文

    D、在同一連接下等待應答

    E、使用recv命令讀取報文,完成一次數據交換

    F、通信任務結束時,關閉TCP連接

  2、異步串行傳輸的兩種傳輸方式(modbus RTU和modbus ASCII)

   異步串行傳輸時, 控制器可以設置爲兩種傳輸模式(ASCII或RTU)中的任何一種在標準的Modbus網絡通信。用戶選擇想要的模式,包括串口通信參數(波特率、校驗方式等),在配置每個控制器的時候,在一個Modbus網絡上的所有設備都必須選擇相同的傳輸模式和串口參數。

  ASCII模式:

起始位 設備地址 功能代碼 數據數量 數據 LRC高字節 LRC低字節 結束符
2*8bit 2*8bit n n*8bit 8bit 8bit CR、LF(回車、換行)

 

 

 

  RTU模式:

起始位 設備地址 功能代碼 數據數量 數據 CRC低字節 CRC高字節 結束符
8bit 8bit n n*8bit 8bit 8bit

  

 

 

  2.1、ASCII模式

     當控制器設爲在Modbus網絡上以ASCII(美國標準信息交換代碼)模式通信,在消息中的每個8Bit字節都作爲兩個ASCII字符發送。

  這種方式的主要優點是字符發送的時間間隔可達到1秒而不產生錯誤。

  代碼系統:

  • 十六進制,ASCII字符0...9,A...F
  • 消息中的每個ASCII字符都是一個十六進制字符組成
  • 每個字節的位:1個起始位、7個數據位(最小的有效位先發送)、1個奇偶校驗位(無校驗則無)、1個停止位(有校驗時)、2個Bit(無校驗時)
  • 錯誤檢測域:LRC(縱向冗長檢測)

  2.2、RTU模式

     當控制器設爲在Modbus網絡上以RTU(遠程終端單元)模式通信,在消息中的每個8Bit字節包含兩個4Bit的十六進制字符。這種方式的主要優點是:在同樣的波特率下,可比ASCII方式傳送更多的數據。

  代碼系統:

  • 8位二進制,十六進制數0...9,A...F
  • 消息中的每個8位域都是兩個十六進制字符組成
  • 每個字節的位:1個起始位、8個數據位(最小的有效位先發送)、1個奇偶校驗位(無校驗則無)、1個停止位(有校驗時),2個Bit(無校驗時)
  • 錯誤檢測域:CRC(循環冗長檢測)

  2.3、RTU和ASCII的區別

  (1)、RTU模式下,一個字節的數據,傳輸的就是一個字節。ASCII模式下,同樣一個字節數據用了兩個字節來傳輸。例如,要傳輸數字0x5B,RTU傳輸的是0101 1011(二進制),而ASCII傳輸的是00110101和01000010。可見,ASCII傳輸的速率是RTU的一半。  

  (2)、ASCII模式採用LRC校驗,RTU模式採用16位CRC校驗。

  (3)、ASCII有開始標記和結束標記,RTU沒有

四、Modbus消息幀

     兩種傳輸模式中(ASCII或RTU),傳輸設備以將Modbus消息轉爲有起點和終點的幀,這就允許接收的設備在消息起始處開始工作,讀地址分配信息,判斷哪一個設備被選中(廣播方式則傳給所有設備),判知何時信息已完成。部分的消息也能偵測到並且錯誤能設置爲返回結果。

  1、ASCII幀

   使用ASCII模式,消息以冒號(:)字符(ASCII碼 3AH)開始,以回車換行符結束(ASCII碼 0DH,0AH)。 

   其它域可以使用的傳輸字符是十六進制的0...9,A...F。網絡上的設備不斷偵測“:”字符,當有一個冒號接收到時,每個設備都解碼下個域(地址域)來判斷是否發給自己的。 

   消息中字符間發送的時間間隔最長不能超過1秒,否則接收的設備將認爲傳輸錯誤。一個典型消息幀如下所示:

起始位 設備地址 功能代碼 數據 LRC校驗 結束符
1個字符 2個字符 2個字符 n個字符 2個字符 2個字符

 

   2、RTU幀

    使用RTU模式,消息發送至少要以3.5個字符時間的停頓間隔開始。在網絡波特率下多樣的字符時間,這是最容易實現的(如下圖的T1-T2-T3-T4所示)。傳輸的第一個域是設備地址。可以使用的傳輸字符是十六進制的0...9,A...F。網絡設備不斷偵測網絡總線,包括停頓間隔時間內。當第一個域(地址域)接收到,每個設備都進行解碼以判斷是否發往自己的。在最後一個傳輸字符之後,一個至少3.5個字符時間的停頓標定了消息的結束。一個新的消息可在此停頓後開始。 

    整個消息幀必須作爲一連續的流轉輸。如果在幀完成之前有超過1.5個字符時間的停頓時間,接收設備將刷新不完整的消息並假定下一字節是一個新消息的地址域。同樣地,如果一個新消息在小於3.5個字符時間內接着前個消息開始,接收的設備將認爲它是前一消息的延續。這將導致一個錯誤,因爲在最後的CRC域的值不可能是正確的。一典型的消息幀如下所示:

起始位 設備地址 功能代碼 數據 CRC校驗 結束符
T1-T2-T3-T4 8Bit 8Bit n個8Bit 16Bit T1-T2-T3-T4

 

  3、兩種幀的分析

  (1)、地址域

    消息幀的地址域包含兩個字節(ASCII)或一個字節(RTU)。可能的從設備地址是0...247 (十進制)。單個設備的地址範圍是1...247。主設備通過將要聯絡的從設備的地址放入消息中的地址域來選通從設備。當從設備發送迴應消息時,它把自己的地址放入迴應的地址域中,以便主設備知道是哪一個設備作出迴應。 

    地址0是用作廣播地址,以使所有的從設備都能認識。當Modbus協議用於更高水準的網絡,廣播可能不允許或以其它方式代替。

  (2)、如何處理功能域

    消息幀中的功能代碼域包含了兩個字節(ASCII)或一個字節(RTU)。可能的代碼範圍是十進制的1...255。當然,有些代碼是適用於所有控制器,有此是應用於某種控制器,還有些保留以備後用。 

    當消息從主設備發往從設備時,功能代碼域將告之從設備需要執行哪些行爲。例如去讀取輸入的開關狀態,讀一組寄存器的數據內容,讀從設備的診斷狀態,允許調入、記錄、校驗在從設備中的程序等。 

    當從設備迴應時,它使用功能代碼域來指示是正常回應(無誤)還是有某種錯誤發生(稱作異議迴應)。對正常回應,從設備僅迴應相應的功能代碼。對異議迴應,從設備返回一等同於正常代碼的代碼,但最重要的位置爲邏輯1。

    例如:一從主設備發往從設備的消息要求讀一組保持寄存器,將產生如下功能代碼:0 0 0 0 0 0 1 1 (十六進制03H)

    對正常回應,從設備僅迴應同樣的功能代碼。對異議迴應,它返回:1 0 0 0 0 0 1 1 (十六進制83H)

    除功能代碼因異議錯誤作了修改外,從設備將一獨特的代碼放到迴應消息的數據域中,這能告訴主設備發生了什麼錯誤。

    主設備應用程序得到異議的迴應後,典型的處理過程是重發消息,或者診斷髮給從設備的消息並報告給操作員。

  (3)、數據域

     數據域是由兩個十六進制數集合構成的,範圍00...FF。根據網絡傳輸模式,這可以是由一對ASCII字符組成或由一RTU字符組成。

     從主設備發給從設備消息的數據域包含附加的信息:從設備必須用於進行執行由功能代碼所定義的所爲。這包括了象不連續的寄存器地址,要處理項的數目,域中實際數據字節數。

     例如,如果主設備需要從設備讀取一組保持寄存器(功能代碼03),數據域指定了起始寄存器以及要讀的寄存器數量。如果主設備寫一組從設備的寄存器(功能代碼10十六進制),數據域則指明瞭要寫的起始寄存器以及要寫的寄存器數量,數據域的數據字節數,要寫入寄存器的數據。

     如果沒有錯誤發生,從從設備返回的數據域包含請求的數據。如果有錯誤發生,此域包含一異議代碼,主設備應用程序可以用來判斷採取下一步行動。

     在某種消息中數據域可以是不存在的(0長度)。例如,主設備要求從設備迴應通信事件記錄(功能代碼0B十六進制),從設備不需任何附加的信息。

   (4)、錯誤檢測域

    標準的Modbus網絡有兩種錯誤檢測方法。錯誤檢測域的內容視所選的檢測方法而定。

  ASCII:當選用ASCII模式作字符幀,錯誤檢測域包含兩個ASCII字符。這是使用LRC(縱向冗長檢測)方法對消息內容計算得出的,不包括開始的冒號符及回車換行符。LRC字符附加在回車換行符前面。

  RTU: 當選用RTU模式作字符幀,錯誤檢測域包含一16Bits值(用兩個8位的字符來實現)。錯誤檢測域的內容是通過對消息內容進行循環冗長檢測方法得出的。CRC域附加在消息的最後,添加時先是低字節然後是高字節。故CRC的高位字節是發送消息的最後一個字節。

  (5)、字符的連續傳輸

     當消息在標準的Modbus系列網絡傳輸時,每個字符或字節以如下方式發送(從左到右):

     最低有效位...最高有效位

     使用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 停止位 停止位

 五、錯誤檢測方法

    標準的Modbus串行網絡採用兩種錯誤檢測方法。奇偶校驗對每個字符都可用,幀檢測(LRC或CRC)應用於整個消息。它們都是在消息發送前由主設備產生的,從設備在接收過程中檢測每個字符和整個消息幀。

    用戶要給主設備配置一預先定義的超時時間間隔,這個時間間隔要足夠長,以使任何從設備都能作爲正常反應。如果從設備測到一傳輸錯誤,消息將不會接收,也不會向主設備作出迴應。這樣超時事件將觸發主設備來處理錯誤。發往不存在的從設備的地址也會產生超時。 

  1、奇偶校驗

    用戶可以配置控制器是奇或偶校驗,或無校驗。這將決定了每個字符中的奇偶校驗位是如何設置的。

    如果指定了奇或偶校驗,“1”的位數將算到每個字符的位數中(ASCII模式7個數據位,RTU中8個數據位)。例如RTU字符幀中包含以下8個數據位:1 1 0 0 0 1 0 1

    整個“1”的數目是4個。如果便用了偶校驗,幀的奇偶校驗位將是0,便得整個“1”的個數仍是4個。如果便用了奇校驗,幀的奇偶校驗位將是1,便得整個“1”的個數是5個。

    如果沒有指定奇偶校驗位,傳輸時就沒有校驗位,也不進行校驗檢測。代替一附加的停止位填充至要傳輸的字符幀中。

  2、LRC檢測 

   使用ASCII模式,消息包括了一基於LRC方法的錯誤檢測域。LRC域檢測了消息域中除開始的冒號及結束的回車換行號外的內容。

    LRC域是一個包含一個8位二進制值的字節。LRC值由傳輸設備來計算並放到消息幀中,接收設備在接收消息的過程中計算LRC,並將它和接收到消息中LRC域中的值比較,如果兩值不等,說明有錯誤。

    LRC方法是將消息中的8Bit的字節連續累加,丟棄了進位。

    LRC簡單函數如下:

複製代碼

 1 ///C代碼
 2 static unsigned char LRC(auchMsg,usDataLen)
 3 
 4 unsigned char *auchMsg ; /* 要進行計算的消息 */
 5 unsigned short usDataLen ; /* LRC 要處理的字節的數量*/
 6 
 7 { 
 8   unsigned char uchLRC = 0 ; /* LRC 字節初始化 */
 9   while (usDataLen--) /* 傳送消息 */
10   uchLRC += *auchMsg++ ; /* 累加*/
11 
12   return ((unsigned char)(-((char_uchLRC))) ;
13 }

複製代碼

  3、CRC檢測

     使用RTU模式,消息包括了一基於CRC方法的錯誤檢測域。CRC域檢測了整個消息的內容。

     CRC域是兩個字節,包含一16位的二進制值。它由傳輸設備計算後加入到消息中。接收設備重新計算收到消息的CRC,並與接收到的CRC域中的值比較,如果兩值不同,則有誤。

     CRC是先調入一值是全“1”的16位寄存器,然後調用一過程將消息中連續的8位字節各當前寄存器中的值進行處理。僅每個字符中的8Bit數據對CRC有效,起始位和停止位以及奇偶校驗位均無效。

     CRC產生過程中,每個8位字符都單獨和寄存器內容相或(OR),結果向最低有效位方向移動,最高有效位以0填充。LSB被提取出來檢測,如果LSB爲1,寄存器單獨和預置的值或一下,如果LSB爲0,則不進行。整個過程要重複8次。在最後一位(第8位)完成後,下一個8位字節又單獨和寄存器的當前值相或。最終寄存器中的值,是消息中所有的字節都執行之後的CRC值。

    CRC添加到消息中時,低字節先加入,然後高字節。  

  計算CRC碼的步驟爲:

  • 預置16位寄存器爲十六進制FFFF(即全爲1)。稱此寄存器爲CRC寄存器;
  • 把第一個8位數據與16位CRC寄存器的低位相異或,把結果放於CRC寄存器;
  • 把寄存器的內容右移一位(朝低位),用0填補最高位,檢查最低位;
  • 如果最低位爲0:重複第3步(再次移位); 如果最低位爲1:CRC寄存器與多項式A001(1010 0000 0000 0001)進行異或;
  • 重複步驟3和4,直到右移8次,這樣整個8位數據全部進行了處理;
  • 重複步驟2到步驟5,進行下一個8位數據的處理;
  • 最後得到的CRC寄存器即爲CRC碼。

複製代碼

 1 /**
 2   * @brief modbus rtu校驗
 3   * @param p_data:要校驗的數據的地址
 4   *        data_len:要校驗數據的長度(字節)
 5   *        data_crc:數據的校驗碼
 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 高位字節值表 */
 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, 0x40
30 } ;
31 
32 /* CRC低位字節值表*/
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, 0x40
61 } ;

複製代碼

 CRC冗餘碼在線計算網址: http://www.ip33.com/crc.html

六、Modbus的四種數據類型

  線圈:大小隻有1位,ON或OFF,可讀可寫,既可以是一個輸出量輸出點,也可以是數字量輸入點,有效的地址範圍是1-9999。

  輸入離散量:大小隻有1位,ON或OFF,只讀,即數字量輸出點,有效地址範圍是10001-19999。

  輸入寄存器:16位的寄存器,只讀,可以用作模擬量或16位打包輸入點,有效地址範圍是30001-39999。

  保持寄存器:16位的寄存器,可讀可寫,既可以是一個模擬量或16位打包輸入點,也可以是模擬量或16位打包輸出點,有效地址範圍是40001-49999。

  在PLC或DCS上用點名標記不同的變量,在Modbus則以數據地址來標記每個點。以上所說的地址都是參考地址,而不是實際的物理地址。上述的地址是在設備中的地址,按照PLC的習慣從1開始遞增,而Modbus報文中是從0開始遞增。例如地址偏移爲4、5、6的Holding Register,其實是指參考地址是40005、40006、40007的寄存器。

七、modbus協議的功能碼

地址碼 功能碼 數據區 錯誤校驗碼
8bit 8bit n*8bit 2*8bit

 

 

 

Modbus的操作對象有四種:線圈、離散輸入、輸入寄存器、保持寄存器。

對象 含義
線圈 PLC的輸出位,開關量,在Modbus中可讀可寫
離散量 PLC的輸入位,開關量,在Modbus中只讀
輸入寄存器 PLC中只能從模擬量輸入端改變的寄存器,在Modbus中只讀
保持寄存器 PLC中用於輸出模擬量信號的寄存器,在Modbus中可讀可寫

根據對象的不同,Modbus的功能碼有:

功能碼 名稱 功能
01 讀線圈狀態 讀位(讀N個bit)---讀從機線圈寄存器,位操作
02 讀輸入離散量 讀位(讀N個bit)---讀離散輸入寄存器,位操作
03 讀多個寄存器 讀整型、字符型、狀態字、浮點型(讀N個words)---讀保持寄存器,字節操作
04 讀輸入寄存器 讀整型、狀態字、浮點型(讀N個words)---讀輸入寄存器,字節操作
05 寫單個線圈 寫位(寫一個bit)---寫線圈寄存器,位操作
06 寫單個保持寄存器 寫整型、字符型、狀態字、浮點型(寫一個word)---寫保持寄存器,字節操作
07 讀取異常狀態

取得8個內部線圈的通斷狀態,這8個線圈的地址由控制器決定,用戶邏輯可以將這些線圈定義,以說明從機狀態,短報文適宜於迅速讀取狀態

08 回送診斷校驗 把診斷校驗報文送從機,以對通信處理進行評鑑
09 編程(只用於484) 使主機模擬編程器作用,修改PC從機邏輯
0A 控詢(只用於484)

可使主機與一臺正在執行長程序任務從機通信,探詢該從機是否已完成其操作任務,僅在含有功能碼9的報文發送後,本功能碼才發送

0B 讀取事件計數 可使主機發出單詢問,並隨即判定操作是否成功,尤其是該命令或其他應答產生通信錯誤時
0C 讀取通訊事件記錄 可是主機檢索每臺從機的ModBus事務處理通信事件記錄。如果某項事務處理完成,記錄會給出有關錯誤
0D 編程(184/384/484/584) 可使主機模擬編程器功能修改PC從機邏輯
0E 探詢(184/384/484/584)

可使主機與正在執行任務的從機通信,定期控詢該從機是否已完成其程序操作,僅在含有功能13的報文發送後,本功能碼才得發送

0F 寫多個線圈 可以寫多個線圈---強置一串連續邏輯線圈的通斷
10 寫多個保持寄存器 寫多個保持寄存器---把具體的二進制值裝入一串連續的保持寄存器
11 報告從機標識 可使主機判斷編址從機的類型及該從機運行指示燈的狀態
12 (884和MICRO84) 可使主機模擬編程功能,修改PC狀態邏輯
13 重置通信鏈路 發生非可修改錯誤後,是從機復位於已知狀態,可重置順序字節
14 讀取通用參數(584L) 顯示擴展存儲文件中的數據信息
15 寫入通用參數(584L) 把通用參數寫入擴展存儲文件
16~40 保留做擴展功能備用  
41~48 保留以備用戶功能所用 留作用戶功能的擴展編碼
49~77 非法功能  
78~7F 保留 留作內部作用
80~FF 保留 用於異常應答

 

常用功能碼如下:

功能碼 名稱 功能 對應的地址類型
01 讀線圈狀態 讀位(讀N個bit)---讀從機線圈寄存器,位操作 0x
02 讀輸入離散量 讀位(讀N個bit)---讀離散輸入寄存器,位操作 1x
03 讀多個寄存器 讀整型、字符型、狀態字、浮點型(讀N個words)---讀保持寄存器,字節操作 4X
04 讀輸入寄存器 讀整型、狀態字、浮點型(讀N個words)---讀輸入寄存器,字節操作 3x
05 寫單個線圈 寫位(寫一個bit)---寫線圈寄存器,位操作 0x
06 寫單個保持寄存器 寫整型、字符型、狀態字、浮點型(寫一個word)---寫保持寄存器,字節操作 4x
0F 寫多個線圈 寫位(寫n個bit)---強置一串連續邏輯線圈的通斷 0x
10 寫多個保持寄存器 寫整形、字符型、狀態字、浮點型(寫n個word)---把具體的二進制值裝入一串連續的保持寄存器 4x

 

八、PDU詳細結構

  1、0x01:讀線圈

  在從站中讀1~2000個連續線圈狀態,ON=1,OFF=0

  • 請求:MBAP 功能碼 起始地址H 起始地址L 數量H 數量L(共12字節)
  • 響應:MBAP 功能碼 數據長度 數據(一個地址的數據爲1位)
  • 如:在從站0x01中,讀取開始地址爲0x0002的線圈數據,讀0x0008位
    00 01 00 00 00 06 01 01 00 02 00 08
  • 回:數據長度爲0x01個字節,數據爲0x01,第一個線圈爲ON,其餘爲OFF
    00 01 00 00 00 04 01 01 01 01

  2、0x05:寫單個線圈

  將從站中的一個輸出寫成ON或OFF,0xFF00請求輸出爲ON,0x000請求輸出爲OFF

  • 請求:MBAP 功能碼 輸出地址H 輸出地址L 輸出值H 輸出值L(共12字節)
  • 響應:MBAP 功能碼 輸出地址H 輸出地址L 輸出值H 輸出值L(共12字節)
  • 如:將地址爲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,數據域中置1的位請求相應輸出位ON,置0的位請求響應輸出爲OFF

  • 請求:MBAP 功能碼 起始地址H 起始地址L 輸出數量H 輸出數量L 字節長度 輸出值H 輸出值L
  • 響應:MBAP 功能碼 起始地址H 起始地址L 輸出數量H 輸出數量L

  4、0x02:讀離散量輸入

  從一個從站中讀1~2000個連續的離散量輸入狀態

  • 請求:MBAP 功能碼 起始地址H 起始地址L 數量H 數量L(共12字節)
  • 響應:MBAP 功能碼 數據長度 數據(長度:9+ceil(數量/8))
  • 如:從地址0x0000開始讀0x0012個離散量輸入
    00 01 00 00 00 06 01 02 00 00 00 12
  • 回:數據長度爲0x03個字節,數據爲0x01 04 00,表示第一個離散量輸入和第11個離散量輸入爲ON,其餘爲OFF
    00 01 00 00 00 06 01 02 03 01 04 00

  5、0x04:讀輸入寄存器

  從一個遠程設備中讀1~2000個連續輸入寄存器

  • 請求:MBAP 功能碼 起始地址H 起始地址L 寄存器數量H 寄存器數量L(共12字節)
  • 響應:MBAP 功能碼 數據長度 寄存器數據(長度:9+寄存器數量×2)
  • 如:讀起始地址爲0x0002,數量爲0x0005的寄存器數據
    00 01 00 00 00 06 01 04 00 02 00 05
  • 回:數據長度爲0x0A,第一個寄存器的數據爲0x0c,其餘爲0x00
    00 01 00 00 00 0D 01 04 0A 00 0C 00 00 00 00 00 00 00 00

  6、0x03:讀保持寄存器

  從遠程設備中讀保持寄存器連續塊的內容

  • 請求:MBAP 功能碼 起始地址H 起始地址L 寄存器數量H 寄存器數量L(共12字節)
  • 響應:MBAP 功能碼 數據長度 寄存器數據(長度:9+寄存器數量×2)
  • 如:起始地址是0x0000,寄存器數量是 0x0003
    00 01 00 00 00 06 01 03 00 00 00 03
  • 回:數據長度爲0x06,第一個寄存器的數據爲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字節)
  • 響應:MBAP 功能碼 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字節)
  • 如:向地址是0x0000的寄存器寫入數據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

  8、0x10:寫多個保持寄存器

  在一個遠程設備中寫連續寄存器塊(1~123個寄存器)

  • 請求:MBAP 功能碼 起始地址H 起始地址L 寄存器數量H 寄存器數量L 字節長度 寄存器值(13+寄存器數量×2)
  • 響應:MBAP 功能碼 起始地址H 起始地址L 寄存器數量H 寄存器數量L(共12字節)
  • 如:向起始地址爲0x0000,數量爲0x0001的寄存器寫入數據,數據長度爲0x02,數據爲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

九、數據解析

  ModBus  TCP/IP與串行鏈路Modbus的數據域是一致的,具體數據域可以參考串行modbus。這裏給出幾個ModbusTcp的鏈路解析說明,輔助新人分析報文。

  1、數據請求

97 76 00 00 00 06 04  04 00 7D 00 7D

 

示例

長度

說明

備註

Map報文頭

0x97

1

事務處理標識符Hi

客戶機發起,服務器複製,用於事務處理配對

0x96

1

事務處理標識符Lo

0x0000

2

協議標識符號

客戶機發起,服務器複製

Modbus協議 = 0.

0x0006

2

長度

從本字節下一個到最後

 

0x04

1

單元標識符

客戶機發起,服務器複製

串口鏈路或其他總線上遠程終端標識

功能碼

0x04

1

功能碼,讀寄存器

參考標準modbus協議

數據

0x007D

2

起始地址

 

0x 007D

2

寄存器數量

 

校驗

 

  2、數據請求回覆

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

客戶機發起,服務器複製,用於事務處理配對

0x96

1

事務處理標識符Lo

0x0000

2

協議標識符號

客戶機發起,服務器複製

Modbus協議 = 0.

0x00FD

2

長度

從本字節下一個到最後

 

0x04

1

單元標識符

客戶機發起,服務器複製

串口鏈路或其他總線上遠程終端標識

功能碼

0x04

1

功能碼,讀寄存器

參考標準modbus協議

數據

0x FA

1

字節個數

 

0x----

 

數據

校驗

 

  3、寫多個寄存器

97 79 00 00 00 09 04 10 00 00 00 01 02 00 01

 

示例

長度

說明

備註

Map報文頭

0x97

1

事務處理標識符Hi

客戶機發起,服務器複製,用於事務處理配對

0x79

1

事務處理標識符Lo

0x0000

2

協議標識符號

客戶機發起,服務器複製

Modbus協議 = 0.

0x0009

2

長度

從本字節下一個到最後

 

0x04

1

單元標識符

客戶機發起,服務器複製

串口鏈路或其他總線上遠程終端標識

功能碼

0x10

1

功能碼,讀寄存器

參考標準modbus協議

數據

0x0000

2

起始地址

 

0x 0001

2

寫寄存器數量

 

0x 02

1

寫字節的個數

 

00 01

2

目標值

 

校驗

 

  4、寫多個寄存器響應

97 79 00 00 00 06 04 10 00 00 00 01

 

示例

長度

說明

備註

Map報文頭

0x97

1

事務處理標識符Hi

客戶機發起,服務器複製,用於事務處理配對

0x79

1

事務處理標識符Lo

0x0000

2

協議標識符號

客戶機發起,服務器複製

Modbus協議 = 0.

0x0006

2

長度

從本字節下一個到最後

 

0x04

1

單元標識符

客戶機發起,服務器複製

串口鏈路或其他總線上遠程終端標識

功能碼

0x10

1

功能碼,讀寄存器

參考標準modbus協議

數據

0x0000

2

起始地址

 

0x 0001

2

寄存器個數

 

校驗

 

 十、五種量的概念

  在工業自動化控制中,經常會遇到開關量,數字量,模擬量,離散量,脈衝量等各種概念,而人們在實際應用中,對於這些概念又很容易混淆。現將各種概念羅列如下:

  1、開關量

  一般指的是觸點的“開”與“關”的狀態,一般在計算機設備中也會用“0”或“1”來表示開關量的狀態。開關量分爲有源開關量信號和無源開關量信號,有源開關量信號指的是“開”與“關”的狀態是帶電源的信號,專業叫法爲躍階信號,可以理解爲脈衝量,一般的都有220VAC, 110VAC,24VDC,12VDC等信號,無源開關量信號指的是“開”和“關”的狀態時不帶電源的信號,一般又稱之爲幹接點。電阻測試法爲電阻0或無窮大。

  2、數字量

  很多人會將數字量與開關量混淆,也將其與模擬量混淆。數字量在時間和數量上都是離散的物理量,其表示的信號則爲數字信號。數字量是由0和1組成的信號,經過編碼形成有規律的信號,量化後的模擬量就是數字量。

  3、模擬量

  模擬量的概念與數字量相對應,但是經過量化之後又可以轉化爲數字量。模擬量是在時間和數量上都是連續的物理量,其表示的信號則爲模擬信號。模擬量在連續的變化過程中任何一個取值都是一個具體有意義的物理量,如溫度,電壓,電流等。

  4、離散量

  離散量是將模擬量離散化之後得到的物理量。即任何儀器設備對於模擬量都不可能有個完全精確的表示,因爲他們都有一個採樣週期,在該採樣週期內,其物理量的數值都是不變的,而實際上的模擬量則是變化的。這樣就將模擬量離散化,成爲了離散量。

  5、脈衝量

  脈衝量就是瞬間電壓或電流由某一值躍變到另一值的信號量。在量化後,其變化持續有規律就是數字量,如果其由0變成某一固定值並保持不變,其就是開關量。

  綜上所述,模擬量就是在某個過程中時間和數量連續變化的物理量,由於在實際的應用中,所有的儀器設備對於外界數據的採集都有一個採樣週期,其採集的數據只有在下一個採樣週期開始時纔有變動,採樣週期內其數值並不隨模擬量的變化而變動。
這樣就將模擬量離散化了,例如:某設備的採樣週期爲1秒,其在第五秒的時間採集的溫度爲35度,而第六秒的溫度爲36度,該設備就只能標稱第五秒時間溫度35度,第六秒時間溫度36度,而第五點五秒的時間其標稱也只是35度,但是其實際的模擬量是35.5度。這樣就將模擬信號離散化。其採集的數據就是離散化了,不再是連續的模擬量信號。
由於計算機只識別0和1兩個信號,即開關量信號,用其來表示數值都是使用數字串來表示,由於計算能力的問題,其數字串不能無限長,即其表達的精度也是有限的,同樣的以溫度爲例,由於數字串限制,其表達溫度的精度只能達到0.1度,小於該單位的數值則不能被標稱,這樣就必須將離散量進行量化,將其變爲數字量。即35.68度的溫度則表示爲35.6度。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章