You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
262 lines
7.1 KiB
262 lines
7.1 KiB
#include "uart1.h"
|
|
#include "sw_timer.h"
|
|
#include "ring_buffer.h"
|
|
|
|
|
|
#define UARTn_TX_INTERRUTP_ENABLE FALSE
|
|
|
|
|
|
#define UARTn_PERIPHERAL UART1
|
|
#define UARTn_INTERRUPT_HANDLER UART1_IRQn
|
|
#define UARTn_INTERRUPT_MASK MSK_UART1
|
|
#define UARTn_INTERRUPT_PRIORITY 3
|
|
#define UARTn_TX_PORT PB
|
|
#define UARTn_TX_PIN_NUM 6
|
|
#define UARTn_RX_PORT PB
|
|
#define UARTn_RX_PIN_NUM 7
|
|
|
|
#define UARTn_TX_BUFFER_SIZE 200
|
|
#define UARTn_RX_BUFFER_SIZE 100
|
|
|
|
|
|
|
|
static uint8_t Tx_Buffer[UARTn_TX_BUFFER_SIZE];
|
|
static uint8_t Rx_Buffer[UARTn_RX_BUFFER_SIZE];
|
|
static RING_BUFFER RingBuffer_Tx;
|
|
static RING_BUFFER RingBuffer_Rx;
|
|
|
|
|
|
#if (UARTn_TX_INTERRUTP_ENABLE == TRUE)
|
|
static volatile uint8_t Uartn_TxIntEnable = FALSE;
|
|
static void Uart1_Init_TransmitSet(void);
|
|
#else
|
|
static void Uart1_Transmit_Process(void);
|
|
#endif
|
|
|
|
|
|
|
|
static void Uart1_Receive_Handler(void);
|
|
|
|
|
|
void Uart1_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_RX_PORT, UARTn_RX_PIN_NUM, ALTERN_FUNC );
|
|
HAL_GPIO_ConfigFunction((Pn_Type*)UARTn_RX_PORT, UARTn_RX_PIN_NUM, AFSRx_AF1 );
|
|
HAL_GPIO_ConfigPullup((Pn_Type*)UARTn_RX_PORT, UARTn_RX_PIN_NUM, PUPDx_EnablePU );
|
|
|
|
HAL_GPIO_ConfigOutput((Pn_Type*)UARTn_TX_PORT, UARTn_TX_PIN_NUM, ALTERN_FUNC );
|
|
HAL_GPIO_ConfigFunction((Pn_Type*)UARTn_TX_PORT, UARTn_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_PERIPHERAL, &UARTn_Config);
|
|
|
|
/* Enable UART Rx interrupt */
|
|
HAL_UART_ConfigInterrupt((UARTn_Type*)UARTn_PERIPHERAL, UARTn_INTCFG_RBR, ENABLE );
|
|
|
|
#if (UARTn_TX_INTERRUTP_ENABLE == TRUE)
|
|
// Reset Tx Interrupt state
|
|
Uartn_TxIntEnable = RESET;
|
|
#else
|
|
SW_Timer_Callback_Register(SW_TIMER_RUN_CONTINUE, 0, Uart1_Transmit_Process);
|
|
#endif
|
|
|
|
RingBuffer_Initialization(&RingBuffer_Rx, false, UARTn_RX_BUFFER_SIZE, &Rx_Buffer[0]);
|
|
RingBuffer_Initialization(&RingBuffer_Tx, false, UARTn_TX_BUFFER_SIZE, &Tx_Buffer[0]);
|
|
|
|
NVIC_SetPriority(UARTn_INTERRUPT_HANDLER, UARTn_INTERRUPT_PRIORITY);
|
|
NVIC_EnableIRQ(UARTn_INTERRUPT_HANDLER );
|
|
HAL_INT_EInt_MaskDisable(UARTn_INTERRUPT_MASK);
|
|
}
|
|
|
|
|
|
|
|
void Uart1_Transmit(uint8_t TxData)
|
|
{
|
|
#if (UARTn_TX_INTERRUTP_ENABLE == TRUE)
|
|
/* 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_TxIntEnable == RESET)
|
|
{
|
|
Uart1_Init_TransmitSet();
|
|
}
|
|
/*
|
|
* Otherwise, re-enables Tx Interrupt
|
|
*/
|
|
else
|
|
{
|
|
HAL_UART_ConfigInterrupt((UARTn_Type*)UARTn_PERIPHERAL, UARTn_INTCFG_THRE, ENABLE );
|
|
}
|
|
#else
|
|
RingBuffer_Enqueue(&RingBuffer_Tx, TxData);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
void Uart1_TransmitData(uint8_t* pTxData, uint32_t TxLen)
|
|
{
|
|
uint32_t i;
|
|
#if (UARTn_TX_INTERRUTP_ENABLE == TRUE)
|
|
HAL_UART_ConfigInterrupt( ( UARTn_Type* )UARTn_PERIPHERAL, UARTn_INTCFG_THRE, DISABLE );
|
|
|
|
for(i = 0 ; i < TxLen ; i++)
|
|
RingBuffer_Enqueue(&RingBuffer_Tx, pTxData[i]);
|
|
|
|
if(Uartn_TxIntEnable == RESET)
|
|
{
|
|
Uart1_Init_TransmitSet();
|
|
}
|
|
else
|
|
{
|
|
HAL_UART_ConfigInterrupt( ( UARTn_Type* )UARTn_PERIPHERAL, UARTn_INTCFG_THRE, ENABLE );
|
|
}
|
|
#else
|
|
for(i = 0 ; i < TxLen ; i++)
|
|
RingBuffer_Enqueue(&RingBuffer_Tx, pTxData[i]);
|
|
#endif
|
|
}
|
|
|
|
|
|
#if (UARTn_TX_INTERRUTP_ENABLE == TRUE)
|
|
static void Uart1_Init_TransmitSet(void)
|
|
{
|
|
// Disable THRE interrupt
|
|
HAL_UART_ConfigInterrupt( ( UARTn_Type* )UARTn_PERIPHERAL, UARTn_INTCFG_THRE, DISABLE );
|
|
|
|
/* Wait until THR empty */
|
|
while( HAL_UART_CheckBusy( ( UARTn_Type* )UARTn_PERIPHERAL ) == SET );
|
|
|
|
while(RingBuffer_Get_DataSize(&RingBuffer_Tx) != 0)
|
|
{
|
|
uint8_t TxData;
|
|
RingBuffer_GetData(&RingBuffer_Tx, &TxData);
|
|
|
|
if(HAL_UART_Transmit( ( UARTn_Type* )UARTn_PERIPHERAL, &TxData, 1, NONE_BLOCKING ) )
|
|
{
|
|
/* Update transmit ring FIFO tail pointer */
|
|
RingBuffer_PopData(&RingBuffer_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_Tx) == 0)
|
|
{
|
|
HAL_UART_ConfigInterrupt((UARTn_Type*)UARTn_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_PERIPHERAL, UARTn_INTCFG_THRE, ENABLE );
|
|
}
|
|
}
|
|
#else
|
|
static void Uart1_Transmit_Process(void)
|
|
{
|
|
if(RingBuffer_Get_DataSize(&RingBuffer_Tx) != 0)
|
|
{
|
|
uint8_t TxData;
|
|
RingBuffer_GetData(&RingBuffer_Tx, &TxData);
|
|
|
|
if(HAL_UART_Transmit((UARTn_Type*)UARTn_PERIPHERAL, &TxData, 1, NONE_BLOCKING))
|
|
{
|
|
/* Update transmit ring FIFO tail pointer */
|
|
RingBuffer_PopData(&RingBuffer_Tx);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
static void Uart1_Receive_Handler(void)
|
|
{
|
|
uint8_t tmpc;
|
|
uint32_t rLen;
|
|
|
|
while(1)
|
|
{
|
|
rLen = HAL_UART_Receive((UARTn_Type*)UARTn_PERIPHERAL, &tmpc, 1, NONE_BLOCKING );
|
|
if (rLen)
|
|
{
|
|
RingBuffer_Enqueue(&RingBuffer_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_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_Receive_Handler();
|
|
}
|
|
else if(tmp == UARTn_IIR_INTID_THRE) // Transmitter Holding Register Empty
|
|
{
|
|
#if (UARTn_TX_INTERRUTP_ENABLE == TRUE)
|
|
Uart1_Init_TransmitSet();
|
|
#endif
|
|
}
|
|
else if(tmp == UARTn_IIR_INTID_TXE) // Transmitter Register Empty
|
|
{
|
|
}
|
|
}
|
|
|
|
|
|
uint32_t Uart1_Get_RecvDataCount(void)
|
|
{
|
|
return RingBuffer_Get_DataSize(&RingBuffer_Rx);
|
|
}
|
|
|
|
uint8_t Uart1_Get_RecvData(void)
|
|
{
|
|
uint8_t retData;
|
|
RingBuffer_Dequeue(&RingBuffer_Rx, &retData);
|
|
return retData;
|
|
}
|