1,概述

通用异步收发传输器(Universal Asynchronous Receiver/Transmitter,通常称为 UART)是一种异步收发传输器,提供了与外部设备进行全双工数据交换的灵活方式。

2,API参考

2.1 主要结构体、枚举、联合体介绍

2.1.1 UART_ID枚举

  • 在makefile文件或者头文件中可以定义CHIP_HAS_UART宏,用于移植至拥有不同数量UART的芯片型号。

    1. enum HAL_UART_ID_T {
    2. HAL_UART_ID_0 = 0,
    3. #if (CHIP_HAS_UART >= 2) //芯片拥有2个UART
    4. HAL_UART_ID_1,
    5. #endif
    6. #if (CHIP_HAS_UART >= 3) //芯片拥有3个UART
    7. HAL_UART_ID_2,
    8. #endif
    9. #if (CHIP_HAS_UART >= 4) //芯片拥有4个UART
    10. HAL_UART_ID_3,
    11. #endif
    12. #ifdef BT_UART
    13. HAL_UART_ID_BT,
    14. #endif
    15. HAL_UART_ID_QTY
    16. };

    2.1.2 串口通信各参数枚举

  • 串口通信时需要设置数据位、校验位、停止位等参数,这些参数都被规定在下列枚举中

    • 校验位枚举

      1. enum HAL_UART_PARITY_T {
      2. HAL_UART_PARITY_NONE, //无校验
      3. HAL_UART_PARITY_ODD, //奇校验
      4. HAL_UART_PARITY_EVEN, //偶校验
      5. HAL_UART_PARITY_FORCE1, //校验位强制为1
      6. HAL_UART_PARITY_FORCE0, //校验位强制为0
      7. };
    • 停止位枚举

      1. enum HAL_UART_STOP_BITS_T {
      2. HAL_UART_STOP_BITS_1, //停止位1位
      3. HAL_UART_STOP_BITS_2, //停止位2位
      4. };
    • 数据位枚举

      enum HAL_UART_DATA_BITS_T {
      HAL_UART_DATA_BITS_5, //数据位5位
      HAL_UART_DATA_BITS_6, //数据位6位
      HAL_UART_DATA_BITS_7, //数据位7位
      HAL_UART_DATA_BITS_8, //数据位8位
      };
      
    • 流控制枚举

      enum HAL_UART_FLOW_CONTROL_T {
      HAL_UART_FLOW_CONTROL_NONE, //无流控制
      HAL_UART_FLOW_CONTROL_RTS,    //RTS流控制
      HAL_UART_FLOW_CONTROL_CTS,    //CTS流控制
      HAL_UART_FLOW_CONTROL_RTSCTS, //RTS CTS流控制
      };
      
    • FIFO中断深度级别枚举

      enum HAL_UART_FIFO_LEVEL_T {
      HAL_UART_FIFO_LEVEL_1_8, //在1/8深度时产生中断
      HAL_UART_FIFO_LEVEL_1_4, //在1/4深度时产生中断
      HAL_UART_FIFO_LEVEL_1_2, //在1/2深度时产生中断
      HAL_UART_FIFO_LEVEL_3_4, //在3/4深度时产生中断
      HAL_UART_FIFO_LEVEL_7_8, //在7/8深度时产生中断
      };
      

      注:当FIFO里剩余的数据减少(发送时)或累计(接收时)到预设的深度时触发中断。

    • UART传输模式枚举

      enum HAL_UART_XFER_TYPE_T {
      HAL_UART_XFER_TYPE_TX       = (1 << 0), //发送模式
      HAL_UART_XFER_TYPE_RX       = (1 << 1), //接收模式
      };
      

      注:在配置UART时不会用到传输模式枚举,只有在UART暂停和UART继续两个函数中有使用到

2.1.3 UART配置结构体

struct HAL_UART_CFG_T {
    enum HAL_UART_PARITY_T parity;            //校验位
    enum HAL_UART_STOP_BITS_T stop;            //停止位
    enum HAL_UART_DATA_BITS_T data;            //数据位
    enum HAL_UART_FLOW_CONTROL_T flow;        //流控制
    enum HAL_UART_FIFO_LEVEL_T rx_level;    //FIFO接收中断深度
    enum HAL_UART_FIFO_LEVEL_T tx_level;    //FIFO发送中断深度
    uint32_t baud;                            //波特率
    bool dma_rx : 1;                        //dma接收
    bool dma_tx : 1;                        //dma发送
    bool dma_rx_stop_on_err : 1;            //dma接受错误停止
};

2.1.4 UART各个寄存器联合体

  • UART状态寄存器联合体

    union HAL_UART_STATUS_T {
      struct {
          uint32_t FE   :1; // frame error
          uint32_t PE   :1; // parity error
          uint32_t BE   :1; // break error
          uint32_t OE   :1; // overrun error
      };
      uint32_t reg;
    };
    
  • UART标志位寄存器联合体

    union HAL_UART_FLAG_T {
      struct {
          uint32_t CTS  :1;
          uint32_t DSR  :1;
          uint32_t DCD  :1;
          uint32_t BUSY :1;
          uint32_t RXFE :1; // rx fifo empty
          uint32_t TXFF :1; // tx fifo full
          uint32_t RXFF :1; // rx fifo full
          uint32_t TXFE :1; // tx fifo empty
          uint32_t RI   :1; // ring indicator
      };
      uint32_t reg;
    };
    
  • UART中断寄存器联合体

    union HAL_UART_IRQ_T {
      struct {
          uint32_t RIM  :1; // ri
          uint32_t CTSM :1; // cts
          uint32_t DCDM :1; // dcd
          uint32_t DSRM :1; // dsr
          uint32_t RX   :1; // rx
          uint32_t TX   :1; // tx
          uint32_t RT   :1; // receive timeout
          uint32_t FE   :1; // framing error
          uint32_t PE   :1; // parity error
          uint32_t BE   :1; // break error
          uint32_t OE   :1; // overrun
      };
      uint32_t reg;
    };
    

    2.1.5 UART中断回调函数指针

    //UART中断
    typedef void (*HAL_UART_IRQ_HANDLER_T)(enum HAL_UART_ID_T id, union HAL_UART_IRQ_T status);
    //dma接收中断
    typedef void (*HAL_UART_IRQ_RXDMA_HANDLER_T)(uint32_t xfer_size, int dma_error, union HAL_UART_IRQ_T status);
    //dma发送中断
    typedef void (*HAL_UART_IRQ_TXDMA_HANDLER_T)(uint32_t xfer_size, int dma_error);
    

    2.2 主要函数介绍

    2.2.1 UART开启

  • 函数原型:

    int hal_uart_open(enum HAL_UART_ID_T id, const struct HAL_UART_CFG_T *cfg);
    
  • 功能描述:打开指定UART

  • 函数参数:

    • id:UART id
    • *cfg:UART配置结构体指针

      2.2.2 UART重开启

  • 函数原型:

    int hal_uart_reopen(enum HAL_UART_ID_T id, const struct HAL_UART_CFG_T *cfg);
    
  • 功能描述:重新打开指定UART

  • 函数参数:

    • id:UART id
    • *cfg:UART配置结构体指针

      2.2.3 UART关闭

  • 函数原型:

    int hal_uart_close(enum HAL_UART_ID_T id);
    
  • 功能描述:关闭指定UART

  • 函数参数:

    • id:UART id

      2.2.4 UART开启查询

  • 函数原型:

    int hal_uart_opened(enum HAL_UART_ID_T id);
    
  • 功能描述:查询指定UART是否开启

  • 函数参数:
    • id:UART id
  • 返回值:

    • 0:关闭
    • 1:开启

      2.2.5 UART进入睡眠

  • 函数原型:

    void hal_uart_sleep(void);
    
  • 功能描述:令所有UART进入睡眠模式

    2.2.6 UART唤醒

  • 函数原型:

    void hal_uart_wakeup(void);
    
  • 功能描述:唤醒所有UART

    2.2.7 改变UART波特率

  • 函数原型:

    int hal_uart_change_baud_rate(enum HAL_UART_ID_T id, uint32_t rate);
    
  • 功能描述:改变指定UART的波特率

  • 函数参数:
    • id:UART id
    • rate:指定波特率
  • 返回值:

    • 0:修改成功
    • 1:串口未开启
    • 2:串口繁忙

      2.2.8 UART暂停

  • 函数原型:

    int hal_uart_pause(enum HAL_UART_ID_T id, enum HAL_UART_XFER_TYPE_T type);
    
  • 功能描述:暂停指定UART的接收或发送

  • 函数参数:
    • id:UART id
    • type:接收或发送模式
  • 返回值:

    • 0:暂停成功
    • 1:暂停失败

      2.2.9 UART继续

  • 函数原型:

    int hal_uart_continue(enum HAL_UART_ID_T id, enum HAL_UART_XFER_TYPE_T type);
    
  • 功能描述:继续UART接收或发送数据

  • 函数参数:
    • id:UART id
    • type:接收或发送模式
  • 返回值:

    • 0:继续成功
    • 1:继续失败

      2.2.10 判断UART是否可读

  • 函数原型:

    int hal_uart_readable(enum HAL_UART_ID_T id);
    
  • 功能描述:判断指定UART是否可读

  • 函数参数:
    • id:UART id
  • 返回值:

    • 0:可读
    • 1:不可读

      2.2.11 判断UART是否可写

  • 函数原型:

    int hal_uart_writeable(enum HAL_UART_ID_T id);
    
  • 功能描述:判断指定UART是否可写

  • 函数参数:
    • id:UART id
  • 返回值:

    • 0:可写
    • 1:不可写

      2.2.12 获取单个字符

  • 函数原型:

    uint8_t hal_uart_getc(enum HAL_UART_ID_T id);
    
  • 功能描述:获取指定UART收到的单个字符

  • 函数参数:
    • id:UART id
  • 返回值

    • 接收到的字符

      2.2.13 发送单个字符

  • 函数原型:

    int hal_uart_putc(enum HAL_UART_ID_T id, uint8_t c);
    
  • 功能描述:发送一字节字符

  • 函数参数:
    • id:UART id
    • c:待发送字符
  • 返回值:

    • 0:发送成功

      2.2.14 获取阻塞单个字符

  • 函数原型:

    uint8_t hal_uart_blocked_getc(enum HAL_UART_ID_T id);
    
  • 功能描述:等待直至指定UART可读后获取单个字符

  • 函数参数:
    • id:UART id
  • 返回值:

    • 接收到的字符

      2.2.15 发送阻塞单个字符

  • 函数原型:

    int hal_uart_blocked_putc(enum HAL_UART_ID_T id, uint8_t c);
    
  • 功能描述:等待直至指定UART可写后发送单个字符

  • 函数参数:
    • id:UART id
    • c:待发送字符
  • 返回值

    • 0:发送成功

      2.2.16 获取UART标志位寄存器

  • 函数原型:

    union HAL_UART_FLAG_T hal_uart_get_flag(enum HAL_UART_ID_T id);
    
  • 功能描述:获取指定UART的标志位寄存器值

  • 函数参数:
    • id:UART id
  • 返回值:

    • union HAL_UART_FLAG_T:返回指定UART的标志位寄存器联合体

      2.2.17 获取UART状态位寄存器

  • 函数原型:

    union HAL_UART_STATUS_T hal_uart_get_status(enum HAL_UART_ID_T id);
    
  • 功能描述:获取指定UART的状态位寄存器值

  • 函数参数:
    • id:UART id
  • 返回值:

    • union HAL_UART_STATUS_T:返回指定UART的状态位寄存器联合体

      2.2.18 清除UART状态位

  • 函数原型:

    void hal_uart_clear_status(enum HAL_UART_ID_T id);
    
  • 功能描述:将指定UART状态位寄存器清0

  • 函数参数:

    • id:UART id

      2.2.19 设置break信号

  • 函数原型:

    void hal_uart_break_set(enum HAL_UART_ID_T id);
    
  • 功能描述:指定UART设置break信号

  • 函数参数:

    • id:UART id

      2.2.20 清除break信号

  • 函数原型:

    void hal_uart_break_clear(enum HAL_UART_ID_T id);
    
  • 函数功能:清除指定UART的break信号

  • 函数参数:

    • id:UART id

      2.2.21清空FIFO

  • 函数原型

    void hal_uart_flush(enum HAL_UART_ID_T id, uint32_t ticks);
    
  • 函数功能:接收完当前最后一个字符后,清空FIFO缓存

  • 函数参数:

    • id:UART id
    • ticks:等待字符接收时间

      2.2.22 清除IRQ

  • 函数原型:

    void hal_uart_clear_irq(enum HAL_UART_ID_T id, union HAL_UART_IRQ_T irq);
    
  • 函数功能:清除指定UART irq

  • 函数参数:

    • id:UART id
    • irq:irq寄存器

      2.2.23 设置irq handler

  • 函数原型:

    HAL_UART_IRQ_HANDLER_T hal_uart_irq_set_handler(enum HAL_UART_ID_T id, HAL_UART_IRQ_HANDLER_T handler);
    
  • 函数功能:为指定UART设置irq

  • 函数参数:
    • id:UART id
    • handler:irq handler
  • 返回值:

    • UART原先的irq handler

      2.2.24 UART DMA接收开始

  • 函数原型:

    int hal_uart_dma_recv(enum HAL_UART_ID_T id, uint8_t *buf, uint32_t len,
                        struct HAL_DMA_DESC_T *desc, uint32_t *desc_cnt);
    
  • 函数功能:UART DMA接收开始

  • 函数参数:
    • id:UART id
    • *buf:UART buffer
    • len:BUART buffer length
    • *desc:dma参数结构体
    • desc_cnt:descriptor count
  • 返回值:

    • 0:成功

      2.2.25 UART DMA设置irq handler

  • 函数原型:

    void hal_uart_irq_set_dma_handler(enum HAL_UART_ID_T id, HAL_UART_IRQ_RXDMA_HANDLER_T rxdma, HAL_UART_IRQ_TXDMA_HANDLER_T txdma);
    
  • 函数功能:设置UART DMA的接收与发送中断

  • 函数参数:

    • id:UART id
    • rxdma:DMA接收中断handler
    • txdma:DMA发送中断handler

      2.2.26 UART DMA 双缓存接收开始

  • 函数原型:

    int hal_uart_dma_recv_pingpang(enum HAL_UART_ID_T id, uint8_t *buf, uint32_t len,
                        struct HAL_DMA_DESC_T *desc, uint32_t *desc_cnt);
    
  • 函数功能:UART DMA 双缓存接收开始

  • 函数参数:
    • id:UART id
    • *buf:UART buffer
    • len:BUART buffer length
    • *desc:dma参数结构体
    • desc_cnt:descriptor count
  • 返回值:

    • 0:成功

      2.2.27 UART DMA 寻址接收

  • 函数原型: ```c int hal_uart_dma_recv_mask(enum HAL_UART_ID_T id, uint8_t *buf, uint32_t len,

                         struct HAL_DMA_DESC_T *desc, uint32_t *desc_cnt,
                         const union HAL_UART_IRQ_T *mask);
    

- 函数功能:UART DMA 寻址接收开始
- 函数参数:
   - id:UART id
   - *buf:UART buffer
   - len:BUART buffer length
   - *desc:dma参数结构体
   - desc_cnt:descriptor count
   - mask:寻址掩码
- 返回值:
   - 0:成功
<a name="IuhXs"></a>
### 2.2.28 UART DMA 双缓存寻址接收

- 函数原型:
```c
int hal_uart_dma_recv_mask_pingpang(enum HAL_UART_ID_T id, uint8_t *buf, uint32_t len,
                                    struct HAL_DMA_DESC_T *desc, uint32_t *desc_cnt,
                                    const union HAL_UART_IRQ_T *mask, uint32_t step);
  • 函数功能:UART DMA 寻址接收开始
  • 函数参数:
    • id:UART id
    • *buf:UART buffer
    • len:BUART buffer length
    • *desc:dma参数结构体
    • desc_cnt:descriptor count
    • mask:寻址掩码
    • step:传输步骤次数
  • 返回值:

    • 0:成功

      2.2.29 获取UART DMA接收地址

  • 函数原型:

    uint32_t hal_uart_get_dma_recv_addr(enum HAL_UART_ID_T id);
    
  • 函数功能:获取DMA接收地址

  • 函数参数:
    • id:UART id
  • 返回值:

    • 接收地址

      2.2.30 停止UART DMA接收

  • 函数原型:

    uint32_t hal_uart_stop_dma_recv(enum HAL_UART_ID_T id);
    
  • 函数功能:停止UART DMA接收

  • 函数参数:
    • id:UART id
  • 返回值

    • FIFO中剩余的数据

      2.2.31 UART DMA发送

  • 函数原型:

    int hal_uart_dma_send(enum HAL_UART_ID_T id, const uint8_t *buf, uint32_t len,
                        struct HAL_DMA_DESC_T *desc, uint32_t *desc_cnt);
    
  • 函数功能:UART DMA发送数据

  • 函数参数:

    • id:UART id
    • *buf:发送buffer
    • len:buffer length
    • *desc:dma参数结构体
    • desc_cnt:descriptor count

      2.2.32 UART DMA发送停止

  • 函数原型:

    uint32_t hal_uart_stop_dma_send(enum HAL_UART_ID_T id);
    
  • 函数功能:停止UART DMA发送

  • 函数参数:
    • id:UART id
  • 返回值

    • FIFO中剩余的数据

      3,使用教程

      3.1 头文件引用

      #include "hal_iomux.h" //IO多路输入输出配置文件
      #include "hal_uart.h"  //UART配置头文件
      

      3.2 UART 配置与开启

  • UART的配置信息通过新建HAL_UART_CFG_T来进行配置,如下

    static struct HAL_UART_CFG_T uart_cfg = {
      .parity = HAL_UART_PARITY_NONE,
      .stop = HAL_UART_STOP_BITS_1,
      .data = HAL_UART_DATA_BITS_8,
      .flow = HAL_UART_FLOW_CONTROL_NONE,
      .tx_level = HAL_UART_FIFO_LEVEL_1_2,
      .rx_level = HAL_UART_FIFO_LEVEL_1_4, // max 16 bytes received once, it does not work to change it to other values.
      .baud = 921600,                       
      .dma_rx = false,
      .dma_tx = false,
      .dma_rx_stop_on_err = false,
    };
    
  • 当确定好UART配置后,接下来需要决定使用哪个UART,并使用iomux头文件中的API进行UART IO口配置

    hal_set_uart_iomux(uart_id); //uart id为enum HAL_UART_ID_T枚举
    
  • 随后启用UART即可

    hal_uart_open(uart_id, &uart_cfg); //uart id为enum HAL_UART_ID_T枚举
                                     //uart_cfg为前文中定义的UART配置结构体
    

    3.3 UART的接收与发送

  • 利用2.2.x中的各类API可以采用不同的方式来接收与发送数据,这里采用最基础的API来实现一个基础的UART ECHO功能

  • UART发送处理函数

    static void uart_tx(const void *buf, int len) //void *buf确保能发送各种类型数据 
    {
      int i;
      for (i = 0; i < len; i++) {
          hal_uart_blocked_putc(uart_id, *((char *)buf + i));
          //使用阻塞发送函数,确保数据不会因为UART繁忙而取消发送
      }
    }
    
  • UART接收处理函数

    static void uart_rx(void)
    {
      static uint32_t i = 0;
      while (hal_uart_readable(uart_id)) {
          ASSERT(i < sizeof(uart_buf), "buf full");  //确认buffer是否溢出
          uart_buf[i++] = hal_uart_getc(uart_id);    //获取接收数据并存储在buffer内
      }
      if (i > 0) {
          uart_tx(uart_buf, i);     //ECHO
          i = 0;
      }
    }
    
  • ECHO主函数

    void uart_echo(void)
    {
      printf("[%s:%d] %s\r\n", __FILE__, __LINE__, __func__); //log信息
      hal_set_uart_iomux(uart_id); //UART IO设置
      hal_uart_open(uart_id, &uart_cfg); //开启UART
    
      while (1) {    
          uart_rx();        //轮询接收数据
          osDelay(10);    
      }
    }