首先我们下载FreeModbus源码,然后放到自己的工程中,新建一个MODBUS_TCP和PORT_TCP文件夹,然后将相关文件复制到里面,如下图所示:
然后修改porttcp中的代码:
首先定义一个数组用于接收数据:- static UCHAR aucTCPBuf[MB_TCP_BUF_SIZE]; //接收缓冲区
复制代码
然后在xMBTCPPortInit中初始化socket连接,然后监听端口。
- BOOL
- xMBTCPPortInit( USHORT usTCPPort )
- {
- BOOL bOkay = FALSE;
- // 侦听端口 Modbus-TCP 端口
- socket_init(SOCK_TCP_PORT,Sn_MR_TCP_TCP,local_tcp_port++,Sn_MR_ND_TCP);
- listen_tcp_socket(SOCK_TCP_PORT);
- bOkay = TRUE;
- return bOkay;
- }
复制代码
然后在xMBTCPPortSendResponse函数中发送数据
- BOOL
- xMBTCPPortSendResponse(const UCHAR * pucMBTCPFrame, USHORT usTCPLength )
- {
- send_tcp_socket_data(SOCK_TCP_PORT,(UCHAR*)pucMBTCPFrame,usTCPLength);
- return TRUE;
- }
复制代码
然后在xMBPortTCPPool执行接收和其他操作
- BOOL
- xMBPortTCPPool( void )
- {
- unsigned short int us_rlen;
- unsigned char i;
- i=get_tcp_socket_state(SOCK_TCP_PORT);
- if(i==SOCK_ESTABLISHED_TCP)
- {
- if(get_tcp_socket_irq(SOCK_TCP_PORT) & Sn_IR_CON_TCP) //查看中断有没有发生
- {
- clear_tcp_socket_irq(SOCK_TCP_PORT, Sn_IR_CON_TCP); /*清除接收中断标志位*/
- }
- us_rlen=get_tcp_rx_buffer_size(SOCK_TCP_PORT); //获取接收到的数据字节 /*定义len为已接收数据的长度*/
- if(us_rlen==0) //没有接收到数据
- return FALSE; //返回
- else
- {
- recv_tcp_socket_data(SOCK_TCP_PORT,aucTCPBuf,us_rlen); //接收数据 /*接收来自Server的数据*/
- printf("receive\r\n");
- usTCPBufLen=us_rlen;
- }
- ( void )xMBPortEventPost( EV_FRAME_RECEIVED ); //发送已接收到新数据到Modbus-TCP状态机
- }
- else if(i==SOCK_CLOSED_TCP) //如果socket关闭
- {
- socket_init(SOCK_TCP_PORT,Sn_MR_TCP_TCP,local_tcp_port++,Sn_MR_ND_TCP);//重新初始化
- }
- else if(i==SOCK_INIT_TCP) //如果socket初始化完毕,监听端口
- {
- listen_tcp_socket(SOCK_TCP_PORT);
- }
- else if(i==SOCK_CLOSE_WAIT_TCP) //如果socket等待关闭,关闭socket连接
- {
- close_tcp_socket(SOCK_TCP_PORT);
- }
- return TRUE;
- }
复制代码
其次还要实现读线圈、写线圈、读离散输入、写保持寄存器、读保持寄存器、读输入寄存器等功能,如下:
- #define REG_INPUT_START 0x0001 //输入寄存器起始地址
- #define REG_INPUT_NREGS 8 //输入寄存器数量
- #define REG_HOLDING_START 0x0001 //保持寄存器起始地址
- #define REG_HOLDING_NREGS 8 //保持寄存器数量
- #define REG_COILS_START 0x0001 //线圈起始地址
- #define REG_COILS_SIZE 16 //线圈数量
- #define REG_DISCRETE_START 0x0001 //开关寄存器其实地址
- #define REG_DISCRETE_SIZE 16 //开关寄存器数量
- //输入寄存器内容
- uint16_t usRegInputBuf[REG_INPUT_NREGS] = {0x1000,0x1001,0x1002,0x1003,0x1004,0x1005,0x1006,0x1007};
- //保持寄存器内容
- uint16_t usRegHoldingBuf[REG_HOLDING_NREGS] = {0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,0x2006,0x2007};
- //线圈状态
- uint8_t ucRegCoilsBuf[REG_COILS_SIZE] = {0x01,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00};
- //离散寄存器内容
- uint8_t ucRegDiscreteBuf[REG_DISCRETE_SIZE] = {0x01,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x01};
- /****************************************************************************
- * 名 称:eMBRegInputCB
- * 功 能:读取输入寄存器,对应功能码是 04 eMBFuncReadInputRegister
- * 入口参数:pucRegBuffer: 数据缓存区,用于响应主机
- * usAddress: 寄存器地址
- * usNRegs: 要读取的寄存器个数
- * 出口参数:
- * 注 意:上位机发来的 帧格式是: SlaveAddr(1 Byte)+FuncCode(1 Byte)
- * +StartAddrHiByte(1 Byte)+StartAddrLoByte(1 Byte)
- * +LenAddrHiByte(1 Byte)+LenAddrLoByte(1 Byte)+
- * +CRCAddrHiByte(1 Byte)+CRCAddrLoByte(1 Byte)
- * 3 区
- ****************************************************************************/
- eMBErrorCode
- eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
- {
- eMBErrorCode eStatus = MB_ENOERR;
- int iRegIndex;
- if( ( usAddress >= REG_INPUT_START )
- && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
- {
- iRegIndex = ( int )( usAddress - REG_INPUT_START );
- while( usNRegs > 0 )
- {
- *pucRegBuffer++ = ( UCHAR )( usRegInputBuf[iRegIndex] >> 8 );
- *pucRegBuffer++ = ( UCHAR )( usRegInputBuf[iRegIndex] & 0xFF );
- iRegIndex++;
- usNRegs--;
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- /****************************************************************************
- * 名 称:eMBRegHoldingCB
- * 功 能:对应功能码有:06 写保持寄存器 eMBFuncWriteHoldingRegister
- * 16 写多个保持寄存器 eMBFuncWriteMultipleHoldingRegister
- * 03 读保持寄存器 eMBFuncReadHoldingRegister
- * 23 读写多个保持寄存器 eMBFuncReadWriteMultipleHoldingRegister
- * 入口参数:pucRegBuffer: 数据缓存区,用于响应主机
- * usAddress: 寄存器地址
- * usNRegs: 要读写的寄存器个数
- * eMode: 功能码
- * 出口参数:
- * 注 意:4 区
- ****************************************************************************/
- eMBErrorCode
- eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
- {
- eMBErrorCode eStatus = MB_ENOERR;
- int iRegIndex;
- if((usAddress >= REG_HOLDING_START)&&\
- ((usAddress+usNRegs) <= (REG_HOLDING_START + REG_HOLDING_NREGS)))
- {
- iRegIndex = (int)(usAddress - REG_HOLDING_START);
- switch(eMode)
- {
- case MB_REG_READ://读 MB_REG_READ = 0
- while(usNRegs > 0)
- {
- *pucRegBuffer++ = (u8)(usRegHoldingBuf[iRegIndex] >> 8);
- *pucRegBuffer++ = (u8)(usRegHoldingBuf[iRegIndex] & 0xFF);
- iRegIndex++;
- usNRegs--;
- }
- break;
- case MB_REG_WRITE://写 MB_REG_WRITE = 0
- while(usNRegs > 0)
- {
- usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
- usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
- iRegIndex++;
- usNRegs--;
- }
- break;
- }
- }
- else//错误
- {
- eStatus = MB_ENOREG;
- }
-
- return eStatus;
- }
- /****************************************************************************
- * 名 称:eMBRegCoilsCB
- * 功 能:对应功能码有:01 读线圈 eMBFuncReadCoils
- * 05 写线圈 eMBFuncWriteCoil
- * 15 写多个线圈 eMBFuncWriteMultipleCoils
- * 入口参数:pucRegBuffer: 数据缓存区,用于响应主机
- * usAddress: 线圈地址
- * usNCoils: 要读写的线圈个数
- * eMode: 功能码
- * 出口参数:
- * 注 意:如继电器
- * 0 区
- ****************************************************************************/
- eMBErrorCode
- eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
- {
- eMBErrorCode eStatus = MB_ENOERR;
- int iRegIndex;
- u8 i;
- USHORT readNumber=usNCoils;
- USHORT coilValue=0x0000;
- if((usAddress >= REG_COILS_START)&&\
- ((usAddress+usNCoils) <= (REG_COILS_START + REG_COILS_SIZE)))
- {
- iRegIndex = (int)(usAddress + usNCoils-REG_COILS_START);
- switch(eMode)
- {
- case MB_REG_READ://读 MB_REG_READ = 0
- for(i=0;i<usNCoils;i++)
- {
- readNumber--;
- iRegIndex--;
- coilValue|=ucRegCoilsBuf[iRegIndex]<<readNumber;
- }
- if(usNCoils<=8)
- {
- * pucRegBuffer=coilValue;
- }
- else
- {
- * pucRegBuffer++ = (coilValue)&0x00ff;
- * pucRegBuffer++ = (coilValue>>8)&0x00ff;
- }
- break;
- case MB_REG_WRITE://写 MB_REG_WRITE = 1
- while(usNCoils > 0)
- {
- // usRegHoldingBuf[iRegIndex] = *pucRegBuffer++ << 8;
- // usRegHoldingBuf[iRegIndex] |= *pucRegBuffer++;
- iRegIndex++;
- usNCoils--;
- }
- break;
- }
- }
- else//错误
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
- /****************************************************************************
- * 名 称:eMBRegDiscreteCB
- * 功 能:读取离散寄存器,对应功能码有:02 读离散寄存器 eMBFuncReadDiscreteInputs
- * 入口参数:pucRegBuffer: 数据缓存区,用于响应主机
- * usAddress: 寄存器地址
- * usNDiscrete: 要读取的寄存器个数
- * 出口参数:
- * 注 意:1 区
- ****************************************************************************/
- eMBErrorCode
- eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
- {
- eMBErrorCode eStatus = MB_ENOERR;
- int iRegIndex;
- u8 i;
- USHORT readNumber=usNDiscrete;
- USHORT coilValue=0x0000;
- iRegIndex = (int)(usAddress + usNDiscrete-REG_DISCRETE_START);
- if((usAddress >= REG_DISCRETE_START)&&\
- ((usAddress+usNDiscrete) <= (REG_DISCRETE_START + REG_DISCRETE_SIZE)))
- {
- for(i=0;i<usNDiscrete;i++)
- {
- readNumber--;
- iRegIndex--;
- coilValue|=ucRegDiscreteBuf[iRegIndex]<<readNumber;
- }
- if(usNDiscrete<=8)
- {
- * pucRegBuffer=coilValue;
- }
- else
- {
- * pucRegBuffer++ = (coilValue)&0x00ff;
- * pucRegBuffer++ = (coilValue>>8)&0x00ff;
- }
- }
- else
- {
- eStatus = MB_ENOREG;
- }
- return eStatus;
- }
复制代码
|