/* * FreeModbus Libary: RT-Thread Port * Copyright (C) 2013 Armink * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * File: $Id: portserial.c,v 1.60 2013/08/13 15:07:05 Armink $ */ #include "port.h" /* ----------------------- Modbus includes ----------------------------------*/ #include "mb.h" #include "mbport.h" static usart_type* port_uart_list[] = {UART5, UART7}; static usart_type* port_uart; /* ----------------------- Static variables ---------------------------------*/ /* software simulation serial transmit IRQ handler thread */ static TaskHandle_t thread_serial_soft_trans_irq = NULL; /* serial event */ static EventGroupHandle_t event_serial; /* modbus slave serial device */ //static UART_HandleTypeDef *serial; /* * Serial FIFO mode */ static volatile uint8_t rx_buff[FIFO_SIZE_MAX]; static Serial_fifo Slave_serial_rx_fifo; /* ----------------------- Defines ------------------------------------------*/ /* serial transmit event */ #define EVENT_SERIAL_TRANS_START (1 << 0) /* ----------------------- static functions ---------------------------------*/ static void prvvUARTTxReadyISR(void); static void prvvUARTRxISR(void); static void serial_soft_trans_irq(void *parameter); //static void Slave_TxCpltCallback(struct __UART_HandleTypeDef *huart); //static void Slave_RxCpltCallback(struct __UART_HandleTypeDef *huart); static int stm32_getc(void); static int stm32_putc(CHAR c); /* ----------------------- Start implementation -----------------------------*/ BOOL xMBPortSerialInit(UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity) { /** * set 485 mode receive and transmit control IO * @note MODBUS_SLAVE_RT_CONTROL_PIN_INDEX need be defined by user */ BOOL bStatus = FALSE; usart_parity_selection_type usart_parity; usart_stop_bit_num_type usart_stop; usart_data_bit_num_type usart_data; gpio_init_type gpio_init_struct; bStatus = TRUE; if(ucPORT < (sizeof(port_uart_list) / sizeof(usart_type*))) { port_uart = port_uart_list[ucPORT]; } else { bStatus = FALSE; } switch ( eParity ) { case MB_PAR_NONE: usart_parity = USART_PARITY_NONE; usart_stop = USART_STOP_2_BIT; break; case MB_PAR_ODD: usart_parity = USART_PARITY_ODD; usart_stop = USART_STOP_1_BIT; break; case MB_PAR_EVEN: usart_parity = USART_PARITY_EVEN; usart_stop = USART_STOP_1_BIT; break; default: bStatus = FALSE; break; } switch ( ucDataBits ) { case 8: if(usart_stop == USART_STOP_1_BIT) { usart_data = USART_DATA_9BITS; } else if(usart_stop == USART_STOP_2_BIT) { usart_data = USART_DATA_8BITS; } else { bStatus = FALSE; } break; case 7: if(usart_stop == USART_STOP_1_BIT) { usart_data = USART_DATA_8BITS; } else if(usart_stop == USART_STOP_2_BIT) { usart_data = USART_DATA_8BITS; //before F435 not support 7bit. } else { bStatus = FALSE; } break; default: bStatus = FALSE; break; } /* configure uart param */ usart_parity_selection_config(port_uart, usart_parity); usart_init(port_uart, ulBaudRate, usart_data, usart_stop); // usart_rs485_delay_time_config(port_uart, 2, 2); // usart_de_polarity_set(port_uart, USART_DE_POLARITY_HIGH); // usart_rs485_mode_enable(port_uart, TRUE); usart_transmitter_enable(port_uart, TRUE); usart_receiver_enable(port_uart, TRUE); usart_enable(port_uart, TRUE); NVIC_ClearPendingIRQ(UART5_IRQn); nvic_irq_enable(UART5_IRQn, 0, 1); /* software initialize */ Slave_serial_rx_fifo.buffer = rx_buff; Slave_serial_rx_fifo.get_index = 0; Slave_serial_rx_fifo.put_index = 0; /* 创建串口发送线程*/ event_serial = xEventGroupCreate(); //创建事件 if (NULL != event_serial) { MODBUS_DEBUG("Create Slave event_serial Event success!\r\n"); } else { MODBUS_DEBUG("Create Slave event_serial Event Faild!\r\n"); } BaseType_t xReturn = xTaskCreate((TaskFunction_t)serial_soft_trans_irq, /* 任务函数*/ (const char *)"slave trans", /* 任务名称*/ (uint16_t)128, /* 栈*/ (void *)NULL, /* 入口参数 */ (UBaseType_t)12, /* 优先级*/ (TaskHandle_t *)&thread_serial_soft_trans_irq); /*任务句柄*/ if (xReturn == pdPASS) { MODBUS_DEBUG("xTaskCreate slave trans success\r\n"); } return TRUE; } void vMBPortSerialEnable(BOOL xRxEnable, BOOL xTxEnable) { // __HAL_UART_CLEAR_FLAG(serial,UART_FLAG_RXNE); // __HAL_UART_CLEAR_FLAG(serial,UART_FLAG_TC); // if (xRxEnable) { // /* enable RX interrupt */ // __HAL_UART_ENABLE_IT(serial, UART_IT_RXNE); // /* switch 485 to receive mode */ // MODBUS_DEBUG("RS485_RX_MODE\r\n"); // SLAVE_RS485_RX_MODE; // } else { // /* switch 485 to transmit mode */ // MODBUS_DEBUG("RS485_TX_MODE\r\n"); // SLAVE_RS485_TX_MODE; // /* disable RX interrupt */ // __HAL_UART_DISABLE_IT(serial, UART_IT_RXNE); // } if(xRxEnable == TRUE) { usart_interrupt_enable(port_uart, USART_RDBF_INT, TRUE); } else { usart_interrupt_enable(port_uart, USART_RDBF_INT, FALSE); } //涓嶄娇鐢ㄥ彂閫佷腑鏂 // if(xTxEnable == TRUE) // { // usart_interrupt_enable(port_uart, USART_TDBE_INT, TRUE); // } // else // { // usart_interrupt_enable(port_uart, USART_TDBE_INT, FALSE); // } if (xTxEnable) { /* start serial transmit */ xEventGroupSetBits(event_serial, EVENT_SERIAL_TRANS_START); } else { /* stop serial transmit */ xEventGroupClearBits(event_serial, EVENT_SERIAL_TRANS_START); /*测试帧数*/ // printf("ms=%.2f,fps=%.2f\r\n", __HAL_TIM_GetCounter(&htim7) / 100.f, // 1000.f / (__HAL_TIM_GetCounter(&htim7) / 100.f)); } } void vMBPortClose(void) { } /*Send a byte*/ BOOL xMBPortSerialPutByte(CHAR ucByte) { stm32_putc(ucByte); return TRUE; } /*Get a byte from fifo*/ BOOL xMBPortSerialGetByte(CHAR *pucByte) { Get_from_fifo(&Slave_serial_rx_fifo, (uint8_t *)pucByte, 1); return TRUE; } /* * Create an interrupt handler for the transmit buffer empty interrupt * (or an equivalent) for your target processor. This function should then * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that * a new character can be sent. The protocol stack will then call * xMBPortSerialPutByte( ) to send the character. */ void prvvUARTTxReadyISR(void) { pxMBFrameCBTransmitterEmpty(); } /* * Create an interrupt handler for the receive interrupt for your target * processor. This function should then call pxMBFrameCBByteReceived( ). The * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the * character. */ void prvvUARTRxISR(void) { pxMBFrameCBByteReceived(); } /** * Software simulation serial transmit IRQ handler. * * @param parameter parameter */ static void serial_soft_trans_irq(void *parameter) { uint32_t recved_event; while (1) { /* waiting for serial transmit start */ xEventGroupWaitBits(event_serial, /* 事件对象句柄 */ EVENT_SERIAL_TRANS_START, /* 接收任务感兴趣的事件 */ pdFALSE, /* 退出时清除事件?? */ pdFALSE, /* 满足感兴趣的所有事?? */ portMAX_DELAY); /* 指定超时事件,无限等待 */ /* execute modbus callback */ prvvUARTTxReadyISR(); } } /*UART发送一个字节*/ static int stm32_putc(CHAR c) { // serial->Instance->DR = c; // while (!(serial->Instance->SR & UART_FLAG_TC)) // ; usart_data_transmit(port_uart, c); return TRUE; } void vUSARTHandler( void ) { int ch = -1; if(port_uart->ctrl1_bit.rdbfien == SET) { if(usart_flag_get(port_uart, USART_RDBF_FLAG) == SET) { ch = usart_data_receive(port_uart); Put_in_fifo(&Slave_serial_rx_fifo, (uint8_t *)&ch, 1); prvvUARTRxISR(); } } if(port_uart->ctrl1_bit.tdbeien == SET) { if(usart_flag_get(port_uart, USART_TDBE_FLAG) == SET) { prvvUARTTxReadyISR(); } } } //void UART7_IRQHandler(void) //{ // vUSARTHandler( ); //}