移植FreeModbus到FreeRTOS系统上

实测连接西门子的组态屏运行正常

1、串口驱动移植
portserial.c

BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits,
        eMBParity eParity)
{
	modubs_user_usart_init();
	
	__HAL_UART_DISABLE( &huart3 );
	
	__HAL_UART_DISABLE_IT( &huart3, UART_IT_TXE );
	__HAL_UART_DISABLE_IT( &huart3, UART_IT_RXNE );
	__HAL_UART_CLEAR_FLAG( &huart3, UART_FLAG_TC | UART_FLAG_RXNE );
	
	__HAL_UART_ENABLE( &huart3 );

    return TRUE;
}

void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable)
{
    if(xRxEnable == TRUE)
	{
		__HAL_UART_ENABLE_IT( &huart3, UART_IT_RXNE );
	}
	else
	{
		__HAL_UART_DISABLE_IT( &huart3, UART_IT_RXNE );
	}

	if(xTxEnable == TRUE)
	{
		__HAL_UART_ENABLE_IT( &huart3, UART_IT_TXE );
	}
	else
	{
		__HAL_UART_DISABLE_IT( &huart3, UART_IT_TXE );
	}
}

void vMBPortClose(void)
{
    
}

BOOL xMBPortSerialPutByte(CHAR ucByte)
{
//	modbus_user_send_byte(ucByte);
	huart3.Instance->DR = (ucByte & (uint16_t)0x01FF);
    return TRUE;
}

BOOL xMBPortSerialGetByte(CHAR * pucByte)
{
//	modbus_user_recv_byte(pucByte);
	*pucByte = (uint16_t)(huart3.Instance->DR & (uint16_t)0x01FF);
    return TRUE;
}

初始化,使能接收发送,发送字节,接收字节等几个函数

2、portevent.c

/* ----------------------- Variables ----------------------------------------*/
static eMBEventType eQueuedEvent;
static BOOL     xEventInQueue;

/* ----------------------- Start implementation -----------------------------*/
BOOL
xMBPortEventInit( void )
{
    xEventInQueue = FALSE;
    return TRUE;
}

BOOL
xMBPortEventPost( eMBEventType eEvent )
{
    xEventInQueue = TRUE;
    eQueuedEvent = eEvent;
		
    return TRUE;
}

BOOL
xMBPortEventGet( eMBEventType * eEvent )
{
    BOOL            xEventHappened = FALSE;

    if( xEventInQueue )
    {
        *eEvent = eQueuedEvent;
        xEventInQueue = FALSE;
        xEventHappened = TRUE;
    }
    return xEventHappened;
}

FreeRTOS中的事件接口

3、porttimer.c

BOOL xMBPortTimersInit(USHORT usTim1Timerout50us)
{
	modbus_user_timer_init();
	
	__HAL_TIM_CLEAR_IT( &htim6, TIM_IT_UPDATE );
	__HAL_TIM_ENABLE_IT( &htim6, TIM_IT_UPDATE );
    return TRUE;
}

void vMBPortTimersEnable()
{
	__HAL_TIM_SET_COUNTER( &htim6, 0 );
	
	HAL_TIM_Base_Start( &htim6 );
}

void vMBPortTimersDisable()
{
	HAL_TIM_Base_Stop( &htim6 );
}

void prvvTIMERExpiredISR(void)
{
    (void) pxMBPortCBTimerExpired();
}

需要使用硬件定时器,系统定时器速度跟不上

4、modbus线程

void moudbus_user_task(void* parameter)
{
	TickType_t ticks = xTaskGetTickCount();
	eMBInit(MB_RTU, 0x01, 1, 115200,  MB_PAR_EVEN);
	eMBEnable();
	while (1)
	{
		eMBPoll();
		modbus_user_variate_limit();
		daemon_refresh();
		//一ms一个处理周期
		vTaskDelayUntil( &ticks, 1 );
	}
}

建立一个处理modbus数据处理的线程,主要调用函数是eMBPoll();

5、modbus回调函数,PC端数据与单片机端数据交互

RTN_T modbus_user_reg_cb(uint8_t * buffer, uint16_t address, uint16_t nregs, eMBRegisterMode mode){
	
//	uint8_t slave_addr;
	
	DEVICE_T	*device_ptr=NULL;
	void		*modbus_ptr=NULL;
	SENSOR_T	*sensor_ptr=NULL;			
	SYS_INTERACTION_T *sys_interaction_ptr = &master_working.sys_interaction;
	
	modbus_user_log("orig address %d\r\n",address);
	modbus_user_log("orig nregs %d\r\n",nregs);
	
//	modbus_user_log("get slave %d\r\n",slave_addr);
//	modbus_user_log("get address %d\r\n",address);
	
	。。。。。。。。。。
	
	if( mode==MB_REG_READ ){
		modubs_user_read_reg((uint16_t*)modbus_ptr,buffer,address,nregs);
	}
	else if( mode==MB_REG_WRITE ){
		master_config.write_time = 0;
		master_config.modbus_write = CONFIG_WRITE_ONCE;
		modubs_user_write_reg((uint16_t*)modbus_ptr,buffer,address,nregs);
	}
	return RTN_OK;
}

主要由mode变量决定的读写操作,modbus_ptr决定读写的地址,由回调函数传入地址计算偏移地址得到

源码下载地址:https://download.csdn.net/download/dmjkun/10889623

你可能感兴趣的:(FreeRTOS,Modbus)