eMBMasterReqErrCode eMBMasterReqReadHoldingRegister(uint8_t ucSndAddr, uint16_t usRegAddr, uint16_t usNRegs, uint32_t lTimeOut) { uint8_t *ucMBFrame; eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; if (ucSndAddr > CONFIG_MB_MASTER_TOTAL_SLAVE_NUM) { eErrStatus = MB_MRE_ILL_ARG; } else if (xMBMasterRunResTake(lTimeOut) == false) { eErrStatus = MB_MRE_MASTER_BUSY; } else { vMBMasterGetPDUSndBuf(&ucMBFrame); vMBMasterSetDestAddress(ucSndAddr); ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_HOLDING_REGISTER; ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usRegAddr >> 8; ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usRegAddr; ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8; ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs; vMBMasterSetPDUSndLength(MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE); (void)xMBMasterPortEventPost(EV_MASTER_FRAME_SENT); eErrStatus = eMBMasterWaitRequestFinish(); } return eErrStatus; }
/** * This function will request read holding register. * * @param ucSndAddr salve address * @param usRegAddr register start address * @param usNRegs register total number * @param lTimeOut timeout (-1 will waiting forever) * * @return error code */ eMBMasterReqErrCode eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut ) { UCHAR *ucMBFrame; eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; chprintf((BaseSequentialStream *)&itm_port, "Resource Taken %s\n", xMBMasterRunResTake( lTimeOut ) ? "true" : "false"); populate(&list_RTC, (DeviceElement){ucSndAddr, "RTC", CONNECTIONLESS, nReqTimeOut, nReqs++, 3, usRegAddr, usNRegs, 0, 0}); if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; else { vMBMasterGetPDUSndBuf(&ucMBFrame); vMBMasterSetDestAddress(ucSndAddr); ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_HOLDING_REGISTER; ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usRegAddr >> 8; ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usRegAddr; ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8; ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs; vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); xMBMasterRunResLock(); //eErrStatus = eMBMasterWaitRequestFinish( ); } return eErrStatus; }
/** * This function will request write multiple holding register. * * @param ucSndAddr salve address * @param usRegAddr register start address * @param usNRegs register total number * @param pusDataBuffer data to be written * @param lTimeOut timeout (-1 will waiting forever) * * @return error code */ eMBMasterReqErrCode eMBMasterReqWriteMultipleHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, USHORT * pusDataBuffer, LONG lTimeOut ) { UCHAR *ucMBFrame; USHORT usRegIndex = 0; eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; else { vMBMasterGetPDUSndBuf(&ucMBFrame); vMBMasterSetDestAddress(ucSndAddr); ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_MULTIPLE_REGISTERS; ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] = usRegAddr >> 8; ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] = usRegAddr; ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF] = usNRegs >> 8; ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1] = usNRegs ; ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF] = usNRegs * 2; ucMBFrame += MB_PDU_REQ_WRITE_MUL_VALUES_OFF; while( usNRegs > usRegIndex) { *ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8; *ucMBFrame++ = pusDataBuffer[usRegIndex++] ; } vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + 2*usNRegs ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); } return eErrStatus; }
/** * This function will request write holding register. * * @param ucSndAddr slave address * @param usRegAddr register start address * @param usRegData register data to be written * @param lTimeOut timeout (-1 will waiting forever) * * @return error code */ eMBMasterReqErrCode eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut ) { UCHAR *ucMBFrame; eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; //chprintf((BaseSequentialStream *)&itm_port, "Resource Taken %s\n", xMBMasterRunResTake( lTimeOut ) ? "true" : "false"); if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; else { vMBMasterGetPDUSndBuf(&ucMBFrame); vMBMasterSetDestAddress(ucSndAddr); ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_REGISTER; ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF] = usRegAddr >> 8; ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1] = usRegAddr; ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF] = usRegData >> 8; ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usRegData ; vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); eErrStatus = eMBMasterWaitRequestFinish( ); } return eErrStatus; }
eMBException eMBMasterFuncWriteMultipleCoils( UCHAR * pucFrame, USHORT * usLen ) { USHORT usRegAddress; USHORT usCoilCnt; UCHAR ucByteCount; UCHAR ucByteCountVerify; UCHAR *ucMBFrame; eMBException eStatus = MB_EX_NONE; eMBErrorCode eRegStatus; /* If this request is broadcast, the *usLen is not need check. */ if( ( *usLen == MB_PDU_FUNC_WRITE_MUL_SIZE ) || xMBMasterRequestIsBroadcast() ) { vMBMasterGetPDUSndBuf(&ucMBFrame); usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 ); usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] ); usRegAddress++; usCoilCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF] << 8 ); usCoilCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF + 1] ); ucByteCount = ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF]; /* Compute the number of expected bytes in the request. */ if( ( usCoilCnt & 0x0007 ) != 0 ) { ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 + 1 ); } else { ucByteCountVerify = ( UCHAR )( usCoilCnt / 8 ); } if( ( usCoilCnt >= 1 ) && ( ucByteCountVerify == ucByteCount ) ) { eRegStatus = eMBMasterRegCoilsCB( &ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF], usRegAddress, usCoilCnt, MB_REG_WRITE ); /* If an error occured convert it into a Modbus exception. */ if( eRegStatus != MB_ENOERR ) { eStatus = prveMBError2Exception( eRegStatus ); } } else { eStatus = MB_EX_ILLEGAL_DATA_VALUE; } } else { /* Can't be a valid write coil register request because the length * is incorrect. */ eStatus = MB_EX_ILLEGAL_DATA_VALUE; } return eStatus; }
eMBMasterReqErrCode eMBMasterReqWriteMultipleCoils(uint8_t ucSndAddr, uint16_t usCoilAddr, uint16_t usNCoils, uint8_t *pucDataBuffer, uint32_t lTimeOut) { uint8_t *ucMBFrame; uint16_t usRegIndex = 0; uint8_t ucByteCount; eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; if (ucSndAddr > CONFIG_MB_MASTER_TOTAL_SLAVE_NUM) { eErrStatus = MB_MRE_ILL_ARG; } else if (usNCoils > MB_PDU_REQ_WRITE_MUL_COILCNT_MAX) { eErrStatus = MB_MRE_ILL_ARG; } else if (xMBMasterRunResTake(lTimeOut) == false) { eErrStatus = MB_MRE_MASTER_BUSY; } else { vMBMasterGetPDUSndBuf(&ucMBFrame); vMBMasterSetDestAddress(ucSndAddr); ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_MULTIPLE_COILS; ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] = usCoilAddr >> 8; ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] = usCoilAddr; ucMBFrame[MB_PDU_REQ_WRITE_MUL_COILCNT_OFF] = usNCoils >> 8; ucMBFrame[MB_PDU_REQ_WRITE_MUL_COILCNT_OFF + 1] = usNCoils; if ((usNCoils & 0x0007) != 0) { ucByteCount = (uint8_t) (usNCoils / 8 + 1); } else { ucByteCount = (uint8_t) (usNCoils / 8); } ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF] = ucByteCount; ucMBFrame += MB_PDU_REQ_WRITE_MUL_VALUES_OFF; while (ucByteCount > usRegIndex) { *ucMBFrame++ = pucDataBuffer[usRegIndex++]; } vMBMasterSetPDUSndLength(MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + ucByteCount); (void)xMBMasterPortEventPost(EV_MASTER_FRAME_SENT); eErrStatus = eMBMasterWaitRequestFinish(); } return eErrStatus; }
eMBException eMBMasterFuncReadWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen ) { USHORT usRegReadAddress; USHORT usRegReadCount; USHORT usRegWriteAddress; USHORT usRegWriteCount; UCHAR *ucMBFrame; 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_READWRITE_SIZE_MIN ) { vMBMasterGetPDUSndBuf(&ucMBFrame); usRegReadAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] << 8U ); usRegReadAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1] ); usRegReadAddress++; usRegReadCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF] << 8U ); usRegReadCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1] ); usRegWriteAddress = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF] << 8U ); usRegWriteAddress |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1] ); usRegWriteAddress++; usRegWriteCount = ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF] << 8U ); usRegWriteCount |= ( USHORT )( ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] ); if( ( 2 * usRegReadCount ) == pucFrame[MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF] ) { /* Make callback to update the register values. */ eRegStatus = eMBMasterRegHoldingCB( &ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF], usRegWriteAddress, usRegWriteCount, MB_REG_WRITE ); if( eRegStatus == MB_ENOERR ) { /* Make the read callback. */ eRegStatus = eMBMasterRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF], usRegReadAddress, usRegReadCount, MB_REG_READ); } if( eRegStatus != MB_ENOERR ) { eStatus = prveMBError2Exception( eRegStatus ); } } else { eStatus = MB_EX_ILLEGAL_DATA_VALUE; } } return eStatus; }
eMBException eMBMasterFuncWriteMultipleHoldingRegister(uint8_t *pucFrame, uint16_t *usLen) { uint8_t *ucMBFrame; uint16_t usRegAddress; uint16_t usRegCount; uint8_t ucRegByteCount; eMBException eStatus = MB_EX_NONE; eMBErrorCode eRegStatus; /* If this request is broadcast, the *usLen is not need check. */ if ((*usLen == MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE) || xMBMasterRequestIsBroadcast()) { vMBMasterGetPDUSndBuf(&ucMBFrame); usRegAddress = (uint16_t) (ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] << 8); usRegAddress |= (uint16_t) (ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1]); usRegAddress++; usRegCount = (uint16_t) (ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF] << 8); usRegCount |= (uint16_t) (ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1]); ucRegByteCount = ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF]; if (ucRegByteCount == 2 * usRegCount) { /* Make callback to update the register values. */ eRegStatus = eMBMasterRegHoldingCB(&ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF], usRegAddress, usRegCount, MB_REG_WRITE); /* If an error occured convert it into a Modbus exception. */ if (eRegStatus != MB_ENOERR) { eStatus = prveMBError2Exception(eRegStatus); } } else { eStatus = MB_EX_ILLEGAL_DATA_VALUE; } } else { /* Can't be a valid request because the length is incorrect. */ eStatus = MB_EX_ILLEGAL_DATA_VALUE; } return eStatus; }
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; }
eMBMasterReqErrCode eMBMasterReqReadWriteMultipleHoldingRegister(uint8_t ucSndAddr, uint16_t usReadRegAddr, uint16_t usNReadRegs, uint16_t *pusDataBuffer, uint16_t usWriteRegAddr, uint16_t usNWriteRegs, uint32_t lTimeOut) { uint8_t *ucMBFrame; uint16_t usRegIndex = 0; eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; if (ucSndAddr > CONFIG_MB_MASTER_TOTAL_SLAVE_NUM) { eErrStatus = MB_MRE_ILL_ARG; } else if (xMBMasterRunResTake(lTimeOut) == false) { eErrStatus = MB_MRE_MASTER_BUSY; } else { vMBMasterGetPDUSndBuf(&ucMBFrame); vMBMasterSetDestAddress(ucSndAddr); ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READWRITE_MULTIPLE_REGISTERS; ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] = usReadRegAddr >> 8; ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1] = usReadRegAddr; ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF] = usNReadRegs >> 8; ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1] = usNReadRegs; ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF] = usWriteRegAddr >> 8; ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1] = usWriteRegAddr; ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF] = usNWriteRegs >> 8; ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] = usNWriteRegs; ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF] = usNWriteRegs * 2; ucMBFrame += MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF; while (usNWriteRegs > usRegIndex) { *ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8; *ucMBFrame++ = pusDataBuffer[usRegIndex++]; } vMBMasterSetPDUSndLength(MB_PDU_SIZE_MIN + MB_PDU_REQ_READWRITE_SIZE_MIN + 2 * usNWriteRegs); (void)xMBMasterPortEventPost(EV_MASTER_FRAME_SENT); eErrStatus = eMBMasterWaitRequestFinish(); } return eErrStatus; }
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 an error occured convert it into a Modbus exception. */ if( eRegStatus != MB_ENOERR ) { eStatus = prveMBError2Exception( eRegStatus ); } } else { eStatus = MB_EX_ILLEGAL_DATA_VALUE; } } else { /* Can't be a valid request because the length is incorrect. */ eStatus = MB_EX_ILLEGAL_DATA_VALUE; } return eStatus; }
/** * This function will request write holding register. * * @param ucSndAddr salve address * @param usRegAddr register start address * @param usRegData register data to be written * @param lTimeOut timeout (-1 will waiting forever) * * @return error code */ eMBMasterReqErrCode eMBMasterReqWriteHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut ) { UCHAR *ucMBFrame; eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; else { vMBMasterGetPDUSndBuf(&ucMBFrame); vMBMasterSetDestAddress(ucSndAddr); ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_REGISTER; ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF] = usRegAddr >> 8; ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1] = usRegAddr; ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF] = usRegData >> 8; ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usRegData ; vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); } return eErrStatus; }
eMBMasterReqErrCode eMBMasterReqReadHoldingRegister( UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs ) { UCHAR *ucMBFrame; eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; if ( xMBMasterGetIsBusy() ) eErrStatus = MB_MRE_MASTER_BUSY; else if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; else { vMBMasterGetPDUSndBuf(&ucMBFrame); vMBMasterSetDestAddress(ucSndAddr); ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_HOLDING_REGISTER; ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usRegAddr >> 8; ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usRegAddr; ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8; ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs; vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); } return eErrStatus; }
eMBMasterReqErrCode eMBMasterReqWriteCoil(uint8_t ucSndAddr, uint16_t usCoilAddr, uint16_t usCoilData, uint32_t lTimeOut) { uint8_t *ucMBFrame; eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; if (ucSndAddr > CONFIG_MB_MASTER_TOTAL_SLAVE_NUM) { eErrStatus = MB_MRE_ILL_ARG; } else if ((usCoilData != 0xFF00) && (usCoilData != 0x0000)) { eErrStatus = MB_MRE_ILL_ARG; } else if (xMBMasterRunResTake(lTimeOut) == false) { eErrStatus = MB_MRE_MASTER_BUSY; } else { vMBMasterGetPDUSndBuf(&ucMBFrame); vMBMasterSetDestAddress(ucSndAddr); ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_SINGLE_COIL; ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF] = usCoilAddr >> 8; ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1] = usCoilAddr; ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF] = usCoilData >> 8; ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usCoilData; vMBMasterSetPDUSndLength(MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE); (void)xMBMasterPortEventPost(EV_MASTER_FRAME_SENT); eErrStatus = eMBMasterWaitRequestFinish(); } return eErrStatus; }
/** * This function will request read coil. * * @param ucSndAddr salve address * @param usCoilAddr coil start address * @param usNCoils coil total number * @param lTimeOut timeout (-1 will waiting forever) * * @return error code */ eMBMasterReqErrCode eMBMasterReqReadCoils( UCHAR ucSndAddr, USHORT usCoilAddr, USHORT usNCoils ,LONG lTimeOut ) { UCHAR *ucMBFrame; eMBMasterReqErrCode eErrStatus = MB_MRE_NO_ERR; if ( ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM ) eErrStatus = MB_MRE_ILL_ARG; //else if ( xMBMasterRunResTake( lTimeOut ) == FALSE ) eErrStatus = MB_MRE_MASTER_BUSY; else { vMBMasterGetPDUSndBuf(&ucMBFrame); vMBMasterSetDestAddress(ucSndAddr); ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_COILS; ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usCoilAddr >> 8; ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usCoilAddr; ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF ] = usNCoils >> 8; ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1] = usNCoils; vMBMasterSetPDUSndLength( MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE ); ( void ) xMBMasterPortEventPost( EV_MASTER_FRAME_SENT ); eErrStatus = eMBMasterWaitRequestFinish( ); } return eErrStatus; }
eMBException eMBMasterFuncReadCoils(uint8_t *pucFrame, uint16_t *usLen) { uint8_t *ucMBFrame; uint16_t usRegAddress; uint16_t usCoilCount; uint8_t ucByteCount; 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 = (uint16_t) (ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8); usRegAddress |= (uint16_t) (ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1]); usRegAddress++; usCoilCount = (uint16_t) (ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF] << 8); usCoilCount |= (uint16_t) (ucMBFrame[MB_PDU_REQ_READ_COILCNT_OFF + 1]); /* Test if the quantity of coils is a multiple of 8. If not last byte is * only partially field with unused coils set to zero. */ if ((usCoilCount & 0x0007) != 0) { ucByteCount = (uint8_t) (usCoilCount / 8 + 1); } else { ucByteCount = (uint8_t) (usCoilCount / 8); } /* Check if the number of registers to read is valid. If not return * Modbus illegal data value exception. */ if ((usCoilCount >= 1) && (ucByteCount == pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF])) { /* Make callback to fill the buffer. */ eRegStatus = eMBMasterRegCoilsCB(&pucFrame[MB_PDU_FUNC_READ_VALUES_OFF], usRegAddress, usCoilCount, MB_REG_READ); /* If an error occurred convert it into a Modbus exception. */ if (eRegStatus != MB_ENOERR) { eStatus = prveMBError2Exception(eRegStatus); } } else { eStatus = MB_EX_ILLEGAL_DATA_VALUE; } } else { /* Can't be a valid read coil register request because the length is * incorrect. */ eStatus = MB_EX_ILLEGAL_DATA_VALUE; } return eStatus; }
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; } }