STM32驅動w5500移植FreeModbus實現ModbusTCP

首先我們下載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;
}


完整代碼下載STM32驅動w5500移植FreeModbus實現ModbusTCP完整代碼下載

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章