eMBException eMBMasterFuncReadHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) { UCHAR *ucMBFrame; USHORT usRegAddress; USHORT usRegCount; eMBException eStatus = MB_EX_NONE; eMBErrorCode eRegStatus; /* If this request is broadcast, and it's read mode. This request don't need execute. */ if ( xMBMasterRequestIsBroadcast() ) { eStatus = MB_EX_NONE; } else if( *usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN ) { vMBMasterGetPDUSndBuf(&ucMBFrame); usRegAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8 ); usRegAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] ); usRegAddress++; usRegCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8 ); usRegCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] ); /* Check if the number of registers to read is valid. If not * return Modbus illegal data value exception. */ if( ( usRegCount >= 1 ) && ( 2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF] ) ) { /* Make callback to fill the buffer. */ eRegStatus = eMBMasterRegHoldingCB( &pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usRegCount, MB_REG_READ ); if(eMBMasterGetErrorType() == EV_ERROR_RESPOND_TIMEOUT) nReqTimeOut++; vMBMasterSetErrorType(EV_NO_ERROR); populate(&list_RTC, (DeviceElement){(uint32_t)ucMBMasterGetDestAddress(), "RTC", CONNECTED, nReqTimeOut, nReqs, 3, usRegAddress, usRegCount, 0, 0}); /* If an error occured convert it into a Modbus exception. */ if( eRegStatus != MB_ENOERR ) { eStatus = prveMBError2Exception( eRegStatus ); populate(&list_RTC, (DeviceElement){(uint32_t)ucMBMasterGetDestAddress(), "RTC(E)", CONNECTIONLESS, nReqTimeOut, nReqs, 3, usRegAddress, usRegCount, 0, 0}); } } else { eStatus = MB_EX_ILLEGAL_DATA_VALUE; populate(&list_RTC, (DeviceElement){(uint32_t)ucMBMasterGetDestAddress(), "RTC(IDV)", CONNECTIONLESS, nReqTimeOut, nReqs, 3, usRegAddress, usRegCount, 0, 0}); } } else { /* Can't be a valid request because the length is incorrect. */ eStatus = MB_EX_ILLEGAL_DATA_VALUE; } return eStatus; }
//******************************输入寄存器回调函数********************************** //函数定义: eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) //描 述:输入寄存器相关的功能(读、连续读) //入口参数:pucRegBuffer : 回调函数将Modbus寄存器的当前值写入的缓冲区 // usAddress : 寄存器的起始地址,输入寄存器的地址范围是1-65535。 // usNRegs : 寄存器数量 //出口参数:eMBErrorCode : 这个函数将返回的错误码 //备 注:Editor:Armink 2013-11-25 Company: BXXJS //********************************************************************************** eMBErrorCode eMBMasterRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs ) { eMBErrorCode eStatus = MB_ENOERR; USHORT iRegIndex; USHORT * pusRegInputBuf; USHORT REG_INPUT_START; USHORT REG_INPUT_NREGS; USHORT usRegInStart; pusRegInputBuf = usMRegInBuf[ucMBMasterGetDestAddress() - 1]; REG_INPUT_START = M_REG_INPUT_START; REG_INPUT_NREGS = M_REG_INPUT_NREGS; usRegInStart = usMRegInStart; usAddress--;//FreeModbus功能函数中已经加1,为保证与缓冲区首地址一致,故减1 if( ( usAddress >= REG_INPUT_START ) && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) ) { iRegIndex = usAddress - usRegInStart; while( usNRegs > 0 ) { pusRegInputBuf[iRegIndex] = *pucRegBuffer++ << 8; pusRegInputBuf[iRegIndex] |= *pucRegBuffer++; iRegIndex++; usNRegs--; } } else { eStatus = MB_ENOREG; } return eStatus; }
//******************************保持寄存器回调函数********************************** //函数定义: eMBErrorCode eMBMasterRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode ) //描 述:保持寄存器相关的功能(读、连续读、写、连续写) //入口参数:pucRegBuffer : 如果需要更新用户寄存器数值,这个缓冲区必须指向新的寄存器数值。 // 如果协议栈想知道当前的数值,回调函数必须将当前值写入这个缓冲区 // usAddress : 寄存器的起始地址。 // usNRegs : 寄存器数量 // eMode : 如果该参数为eMBRegisterMode::MB_REG_WRITE,用户的应用数值将从pucRegBuffer中得到更新。 // 如果该参数为eMBRegisterMode::MB_REG_READ,用户需要将当前的应用数据存储在pucRegBuffer中 //出口参数:eMBErrorCode : 这个函数将返回的错误码 //备 注:Editor:Armink 2013-11-25 Company: BXXJS //********************************************************************************** eMBErrorCode eMBMasterRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode ) { eMBErrorCode eStatus = MB_ENOERR; USHORT iRegIndex; USHORT * pusRegHoldingBuf; USHORT REG_HOLDING_START; USHORT REG_HOLDING_NREGS; USHORT usRegHoldStart; pusRegHoldingBuf = usMRegHoldBuf[ucMBMasterGetDestAddress() - 1]; REG_HOLDING_START = M_REG_HOLDING_START; REG_HOLDING_NREGS = M_REG_HOLDING_NREGS; usRegHoldStart = usMRegHoldStart; //If mode is read,the master will wirte the received date to bufffer. eMode = MB_REG_WRITE; usAddress--;//FreeModbus功能函数中已经加1,为保证与缓冲区首地址一致,故减1 if( ( usAddress >= REG_HOLDING_START ) && ( usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS ) ) { iRegIndex = usAddress - usRegHoldStart; switch ( eMode ) { /* Pass current register values to the protocol stack. */ case MB_REG_READ: while( usNRegs > 0 ) { *pucRegBuffer++ = ( unsigned char )( pusRegHoldingBuf[iRegIndex] >> 8 ); *pucRegBuffer++ = ( unsigned char )( pusRegHoldingBuf[iRegIndex] & 0xFF ); iRegIndex++; usNRegs--; } break; /* Update current register values with new values from the * protocol stack. */ case MB_REG_WRITE: while( usNRegs > 0 ) { pusRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8; pusRegHoldingBuf[iRegIndex] |= *pucRegBuffer++; iRegIndex++; usNRegs--; } break; } }
eMBErrorCode eMBMasterPoll( void ) { static UCHAR *ucMBFrame; static UCHAR ucRcvAddress; static UCHAR ucFunctionCode; static USHORT usLength; static eMBException eException; // int i; eMBErrorCode eStatus = MB_ENOERR; eMBMasterEventType eEvent; /* Check if the protocol stack is ready. */ if( eMBState != STATE_ENABLED ) { return MB_EILLSTATE; } /* Check if there is a event available. If not return control to caller. * Otherwise we will handle the event. */ if( xMBMasterPortEventGet( &eEvent ) == TRUE ) { switch ( eEvent ) { case EV_MASTER_READY: break; case EV_MASTER_FRAME_RECEIVED: eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength ); if ( eStatus == MB_ENOERR ) { ( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE ); } else { ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); } #if 0 /* Check if the frame is for us. If not ,send an error process event. */ if ( ( eStatus == MB_ENOERR ) && ( ucRcvAddress == ucMBMasterGetDestAddress() ) ) { ( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE ); } else { ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); } #endif break; case EV_MASTER_EXECUTE: //接受到了一帧RTU 数据 //Mb2TcpBuff[256]; if(usLength<256) { Mb2TcpLenth=usLength;//更新接受到的数据长度,准备启动TCP发送 Mb2TcpBuff[0]=0xFF; Mb2TcpBuff[1]=0x55; Mb2TcpBuff[2]=Statues_MB; Mb2TcpBuff[3]=UID_STM32[0]; Mb2TcpBuff[4]=UID_STM32[1]; Mb2TcpBuff[5]=UID_STM32[2]; memcpy(&Mb2TcpBuff[6],ucMBFrame,Mb2TcpLenth);//数据复制进TCP发送buf中 Mb2TcpBuff[Mb2TcpLenth+6]=0x24; Mb2TcpBuff[Mb2TcpLenth+6+1]=0x0d; Mb2TcpBuff[Mb2TcpLenth+6+2]=0x0a; Mb2TcpLenth+=9; } eException = MB_EX_ILLEGAL_FUNCTION; #if 0 ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF]; eException = MB_EX_ILLEGAL_FUNCTION; for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ) { // No more function handlers registered. Abort. if( xMasterFuncHandlers[i].ucFunctionCode == 0 ) { break; } else if( xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode ) { vMBMasterSetCBRunInMasterMode(TRUE); eException = xMasterFuncHandlers[i].pxHandler( ucMBFrame, &usLength ); vMBMasterSetCBRunInMasterMode(FALSE); break; } } /* If receive frame has exception .The receive function code highest bit is 1.*/ if(ucFunctionCode >> 7) eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF]; /* If master has exception ,Master will send error process.Otherwise the Master is idle.*/ if (eException != MB_EX_NONE) ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); else vMBMasterSetIsBusy( FALSE ); #endif break; case EV_MASTER_FRAME_SENT: /* Master is busy now. */ vMBMasterSetIsBusy( TRUE ); vMBMasterGetPDUSndBuf( &ucMBFrame ); eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, ucMBMasterGetPDUSndLength() ); break; case EV_MASTER_ERROR_PROCESS: vMBMasterSetIsBusy( FALSE ); break; } } return MB_ENOERR; }
eMBErrorCode eMBMasterPoll( void ) { static UCHAR *ucMBFrame; static UCHAR ucRcvAddress; static UCHAR ucFunctionCode; static USHORT usLength; static eMBException eException; int i , j; eMBErrorCode eStatus = MB_ENOERR; eMBMasterEventType eEvent; eMBMasterErrorEventType errorType; /* Check if the protocol stack is ready. */ if( eMBState != STATE_ENABLED ) { return MB_EILLSTATE; } /* Check if there is a event available. If not return control to caller. * Otherwise we will handle the event. */ if( xMBMasterPortEventGet( &eEvent ) == TRUE ) { switch ( eEvent ) { case EV_MASTER_READY: break; case EV_MASTER_FRAME_RECEIVED: eStatus = peMBMasterFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength ); /* Check if the frame is for us. If not ,send an error process event. */ if ( ( eStatus == MB_ENOERR ) && ( ucRcvAddress == ucMBMasterGetDestAddress() ) ) { ( void ) xMBMasterPortEventPost( EV_MASTER_EXECUTE ); } else { vMBMasterSetErrorType(EV_ERROR_RECEIVE_DATA); ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); } break; case EV_MASTER_EXECUTE: ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF]; eException = MB_EX_ILLEGAL_FUNCTION; /* If receive frame has exception .The receive function code highest bit is 1.*/ if(ucFunctionCode >> 7) { eException = (eMBException)ucMBFrame[MB_PDU_DATA_OFF]; } else { for (i = 0; i < MB_FUNC_HANDLERS_MAX; i++) { /* No more function handlers registered. Abort. */ if (xMasterFuncHandlers[i].ucFunctionCode == 0) { break; } else if (xMasterFuncHandlers[i].ucFunctionCode == ucFunctionCode) { vMBMasterSetCBRunInMasterMode(TRUE); /* If master request is broadcast, * the master need execute function for all slave. */ if ( xMBMasterRequestIsBroadcast() ) { usLength = usMBMasterGetPDUSndLength(); for(j = 1; j <= MB_MASTER_TOTAL_SLAVE_NUM; j++){ vMBMasterSetDestAddress(j); eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength); } } else { eException = xMasterFuncHandlers[i].pxHandler(ucMBFrame, &usLength); } vMBMasterSetCBRunInMasterMode(FALSE); break; } } } /* If master has exception ,Master will send error process.Otherwise the Master is idle.*/ if (eException != MB_EX_NONE) { vMBMasterSetErrorType(EV_ERROR_EXECUTE_FUNCTION); ( void ) xMBMasterPortEventPost( EV_MASTER_ERROR_PROCESS ); } else { vMBMasterCBRequestScuuess( ucMBMasterGetDestAddress()); vMBMasterRunResRelease( ); } break; case EV_MASTER_FRAME_SENT: /* Master is busy now. */ vMBMasterGetPDUSndBuf( &ucMBFrame ); eStatus = peMBMasterFrameSendCur( ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength() ); break; case EV_MASTER_ERROR_PROCESS: /* Execute specified error process callback function. */ errorType = eMBMasterGetErrorType(); vMBMasterGetPDUSndBuf( &ucMBFrame ); switch (errorType) { case EV_ERROR_RESPOND_TIMEOUT: vMBMasterErrorCBRespondTimeout(ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength()); break; case EV_ERROR_RECEIVE_DATA: vMBMasterErrorCBReceiveData(ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength()); break; case EV_ERROR_EXECUTE_FUNCTION: vMBMasterErrorCBExecuteFunction(ucMBMasterGetDestAddress(), ucMBFrame, usMBMasterGetPDUSndLength()); break; } vMBMasterRunResRelease(); break; } }