实测连接西门子的组态屏运行正常
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