diff --git a/BSP/inc/bsp.h b/BSP/inc/bsp.h index 74d1f07..1f6002c 100644 --- a/BSP/inc/bsp.h +++ b/BSP/inc/bsp.h @@ -48,6 +48,7 @@ /* RT_USING_UART */ #define RT_USING_UART3 +#define RT_USING_UART2 #define RT_USING_UART1 #define RT_UART_RX_BUFFER_SIZE 64 diff --git a/BSP/src/usart.c b/BSP/src/usart.c index ebcc908..3770e5e 100644 --- a/BSP/src/usart.c +++ b/BSP/src/usart.c @@ -86,8 +86,6 @@ static rt_err_t stm32_configure(struct rt_serial_device *serial, struct serial_c /* Enable USART */ USART_Cmd(uart->uart_device, ENABLE); - /* enable interrupt */ - USART_ITConfig(uart->uart_device, USART_IT_RXNE, ENABLE); return RT_EOK; } diff --git a/FreeModbus/port/rtt/portserial.c b/FreeModbus/port/rtt/portserial.c index e49852b..e892b56 100644 --- a/FreeModbus/port/rtt/portserial.c +++ b/FreeModbus/port/rtt/portserial.c @@ -123,8 +123,6 @@ BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, rt_thread_startup(&thread_serial_soft_trans_irq); rt_event_init(&event_serial, "slave event", RT_IPC_FLAG_PRIO); - - return TRUE; } diff --git a/FreeModbus/port/rtt/portserial_m.c b/FreeModbus/port/rtt/portserial_m.c index 37660ec..e88701f 100644 --- a/FreeModbus/port/rtt/portserial_m.c +++ b/FreeModbus/port/rtt/portserial_m.c @@ -24,124 +24,162 @@ /* ----------------------- Modbus includes ----------------------------------*/ #include "mb.h" #include "mbport.h" +#include "rtdevice.h" +#include "bsp.h" #if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 +/* ----------------------- Static variables ---------------------------------*/ +ALIGN(RT_ALIGN_SIZE) +/* software simulation serial transmit IRQ handler thread stack */ +static rt_uint8_t serial_soft_trans_irq_stack[512]; +/* software simulation serial transmit IRQ handler thread */ +static struct rt_thread thread_serial_soft_trans_irq; +/* serial event */ +static struct rt_event event_serial; +/* modbus slave serial device */ +static rt_serial_t *serial; + +/* ----------------------- Defines ------------------------------------------*/ +/* serial transmit event */ +#define EVENT_SERIAL_TRANS_START (1<<0) + /* ----------------------- static functions ---------------------------------*/ static void prvvUARTTxReadyISR(void); static void prvvUARTRxISR(void); +static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size); +static void serial_soft_trans_irq(void* parameter); + /* ----------------------- Start implementation -----------------------------*/ +BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, + eMBParity eParity) +{ + GPIO_InitTypeDef GPIO_InitStructure; + + /* set 485 model receive and transmit control IO */ + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + /* set serial name */ + if (ucPORT == 1) { +#if defined(RT_USING_UART1) || defined(RT_USING_REMAP_UART1) + extern struct rt_serial_device serial1; + serial = &serial1; +#endif + } else if (ucPORT == 2) { +#if defined(RT_USING_UART2) + extern struct rt_serial_device serial2; + serial = &serial2; +#endif + } else if (ucPORT == 3) { +#if defined(RT_USING_UART3) + extern struct rt_serial_device serial3; + serial = &serial3; +#endif + } + /* set serial configure parameter */ + serial->config.baud_rate = ulBaudRate; + serial->config.stop_bits = STOP_BITS_1; + switch(eParity){ + case MB_PAR_NONE: { + serial->config.data_bits = DATA_BITS_8; + serial->config.parity = PARITY_NONE; + break; + } + case MB_PAR_ODD: { + serial->config.data_bits = DATA_BITS_9; + serial->config.parity = PARITY_ODD; + break; + } + case MB_PAR_EVEN: { + serial->config.data_bits = DATA_BITS_9; + serial->config.parity = PARITY_EVEN; + break; + } + } + /* disable all interrupt */ + ENTER_CRITICAL_SECTION(); + /* set serial configure */ + serial->ops->configure(serial, &(serial->config)); + + /* resume all interrupt */ + EXIT_CRITICAL_SECTION(); + /* open serial device */ + if (!serial->parent.open(&serial->parent, + RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX )) { + serial->parent.rx_indicate = serial_rx_ind; + } else { + return FALSE; + } + + /* software initialize */ + rt_thread_init(&thread_serial_soft_trans_irq, + "slave trans", + serial_soft_trans_irq, + RT_NULL, + serial_soft_trans_irq_stack, + sizeof(serial_soft_trans_irq_stack), + 10, 5); + rt_thread_startup(&thread_serial_soft_trans_irq); + rt_event_init(&event_serial, "slave event", RT_IPC_FLAG_PRIO); + + return TRUE; +} void vMBMasterPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) { + rt_uint32_t recved_event; if (xRxEnable) { - /* 485通信时,等待串口移位寄存器中的数据发送完成后,再去使能485的接收、失能485的发送*/ - while (!USART_GetFlagStatus(USART2,USART_FLAG_TC)); - MASTER_RS485_RECEIVE_MODE; - USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); + /* waiting for last transmit complete */ + while (1) + { + if (serial->ops->control(serial, RT_DEVICE_CTRL_GET_FLAG, (void *)RT_DEVICE_FLAG_INT_TX)) + { + break; + } + } + /* enable RX interrupt */ + serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX); + /* switch 485 to receive mode */ + SLAVE_RS485_RECEIVE_MODE; } else { - MASTER_RS485_TRANS_MODE; - USART_ITConfig(USART2, USART_IT_RXNE, DISABLE); + /* switch 485 to transmit mode */ + SLAVE_RS485_TRANS_MODE; + /* disable RX interrupt */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *)RT_DEVICE_FLAG_INT_RX); } if (xTxEnable) { - USART_ITConfig(USART2, USART_IT_TXE, ENABLE); + /* start serial transmit */ + rt_event_send(&event_serial, EVENT_SERIAL_TRANS_START); } else { - USART_ITConfig(USART2, USART_IT_TXE, DISABLE); + /* stop serial transmit */ + rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 0, + &recved_event); } } void vMBMasterPortClose(void) { - USART_ITConfig(USART2, USART_IT_TXE | USART_IT_RXNE, DISABLE); - USART_Cmd(USART2, DISABLE); -} -//默认一个主机 串口2 波特率可设置 奇偶检验可设置 -BOOL xMBMasterPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, - eMBParity eParity) -{ - GPIO_InitTypeDef GPIO_InitStructure; - USART_InitTypeDef USART_InitStructure; - NVIC_InitTypeDef NVIC_InitStructure; - //======================时钟初始化======================================= - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); - RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); - //======================IO初始化======================================= - //USART2_TX - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; - GPIO_Init(GPIOA, &GPIO_InitStructure); - //USART2_RX - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; - GPIO_Init(GPIOA, &GPIO_InitStructure); - //配置485发送和接收模式 -// TODO 暂时先写B13 等之后组网测试时再修改 - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; - GPIO_Init(GPIOB, &GPIO_InitStructure); - //======================串口初始化======================================= - USART_InitStructure.USART_BaudRate = ulBaudRate; - //设置校验模式 - switch (eParity) - { - case MB_PAR_NONE: //无校验 - USART_InitStructure.USART_Parity = USART_Parity_No; - USART_InitStructure.USART_WordLength = USART_WordLength_8b; - break; - case MB_PAR_ODD: //奇校验 - USART_InitStructure.USART_Parity = USART_Parity_Odd; - USART_InitStructure.USART_WordLength = USART_WordLength_9b; - break; - case MB_PAR_EVEN: //偶校验 - USART_InitStructure.USART_Parity = USART_Parity_Even; - USART_InitStructure.USART_WordLength = USART_WordLength_9b; - break; - default: - return FALSE; - } - - USART_InitStructure.USART_StopBits = USART_StopBits_1; - USART_InitStructure.USART_HardwareFlowControl = - USART_HardwareFlowControl_None; - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; - if (ucPORT != 2) - return FALSE; - - ENTER_CRITICAL_SECTION(); //关全局中断 - - USART_Init(USART2, &USART_InitStructure); - USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); - USART_Cmd(USART2, ENABLE); - - //=====================中断初始化====================================== - //设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级 - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); - NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); - - EXIT_CRITICAL_SECTION(); //开全局中断 - - return TRUE; + serial->parent.close(&(serial->parent)); } BOOL xMBMasterPortSerialPutByte(CHAR ucByte) { - USART_SendData(USART2, ucByte); - return TRUE; + serial->parent.write(&(serial->parent), 0, &ucByte, 1); + return TRUE; } BOOL xMBMasterPortSerialGetByte(CHAR * pucByte) { - *pucByte = USART_ReceiveData(USART2); + serial->parent.read(&(serial->parent), 0, pucByte, 1); return TRUE; } @@ -167,33 +205,35 @@ void prvvUARTRxISR(void) { pxMBMasterFrameCBByteReceived(); } -/******************************************************************************* - * Function Name : USART2_IRQHandler - * Description : This function handles USART2 global interrupt request. - * Input : None - * Output : None - * Return : None - *******************************************************************************/ -void USART2_IRQHandler(void) -{ - rt_interrupt_enter(); - //溢出错误 - if (USART_GetFlagStatus(USART2, USART_FLAG_ORE) == SET) - { - prvvUARTRxISR(); - } - //接收中断 - if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET) - { - USART_ClearITPendingBit(USART2, USART_IT_RXNE); - prvvUARTRxISR(); - } - //发送中断 - if (USART_GetITStatus(USART2, USART_IT_TXE) == SET) + +/** + * Software simulation serial transmit IRQ handler. + * + * @param parameter parameter + */ +static void serial_soft_trans_irq(void* parameter) { + rt_uint32_t recved_event; + while (1) { + /* waiting for serial transmit start */ + rt_event_recv(&event_serial, EVENT_SERIAL_TRANS_START, RT_EVENT_FLAG_OR, + RT_WAITING_FOREVER, &recved_event); + /* execute modbus callback */ prvvUARTTxReadyISR(); } - rt_interrupt_leave(); +} + +/** + * This function is serial receive callback function + * + * @param dev the device of serial + * @param size the data size that receive + * + * @return return RT_EOK + */ +static rt_err_t serial_rx_ind(rt_device_t dev, rt_size_t size) { + prvvUARTRxISR(); + return RT_EOK; } #endif diff --git a/FreeModbus/port/rtt/porttimer.c b/FreeModbus/port/rtt/porttimer.c index 7880434..1c08f1c 100644 --- a/FreeModbus/port/rtt/porttimer.c +++ b/FreeModbus/port/rtt/porttimer.c @@ -56,6 +56,7 @@ void prvvTIMERExpiredISR(void) { (void) pxMBPortCBTimerExpired(); } + /** * This function is PLC uart receive timer callback function * diff --git a/FreeModbus/port/rtt/porttimer_m.c b/FreeModbus/port/rtt/porttimer_m.c index 0a98e41..2bb60e3 100644 --- a/FreeModbus/port/rtt/porttimer_m.c +++ b/FreeModbus/port/rtt/porttimer_m.c @@ -30,7 +30,9 @@ #if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0 /* ----------------------- Variables ----------------------------------------*/ static USHORT usT35TimeOut50us; -static USHORT usPrescalerValue = 0; +static struct rt_timer timer; +static void prvvTIMERExpiredISR(void); +static void timer_timeout_ind(void* parameter); /* ----------------------- static functions ---------------------------------*/ static void prvvTIMERExpiredISR(void); @@ -38,102 +40,58 @@ static void prvvTIMERExpiredISR(void); /* ----------------------- Start implementation -----------------------------*/ BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us) { - NVIC_InitTypeDef NVIC_InitStructure; - //====================================时钟初始化=========================== - //使能定时器2时钟 - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); - //====================================定时器初始化=========================== - //定时器时间基配置说明 - //HCLK为72MHz,APB1经过2分频为36MHz - //TIM2的时钟倍频后为72MHz(硬件自动倍频,达到最大) - //TIM2的分频系数为3599,时间基频率为72 / (1 + Prescaler) = 20KHz,基准为50us - //TIM最大计数值为usTim1Timerout50u - usPrescalerValue = (uint16_t) (SystemCoreClock / 20000) - 1; - //保存T35定时器计数值 + /* backup T35 ticks */ usT35TimeOut50us = usTimeOut50us; - //预装载使能 - TIM_ARRPreloadConfig(TIM2, ENABLE); - //====================================中断初始化=========================== - //设置NVIC优先级分组为Group2:0-3抢占式优先级,0-3的响应式优先级 - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); - NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); - //清除溢出中断标志位 - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - //定时器3溢出中断关闭 - TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE); - //定时器3禁能 - TIM_Cmd(TIM2, DISABLE); + rt_timer_init(&timer, "plc_recv_timer", + timer_timeout_ind, /* bind timeout callback function */ + RT_NULL, + (50 * usT35TimeOut50us) / (1000 * 1000 / RT_TICK_PER_SECOND), + RT_TIMER_FLAG_ONE_SHOT); /* one shot */ + return TRUE; } void vMBMasterPortTimersT35Enable() { - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + rt_tick_t timer_tick = (50 * usT35TimeOut50us) + / (1000 * 1000 / RT_TICK_PER_SECOND); /* Set current timer mode,don't change it.*/ vMBMasterSetCurTimerMode(MB_TMODE_T35); - TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue; - TIM_TimeBaseStructure.TIM_ClockDivision = 0; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseStructure.TIM_Period = (uint16_t) usT35TimeOut50us; - TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); + rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); - TIM_SetCounter(TIM2, 0); - TIM_Cmd(TIM2, ENABLE); + rt_timer_start(&timer); } void vMBMasterPortTimersConvertDelayEnable() { - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + rt_tick_t timer_tick = MB_MASTER_DELAY_MS_CONVERT * RT_TICK_PER_SECOND / 1000; /* Set current timer mode,don't change it.*/ vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY); - TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue; - TIM_TimeBaseStructure.TIM_ClockDivision = 0; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseStructure.TIM_Period = (uint16_t)(MB_MASTER_DELAY_MS_CONVERT * 1000 / 50); - TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); + rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); - TIM_SetCounter(TIM2, 0); - TIM_Cmd(TIM2, ENABLE); + rt_timer_start(&timer); } void vMBMasterPortTimersRespondTimeoutEnable() { - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + rt_tick_t timer_tick = MB_MASTER_TIMEOUT_MS_RESPOND * RT_TICK_PER_SECOND / 1000; /* Set current timer mode,don't change it.*/ vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT); - TIM_TimeBaseStructure.TIM_Prescaler = usPrescalerValue; - TIM_TimeBaseStructure.TIM_ClockDivision = 0; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseStructure.TIM_Period = (uint16_t)(MB_MASTER_TIMEOUT_MS_RESPOND * 1000 / 50); - TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); + rt_timer_control(&timer, RT_TIMER_CTRL_SET_TIME, &timer_tick); - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); - TIM_SetCounter(TIM2, 0); - TIM_Cmd(TIM2, ENABLE); + rt_timer_start(&timer); } void vMBMasterPortTimersDisable() { - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); - TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE); - TIM_SetCounter(TIM2, 0); - TIM_Cmd(TIM2, DISABLE); + rt_timer_stop(&timer); } void prvvTIMERExpiredISR(void) @@ -141,17 +99,14 @@ void prvvTIMERExpiredISR(void) (void) pxMBMasterPortCBTimerExpired(); } -void TIM2_IRQHandler(void) +/** + * This function is PLC uart receive timer callback function + * + * @param parameter null + */ +static void timer_timeout_ind(void* parameter) { - rt_interrupt_enter(); - if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) - { - - TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清中断标记 - TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除定时器TIM2溢出中断标志位 - prvvTIMERExpiredISR(); - } - rt_interrupt_leave(); + prvvTIMERExpiredISR(); } #endif