Modbus協議和應用開發介紹

因業務須要了解Modbus協議的使用,所以對Modbus的協議,以及相應的C#處理應用進行了解,針對協議的幾種方式(RTU、ASCII、TCPIP)進行了封裝,以及對Modbus的各類功能碼的特色進行了詳細的瞭解,本篇隨筆基於這些知識進行了必定的梳理和介紹,主要內容包括Modbus協議簡要介紹、Modbus模擬工具使用和Modbus應用開發幾個部分。數據庫

1)Modbus協議簡要介紹

Modbus 協議是應用於電子控制器上的一種通用語言。經過此協議,控制器相互之間、控制器經由網絡(例如以太網)和其它設備之間能夠通訊。它已經成爲一通用工業標準。有了它,不一樣廠商生產的控制設備能夠連成工業網絡,進行集中監控。服務器

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

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

Modbus由MODICON公司於1979年開發,是一種工業現場總線協議標準。1996年施耐德公司推出基於以太網TCP/IP的modbus協議:modbusTCP。函數

Modbus協議是一項應用層報文傳輸協議,包括ASCII、RTU、TCP三種報文類型。工具

標準的Modbus協議物理層接口有RS23二、RS42二、RS485和以太網接口,採用master/slave方式通訊。學習

對於串行鏈接,存在兩個變種,它們在數值數據表示不一樣和協議細節上略有不一樣。Modbus RTU是一種緊湊的,採用二進制表示數據的方式,Modbus ASCII是一種人類可讀的,冗長的表示方式。這兩個變種都使用串行通訊(serial communication)方式。RTU格式後續的命令/數據帶有循環冗餘校驗的校驗和,而ASCII格式採用縱向冗餘校驗的校驗和。被配置爲RTU變種的節點不會和設置爲ASCII變種的節點通訊,反之亦然。
對於經過TCP/IP(例如以太網)的鏈接,存在多個Modbus/TCP變種,這種方式不須要校驗和計算。
對於全部的這三種通訊協議在數據模型和功能調用上都是相同的,只有封裝方式是不一樣的。
Modbus有一個擴展版本Modbus Plus(Modbus+或者MB+),不過此協議是Modicon專有的,和Modbus不一樣。它須要一個專門的協處理器來處理相似HDLC的高速令牌旋轉。它使用1Mbit/s的雙絞線,而且每一個節點都有轉換隔離裝置,是一種採用轉換/邊緣觸發而不是電壓/水平觸發的裝置。鏈接Modbus Plus到計算機須要特別的接口,一般是支持ISA(SA85),PCI或者PMCIA總線的板卡。測試

MODBUS 協議定義了一個與基礎通訊層無關的簡單協議數據單元(PDU)。this

Modbus串行連路上的的PDU以下所示。spa

錯誤檢驗域是對報文內容執行"冗餘校驗" 的計算結果。根據不一樣的傳輸模式(RTU or ASCII) 使用兩種不一樣的計算方法。

RTU的報文格式以下所示。

ASCII碼的報文格式以下所示。

 

 在 ASCII 模式, 報文用特殊的字符區分幀起始和幀結束。一個報文必須以一個‘冒號’ ( : ) (ASCII 十六進制3A )起始,以‘回車-換行’ (CR LF) 對(ASCII 十六進制0D 和0A) 結束。

 

而Modbus TCP數據幀包含報文頭、功能代碼和數據3部分。

MBAP Header長度共7個字節,分別爲Transaction identifier(事務標識符),Protocol identifier(協議標識符),Length(長度),

 Unitidentifier(單元標識符)組成,具體以下表所示:

請求和響應帶有六個字節的前綴,以下:
      byte 0:     事務處理標識符 –由服務器複製 –一般爲 0
      byte 1:     事務處理標識符 –由服務器複製 –一般爲 0
      byte 2:     協議標識符= 0
      byte 3:     協議標識符= 0
      byte 4:     長度字段 (上半部分字節) = 0 (全部的消息長度小於256)
      byte 5:     長度字段  (下半部分字節)   = 後面字節的數量
      byte 6:     單元標識符 (原「從站地址」)
      byte 7:     MODBUS 功能代碼
      byte 8 on:   所需的數據

數據區:數據區是根據不一樣的功能碼而不一樣。數據區能夠是實際數值、設置點、主機發送給從機或從機發送給主機的地址。

標準的Modicon控制器使用RS232C實現串行的Modbus。Modbus的ASCII、RTU協議規定了消息、數據的結構、命令和就答的方式,數據通信採用Maser/Slave方式。 
Modbus協議須要對數據進行校驗,串行協議中除有奇偶校驗外,ASCII模式採用LRC校驗,RTU模式採用16位CRC校驗.
ModbusTCP模式沒有額外規定校驗,由於TCP協議是一個面向鏈接的可靠協議。

對於常規的Modbus串口協議,咱們來看看03功能碼的讀取寄存器的操做請求和響應代碼瞭解下。

請求PDU格式以下所示。

 響應的PDU格式以下所示。

 一個請求讀寄存器108-110 的實例:

能夠注意到,不少數據的處理,須要拆分高位低位,高位在前,低位在後的模式。 

根據這些RTU、ASCII、TCPIP的Modbus協議的不一樣,咱們能夠構建一個通用的處理程序來處理這些操做,在後面的應用開發部分繼續介紹。

 

2)Modbus模擬工具使用

通常在作Mobus前期的開發的時候,通常不是針對具體的Modbus設備進行寄存器的處理,而是使用Modbus模擬工具來進行調試,通常咱們須要配合Modbus Slave、Modbus Poll、Virtual Serial Port Driver這幾個模擬軟件來進行開發的。

Modbus Poll :Modbus主機仿真器,用於測試和調試Modbus從設備。該軟件支持Modbus的RTU、ASCII、TCP/IP。用來幫助開發人員測試Modbus從設備,或者其它Modbus協議的測試和仿真。

 Modbus Slave: Modbus從設備仿真器,能夠仿真32個從設備/地址域。每一個接口都提供了對EXCEL報表的OLE自動化支持。主要用來模擬Modbus從站設備,接收主站的命令包,回送數據包。幫助Modbus通信設備開發人員進行Modbus通信協議的模擬和測試,用於模擬、測試、調試Modbus通信設備。 

 Virtual Serial Port Driver:虛擬串口工具,不須要串口接線,提供虛擬的串口,適合學習和調試使用。

配合這幾款軟件,咱們就能夠實現串口Modbus協議的模擬測試了,若是咱們使用Modbus的TCPIP協議,那麼咱們不須要VSPD也能夠。

若是咱們使用Modbus協議的串口通信方式,那麼咱們先要使用VSPD進行串口的配對模擬,模擬出兩個通信的串口端口,端口配對模擬成功後,咱們能夠看到設備管理器中增長了兩個端口了。

 接着使用從機模擬器,模擬一個Modbus從機供測試,經過菜單【Connection】【Connect】啓動,咱們選擇鏈接方式爲串口,端口則選擇咱們配對的其中一個端口便可,以下圖所示。

 其中模式選擇RTU或者ASCII均可以,這兩個模式協議有所不一樣,一旦從機選擇RTU模式,那麼Modbus主機也須要選擇對應的RTU模式,反之亦然。 

其餘串口設置,如波特率、數據位、奇偶位、中止位等默認配置便可。

若是咱們選擇TCPIP模式,那麼對應Modbus主機也須要選擇TCPIP方式。

 一旦Modbus從機啓動,就會處理來自Modbus主機的指令請求(若是有的話),並作相應處理,咱們能夠經過【Display】【Communication】菜單彈出的對話框,瞭解到對應請求和應答的協議詳細信息。

 Modbus主機的啓動和ModBus從機相似,咱們根據ModBus從機的配置,選擇對應的主機配置,Modbus模擬主機啓動和查看通信記錄界面以下所示。

另外咱們能夠經過【Display】裏面選擇內容顯示的進制格式。

在從機的設置裏面,咱們能夠修改從機的定義信息,以便設置對應的從機ID,功能碼,其實地址,長度或者數量的信息,以下界面所示。

 咱們能夠根據實際的寄存器地址和數量,設置對應的數值,以下是顯示4個數據的內容設置和顯示內容。

設置後正常的內容顯示以下。

 同時咱們也須要設置對應Modbus主機模擬器的地址和數量,正確設置後能夠正常顯示。

經過更深一步的設置或者調整,咱們能夠極大程度的進行模擬Modbus實際設備的處理方式,從而在沒有實際Modbus硬件設備的狀況下儘量經過前期的模擬完成常規功能的測試和準備。

在咱們開發Modbus應用的時候,咱們對照相應的主從機Modbus協議請求和應答,可以檢查咱們程序的輸出是否正常,從而能夠快速的開發Modbus的應用處理功能。

3)Modbus應用開發

爲了模擬對接Modbus的RTU、ASCII、TCP/IP協議處理,我根據不一樣協議的處理方式定義了一個輔助函數,而後統一進行處理,以便達到統一調用的處理便利。

首先咱們來看看使用串口模式下(RTU、ASCII)的處理界面效果,這個直接獲取模擬器Modbus Slave從機的數值進行顯示的。

TCPIP網絡方式對接Modbus界面處理效果以下所示。

二者數據均來源於Modbus Slave從機的數值,只是它們對接的方式不一樣。

 

串口的處理,我經過SerialPortUtil類來使用Windows的串口類,處理對應的串口操做,經過定義事件的方式,使得串口收到數據的時候,及時通知調用者進行界面更新處理便可。

//使用字符串參數構造
serial = new SerialPortUtil(portname, this.txtBaudRate.Text, this.txtParity.Text, this.txtDataBits.Text, this.txtStopBit.Text);
//收到數據處理的事件
serial.DataReceived += Serial_DataReceived;
serial.RTUMode = this.radRTU.Checked;//默認RTU模式爲True,不然使用ASCII模式

收到數據後,及時經過委託方式,通知UI進行界面的更新顯示。

/// <summary>
/// 收到串口響應事件後,及時進行處理(更新在界面上)
/// </summary>
/// <param name="e"></param>
private void Serial_DataReceived(DataReceivedEventArgs e)
{
    //記錄在日誌,方便複製
    LogTextHelper.Info(e.DataReceived);

    //使用委託進行處理界面控件的數據更新
    this.txtResponse.Invoke(new MethodInvoker(()=> 
    {
        //顯示在界面上
        this.txtResponse.AppendText(e.DataReceived);
        this.txtResponse.AppendText(Environment.NewLine);

        var dataBytes = e.BytesReceived;
        if(dataBytes != null && dataBytes.Length > 2)
        {
            var function = dataBytes[1];
            if(function > 0x80)//128
            {
                //Modbus的異常代碼大於128,若是是異常,則能夠解析錯誤
                var newFunction = function - 0x80;
                lblTips.Text = "響應有異常,功能代碼:" + newFunction.ToString("D2");
                lblTips.Text += ",錯誤描述:" + ((ModBusExceptionCode)newFunction).ToString();
            }
            else
            {
                lblTips.Text = "響應正常";//小於128的爲正常響應
            }
        }
    }));
}

而對於網絡方式,咱們先要定義一個Socket通信的基類,封裝相關的通信處理操做。

 

 

而後簡單構建一個子類進行使用,以下所示。

    /// <summary>
    /// 通訊類子類
    /// </summary>
    public class ModbusClient : BaseSocketClient
    {
        public ModbusClient()
        {
            this.Name = "ModbusClient";
        }
    }

界面處理的時候,咱們只須要初始化一個ModbusClient類來使用便可,以下代碼所示。

client = new ModbusClient();
//收到數據處理的事件
client.DataReceived += Client_DataReceived;

收到數據通知界面進行更新的操做以下所示。

private void Client_DataReceived(DataReceivedEventArgs e)
{
    //記錄在日誌,方便複製
    LogTextHelper.Info(e.DataReceived);

    //使用委託進行處理界面控件的數據更新
    this.txtResponse.Invoke(new MethodInvoker(() =>
    {
        this.txtResponse.AppendText(e.DataReceived);
        this.txtResponse.AppendText(Environment.NewLine);

        var dataBytes = e.BytesReceived;
        if (dataBytes != null && dataBytes.Length > 2)
        {
            //串口功能碼爲第二個字節,TCP/IP功能碼爲第8個
            var function = dataBytes[7];
            if (function > 0x80)//128
            {
                //Modbus的異常代碼大於128,若是是異常,則能夠解析錯誤
                var newFunction = function - 0x80;
                lblTips.Text = "響應有異常,功能代碼:" + newFunction.ToString("D2");
                lblTips.Text += ",錯誤描述:" + ((ModBusExceptionCode)newFunction).ToString();
            }
            else
            {
                lblTips.Text = "響應正常";//小於128的爲正常響應
            }
        }
    }));
}

不論是串口的RTU或者ASCII,又或者是TCPIP的協議,咱們能夠經過定義一個協議封裝的輔助類ModbusQueryHelper來處理協議的具體細節。

    /// <summary>
    /// Modbus查詢消息生成輔助類,能夠用於串口RTU/ASCII協議,也能夠用於TCPIP協議。
    /// 用於生成各類功能代碼的消息內容。
    /// </summary>
    public class ModbusQueryHelper
    {
        /// <summary>
        /// 是否爲RTU模式,默認爲True,不然爲ASCII方式
        /// </summary>
        public ModbusProtocol Protocol { get; set; } = ModbusProtocol.RTU;

        /// <summary>
        /// 默認函數
        /// </summary>
        public ModbusQueryHelper()
        {
        }

        /// <summary>
        /// 參數化構造,指定RTU模式
        /// </summary>
        /// <param name="protocal">Modbus協議:ASCII,RTU, TCP,默認爲RTU</param>
        public ModbusQueryHelper(ModbusProtocol protocal)
        {
            this.Protocol = protocal;
        }

而其中ModbusProtocol是一個枚舉,定義以下所示。

    /// <summary>
    /// 幾種經常使用的Modbus協議
    /// </summary>
    public enum ModbusProtocol
    {
        /// <summary>
        /// 串口的ASCII模式
        /// </summary>
        ASCII,
        /// <summary>
        /// 串口的RTU模式
        /// </summary>
        RTU, 
        /// <summary>
        /// 網絡TCPIP模式
        /// </summary>
        TCP
    }

咱們經過ModbusQueryHelper 類,能夠處理不一樣協議之間的封裝細節,並能夠對各類功能碼的協議進行封裝處理。

 

 

 

 以上就是 相關Modbus的應用處理和封裝,對於常規的Modbus協議能夠極大簡化對接處理,在實際對接Modbus設備的時候,咱們只須要根據對應的說明書,獲取對應的內容,就能夠把例如溫度、溼度、轉速等一些設備或者機器人的參數得到,並記錄在數據庫裏面,而後在應用模塊中整合一些圖表展現就能夠很好的實現看板功能了。

相關文章
相關標籤/搜索