//UART 库

#include "stdio.h"

#include "sys.h"
#include "systick.h"

#include "uart.h"

COM_PORT_E printf_Com = COM1;
COM_PORT_E getchar_Com = COM1;

//USART1 PA9 PA10
#define USART1_CLK_ENABLE() __HAL_RCC_USART1_CLK_ENABLE()

#define USART1_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define USART1_TX_GPIO_PORT GPIOA
#define USART1_TX_PIN GPIO_PIN_9
#define USART1_TX_AF GPIO_AF7_USART1

#define USART1_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define USART1_RX_GPIO_PORT GPIOA
#define USART1_RX_PIN GPIO_PIN_10
#define USART1_RX_AF GPIO_AF7_USART1

//USART2 PD5 PD6
#define USART2_CLK_ENABLE() __HAL_RCC_USART2_CLK_ENABLE()

#define USART2_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
#define USART2_TX_GPIO_PORT GPIOD
#define USART2_TX_PIN GPIO_PIN_5
#define USART2_TX_AF GPIO_AF7_USART2

#define USART2_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
#define USART2_RX_GPIO_PORT GPIOD
#define USART2_RX_PIN GPIO_PIN_6
#define USART2_RX_AF GPIO_AF7_USART2

//USART3 PB10 PB11
#define USART3_CLK_ENABLE() __HAL_RCC_USART3_CLK_ENABLE()

#define USART3_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define USART3_TX_GPIO_PORT GPIOB
#define USART3_TX_PIN GPIO_PIN_10
#define USART3_TX_AF GPIO_AF7_USART3

#define USART3_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define USART3_RX_GPIO_PORT GPIOB
#define USART3_RX_PIN GPIO_PIN_11
#define USART3_RX_AF GPIO_AF7_USART3

//UART4 PC10 PC11
#define UART4_CLK_ENABLE() __HAL_RCC_UART4_CLK_ENABLE()

#define UART4_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
#define UART4_TX_GPIO_PORT GPIOC
#define UART4_TX_PIN GPIO_PIN_10
#define UART4_TX_AF GPIO_AF8_UART4

#define UART4_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
#define UART4_RX_GPIO_PORT GPIOC
#define UART4_RX_PIN GPIO_PIN_11
#define UART4_RX_AF GPIO_AF8_UART4

//UART5 PC12 PD2
#define UART5_CLK_ENABLE() __HAL_RCC_UART5_CLK_ENABLE()

#define UART5_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
#define UART5_TX_GPIO_PORT GPIOC
#define UART5_TX_PIN GPIO_PIN_12
#define UART5_TX_AF GPIO_AF8_UART5

#define UART5_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
#define UART5_RX_GPIO_PORT GPIOD
#define UART5_RX_PIN GPIO_PIN_2
#define UART5_RX_AF GPIO_AF8_UART5

//USART6 PG14 PC7
#define USART6_CLK_ENABLE() __HAL_RCC_USART6_CLK_ENABLE()

#define USART6_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOG_CLK_ENABLE()
#define USART6_TX_GPIO_PORT GPIOG
#define USART6_TX_PIN GPIO_PIN_14
#define USART6_TX_AF GPIO_AF7_USART6

#define USART6_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
#define USART6_RX_GPIO_PORT GPIOC
#define USART6_RX_PIN GPIO_PIN_7
#define USART6_RX_AF GPIO_AF7_USART6

//UART7 PB4 PB3
#define UART7_CLK_ENABLE() __HAL_RCC_UART7_CLK_ENABLE()

#define UART7_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define UART7_TX_GPIO_PORT GPIOB
#define UART7_TX_PIN GPIO_PIN_4
#define UART7_TX_AF GPIO_AF11_UART7

#define UART7_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define UART7_RX_GPIO_PORT GPIOB
#define UART7_RX_PIN GPIO_PIN_3
#define UART7_RX_AF GPIO_AF11_UART7

//UART8 PJ8 PJ9
#define UART8_CLK_ENABLE() __HAL_RCC_UART8_CLK_ENABLE()

#define UART8_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOJ_CLK_ENABLE()
#define UART8_TX_GPIO_PORT GPIOJ
#define UART8_TX_PIN GPIO_PIN_8
#define UART8_TX_AF GPIO_AF8_UART8

#define UART8_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOJ_CLK_ENABLE()
#define UART8_RX_GPIO_PORT GPIOJ
#define UART8_RX_PIN GPIO_PIN_9
#define UART8_RX_AF GPIO_AF8_UART8

//定义每个串口结构体变量
#if UART1_FIFO_EN == 1
static UART_T g_tUart1;
static uint8_t g_TxBuf1[UART1_TX_BUF_SIZE]; //发送缓冲区
static uint8_t g_RxBuf1[UART1_RX_BUF_SIZE]; //接收缓冲区
#endif

#if UART2_FIFO_EN == 1
static UART_T g_tUart2;
static uint8_t g_TxBuf2[UART2_TX_BUF_SIZE]; //发送缓冲区
static uint8_t g_RxBuf2[UART2_RX_BUF_SIZE]; //接收缓冲区
#endif

#if UART3_FIFO_EN == 1
static UART_T g_tUart3;
static uint8_t g_TxBuf3[UART3_TX_BUF_SIZE]; //发送缓冲区
static uint8_t g_RxBuf3[UART3_RX_BUF_SIZE]; //接收缓冲区
#endif

#if UART4_FIFO_EN == 1
static UART_T g_tUart4;
static uint8_t g_TxBuf4[UART4_TX_BUF_SIZE]; //发送缓冲区
static uint8_t g_RxBuf4[UART4_RX_BUF_SIZE]; //接收缓冲区
#endif

#if UART5_FIFO_EN == 1
static UART_T g_tUart5;
static uint8_t g_TxBuf5[UART5_TX_BUF_SIZE]; //发送缓冲区
static uint8_t g_RxBuf5[UART5_RX_BUF_SIZE]; //接收缓冲区
#endif

#if UART6_FIFO_EN == 1
static UART_T g_tUart6;
static uint8_t g_TxBuf6[UART6_TX_BUF_SIZE]; //发送缓冲区
static uint8_t g_RxBuf6[UART6_RX_BUF_SIZE]; //接收缓冲区
#endif

#if UART7_FIFO_EN == 1
static UART_T g_tUart7;
static uint8_t g_TxBuf7[UART7_TX_BUF_SIZE]; //发送缓冲区
static uint8_t g_RxBuf7[UART7_RX_BUF_SIZE]; //接收缓冲区
#endif

#if UART8_FIFO_EN == 1
static UART_T g_tUart8;
static uint8_t g_TxBuf8[UART8_TX_BUF_SIZE]; //发送缓冲区
static uint8_t g_RxBuf8[UART8_RX_BUF_SIZE]; //接收缓冲区
#endif

static void UartVarInit(void);
static void InitHardUart(void);
static void UartSend(UART_T *_pUart, uint8_t *_ucaBuf, uint16_t _usLen);
static uint8_t UartGetChar(UART_T *_pUart, uint8_t *_pByte);
static void UartIRQ(UART_T *_pUart);

/**
  * @brief  初始化串口
  */
void Uart_Init(void)
{
    UartVarInit(); //初始化全局变量

    InitHardUart(); //配置串口的硬件参数
}

/**
  * @brief  将 COM 端口号转换为 UART 指针
  * @param  _ucPort: 端口号 (COM1-8)
  * @retval UART 指针
  */
UART_T *ComToUart(COM_PORT_E _ucPort)
{
    if (_ucPort == COM1)
    {
#if UART1_FIFO_EN == 1
        return &g_tUart1;
#else
        return 0;
#endif
    }
    else if (_ucPort == COM2)
    {
#if UART2_FIFO_EN == 1
        return &g_tUart2;
#else
        return 0;
#endif
    }
    else if (_ucPort == COM3)
    {
#if UART3_FIFO_EN == 1
        return &g_tUart3;
#else
        return 0;
#endif
    }
    else if (_ucPort == COM4)
    {
#if UART4_FIFO_EN == 1
        return &g_tUart4;
#else
        return 0;
#endif
    }
    else if (_ucPort == COM5)
    {
#if UART5_FIFO_EN == 1
        return &g_tUart5;
#else
        return 0;
#endif
    }
    else if (_ucPort == COM6)
    {
#if UART6_FIFO_EN == 1
        return &g_tUart6;
#else
        return 0;
#endif
    }
    else if (_ucPort == COM7)
    {
#if UART7_FIFO_EN == 1
        return &g_tUart7;
#else
        return 0;
#endif
    }
    else if (_ucPort == COM8)
    {
#if UART8_FIFO_EN == 1
        return &g_tUart8;
#else
        return 0;
#endif
    }
    else
    {
        return 0;
    }
}

/**
  * @brief  将 COM 端口号转换为 USART_TypeDef*
  * @param  _ucPort: 端口号 (COM1-8)
  * @retval USART_TypeDef*
  */
USART_TypeDef *ComToUSARTx(COM_PORT_E _ucPort)
{
    if (_ucPort == COM1)
    {
#if UART1_FIFO_EN == 1
        return USART1;
#else
        return 0;
#endif
    }
    else if (_ucPort == COM2)
    {
#if UART2_FIFO_EN == 1
        return USART2;
#else
        return 0;
#endif
    }
    else if (_ucPort == COM3)
    {
#if UART3_FIFO_EN == 1
        return USART3;
#else
        return 0;
#endif
    }
    else if (_ucPort == COM4)
    {
#if UART4_FIFO_EN == 1
        return UART4;
#else
        return 0;
#endif
    }
    else if (_ucPort == COM5)
    {
#if UART5_FIFO_EN == 1
        return UART5;
#else
        return 0;
#endif
    }
    else if (_ucPort == COM6)
    {
#if UART6_FIFO_EN == 1
        return USART6;
#else
        return 0;
#endif
    }
    else if (_ucPort == COM7)
    {
#if UART7_FIFO_EN == 1
        return UART7;
#else
        return 0;
#endif
    }
    else if (_ucPort == COM8)
    {
#if UART8_FIFO_EN == 1
        return UART8;
#else
        return 0;
#endif
    }
    else
    {
        return 0;
    }
}

/**
  * @brief  向串口发送一组数据。数据放到发送缓冲区后立即返回，由中断服务程序在后台完成发送
  * @param  _ucPort: 端口号 (COM1-8)
  * @param  _ucaBuf: 待发送的数据缓冲区
  * @param  _usLen : 数据长度
  */
void Uart_SendBuf(COM_PORT_E _ucPort, uint8_t *_ucaBuf, uint16_t _usLen)
{
    UART_T *pUart;

    pUart = ComToUart(_ucPort);
    if (pUart == 0)
    {
        return;
    }

    if (pUart->SendBefore != 0)
    {
        pUart->SendBefore();
    }

    UartSend(pUart, _ucaBuf, _usLen);
}

/**
  * @brief  向串口发送 1 个字节。数据放到发送缓冲区后立即返回，由中断服务程序在后台完成发送
  * @param  _ucPort: 端口号 (COM1-8)
  * @param  _ucByte: 待发送的数据
  */
void Uart_SendChar(COM_PORT_E _ucPort, uint8_t _ucByte)
{
    Uart_SendBuf(_ucPort, &_ucByte, 1);
}

/**
  * @brief  从接收缓冲区读取 1 字节，非阻塞。无论有无数据均立即返回
  * @param  _ucPort: 端口号 (COM1-8)
  * @param  _pByte: 接收到的数据指针
  * @retval 0 表示无数据，1 表示读取到有效字节
  */
uint8_t Uart_GetChar(COM_PORT_E _ucPort, uint8_t *_pByte)
{
    UART_T *pUart;

    pUart = ComToUart(_ucPort);
    if (pUart == 0)
    {
        return 0;
    }

    return UartGetChar(pUart, _pByte);
}

/**
  * @brief  从接收缓冲区读取到特定字节，阻塞，有超时
  * @param  _ucPort: 端口号 (COM1-8)
  * @param  _pBuf: 接收到的数据指针
  * @param  _endByte: 终止字节
  * @param  _timeout: 超时时间
  * @retval 0 表示超时，1 表示成功
  */
uint8_t Uart_GetBuffUntil(COM_PORT_E _ucPort, uint8_t *_pBuf, uint8_t _endByte, uint16_t _timeout)
{
    uint8_t ch;
    int32_t start_t = SysTick_GetRunTime();
    uint16_t i = 0;

    while (1)
    {
        if (Uart_GetChar(_ucPort, &ch) == 1)
        {
            if (ch == _endByte)
            {
                _pBuf[i] = '\0';

                return 1;
            }

            _pBuf[i++] = ch;
        }
        else if (SysTick_GetRunTime() - start_t > _timeout)
        {
            return 0;
        }
    }
}

/**
  * @brief  清零串口发送缓冲区
  * @param  _ucPort: 端口号 (COM1-8)
  */
void Uart_ClearTxFifo(COM_PORT_E _ucPort)
{
    UART_T *pUart;

    pUart = ComToUart(_ucPort);
    if (pUart == 0)
    {
        return;
    }

    pUart->usTxWrite = 0;
    pUart->usTxRead = 0;
    pUart->usTxCount = 0;
}

/**
  * @brief  清零串口接收缓冲区
  * @param  _ucPort: 端口号 (COM1-8)
  */
void Uart_ClearRxFifo(COM_PORT_E _ucPort)
{
    UART_T *pUart;

    pUart = ComToUart(_ucPort);
    if (pUart == 0)
    {
        return;
    }

    pUart->usRxWrite = 0;
    pUart->usRxRead = 0;
    pUart->usRxCount = 0;
}

/**
  * @brief  设置串口的波特率。无校验，收发都使能
  * @param  _ucPort: 端口号 (COM1-8)
  * @param  _BaudRate: 波特率
  */
void Uart_SetBaud(COM_PORT_E _ucPort, uint32_t _BaudRate)
{
    USART_TypeDef *USARTx;

    USARTx = ComToUSARTx(_ucPort);
    if (USARTx == 0)
    {
        return;
    }

    Uart_SetUartParam(USARTx, _BaudRate, UART_PARITY_NONE, UART_MODE_TX_RX);
}

/**
  * @brief  设置串口发送前处理函数
  * @param  _ucPort: 端口号 (COM1-8)
  * @param  Receive: 处理函数
  */
void Uart_BindSendBeforeHandle(COM_PORT_E _ucPort, UartSendBeforeHandler SendBefore)
{
    UART_T *pUart;

    pUart = ComToUart(_ucPort);
    if (pUart == 0)
    {
        return;
    }

    pUart->SendBefore = SendBefore;
}

/**
  * @brief  设置串口发送后处理函数
  * @param  _ucPort: 端口号 (COM1-8)
  * @param  Receive: 处理函数
  */
void Uart_BindSendOverHandle(COM_PORT_E _ucPort, UartSendOverHandler SendOver)
{
    UART_T *pUart;

    pUart = ComToUart(_ucPort);
    if (pUart == 0)
    {
        return;
    }

    pUart->SendOver = SendOver;
}

/**
  * @brief  设置串口接受中断处理函数
  * @param  _ucPort: 端口号 (COM1-8)
  * @param  Receive: 中断处理函数
  */
void Uart_BindReceiveHandle(COM_PORT_E _ucPort, UartReceiveHandler Receive)
{
    UART_T *pUart;

    pUart = ComToUart(_ucPort);
    if (pUart == 0)
    {
        return;
    }

    pUart->Receive = Receive;
}

/**
  * @brief  初始化串口相关的变量
  */
static void UartVarInit(void)
{
#if UART1_FIFO_EN == 1
    g_tUart1.uart = USART1;                   //串口设备
    g_tUart1.pTxBuf = g_TxBuf1;               //发送缓冲区指针
    g_tUart1.pRxBuf = g_RxBuf1;               //接收缓冲区指针
    g_tUart1.usTxBufSize = UART1_TX_BUF_SIZE; //发送缓冲区大小
    g_tUart1.usRxBufSize = UART1_RX_BUF_SIZE; //接收缓冲区大小
    g_tUart1.usTxWrite = 0;                   //发送FIFO写索引
    g_tUart1.usTxRead = 0;                    //发送FIFO读索引
    g_tUart1.usRxWrite = 0;                   //接收FIFO写索引
    g_tUart1.usRxRead = 0;                    //接收FIFO读索引
    g_tUart1.usRxCount = 0;                   //接收到的新数据个数
    g_tUart1.usTxCount = 0;                   //待发送的数据个数
    g_tUart1.SendBefore = 0;                  //发送数据前的回调函数
    g_tUart1.SendOver = 0;                    //发送完毕后的回调函数
    g_tUart1.Receive = 0;                     //接收到新数据后的回调函数
    g_tUart1.Sending = 0;                     //正在发送中标志
#endif

#if UART2_FIFO_EN == 1
    g_tUart2.uart = USART2;                   //串口设备
    g_tUart2.pTxBuf = g_TxBuf2;               //发送缓冲区指针
    g_tUart2.pRxBuf = g_RxBuf2;               //接收缓冲区指针
    g_tUart2.usTxBufSize = UART2_TX_BUF_SIZE; //发送缓冲区大小
    g_tUart2.usRxBufSize = UART2_RX_BUF_SIZE; //接收缓冲区大小
    g_tUart2.usTxWrite = 0;                   //发送FIFO写索引
    g_tUart2.usTxRead = 0;                    //发送FIFO读索引
    g_tUart2.usRxWrite = 0;                   //接收FIFO写索引
    g_tUart2.usRxRead = 0;                    //接收FIFO读索引
    g_tUart2.usRxCount = 0;                   //接收到的新数据个数
    g_tUart2.usTxCount = 0;                   //待发送的数据个数
    g_tUart2.SendBefore = 0;                  //发送数据前的回调函数
    g_tUart2.SendOver = 0;                    //发送完毕后的回调函数
    g_tUart2.Receive = 0;                     //接收到新数据后的回调函数
    g_tUart2.Sending = 0;                     //正在发送中标志
#endif

#if UART3_FIFO_EN == 1
    g_tUart3.uart = USART3;
    g_tUart3.pTxBuf = g_TxBuf3;
    g_tUart3.pRxBuf = g_RxBuf3;
    g_tUart3.usTxBufSize = UART3_TX_BUF_SIZE;
    g_tUart3.usRxBufSize = UART3_RX_BUF_SIZE;
    g_tUart3.usTxWrite = 0;
    g_tUart3.usTxRead = 0;
    g_tUart3.usRxWrite = 0;
    g_tUart3.usRxRead = 0;
    g_tUart3.usRxCount = 0;
    g_tUart3.usTxCount = 0;
    g_tUart3.SendBefore = 0;
    g_tUart3.SendOver = 0;
    g_tUart3.Receive = 0;
    g_tUart3.Sending = 0;
#endif

#if UART4_FIFO_EN == 1
    g_tUart4.uart = UART4;
    g_tUart4.pTxBuf = g_TxBuf4;
    g_tUart4.pRxBuf = g_RxBuf4;
    g_tUart4.usTxBufSize = UART4_TX_BUF_SIZE;
    g_tUart4.usRxBufSize = UART4_RX_BUF_SIZE;
    g_tUart4.usTxWrite = 0;
    g_tUart4.usTxRead = 0;
    g_tUart4.usRxWrite = 0;
    g_tUart4.usRxRead = 0;
    g_tUart4.usRxCount = 0;
    g_tUart4.usTxCount = 0;
    g_tUart4.SendBefore = 0;
    g_tUart4.SendOver = 0;
    g_tUart4.Receive = 0;
    g_tUart4.Sending = 0;
#endif

#if UART5_FIFO_EN == 1
    g_tUart5.uart = UART5;
    g_tUart5.pTxBuf = g_TxBuf5;
    g_tUart5.pRxBuf = g_RxBuf5;
    g_tUart5.usTxBufSize = UART5_TX_BUF_SIZE;
    g_tUart5.usRxBufSize = UART5_RX_BUF_SIZE;
    g_tUart5.usTxWrite = 0;
    g_tUart5.usTxRead = 0;
    g_tUart5.usRxWrite = 0;
    g_tUart5.usRxRead = 0;
    g_tUart5.usRxCount = 0;
    g_tUart5.usTxCount = 0;
    g_tUart5.SendBefore = 0;
    g_tUart5.SendOver = 0;
    g_tUart5.Receive = 0;
    g_tUart5.Sending = 0;
#endif

#if UART6_FIFO_EN == 1
    g_tUart6.uart = USART6;
    g_tUart6.pTxBuf = g_TxBuf6;
    g_tUart6.pRxBuf = g_RxBuf6;
    g_tUart6.usTxBufSize = UART6_TX_BUF_SIZE;
    g_tUart6.usRxBufSize = UART6_RX_BUF_SIZE;
    g_tUart6.usTxWrite = 0;
    g_tUart6.usTxRead = 0;
    g_tUart6.usRxWrite = 0;
    g_tUart6.usRxRead = 0;
    g_tUart6.usRxCount = 0;
    g_tUart6.usTxCount = 0;
    g_tUart6.SendBefore = 0;
    g_tUart6.SendOver = 0;
    g_tUart6.Receive = 0;
    g_tUart6.Sending = 0;
#endif

#if UART7_FIFO_EN == 1
    g_tUart7.uart = UART7;
    g_tUart7.pTxBuf = g_TxBuf7;
    g_tUart7.pRxBuf = g_RxBuf7;
    g_tUart7.usTxBufSize = UART7_TX_BUF_SIZE;
    g_tUart7.usRxBufSize = UART7_RX_BUF_SIZE;
    g_tUart7.usTxWrite = 0;
    g_tUart7.usTxRead = 0;
    g_tUart7.usRxWrite = 0;
    g_tUart7.usRxRead = 0;
    g_tUart7.usRxCount = 0;
    g_tUart7.usTxCount = 0;
    g_tUart7.SendBefore = 0;
    g_tUart7.SendOver = 0;
    g_tUart7.Receive = 0;
    g_tUart7.Sending = 0;
#endif

#if UART8_FIFO_EN == 1
    g_tUart8.uart = UART8;
    g_tUart8.pTxBuf = g_TxBuf8;
    g_tUart8.pRxBuf = g_RxBuf8;
    g_tUart8.usTxBufSize = UART8_TX_BUF_SIZE;
    g_tUart8.usRxBufSize = UART8_RX_BUF_SIZE;
    g_tUart8.usTxWrite = 0;
    g_tUart8.usTxRead = 0;
    g_tUart8.usRxWrite = 0;
    g_tUart8.usRxRead = 0;
    g_tUart8.usRxCount = 0;
    g_tUart8.usTxCount = 0;
    g_tUart8.SendBefore = 0;
    g_tUart8.SendOver = 0;
    g_tUart8.Receive = 0;
    g_tUart8.Sending = 0;
#endif
}

/**
  * @brief  配置串口的硬件参数
  * @param  Instance: USART_TypeDef*
  * @param  BaudRate: 波特率
  * @param  Parity: 校验类型，奇校验或者偶校验
  * @param  Mode: 发送和接收模式使能
  */
void Uart_SetUartParam(USART_TypeDef *Instance, uint32_t BaudRate, uint32_t Parity, uint32_t Mode)
{
    UART_HandleTypeDef UartHandle;

    UartHandle.Instance = Instance;

    UartHandle.Init.BaudRate = BaudRate;
    UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
    UartHandle.Init.StopBits = UART_STOPBITS_1;
    UartHandle.Init.Parity = Parity;
    UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    UartHandle.Init.Mode = Mode;
    UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
    UartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    UartHandle.Init.ClockPrescaler = UART_PRESCALER_DIV1;

    UartHandle.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;

    HAL_UART_Init(&UartHandle);
}

/**
  * @brief  配置串口的硬件参数
  */
static void InitHardUart(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;

    /* 
       默认情况下，USART1 和 USART6 选择的 PCLK2，时钟 100MHz
       USART2 USART3 UART4 UART5 UART6 UART7 UART8 选择的时钟是 PLCK1，时钟 100MHz
    */
    RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART16;
    RCC_PeriphClkInit.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
    HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);

#if UART1_FIFO_EN == 1
    USART1_TX_GPIO_CLK_ENABLE();
    USART1_RX_GPIO_CLK_ENABLE();

    USART1_CLK_ENABLE();

    GPIO_InitStruct.Pin = USART1_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = USART1_TX_AF;
    HAL_GPIO_Init(USART1_TX_GPIO_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = USART1_RX_PIN;
    GPIO_InitStruct.Alternate = USART1_RX_AF;
    HAL_GPIO_Init(USART1_RX_GPIO_PORT, &GPIO_InitStruct);

    //配置NVIC the NVIC for UART
    HAL_NVIC_SetPriority(USART1_IRQn, 0, 1);
    HAL_NVIC_EnableIRQ(USART1_IRQn);

    //配置波特率、奇偶校验
    Uart_SetUartParam(USART1, UART1_BAUD, UART_PARITY_NONE, UART_MODE_TX_RX);

    SET_BIT(USART1->ICR, USART_ICR_TCCF);   //清除发送完成标志
    SET_BIT(USART1->RQR, USART_RQR_RXFRQ);  //清除接收标志
    SET_BIT(USART1->CR1, USART_CR1_RXNEIE); //使能接受中断
#endif

#if UART2_FIFO_EN == 1
    USART2_TX_GPIO_CLK_ENABLE();
    USART2_RX_GPIO_CLK_ENABLE();

    USART2_CLK_ENABLE();

    GPIO_InitStruct.Pin = USART2_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = USART2_TX_AF;
    HAL_GPIO_Init(USART2_TX_GPIO_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = USART2_RX_PIN;
    GPIO_InitStruct.Alternate = USART2_RX_AF;
    HAL_GPIO_Init(USART2_RX_GPIO_PORT, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(USART2_IRQn, 0, 2);
    HAL_NVIC_EnableIRQ(USART2_IRQn);

    Uart_SetUartParam(USART2, UART2_BAUD, UART_PARITY_NONE, UART_MODE_TX_RX);

    SET_BIT(USART2->ICR, USART_ICR_TCCF);
    SET_BIT(USART2->RQR, USART_RQR_RXFRQ);
    SET_BIT(USART2->CR1, USART_CR1_RXNEIE);
#endif

#if UART3_FIFO_EN == 1
    USART3_TX_GPIO_CLK_ENABLE();
    USART3_RX_GPIO_CLK_ENABLE();

    USART3_CLK_ENABLE();

    GPIO_InitStruct.Pin = USART3_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = USART3_TX_AF;
    HAL_GPIO_Init(USART3_TX_GPIO_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = USART3_RX_PIN;
    GPIO_InitStruct.Alternate = USART3_RX_AF;
    HAL_GPIO_Init(USART3_RX_GPIO_PORT, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(USART3_IRQn, 0, 3);
    HAL_NVIC_EnableIRQ(USART3_IRQn);

    Uart_SetUartParam(USART3, UART3_BAUD, UART_PARITY_NONE, UART_MODE_TX_RX);

    SET_BIT(USART3->ICR, USART_ICR_TCCF);
    SET_BIT(USART3->RQR, USART_RQR_RXFRQ);
    SET_BIT(USART3->CR1, USART_CR1_RXNEIE);
#endif

#if UART4_FIFO_EN == 1
    UART4_TX_GPIO_CLK_ENABLE();
    UART4_RX_GPIO_CLK_ENABLE();

    UART4_CLK_ENABLE();

    GPIO_InitStruct.Pin = UART4_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = UART4_TX_AF;
    HAL_GPIO_Init(UART4_TX_GPIO_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = UART4_RX_PIN;
    GPIO_InitStruct.Alternate = UART4_RX_AF;
    HAL_GPIO_Init(UART4_RX_GPIO_PORT, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(UART4_IRQn, 0, 4);
    HAL_NVIC_EnableIRQ(UART4_IRQn);

    Uart_SetUartParam(UART4, UART4_BAUD, UART_PARITY_NONE, UART_MODE_TX_RX);

    SET_BIT(UART4->ICR, USART_ICR_TCCF);
    SET_BIT(UART4->RQR, USART_RQR_RXFRQ);
    SET_BIT(UART4->CR1, USART_CR1_RXNEIE);
#endif

#if UART5_FIFO_EN == 1
    UART5_TX_GPIO_CLK_ENABLE();
    UART5_RX_GPIO_CLK_ENABLE();

    UART5_CLK_ENABLE();

    GPIO_InitStruct.Pin = UART5_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = UART5_TX_AF;
    HAL_GPIO_Init(UART5_TX_GPIO_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = UART5_RX_PIN;
    GPIO_InitStruct.Alternate = UART5_RX_AF;
    HAL_GPIO_Init(UART5_RX_GPIO_PORT, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(UART5_IRQn, 0, 5);
    HAL_NVIC_EnableIRQ(UART5_IRQn);

    Uart_SetUartParam(UART5, UART5_BAUD, UART_PARITY_NONE, UART_MODE_TX_RX);

    SET_BIT(UART5->ICR, USART_ICR_TCCF);
    SET_BIT(UART5->RQR, USART_RQR_RXFRQ);
    SET_BIT(UART5->CR1, USART_CR1_RXNEIE);
#endif

#if UART6_FIFO_EN == 1
    USART6_TX_GPIO_CLK_ENABLE();
    USART6_RX_GPIO_CLK_ENABLE();

    USART6_CLK_ENABLE();

    GPIO_InitStruct.Pin = USART6_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = USART6_TX_AF;
    HAL_GPIO_Init(USART6_TX_GPIO_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = USART6_RX_PIN;
    GPIO_InitStruct.Alternate = USART6_RX_AF;
    HAL_GPIO_Init(USART6_RX_GPIO_PORT, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(USART6_IRQn, 0, 6);
    HAL_NVIC_EnableIRQ(USART6_IRQn);

    Uart_SetUartParam(USART6, UART6_BAUD, UART_PARITY_NONE, UART_MODE_TX_RX);

    SET_BIT(USART6->ICR, USART_ICR_TCCF);
    SET_BIT(USART6->RQR, USART_RQR_RXFRQ);
    SET_BIT(USART6->CR1, USART_CR1_RXNEIE);
#endif

#if UART7_FIFO_EN == 1
    UART7_TX_GPIO_CLK_ENABLE();
    UART7_RX_GPIO_CLK_ENABLE();

    UART7_CLK_ENABLE();

    GPIO_InitStruct.Pin = UART7_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = UART7_TX_AF;
    HAL_GPIO_Init(UART7_TX_GPIO_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = UART7_RX_PIN;
    GPIO_InitStruct.Alternate = UART7_RX_AF;
    HAL_GPIO_Init(UART7_RX_GPIO_PORT, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(UART7_IRQn, 0, 6);
    HAL_NVIC_EnableIRQ(UART7_IRQn);

    Uart_SetUartParam(UART7, UART7_BAUD, UART_PARITY_NONE, UART_MODE_TX_RX);

    SET_BIT(UART7->ICR, USART_ICR_TCCF);
    SET_BIT(UART7->RQR, USART_RQR_RXFRQ);
    SET_BIT(UART7->CR1, USART_CR1_RXNEIE);
#endif

#if UART8_FIFO_EN == 1
    UART8_TX_GPIO_CLK_ENABLE();
    UART7_RX_GPIO_CLK_ENABLE();

    UART8_CLK_ENABLE();

    GPIO_InitStruct.Pin = UART8_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = UART8_TX_AF;
    HAL_GPIO_Init(UART8_TX_GPIO_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = UART8_RX_PIN;
    GPIO_InitStruct.Alternate = UART8_RX_AF;
    HAL_GPIO_Init(UART8_RX_GPIO_PORT, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(UART8_IRQn, 0, 6);
    HAL_NVIC_EnableIRQ(UART8_IRQn);

    Uart_SetUartParam(UART8, UART8_BAUD, UART_PARITY_NONE, UART_MODE_TX_RX);

    SET_BIT(UART8->ICR, USART_ICR_TCCF);
    SET_BIT(UART8->RQR, USART_RQR_RXFRQ);
    SET_BIT(UART8->CR1, USART_CR1_RXNEIE);
#endif
}

/**
  * @brief  填写数据到 UART 发送缓冲区，并启动发送中断。中断处理函数发送完毕后，自动关闭发送中断
  * @param  _pUart
  * @param  _ucaBuf
  * @param  _usLen
  */
static void UartSend(UART_T *_pUart, uint8_t *_ucaBuf, uint16_t _usLen)
{
    uint16_t i;

    for (i = 0; i < _usLen; i++)
    {
        //如果发送缓冲区已满，则等待缓冲区空
        while (1)
        {
            __IO uint16_t usCount;

            DISABLE_INT();
            usCount = _pUart->usTxCount;
            ENABLE_INT();

            if (usCount < _pUart->usTxBufSize)
            {
                break;
            }
            else if (usCount == _pUart->usTxBufSize) //数据已填满缓冲区
            {
                if ((_pUart->uart->CR1 & USART_CR1_TXEIE) == 0)
                {
                    SET_BIT(_pUart->uart->CR1, USART_CR1_TXEIE);
                }
            }
        }

        //将新数据填入发送缓冲区
        _pUart->pTxBuf[_pUart->usTxWrite] = _ucaBuf[i];

        DISABLE_INT();
        if (++_pUart->usTxWrite >= _pUart->usTxBufSize)
        {
            _pUart->usTxWrite = 0;
        }
        _pUart->usTxCount++;
        ENABLE_INT();
    }

    SET_BIT(_pUart->uart->CR1, USART_CR1_TXEIE); //使能发送中断（缓冲区空）
}

/**
  * @brief  填写数据到 UART 发送缓冲区，并启动发送中断。中断处理函数发送完毕后，自动关闭发送中断
  * @param  _pUart
  * @param  _pByte
  * @retval 成功返回 1，失败返回 0
  */
static uint8_t UartGetChar(UART_T *_pUart, uint8_t *_pByte)
{
    uint16_t usCount;

    DISABLE_INT();
    usCount = _pUart->usRxCount;
    ENABLE_INT();

    //如果读和写索引相同，则返回 0
    if (usCount == 0)
    {
        return 0;
    }
    else
    {
        *_pByte = _pUart->pRxBuf[_pUart->usRxRead]; //从串口接收 FIFO 取 1 个数据

        //改写 FIFO 读索引
        DISABLE_INT();
        if (++_pUart->usRxRead >= _pUart->usRxBufSize)
        {
            _pUart->usRxRead = 0;
        }
        _pUart->usRxCount--;
        ENABLE_INT();
        return 1;
    }
}

/**
  * @brief  判断发送缓冲区是否为空
  * @param  _ucPort
  * @retval 1 为空，0 为不空
  */
uint8_t Uart_IsTxEmpty(COM_PORT_E _ucPort)
{
    UART_T *pUart;
    uint8_t Sending;

    pUart = ComToUart(_ucPort);
    if (pUart == 0)
    {
        return 0;
    }

    Sending = pUart->Sending;

    if (Sending != 0)
    {
        return 0;
    }
    return 1;
}

/**
  * @brief  供中断服务程序调用，通用串口中断处理函数
  * @param  _pUart
  */
static void UartIRQ(UART_T *_pUart)
{
    uint32_t isrflags = READ_REG(_pUart->uart->ISR);
    uint32_t cr1its = READ_REG(_pUart->uart->CR1);
    uint32_t cr3its = READ_REG(_pUart->uart->CR3);

    //处理接收中断
    if ((isrflags & UART_FLAG_RXNE) != RESET)
    {
        //从串口接收数据寄存器读取数据存放到接收 FIFO
        uint8_t ch = READ_REG(_pUart->uart->RDR);
        _pUart->pRxBuf[_pUart->usRxWrite] = ch;
        if (++_pUart->usRxWrite >= _pUart->usRxBufSize)
            _pUart->usRxWrite = 0;
        if (_pUart->usRxCount < _pUart->usRxBufSize)
            _pUart->usRxCount++;

        //回调函数
        if (_pUart->Receive)
            _pUart->Receive(ch);
    }

    //处理发送缓冲区空中断
    if (((isrflags & UART_FLAG_TXE) != RESET) && (cr1its & USART_CR1_TXEIE) != RESET)
    {
        if (_pUart->usTxCount == 0)
        {
            //发送缓冲区的数据已取完时，禁止发送缓冲区空中断
            CLEAR_BIT(_pUart->uart->CR1, USART_CR1_TXEIE);

            //使能数据发送完毕中断
            SET_BIT(_pUart->uart->CR1, USART_CR1_TCIE);
        }
        else
        {
            _pUart->Sending = 1;

            //从发送 FIFO 取 1 个字节写入串口发送数据寄存器
            _pUart->uart->TDR = _pUart->pTxBuf[_pUart->usTxRead];
            if (++_pUart->usTxRead >= _pUart->usTxBufSize)
            {
                _pUart->usTxRead = 0;
            }
            _pUart->usTxCount--;
        }
    }

    //数据 bit 位全部发送完毕的中断
    if (((isrflags & USART_ISR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
    {
        if (_pUart->usTxCount == 0)
        {
            //如果发送 FIFO 的数据全部发送完毕，禁止数据发送完毕中断
            CLEAR_BIT(_pUart->uart->CR1, USART_CR1_TCIE);

            //回调函数
            if (_pUart->SendOver)
            {
                _pUart->SendOver();
            }

            _pUart->Sending = 0;
        }
        else
        {
            //如果发送 FIFO 的数据还未完毕，则从发送 FIFO 取 1 个数据写入发送数据寄存器
            _pUart->uart->TDR = _pUart->pTxBuf[_pUart->usTxRead];
            if (++_pUart->usTxRead >= _pUart->usTxBufSize)
            {
                _pUart->usTxRead = 0;
            }
            _pUart->usTxCount--;
        }
    }

    //清除中断标志
    SET_BIT(_pUart->uart->ICR, UART_CLEAR_PEF);
    SET_BIT(_pUart->uart->ICR, UART_CLEAR_FEF);
    SET_BIT(_pUart->uart->ICR, UART_CLEAR_NEF);
    SET_BIT(_pUart->uart->ICR, UART_CLEAR_OREF);
    SET_BIT(_pUart->uart->ICR, UART_CLEAR_IDLEF);
    SET_BIT(_pUart->uart->ICR, UART_CLEAR_TCF);
    SET_BIT(_pUart->uart->ICR, UART_CLEAR_LBDF);
    SET_BIT(_pUart->uart->ICR, UART_CLEAR_CTSF);
    SET_BIT(_pUart->uart->ICR, UART_CLEAR_CMF);
    SET_BIT(_pUart->uart->ICR, UART_CLEAR_WUF);
    SET_BIT(_pUart->uart->ICR, UART_CLEAR_TXFECF);
}

#if UART1_FIFO_EN == 1
void USART1_IRQHandler(void)
{
    UartIRQ(&g_tUart1);
}
#endif

#if UART2_FIFO_EN == 1
void USART2_IRQHandler(void)
{
    UartIRQ(&g_tUart2);
}
#endif

#if UART3_FIFO_EN == 1
void USART3_IRQHandler(void)
{
    UartIRQ(&g_tUart3);
}
#endif

#if UART4_FIFO_EN == 1
void UART4_IRQHandler(void)
{
    UartIRQ(&g_tUart4);
}
#endif

#if UART5_FIFO_EN == 1
void UART5_IRQHandler(void)
{
    UartIRQ(&g_tUart5);
}
#endif

#if UART6_FIFO_EN == 1
void USART6_IRQHandler(void)
{
    UartIRQ(&g_tUart6);
}
#endif

#if UART7_FIFO_EN == 1
void UART7_IRQHandler(void)
{
    UartIRQ(&g_tUart7);
}
#endif

#if UART8_FIFO_EN == 1
void UART8_IRQHandler(void)
{
    UartIRQ(&g_tUart8);
}
#endif

void Uart_SetprintfCom(COM_PORT_E _ucPort)
{
    printf_Com = _ucPort;
}

void Uart_SetgetcharCom(COM_PORT_E _ucPort)
{
    getchar_Com = _ucPort;
}

//重定义 fputc 函数，用于 printf
int fputc(int ch, FILE *f)
{
    Uart_SendChar(printf_Com, ch);

    return ch;
}

//重定义 fgetc 函数，用于 getchar
int fgetc(FILE *f)
{
    uint8_t ucData;

    while (Uart_GetChar(getchar_Com, &ucData) == 0)
        ;

    return ucData;
}
