2.3. UART

Overview

提供 UART 应用示例、配置介绍、串口控制流的使用和常见问题。

2.3.1. 应用实例

示例演示:

  • 根据条件执行对应的 uart 收发模式,等待接受来自 UART2 的数据,收到数据后发送回去。

example: 具体示例代码详见 apps/common/example/peripheral/uart/uart_test.c ,示例工程实现需在 apps/demo/demo_DevKitBoard/include/demo_config.h 中开启宏 USE_UART_TEST_DEMO

2.3.2. 常见问题

  • 使用固定引脚的时候,需注意芯片封装是否有支持的引脚, 具体可以通过对应型号原理图查看。

  • 如果有不需要用到的 tx_pin 或者 rx_pin, 需要将其赋值为-1。

  • USB脚只有UART1支持使用、串口流控制也只有UART1支持。

  • 使用通信功能时,例如使用串口1作为通信串口,需要在使用的 board 文件加入以下代码注册串口, 只使用到打印功能时不需要注册。

    REGISTER_DEVICES(device_table) = {
            {"uart1", &uart_dev_ops, (void *)&uart1_data },
    };
    

  • 使用打印功能时,例如使用串口2作为打印,需要在使用的 board 文件加入以下代码初始化串口。

    void debug_uart_init()
    
    
    {
        uart_init(&uart2_data);
    }
    

  • 注意使用到的串口引脚在程序其他地方有没有同时占据使用。

  • 使用重映射方法时需要注意 OUTPUT_CHANNEL 和 INPUT_CHANNEL 在程序其他地方有没有同时占据使用。

  • 串口 TX 或者 RX 能否配置任意引脚?

    答:能,使用重映射方法配置 OUTPUT_CHANNEL和INPUT_CHANNEL。

  • 优先推荐使用一个串口的配置方法, 优先推荐使用固定引脚的配置方法,可以节省 OUTPUT_CHANNEL 和 INPUT_CHANNEL 供其他功能使用。

2.3.3. 串口控制流配置说明使用

  • 1.首先在 board.c 中配置串口信息

    UART1_PLATFORM_DATA_BEGIN(uart1_data)
        .baudrate = 9600,
        .port = PORT_REMAP,
        .output_channel = OUTPUT_CHANNEL1,
        .input_channel = INPUT_CHANNEL1,
        .tx_pin = IO_PORTC_01,
        .rx_pin = IO_PORTC_02,
        .max_continue_recv_cnt = 500,
        .idle_sys_clk_cnt = 500000,
        .clk_src = PLL_48M,
        .rts_pin = IO_PORTB_07,  //配置RTS控制引脚
        .cts_pin = IO_PORTC_06,  //配置CTS控制引脚
        .rts_output_channel = OUTPUT_CHANNEL2,  //配置RTS启用的通道
        .flow_ctl_enable = 1,  ////开启控制流
    UART1_PLATFORM_DATA_END();
    

    1. 使用dev_ioctl来调用串口控制流挂起和唤醒

    dev_ioctl(hdl, UART1_FLOW_CTL_RTS_SUSPEND,0);
    
    dev_ioctl(hdl,UART1_FLOW_CTL_RTS_RESUME,0);
    

2.3.4. UART配置说明

两个串口使用情况配置:

  • 1.串口2用做打印,串口1做通信只用RX引脚

    Note

    串口2使用固定组引脚的配置方法,使用PORTC_9_10中的IO_PORTC_9作为打印,

    串口1使用INPUT_CHANNEL3重映射引脚的配置方法,使用IO_PORTC_10作为通信RX引脚

UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .baudrate = 460800,
    .port = PORT_REMAP,
    .tx_pin = -1,
    .rx_pin = IO_PORTC_10,
    .input_channel = INPUT_CHANNEL3,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .disable_tx_irq=1,
UART1_PLATFORM_DATA_END();

UART2_PLATFORM_DATA_BEGIN(uart2_data)
    .baudrate = 1000000,
    .port = PORTC_9_10,
    .tx_pin = IO_PORTC_09,
    .rx_pin = -1,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .flags = UART_DEBUG,
UART2_PLATFORM_DATA_END();

Note

串口2使用OUTPUT_CHANNEL0重映射引脚的配置方法使用IO_PORTH_06作为打印,

串口1使用固定组引脚的配置方法,使用PORTH_6_7中的IO_PORTH_07作为通信RX引脚

UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .baudrate = 460800,
    .port = PORTH_6_7,
    .tx_pin = -1,
    .rx_pin = IO_PORTH_07,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .disable_tx_irq=1,
UART1_PLATFORM_DATA_END();

UART2_PLATFORM_DATA_BEGIN(uart2_data)
    .baudrate = 1000000,
    .port = PORT_REMAP,
    .tx_pin = IO_PORTH_06,
    .rx_pin = -1,
    .output_channel = OUTPUT_CHANNEL0,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .flags = UART_DEBUG,
UART2_PLATFORM_DATA_END();

Note

串口2使用OUTPUT_CHANNEL0重映射引脚的配置方法,使用IO_PORTC_00作为打印,

串口1使用INPUT_CHANNEL3重映射引脚的配置方法,使用IO_PORTB_01作为通信RX引脚

 UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .baudrate = 460800,
    .port = PORT_REMAP,
    .tx_pin = -1,
    .rx_pin = IO_PORTB_01,
    .input_channel = INPUT_CHANNEL3,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .disable_tx_irq=1,
UART1_PLATFORM_DATA_END();

UART2_PLATFORM_DATA_BEGIN(uart2_data)
    .baudrate = 1000000,
    .port = PORT_REMAP,
    .tx_pin = IO_PORTC_00,
    .rx_pin = -1,
    .output_channel = OUTPUT_CHANNEL0,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .flags = UART_DEBUG,
UART2_PLATFORM_DATA_END();

Note

串口2使用固定组引脚的配置方法,使用PORTC_9_10中的IO_PORTC_9作为打印,

串口1使用固定组引脚的配置方法,使用PORTH_6_7中的IO_PORTH_07作为通信RX引脚

UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .baudrate = 460800,
    .port = PORTH_6_7,
    .tx_pin = -1,
    .rx_pin = IO_PORTH_07,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .disable_tx_irq=1,
UART1_PLATFORM_DATA_END();

UART2_PLATFORM_DATA_BEGIN(uart2_data)
    .baudrate = 1000000,
    .port = PORTC_9_10,
    .tx_pin = IO_PORTC_09,
    .rx_pin = -1,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .flags = UART_DEBUG,
UART2_PLATFORM_DATA_END();
  • 2.串口2用做打印,串口1做通信只用TX引脚。

Note

串口1使用重映射引脚的配置方法,将PC00重映射做tx引脚。使用了OUTPUT_CHANNEL3。

串口2使用固定引脚的配置方法,使用了固定的一组引脚PC9,PC10。只用了PC09做tx脚。

UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .baudrate = 460800,
    .port = PORT_REMAP,
    .tx_pin = IO_PORTC_00,
    .rx_pin = -1,
    .output_channel = OUTPUT_CHANNEL3,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .disable_tx_irq=1,
UART1_PLATFORM_DATA_END();

UART2_PLATFORM_DATA_BEGIN(uart2_data)
    .baudrate = 1000000,
    .port = PORTC_9_10,
    .tx_pin = IO_PORTC_09,
    .rx_pin = -1,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .flags = UART_DEBUG,
UART2_PLATFORM_DATA_END();

Note

串口1使用重映射引脚的配置方法,将PC00重映射做tx引脚。使用了OUTPUT_CHANNEL3。

串口2使用重映射引脚的配置方法,将PC01重映射做tx引脚。使用了OUTPUT_CHANNEL0。

UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .baudrate = 460800,
    .port = PORT_REMAP,
    .tx_pin = IO_PORTC_00,
    .rx_pin = -1,
    .output_channel = OUTPUT_CHANNEL3,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .disable_tx_irq=1,
UART1_PLATFORM_DATA_END();

UART2_PLATFORM_DATA_BEGIN(uart2_data)
    .baudrate = 1000000,
    .port = PORT_REMAP,
    .tx_pin = IO_PORTC_01,
    .rx_pin = -1,
    .output_channel = OUTPUT_CHANNEL0,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .flags = UART_DEBUG,
UART2_PLATFORM_DATA_END();

Note

串口1使用固定引脚的配置方法,使用了固定的一组引脚PH06和PH07。只用了PH06做tx脚。

串口2使用固定引脚的配置方法,使用了固定的一组引脚PC09和PC10。只用了PC09做tx脚。

UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .baudrate = 460800,
    .port = PORTH_6_7,
    .tx_pin = IO_PORTH_06,
    .rx_pin = -1,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .disable_tx_irq=1,
UART1_PLATFORM_DATA_END();

UART2_PLATFORM_DATA_BEGIN(uart2_data)
    .baudrate = 1000000,
    .port = PORT_REMAP,
    .tx_pin = IO_PORTC_01,
    .rx_pin = -1,
    .output_channel = OUTPUT_CHANNEL0,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .flags = UART_DEBUG,
UART2_PLATFORM_DATA_END();

Note

串口1使用固定引脚的配置方法,使用了固定的一组引脚PH06和PH07。只用了PH06做tx脚。

串口2使用重映射引脚的配置方法,将PC01重映射做tx引脚。使用了OUTPUT_CHANNEL0。

 UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .baudrate = 460800,
    .port = PORTH_6_7,
    .tx_pin = IO_PORTH_06,
    .rx_pin = -1,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .disable_tx_irq=1,
UART1_PLATFORM_DATA_END();

UART2_PLATFORM_DATA_BEGIN(uart2_data)
    .baudrate = 1000000,
    .port = PORTC_9_10,
    .tx_pin = IO_PORTC_09,
    .rx_pin = -1,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .flags = UART_DEBUG,
UART2_PLATFORM_DATA_END();
  • 3.串口2用做打印,串口1做通信既用TX引脚又用RX引脚。

Note

串口1使用重映射引脚的配置方法,将PC00重映射做tx引脚。使用了OUTPUT_CHANNEL3。将PC01重映射做rx引脚。使用了INPUT_CHANNEL3。 串口2使用固定引脚的配置方法,使用了固定的一组引脚PC9,PC10。只用了PC09做tx脚。

 UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .baudrate = 460800,
    .port = PORT_REMAP,
    .tx_pin = IO_PORTC_00,
    .rx_pin = IO_PORTC_01,
    .output_channel = OUTPUT_CHANNEL3,
    .input_channel = INPUT_CHANNEL3,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .disable_tx_irq=1,
UART1_PLATFORM_DATA_END();

UART2_PLATFORM_DATA_BEGIN(uart2_data)
    .baudrate = 1000000,
    .port = PORTC_9_10,
    .tx_pin = IO_PORTC_09,
    .rx_pin = -1,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .flags = UART_DEBUG,
UART2_PLATFORM_DATA_END();

Note

串口1使用固定引脚的配置方法,使用了固定的一组引脚PH06和PH07。PH06做tx脚,PH07做rx脚。 串口2使用固定引脚的配置方法,使用了固定的一组引脚PC9,PC10。只用了PC09做tx脚。

UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .baudrate = 460800,
    .port = PORTH_6_7,
    .tx_pin = IO_PORTH_06,
    .rx_pin = IO_PORTH_07,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .disable_tx_irq=1,
UART1_PLATFORM_DATA_END();

UART2_PLATFORM_DATA_BEGIN(uart2_data)
    .baudrate = 1000000,
    .port = PORTC_9_10,
    .tx_pin = IO_PORTC_09,
    .rx_pin = -1,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .flags = UART_DEBUG,
UART2_PLATFORM_DATA_END();

Note

串口1使用固定引脚的配置方法,使用了固定的一组引脚PH06和PH07。PH06做tx脚,PH07做rx脚。

串口2使用重映射引脚的配置方法,将PC01重映射做tx引脚。使用了OUTPUT_CHANNEL0。

UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .baudrate = 460800,
    .port = PORTH_6_7,
    .tx_pin = IO_PORTH_06,
    .rx_pin = IO_PORTH_07,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .disable_tx_irq=1,
UART1_PLATFORM_DATA_END();

UART2_PLATFORM_DATA_BEGIN(uart2_data)
    .baudrate = 1000000,
    .port = PORT_REMAP,
    .tx_pin = IO_PORTC_01,
    .rx_pin = -1,
    .output_channel = OUTPUT_CHANNEL0,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .flags = UART_DEBUG,
UART2_PLATFORM_DATA_END();

Note

串口1使用重映射引脚的配置方法,将PC06重映射做tx引脚。使用了OUTPUT_CHANNEL3。将PC07重映射做rx引脚。使用了INPUT_CHANNEL3。

串口2使用重映射引脚的配置方法,将PC01重映射做tx引脚。使用了OUTPUT_CHANNEL0。

UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .baudrate = 460800,
    .port = PORT_REMAP,
    .tx_pin = IO_PORTC_06,
    .rx_pin = IO_PORTC_07,
    .output_channel = OUTPUT_CHANNEL3,
    .input_channel = INPUT_CHANNEL3,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .disable_tx_irq=1,
UART1_PLATFORM_DATA_END();

UART2_PLATFORM_DATA_BEGIN(uart2_data)
    .baudrate = 1000000,
    .port = PORT_REMAP,
    .tx_pin = IO_PORTC_01,
    .rx_pin = -1,
    .output_channel = OUTPUT_CHANNEL0,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .flags = UART_DEBUG,

UART2_PLATFORM_DATA_END();

一个串口使用情况配置:

Note

串口1使用固定组引脚的配置方法,使用PORTH_6_7中的IO_PORTH_06作为打印, IO_PORTH_07作为通信RX引脚

UART1_PLATFORM_DATA_BEGIN(uart1_data)
    .baudrate = 460800,
    .port = PORTH_6_7,
    .tx_pin = IO_PORTH_06
    .rx_pin = IO_PORTH_07,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .disable_tx_irq=1,
    .flags = UART_DEBUG,
UART1_PLATFORM_DATA_END();

Note

串口1使用固定组引脚的配置方法,使用PORTH_6_7中的IO_PORTH_06作为打印, IO_PORTH_07作为通信RX引脚

UART1_PLATFORM_DATA_BEGIN(uart1_data)
          .baudrate = 460800,
    .port = PORT_REMAP,
    .tx_pin = IO_PORTC_00
    .rx_pin = IO_PORTC_01,
    .input_channel = INPUT_CHANNEL3,
    .output_channel = OUTPUT_CHANNEL3,
    .max_continue_recv_cnt = 1024,
    .idle_sys_clk_cnt = 500000,
    .clk_src = PLL_48M,
    .disable_tx_irq=1,
    .flags = UART_DEBUG,
UART1_PLATFORM_DATA_END();

2.3.5. API参考

UART dev_ioctl funciton selest

UART_MAGIC
UART_FLUSH

串口重载

UART_SET_RECV_ALL

设置串口等待接收满才退出,需先调用下面的阻塞指令

UART_SET_RECV_BLOCK

设置串口接收阻塞

UART_SET_RECV_TIMEOUT

设置串口接收超时

UART_SET_RECV_TIMEOUT_CB

设置串口超时之后回调的函数

UART_GET_RECV_CNT

获得串口当前接收到的计数值

UART_START

开启串口

UART_SET_CIRCULAR_BUFF_ADDR

设置串口循环buf地址

UART_SET_CIRCULAR_BUFF_LENTH

设置串口循环buf长度

UART_SET_BAUDRATE

串口运行过程中更换波特率,初始化串口时不需要调用这

UART_CLK selest

enum uart_clk_src

Values:

enumerator LSB_CLK

低速时钟

enumerator OSC_CLK

晶振时钟

enumerator PLL_48M

PLL48M时钟

UART error

enum [anonymous]

Values:

enumerator UART_CIRCULAR_BUFFER_WRITE_OVERLAY

循环buf写满

enumerator UART_RECV_TIMEOUT

接收超时

enumerator UART_RECV_EXIT

接收终止退出

struct uart_platform_data

Public Members

u8 *name

串口名称,在注册的时候已经配好

u8 irq

中断号,在注册的时候已经对应设置好了

u8 disable_tx_irq

1:不使用发送中断

u8 disable_rx_irq

1:不使用中断接收

u8 disable_ot_irq

1:不使用超时中断

u8 tx_pin_hd

1:tx io开强驱

int tx_pin

发送引脚,不配置需设置-1

int rx_pin

接收引脚,不配置需设置-1

int flags

串口用作打印

u32 baudrate

波特率设置

int port

enum _uart_port0-3的值

int input_channel

输入通道

int output_channel

输出通道

u32 max_continue_recv_cnt

连续接收最大字节

u32 idle_sys_clk_cnt

超时计数器,如果在指定的时间里没有收到任何数据,则产生超时中断

enum uart_clk_src clk_src

选择时钟源