1. 程式人生 > >Modbus協議棧開發筆記之三:Modbus TCP Server開發

Modbus協議棧開發筆記之三:Modbus TCP Server開發

在完成了前面的工作後,我們就可以實現有針對性的應用了,首先我們來實現Modbus TCP的伺服器端應用。當然我們不是做具體的應用,而是對Modbus TCP的伺服器端應用進行封裝以供有需要時呼叫。

這裡我們不涉及TCP的協議,這部分與Modbus沒有必然聯絡,我們只是在其應用層執行Modbus協議而已。

對於Modbus TCP的伺服器我們需要實現幾個功能:首先是對接收到客戶端命令進行解析,我們只實現前面提到的8中常用的功能嗎的支援。其次在解析完成後,我們要實現對應各種功能碼的操作。具體架構如下:

1、命令解析

伺服器作為被動端接收到客戶端的請求後,安裝請求進行處理。所以伺服器接收到資訊後首先對其進行解析,這裡我們只需要一個解析函式就可以完成,當在具體應用中時只要將接收到的資訊呼叫這個函式解析就可以了。

/*解析接收到的資訊,返回響應命令的長度*/

uint16_t ParsingClientAccessCommand(uint8_t *receivedMessage,uint8_t *respondBytes)

其實對外來說只有這一個函式時可見的。當我們要開發一個TCP Server的應用時,就呼叫這個函式。

2、命令處理

命令解析出來了之後,按不同的功能碼來進行不同的處理,我們支援8種功能碼,每種功能嗎都對應處理部分,很多時候大家都會在解析的時候根據解析結果處理,這勢必需要一個很大的解析函式。為了簡化操作,我們將每個功能碼對應的處理部分都封裝為一個函式。然後使用一個函式指標陣列來動態呼叫這些函式,從而簡化這些函式。

首先我們需要8個處理對應個功能碼操作的函式:

/*處理讀線圈狀態命令*/

static uint16_t HandleReadCoilStatusCommand(uint16_t startAddress,uint16_t quantity,uint8_t *receivedMessage,uint8_t *respondBytes)

/*處理讀輸入狀態命令*/

static uint16_t HandleReadInputStatusCommand(uint16_t startAddress,uint16_t quantity,uint8_t *receivedMessage,uint8_t *respondBytes)

/*處理讀保持暫存器命令*/

static uint16_t HandleReadHoldingRegisterCommand(uint16_t startAddress,uint16_t quantity,uint8_t *receivedMessage,uint8_t *respondBytes)

/*處理讀輸入暫存器命令*/

static uint16_t HandleReadInputRegisterCommand(uint16_t startAddress,uint16_t quantity,uint8_t *receivedMessage,uint8_t *respondBytes)

/*處理寫單個線圈命令*/

static uint16_t HandleWriteSingleCoilCommand(uint16_t coilAddress,uint16_t coilValue,uint8_t *receivedMessage,uint8_t *respondBytes)

/*處理寫單個暫存器命令*/

static uint16_t HandleWriteSingleRegisterCommand(uint16_t registerAddress,uint16_t registerValue,uint8_t *receivedMessage,uint8_t *respondBytes)

/*處理寫多個線圈狀態*/

static uint16_t HandleWriteMultipleCoilCommand(uint16_t startAddress,uint16_t quantity,uint8_t *receivedMessage,uint8_t *respondBytes)

/*處理寫多個暫存器狀態*/

static uint16_t HandleWriteMultipleRegisterCommand(uint16_t startAddress,uint16_t quantity,uint8_t *receivedMessage,uint8_t *respondBytes)

然後我們定義一個函式指標陣列來呼叫這下函式:

uint16_t (*HandleClientCommand[])(uint16_t,uint16_t,uint8_t *,uint8_t *)={HandleReadCoilStatusCommand,

                                                                          HandleReadInputStatusCommand,

                                                                          HandleReadHoldingRegisterCommand,

                                                                          HandleReadInputRegisterCommand,

                                                                          HandleWriteSingleCoilCommand,

                                                                          HandleWriteSingleRegisterCommand,

                                                                          HandleWriteMultipleCoilCommand,

                                                                          HandleWriteMultipleRegisterCommand};

3、響應的生成

對於響應命令的生成其實在第二篇中已經說過了,需要說明的是各種寫資料的具體數值以及獲得讀資料的各種具體數值我們將在單獨的檔案中去實現,因為這部分TCP和RTU是相同的,我們將在後續的篇章中說明。

原始碼網址是:https://github.com/foxclever/Modbus

歡迎關注: