#include "uart1_rs485.h" #include "sw_timer.h" #include "ring_buffer.h" #include "gpio_uart_led.h" //#define UARTn_RS485_TX_INTERRUTP_ENABLE #define UARTn_RS485_PERIPHERAL UART1 #define UARTn_RS485_INTERRUPT_HANDLER UART1_IRQn #define UARTn_RS485_INTERRUPT_MASK MSK_UART1 #define UARTn_RS485_INTERRUPT_PRIORITY 3 #define UARTn_RS485_TX_PORT PB #define UARTn_RS485_TX_PIN_NUM 6 #define UARTn_RS485_RX_PORT PB #define UARTn_RS485_RX_PIN_NUM 7 #define UARTn_RS485_TX_BUFFER_SIZE 100 #define UARTn_RS485_RX_BUFFER_SIZE 300 #define UARTn_RS485_REDE_PORT (Pn_Type*)PC #define UARTn_RS485_REDE_NUM 0 #define UARTn_RS485_RECEIVE HAL_GPIO_ClearPin(UARTn_RS485_REDE_PORT, _BIT(UARTn_RS485_REDE_NUM)) #define UARTn_RS485_TRANSMIT HAL_GPIO_SetPin(UARTn_RS485_REDE_PORT, _BIT(UARTn_RS485_REDE_NUM)) static uint8_t Tx_RS485_Buffer[UARTn_RS485_TX_BUFFER_SIZE]; static uint8_t Rx_RS485_Buffer[UARTn_RS485_RX_BUFFER_SIZE]; static RING_BUFFER RingBuffer_RS485_Tx; static RING_BUFFER RingBuffer_RS485_Rx; #if defined(UARTn_RS485_TX_INTERRUTP_ENABLE) static volatile uint8_t Uartn_RS485_TxIntEnable = FALSE; static void Uart1_RS485_Init_TransmitSet(void); #else static void Uart1_RS485_Transmit_Process(void); #endif static void Uart1_RS485_Receive_Handler(void); void Uart1_RS485_Initialization(uint32_t Baudrate, UARTn_DATA_BIT_Type Databit, UARTn_PARITY_BIT_Type Paritybit, UARTn_STOP_BIT_Type Stopbit) { UARTn_CFG_Type UARTn_Config; /* * Initialize UART0 pin connect */ HAL_GPIO_ConfigOutput((Pn_Type*)UARTn_RS485_RX_PORT, UARTn_RS485_RX_PIN_NUM, ALTERN_FUNC ); HAL_GPIO_ConfigFunction((Pn_Type*)UARTn_RS485_RX_PORT, UARTn_RS485_RX_PIN_NUM, AFSRx_AF1 ); HAL_GPIO_ConfigPullup((Pn_Type*)UARTn_RS485_RX_PORT, UARTn_RS485_RX_PIN_NUM, PUPDx_EnablePU ); HAL_GPIO_ConfigOutput((Pn_Type*)UARTn_RS485_TX_PORT, UARTn_RS485_TX_PIN_NUM, ALTERN_FUNC ); HAL_GPIO_ConfigFunction((Pn_Type*)UARTn_RS485_TX_PORT, UARTn_RS485_TX_PIN_NUM, AFSRx_AF1 ); // default: 38400-8-N-1 HAL_UART_ConfigStructInit(&UARTn_Config); UARTn_Config.Baudrate = Baudrate; UARTn_Config.Databits = Databit; UARTn_Config.Parity = Paritybit; UARTn_Config.Stopbits = Stopbit; HAL_UART_Init((UARTn_Type*)UARTn_RS485_PERIPHERAL, &UARTn_Config); HAL_GPIO_ConfigOutput(UARTn_RS485_REDE_PORT, UARTn_RS485_REDE_NUM, PUSH_PULL_OUTPUT); HAL_GPIO_ConfigPullup(UARTn_RS485_REDE_PORT, UARTn_RS485_REDE_NUM, PUPDx_EnablePU); UARTn_RS485_RECEIVE; /* Enable UART Rx interrupt */ HAL_UART_ConfigInterrupt((UARTn_Type*)UARTn_RS485_PERIPHERAL, UARTn_INTCFG_RBR, ENABLE ); #if defined(UARTn_RS485_TX_INTERRUTP_ENABLE) // Reset Tx Interrupt state Uartn_RS485_TxIntEnable = RESET; #else SW_Timer_Callback_Register(SW_TIMER_RUN_CONTINUE, 0, Uart1_RS485_Transmit_Process); #endif RingBuffer_Initialization(&RingBuffer_RS485_Rx, false, UARTn_RS485_RX_BUFFER_SIZE, &Rx_RS485_Buffer[0]); RingBuffer_Initialization(&RingBuffer_RS485_Tx, false, UARTn_RS485_TX_BUFFER_SIZE, &Tx_RS485_Buffer[0]); NVIC_SetPriority(UARTn_RS485_INTERRUPT_HANDLER, UARTn_RS485_INTERRUPT_PRIORITY); NVIC_EnableIRQ(UARTn_RS485_INTERRUPT_HANDLER ); HAL_INT_EInt_MaskDisable(UARTn_RS485_INTERRUPT_MASK); } void Uart1_RS485_Transmit(uint8_t TxData) { #if defined(UARTn_RS485_TX_INTERRUTP_ENABLE) /* Temporarily lock out UART transmit interrupts during this read so the UART transmit interrupt won't cause problems with the index values */ HAL_UART_ConfigInterrupt((UARTn_Type*)UARTn_PERIPHERAL, UARTn_INTCFG_THRE, DISABLE ); RingBuffer_Enqueue(&RingBuffer_Tx, TxData); /* * Check if current Tx interrupt enable is reset, * that means the Tx interrupt must be re-enabled * due to call IntTransmit() function to trigger * this interrupt type */ if(Uartn_RS485_TxIntEnable == RESET) { Uart1_RS485_Init_TransmitSet(); } /* * Otherwise, re-enables Tx Interrupt */ else { HAL_UART_ConfigInterrupt((UARTn_Type*)UARTn_PERIPHERAL, UARTn_INTCFG_THRE, ENABLE ); } #else RingBuffer_Enqueue(&RingBuffer_RS485_Tx, TxData); #endif } void Uart1_RS485_TransmitData(uint8_t* pTxData, uint32_t TxLen) { uint32_t i; #if defined(UARTn_RS485_TX_INTERRUTP_ENABLE) HAL_UART_ConfigInterrupt( ( UARTn_Type* )UARTn_RS485_PERIPHERAL, UARTn_INTCFG_THRE, DISABLE ); for(i = 0 ; i < TxLen ; i++) RingBuffer_Enqueue(&RingBuffer_Tx, pTxData[i]); if(Uartn_RS485_TxIntEnable == RESET) { Uart1_RS485_Init_TransmitSet(); } else { HAL_UART_ConfigInterrupt( ( UARTn_Type* )UARTn_PERIPHERAL, UARTn_INTCFG_THRE, ENABLE ); } #else for(i = 0 ; i < TxLen ; i++) RingBuffer_Enqueue(&RingBuffer_RS485_Tx, pTxData[i]); #endif } #if defined(UARTn_RS485_TX_INTERRUTP_ENABLE) static void Uart1_RS485_Init_TransmitSet(void) { // Disable THRE interrupt HAL_UART_ConfigInterrupt( ( UARTn_Type* )UARTn_RS485_PERIPHERAL, UARTn_INTCFG_THRE, DISABLE ); /* Wait until THR empty */ while( HAL_UART_CheckBusy( ( UARTn_Type* )UARTn_RS485_PERIPHERAL ) == SET ); while(RingBuffer_Get_DataSize(&RingBuffer_Tx) != 0) { uint8_t TxData; RingBuffer_GetData(&RingBuffer_RS485_Tx, &TxData); if(HAL_UART_Transmit( ( UARTn_Type* )UARTn_RS485_PERIPHERAL, &TxData, 1, NONE_BLOCKING ) ) { /* Update transmit ring FIFO tail pointer */ RingBuffer_PopData(&RingBuffer_RS485_Tx); break; } else { break; } } /* If there is no more data to send, disable the transmit interrupt - else enable it or keep it enabled */ if(RingBuffer_Get_DataSize(&RingBuffer_RS485_Tx) == 0) { HAL_UART_ConfigInterrupt((RingBuffer_RS485_Tx*)UARTn_RS485_PERIPHERAL, UARTn_INTCFG_THRE, DISABLE ); // Reset Tx Interrupt state Uartn_TxIntEnable = RESET; } else { // Set Tx Interrupt state Uartn_TxIntEnable = SET; HAL_UART_ConfigInterrupt((UARTn_Type*)UARTn_RS485_PERIPHERAL, UARTn_INTCFG_THRE, ENABLE ); } } #else static void Uart1_RS485_Transmit_Process(void) { if(RingBuffer_Get_DataSize(&RingBuffer_RS485_Tx) != 0) { uint8_t TxData; UARTn_RS485_TRANSMIT; GPIO_UART_RS485_TX_LED_ON; RingBuffer_GetData(&RingBuffer_RS485_Tx, &TxData); if(HAL_UART_Transmit((UARTn_Type*)UARTn_RS485_PERIPHERAL, &TxData, 1, NONE_BLOCKING)) { /* Update transmit ring FIFO tail pointer */ RingBuffer_PopData(&RingBuffer_RS485_Tx); } } else { if(HAL_UART_CheckBusy((UARTn_Type *)UARTn_RS485_PERIPHERAL) == RESET) { UARTn_RS485_RECEIVE; GPIO_UART_RS485_TX_LED_OFF; } } } #endif static void Uart1_RS485_Receive_Handler(void) { uint8_t tmpc; uint32_t rLen; while(1) { rLen = HAL_UART_Receive((UARTn_Type*)UARTn_RS485_PERIPHERAL, &tmpc, 1, NONE_BLOCKING ); if (rLen) { RingBuffer_Enqueue(&RingBuffer_RS485_Rx, tmpc); } else { break; } } } /*********************************************************************//** * @brief UART1 interrupt handler sub-routine * @param[in] None * @return None **********************************************************************/ void UART1_Handler(void) { uint32_t intsrc, tmp; /* Determine the interrupt source */ intsrc = UARTn_RS485_PERIPHERAL->IIR; tmp = intsrc & UARTn_IIR_INTID_MASK; // Receiver Line Status if(tmp == UARTn_IIR_INTID_RLS) // error(Overrun, Parity, Framing or Break Error) { } else if(tmp == UARTn_IIR_INTID_RDA) // Receiver Data Available { Uart1_RS485_Receive_Handler(); } else if(tmp == UARTn_IIR_INTID_THRE) // Transmitter Holding Register Empty { #if defined(UARTn_RS485_TX_INTERRUTP_ENABLE) Uart1_RS485_Init_TransmitSet(); #endif } else if(tmp == UARTn_IIR_INTID_TXE) // Transmitter Register Empty { } } void Uart1_RS485_Push_Data(uint8_t RxData) { RingBuffer_Enqueue(&RingBuffer_RS485_Rx, RxData); } uint32_t Uart1_RS485_Get_RecvDataCount(void) { return RingBuffer_Get_DataSize(&RingBuffer_RS485_Rx); } uint8_t Uart1_RS485_Get_RecvData(void) { uint8_t retData; RingBuffer_Dequeue(&RingBuffer_RS485_Rx, &retData); return retData; }