FreeModbus TCP传输
生活随笔
收集整理的這篇文章主要介紹了
FreeModbus TCP传输
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
首先,在使能modbus協議棧的時候,會調用pvMBFrameStartCur函數
/* 使能modbus */ eMBErrorCode eMBEnable(void) {eMBErrorCode eStatus = MB_ENOERR;/* modbus還未使能 */if(eMBState == STATE_DISABLED){/* 啟動modbus */pvMBFrameStartCur();/* 設置modbus狀態為使能 */eMBState = STATE_ENABLED;}else{/* 狀態不合法 */eStatus = MB_EILLSTATE;}return eStatus; }在tcp模式下pvMBFrameStartCur指針指向eMBTCPStart函數
/* modbus tcp啟動 */ void eMBTCPStart(void) {}因為在初始化的時候已經,已經開啟tcp監聽,并等待客戶端連接了。因此eMBTCPStart函數什么也不用做。
?
主程序接收到接收完成事件之后,對數據幀進行校驗和拆解,最后會得到PDU數據的指針和長度。并向主程序發送執行事件。
/* modbus輪詢 */ eMBErrorCode eMBPoll(void) {....../* 獲取事件 */if(xMBPortEventGet(&eEvent) == TRUE){/* 判斷事件類型 */switch(eEvent){....../* 接收完成事件 */case EV_FRAME_RECEIVED:/* modbus接收函數,獲取地址、PDU指針、PDU長度 */eStatus = peMBFrameReceiveCur(&ucRcvAddress, &ucMBFrame, &usLength);if(eStatus == MB_ENOERR){/* 判斷地址是否吻合 */if((ucRcvAddress == ucMBAddress) || (ucRcvAddress == MB_ADDRESS_BROADCAST)){/* 發送執行事件 */(void)xMBPortEventPost(EV_EXECUTE);}}break;......}}return MB_ENOERR; }下面看一下peMBFrameReceiveCur調用的eMBTCPReceive函數。主要工作是對數據幀進行拆分,并區分是否是modbus協議。
/* modbus tcp接收 */ eMBErrorCode eMBTCPReceive(UCHAR *pucRcvAddress, UCHAR **ppucFrame, USHORT *pusLength) {eMBErrorCode eStatus = MB_EIO;UCHAR *pucMBTCPFrame;USHORT usLength;USHORT usPID;/* 接收到一幀數據 */if(xMBTCPPortGetRequest(&pucMBTCPFrame, &usLength) != FALSE){/* 協議ID */usPID = pucMBTCPFrame[MB_TCP_PID] << 8U;usPID |= pucMBTCPFrame[MB_TCP_PID + 1];/* modbus協議 */if(usPID == MB_TCP_PROTOCOL_ID){/* PDU */*ppucFrame = &pucMBTCPFrame[MB_TCP_FUNC];/* 數據長度 */*pusLength = usLength - MB_TCP_FUNC;/* 成功 */eStatus = MB_ENOERR;/* 在服務器中只有0xFF地址 *//* 在網關程序中,這里需要真正取出單元標識符 */*pucRcvAddress = MB_TCP_PSEUDO_ADDRESS;}}else{eStatus = MB_EIO;}return eStatus; }主程序接收到執行事件之后,判斷功能碼,調用相應功能函數。然后對主機進行響應。
/* modbus輪詢 */ eMBErrorCode eMBPoll(void) {....../* 獲取事件 */if(xMBPortEventGet(&eEvent) == TRUE){/* 判斷事件類型 */switch(eEvent){....../* 執行事件 */case EV_EXECUTE:/* 功能碼 */ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];eException = MB_EX_ILLEGAL_FUNCTION;/* 遍歷所有支持的功能碼 */for(i = 0; i < MB_FUNC_HANDLERS_MAX; i++){/* 遍歷完了 */if(xFuncHandlers[i].ucFunctionCode == 0){break;}/* 匹配到合適的功能碼 */else if(xFuncHandlers[i].ucFunctionCode == ucFunctionCode){/* 調用相關功能 */eException = xFuncHandlers[i].pxHandler(ucMBFrame, &usLength);break;}}/* 不是廣播 */if(ucRcvAddress != MB_ADDRESS_BROADCAST){/* 出現異常 */if(eException != MB_EX_NONE){/* PDU長度初始化為0 */usLength = 0;/* 功能碼+0x80則表示異常 */ucMBFrame[usLength++] = (UCHAR)(ucFunctionCode | MB_FUNC_ERROR);/* 異常碼 */ucMBFrame[usLength++] = eException;}if((eMBCurrentMode == MB_ASCII) && MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS){vMBPortTimersDelay(MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS);} /* 發送響應幀 */eStatus = peMBFrameSendCur(ucMBAddress, ucMBFrame, usLength);}break;......}}return MB_ENOERR; }peMBFrameSendCur指針調用eMBTCPSend對主機進行響應。主要工作為對PDU進行封裝并發送。
/* modbus tcp發送 */ eMBErrorCode eMBTCPSend(UCHAR _unused, const UCHAR *pucFrame, USHORT usLength) {eMBErrorCode eStatus = MB_ENOERR;/* 空出MBAP域 */UCHAR *pucMBTCPFrame = (UCHAR *)pucFrame - MB_TCP_FUNC;/* 數據包計算長度 */USHORT usTCPLength = usLength + MB_TCP_FUNC;/* 更改MBAP中的長度域,其它域保持和請求相同 */pucMBTCPFrame[MB_TCP_LEN] = (usLength + 1) >> 8U;pucMBTCPFrame[MB_TCP_LEN + 1] = (usLength + 1) & 0xFF;/* 發送數據包 */if(xMBTCPPortSendResponse(pucMBTCPFrame, usTCPLength) == FALSE){eStatus = MB_EIO;}return eStatus; }?
總結
以上是生活随笔為你收集整理的FreeModbus TCP传输的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 独立编址与统一编址
- 下一篇: w8服务器dns修改,Win8.1系统的