相比libmodbus,
freeModbus看起来更舒服。
1. 文件与函数:FreeModbus每个文件函数都不是很多。客户端、服务端函数分开。相对每个函数功能比较明确
freeModbus
mbfuncholding_m.c、mbfuncholding.c
函数一共就几个,只看函数列表就猜到函数功能
服务端函数有Master标识
服务端
客户端
libModbus
modbus.c一坨50多个函数。
不认真看,不知道是什么函数
框起了服务器、客户端寄存器函数
2. 文件命名 清晰服务端和客户端函数独立分开
freemodbus:_m结尾的文件是master(服务端)函数
_m服务器文件通过宏定义判断是否编译
libmodbus
要根据MSG_CONFIRMATION判断是服务端还是客户端写寄存器
函数写的很大
3. 写寄存器函数
libModbus
写寄存器-客户端
请求写寄存器-服务端
freeModbus
#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0/*** 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 ( 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_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 );eErrStatus = eMBMasterWaitRequestFinish( );}return eErrStatus;
}
客户端写寄存器
#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0
eMBException
eMBFuncWriteMultipleHoldingRegister( UCHAR * pucFrame, USHORT * usLen )
{USHORT usRegAddress;USHORT usRegCount;UCHAR ucRegByteCount;eMBException eStatus = MB_EX_NONE;eMBErrorCode eRegStatus;if( *usLen >= ( MB_PDU_FUNC_WRITE_MUL_SIZE_MIN + MB_PDU_SIZE_MIN ) ){usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8 );usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1] );usRegAddress++;usRegCount = ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF] << 8 );usRegCount |= ( USHORT )( pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF + 1] );ucRegByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF];if( ( usRegCount >= 1 ) &&( usRegCount <= MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX ) &&( ucRegByteCount == ( UCHAR ) ( 2 * usRegCount ) ) ){/* Make callback to update the register values. */eRegStatus =eMBRegHoldingCB( &pucFrame[MB_PDU_FUNC_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{/* The response contains the function code, the starting* address and the quantity of registers. We reuse the* old values in the buffer because they are still valid.*/*usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF;}}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;
}
#endif
4. 配置文件:freemodbus条件编译文件更小
freemodbus通过启宏定义开启编译,
裁剪了不用的代码,应该可以做的比较小
freeModbus
/*! \brief If Modbus Master ASCII support is enabled. */
#define MB_MASTER_ASCII_ENABLED ( 0 )
/*! \brief If Modbus Master RTU support is enabled. */
#define MB_MASTER_RTU_ENABLED ( 1 )
/*! \brief If Modbus Master TCP support is enabled. */
#define MB_MASTER_TCP_ENABLED ( 0 )
/*! \brief If Modbus Slave ASCII support is enabled. */
#define MB_SLAVE_ASCII_ENABLED ( 0 )
/*! \brief If Modbus Slave RTU support is enabled. */
#define MB_SLAVE_RTU_ENABLED ( 1 )
/*! \brief If Modbus Slave TCP support is enabled. */
#define MB_SLAVE_TCP_ENABLED ( 0 )
/*! \brief The character timeout value for Modbus ASCII.** The character timeout value is not fixed for Modbus ASCII and is therefore* a configuration option. It should be set to the maximum expected delay* time of the network.*/
#define MB_ASCII_TIMEOUT_SEC ( 1 )
/*! \brief Maximum number of Modbus functions codes the protocol stack* should support.** The maximum number of supported Modbus functions must be greater than* the sum of all enabled functions in this file and custom function* handlers. If set to small adding more functions will fail.*/
#define MB_FUNC_HANDLERS_MAX ( 16 )
/*! \brief Number of bytes which should be allocated for the <em>Report Slave ID* </em>command.** This number limits the maximum size of the additional segment in the* report slave id function. See eMBSetSlaveID( ) for more information on* how to set this value. It is only used if MB_FUNC_OTHER_REP_SLAVEID_ENABLED* is set to <code>1</code>.*/
#define MB_FUNC_OTHER_REP_SLAVEID_BUF ( 32 )
/*! \brief If the <em>Report Slave ID</em> function should be enabled. */
#define MB_FUNC_OTHER_REP_SLAVEID_ENABLED ( 1 )
/*! \brief If the <em>Read Input Registers</em> function should be enabled. */
#define MB_FUNC_READ_INPUT_ENABLED ( 1 )
/*! \brief If the <em>Read Holding Registers</em> function should be enabled. */
#define MB_FUNC_READ_HOLDING_ENABLED ( 1 )
/*! \brief If the <em>Write Single Register</em> function should be enabled. */
#define MB_FUNC_WRITE_HOLDING_ENABLED ( 1 )
/*! \brief If the <em>Write Multiple registers</em> function should be enabled. */
#define MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED ( 1 )
/*! \brief If the <em>Read Coils</em> function should be enabled. */
#define MB_FUNC_READ_COILS_ENABLED ( 1 )
/*! \brief If the <em>Write Coils</em> function should be enabled. */
#define MB_FUNC_WRITE_COIL_ENABLED ( 1 )
/*! \brief If the <em>Write Multiple Coils</em> function should be enabled. */
#define MB_FUNC_WRITE_MULTIPLE_COILS_ENABLED ( 1 )
/*! \brief If the <em>Read Discrete Inputs</em> function should be enabled. */
#define MB_FUNC_READ_DISCRETE_INPUTS_ENABLED ( 1 )
/*! \brief If the <em>Read/Write Multiple Registers</em> function should be enabled. */
#define MB_FUNC_READWRITE_HOLDING_ENABLED ( 1 )
libModbus
没看到什么配置文件。
_modbus_set_slave设置服务端 or 客户端
/* Define the slave ID of the remote device to talk in master mode or set the* internal slave ID in slave mode */
static int _modbus_set_slave(modbus_t *ctx, int slave)
{int max_slave = (ctx->quirks & MODBUS_QUIRK_MAX_SLAVE) ? 255 : 247;/* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */if (slave >= 0 && slave <= max_slave) {ctx->slave = slave;} else {errno = EINVAL;return -1;}return 0;
}
5. 移植
libMobus
modbus-rtu.c串口收发、初始化函数
const modbus_backend_t _modbus_rtu_backend = {_MODBUS_BACKEND_TYPE_RTU,_MODBUS_RTU_HEADER_LENGTH,_MODBUS_RTU_CHECKSUM_LENGTH,MODBUS_RTU_MAX_ADU_LENGTH,_modbus_set_slave,_modbus_rtu_build_request_basis,_modbus_rtu_build_response_basis,_modbus_rtu_prepare_response_tid,_modbus_rtu_send_msg_pre,_modbus_rtu_send,_modbus_rtu_receive,_modbus_rtu_recv,_modbus_rtu_check_integrity,_modbus_rtu_pre_check_confirmation,_modbus_rtu_connect,_modbus_rtu_is_connected,_modbus_rtu_close,_modbus_rtu_flush,_modbus_rtu_select,_modbus_rtu_free
};
freeModbus
port文件夹
嵌入式常见软件包