UART设备


说明

UART(Universal Asynchronous Receiver/Transmitter)是一种同步或者异步的串行通信总线接口,发送和接收方按照严格的格式(波特率和数据帧格式)发送和接收。

UART的特点:

  • 空闲时总线保持高电平状态
  • 5~9位数据位,低位在前
  • 一个起始位
  • 可选奇偶检验位
  • 可选1、1.5、2比特的停止位

接口列表

UART的CSI接口如下所示:

函数 说明
csi_uart_init UART设备初始化
csi_uart_uninit UART设备反初始化
csi_uart_baud 设置波特率
csi_uart_format 设置数据位,停止位,校验位
csi_uart_flowctrl 设置流控
csi_uart_attach_callback 注册回调函数
csi_uart_detach_callback 注销回调函数
csi_uart_link_dma 设置与DMA设备的连接
csi_uart_send 同步发送数据
csi_uart_send_async 异步发送数据
csi_uart_receive 同步接收数据
csi_uart_receive_async 异步接收数据
csi_uart_putc 发送字节(同步)
csi_uart_getc 接收字节(同步)
csi_uart_get_state 获取UART设备的当前的读写状态

UART的CSI接口在用户对接时是否必须适配的说明如下所示:

函数 是否必须适配
csi_uart_init 必须
csi_uart_uninit 必须
csi_uart_baud 必须
csi_uart_format 必须
csi_uart_flowctrl 非必须
csi_uart_attach_callback 必须
csi_uart_detach_callback 必须
csi_uart_link_dma 非必须
csi_uart_send 必须
csi_uart_send_async 必须
csi_uart_receive 必须
csi_uart_receive_async 必须
csi_uart_putc 必须
csi_uart_getc 必须
csi_uart_get_state 非必须

接口详细说明

csi_uart_init

csi_error_t csi_uart_init(csi_uart_t *uart, uint32_t idx);
  • 功能描述:

    • 通过设备号初始化对应的uart实例。
  • 参数:

    • uart: 设备句柄(需要用户申请句柄空间)
    • idx: 设备号
  • 返回值:

    • 错误码csi_error_t

csi_uart_t

成员 类型 说明
dev csi_dev_t csi设备统一句柄
callback void (callback)(csi_uart_t uart, csi_uart_event_t event, void *arg) 用户回调函数
arg void* 回调函数参数(用户自定义)
tx_data uint8_t* 发送缓存区地址
tx_size uint32_t 发送数据字节数
rx_data uint8_t* 接收缓存区地址
rx_size uint32_t 接收数据字节数
tx_dma csi_dma_ch_t 用于发送的DMA通道句柄
rx_dma csi_dma_ch_t 用于接收的DMA通道句柄
send csi_error_t (send)(csi_uart_t uart, const void *data, uint32_t size) 异步发送函数指针
receive csi_error_t (receive )(csi_uart_t uart, void *data, uint32_t size) 异步接收函数指针
state csi_state_t UART设备读写状态
priv void* 设备私有变量

csi_uart_uninit

void csi_uart_uninit(csi_uart_t *uart);
  • 功能描述:

    • uart实例反初始化。
    • 该接口会停止uart实例正在进行的传输,并且释放相关的软硬件资源。
  • 参数:

    • uart: 实例句柄。

csi_uart_baud

csi_error_t csi_uart_baud(csi_uart_t *uart, uint32_t baud);
  • 功能描述:

    • uart设备配置波特率
  • 参数

    • uart : 实例句柄
    • baud : 波特率
  • 返回值:

    • 错误码csi_error_t
  • 使用示例:

/* 句柄使用前请先初始化 */
static csi_uart_t g_uart;
csi_error_t ret;
ret = csi_uart_baud(&g_uart, 115200);
if (ret != CSI_OK) {
    return -1;
}

csi_uart_format

csi_error_t csi_uart_format(csi_uart_t *uart,  csi_uart_data_bits_t data_bits, csi_uart_parity_t parity, csi_uart_stop_bits_t stop_bits);
  • 功能描述:

    • uart设备配置数据位,奇偶校验位和停止位
  • 参数:

    • uart : 实例句柄
    • data_bits:数据位
    • parity:校验位
    • stop_bits:停止位
  • 返回值:

    • 错误码csi_error_t
  • 使用示例:

/* 句柄使用前请先初始化 */
static csi_uart_t g_uart;
csi_error_t ret;
ret = csi_uart_format(&g_uart, UART_DATA_BITS_8, UART_PARITY_NONE, UART_STOP_BITS_1);
if (ret != CSI_OK) {
    return -1;
}

csi_uart_data_bits_t

类型 说明
UART_DATA_BITS_5 5位数据位宽
UART_DATA_BITS_6 6位数据位宽
UART_DATA_BITS_7 7位数据位宽
UART_DATA_BITS_8 8位数据位宽
UART_DATA_BITS_9 9位数据位宽

csi_uart_parity_t

类型 说明
UART_PARITY_NONE 无校验
UART_PARITY_EVEN 偶校验
UART_PARITY_ODD 奇校验

csi_uart_stop_bits_t

类型 说明
UART_STOP_BITS_1 1停止位
UART_STOP_BITS_2 2停止位
UART_STOP_BITS_1_5 1.5停止位

csi_uart_flowctrl

csi_error_t csi_uart_flowctrl(csi_uart_t *uart,  csi_uart_flowctrl_t flowctrl);
  • 功能描述:

    • 设置uart设备的流控功能。
  • 参数:

    • uart: 实例句柄。
    • flowctrl: 流控模式
  • 返回值:

    • 错误码csi_error_t

csi_uart_flowctrl_t

类型 说明
UART_FLOWCTRL_NONE 无流控
UART_FLOWCTRL_RTS 发送请求(Require ToSend)
UART_FLOWCTRL_CTS 发送允许(Clear ToSend)
UART_FLOWCTRL_RTS_CTS 发送请求与发送允许功能同时打开

注意: 由于并不是每个UART设备都支持流控功能,因此设备默认为UART_FLOWCTRL_NONE, 不需要特地调用csi_uart_flowctrl将uart设置为UART_FLOWCTRL_NONE。

csi_uart_attach_callback

csi_error_t csi_uart_attach_callback(csi_uart_t *uart, void *callback, void *arg);
  • 功能描述:

    • 设置回调函数,并打开中断的异步模式读写功能
  • 参数:

    • uart: 实例句柄。
    • callback: uart实例的事件回调函数(一般在中断上下文执行)。
    • arg: 回调函数参数(可选,由用户定义)。
  • 返回值:

    • 错误码csi_error_t。

callback

void (*callback)(csi_uart_t *uart, csi_uart_event_t event, void *arg);

其中uart为设备句柄,idx为设备号,event 为传给回调函数的事件类型,arg为用户自定义的回调函数对应的参数。 uart 回调事件枚举类型csi_uart_event_t定义如下:

事件类型 事件说明
UART_EVENT_SEND_COMPLETE 数据发送完成事件
UART_EVENT_RECEIVE_COMPLETE 数据接收完成事件
UART_EVENT_RECEIVE_FIFO_READABLE FIFO残留数据等待接收事件
UART_ENENT_BREAK_INTR 数据接收中断事件
UART_EVENT_ERROR_OVERFLOW 数据接收溢出事件
UART_EVENT_ERROR_PARITY 数据校验位错误事件
UART_EVENT_ERROR_FRAMING 数据无有效停止位事件

注意: 在使用异步工作模式前,必须调用本函数来注册回调函数,否则将无法使用异步接口。

csi_uart_detach_callback

void csi_uart_detach_callback(csi_uart_t *uart);
  • 功能描述:

    • 注销UART设备的回调函数,并关闭异步读写功能。
  • 参数:

    • uart: 实例句柄。

csi_uart_link_dma

csi_error_t csi_uart_link_dma(csi_uart_t *uart, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma);
  • 功能描述:

    • 将DMA通道句柄连入UART句柄中,并打开UART的DMA发送与接收功能
  • 参数:

    • uart: 实例句柄。
    • tx_dma: 用于发送的DMA通道句柄,传NULL时会关闭DMA异步发送功能。
    • rx_dma: 用于接收的DMA通道句柄,传NULL时会关闭DMA异步接收功能。
  • 返回值:

    • CSI_ERROR: 调用失败。
  • 使用示例:

/* 句柄使用前请先初始化 */
static csi_uart_t g_uart;
csi_error_t ret;
csi_dma_ch_t g_dma_ch_tx;
csi_dma_ch_t g_dma_ch_rx;
/* 为发送和接收设置DMA通道 */
ret = csi_uart_link_dma(&g_uart, &g_dma_ch_tx, &g_dma_ch_rx);
if (ret != CSI_OK) {
    return -1;
}

注意: 在调用此函数前,需要先调用csi_uart_attach_callback来注册回调函数,否则将调用失败。

csi_uart_send

int32_t csi_uart_send(csi_uart_t *uart, const void *data, uint32_t size, uint32_t timeout);
  • 功能描述:

    • uart以同步模式启动数据发送。
  • 参数:

    • uart: 实例句柄。
    • data: 待发送数据的缓冲区地址。
    • size: 待发送数据的长度。
    • timeout: 超时时间,单位是毫秒ms,此超时时间指的是字节与字节的间隔时间,即发送上一个字节与下一个字节的间隔时间超过timeout,则会从函数退出。
  • 返回值:

    • 成功发送的字节数或者CSI_ERROR。
  • 使用示例:

/* 句柄使用前请先初始化 */
static csi_uart_t g_uart;
int32_t ret_num;
const uint8_t tx_test_msg[] = "I am uart";
/* 超时时间请根据实际应用场景进行设置 */
ret_num = csi_uart_send(&g_uart, tx_test_msg, sizeof(tx_test_msg), 50);

csi_uart_send_async

csi_error_t csi_uart_send_async(csi_uart_t *uart, const void *data, uint32_t size);
  • 功能描述:

    • uart以异步模式启动数据发送。
  • 参数:

    • uart: 实例句柄。
    • data: 待发送数据的缓冲区地址。
    • size: 待发送数据的长度
  • 返回值:

    • 错误码csi_error_t

注意: 在调用此函数前,需要先调用csi_uart_attach_callback来注册回调函数。本函数根据用户设置的 不同,会进入中断工作模式或DMA工作模式。具体使用方式会在文末用例中综合说明。

csi_uart_receive

int32_t csi_uart_receive(csi_uart_t *uart, void *data, uint32_t size, uint32_t timeout);
  • 功能描述:

    • UART以同步模式启动数据接收。
  • 参数:

    • uart: 实例句柄。
    • data: 待接收数据的缓冲区地址。
    • size: 待接收数据的长度。
    • timeout: 超时时间,单位是毫秒ms,此超时时间指的是字节与字节的间隔时间,即接收上一个字节与下一个字节的间隔时间超过timeout,则会从函数退出。
  • 返回值:

    • 成功接收的字节数或者CSI_ERROR。
  • 使用示例:

/* 句柄使用前请先初始化 */
static csi_uart_t g_uart;
int32_t ret_num;
uint8_t rx_test_msg[16];
/* 超时时间请根据实际应用场景进行设置 */
ret_num = csi_uart_receive(&g_uart, rx_test_msg, sizeof(rx_test_msg), 0xffffffff);

csi_uart_receive_async

csi_error_t csi_uart_receive_async(csi_uart_t *uart, void *data, uint32_t size);
  • 功能描述:

    • UART以异步模式读取数据。
  • 参数:

    • uart: 实例句柄。
    • data: 待接收数据的缓冲区地址。
    • size: 预计接收数据的长度。
  • 返回值:

    • 错误码csi_error_t

注意: 在调用此函数前,需要先调用csi_uart_attach_callback来注册回调函数。本函数根据用户设置的 不同,会进入中断工作模式或DMA工作模式。具体使用方式会在文末用例中综合说明。

csi_uart_getc

uint8_t  csi_uart_getc(csi_uart_t *uart);
  • 功能描述:

    • 从uart 读取一个字节。
  • 参数:

    • uart: 实例句柄。
  • 返回值:

    • 返回读取到的字节内容。

csi_uart_putc

void csi_uart_putc(csi_uart_t *uart, uint8_t ch);
  • 功能描述:

    • 从uart 发送一个字节。
  • 参数:

    • uart: 实例句柄。
    • ch: 需发送的字节内容。

csi_uart_get_state

csi_error_t csi_uart_get_state(csi_uart_t *uart, csi_state_t *state);
  • 功能描述:

    • 获取UART的状态。通过此函数来判断UART设备在获取状态的时刻是否可以进行send和receive操作。
  • 参数:

    • uart: 实例句柄。
    • state:返回读写状态信息
  • 返回值:

    • 错误码csi_error_t

csi_state_t

类型 说明
readable 设备可读
writeable 设备可写
error 错误状态

初始化示例

/* 句柄空间一般使用静态空间 */
static csi_uart_t g_uart;

int main() {
    csi_error_t ret;
    /* init函数的idx参数,请根据soc的实际情况进行选择 */
    ret = csi_uart_init(&g_uart, 0);
    if (ret != CSI_OK) {
        return -1;
    }
}

同步模式使用示例

static csi_uart_t g_uart;
static uint8_t recv_buf[16];
static char send_buf[128];
#define EXAMPLE_UART_IDX        0
#define EXAMPLE_UART_BAUDRATE   115200
#define UART_CHECK_RETURN(ret)                      \
        do {                                        \
            if (ret != CSI_OK) {                    \
                return -1;                          \
            }                                       \
        } while(0);

int example_uart(void)
{
    csi_error_t ret;
    int32_t ret_num;

    /* init uart */
    ret = csi_uart_init(&g_uart, EXAMPLE_UART_IDX);
    UART_CHECK_RETURN(ret);

    /* set uart baudrate */
    ret = csi_uart_baud(&g_uart, EXAMPLE_UART_BAUDRATE);
    UART_CHECK_RETURN(ret);

    /* set uart format */
    ret = csi_uart_format(&g_uart, UART_DATA_BITS_8, UART_PARITY_NONE, UART_STOP_BITS_1);
    UART_CHECK_RETURN(ret);

    strcpy(send_buf, "hello world\n\r");

    ret_num = csi_uart_send(&g_uart, send_buf, strlen(send_buf), 50);
    if (ret_num != strlen(send_buf)) {
        return -1;
    }

    ret_num = csi_uart_receive(&g_uart, recv_buf, sizeof(recv_buf), 0xffffffff);
    if (ret_num != sizeof(recv_buf)) {
        return -1;
    }

    /* Uninit the uart device */
    csi_uart_uninit(&g_uart);
    return 0;
}

异步模式使用示例

中断模式和DMA模式的使用流程基本一致,差别仅在是否调用了csi_uart_link_dma接口。

DMA模式的使用示例

static csi_uart_t g_uart;
static csi_dma_ch_t g_dma_ch_tx;
static csi_dma_ch_t g_dma_ch_rx;
static volatile uint8_t rx_async_flag = 0;
static volatile uint8_t tx_async_flag = 0;
static uint8_t recv_buf[16];
static uint8_t send_buf[128];

#define EXAMPLE_UART_BAUDRATE   115200
#define UART_CHECK_RETURN(ret)                      \
        do {                                        \
            if (ret != CSI_OK) {                    \
                return -1;                          \
            }                                       \
        } while(0);

static void uart_event_cb(csi_uart_t *uart, csi_uart_event_t event, void *arg)
{
    switch (event) {
        case UART_EVENT_SEND_COMPLETE:
            tx_async_flag = 1;
            break;

        case UART_EVENT_RECEIVE_COMPLETE:
            rx_async_flag = 1;
            break;

        default:
            break;
    }
}

/* use console uart to show how to use dma mode */
int example_uart_dma()
{
    csi_error_t ret;

    /* init uart, EXAMPLE_UART_IDX == 0 */
    ret = csi_uart_init(&g_uart, EXAMPLE_UART_IDX);
    UART_CHECK_RETURN(ret);

    /* set uart baudrate */
    ret = csi_uart_baud(&g_uart, EXAMPLE_UART_BAUDRATE);
    UART_CHECK_RETURN(ret);

    /* set uart format */
    ret = csi_uart_format(&g_uart, UART_DATA_BITS_8, UART_PARITY_NONE, UART_STOP_BITS_1);
    UART_CHECK_RETURN(ret);

    /* attach callback to uart device */
    ret = csi_uart_attach_callback(&g_uart, uart_event_cb, NULL);
    UART_CHECK_RETURN(ret);

    /* Link DMA */
    ret = csi_uart_link_dma(&g_uart, &g_dma_ch_tx, &g_dma_ch_rx);
    UART_CHECK_RETURN(ret);

    strcpy(send_buf, "hello world\n\r");

    ret = csi_uart_send_async(&g_uart, send_buf, strlen(send_buf));
    UART_CHECK_RETURN(ret);

    while(1) {
        if (tx_async_flag) {
            tx_async_flag = 0;
            break;
        }
    }

    ret = csi_uart_receive_async(&g_uart, recv_buf, sizeof(recv_buf));
    UART_CHECK_RETURN(ret);

    while(1) {
        if (rx_async_flag) {
            rx_async_flag = 0;
            break;
        }
    }

    /* Unlink DMA */
    ret = csi_uart_link_dma(&g_uart, NULL, NULL);
    UART_CHECK_RETURN(ret);

    /* Detach the uart callback */
    csi_uart_detach_callback(&g_uart);

    /* Uninit the uart device */
    csi_uart_uninit(&g_uart);
    return 0;
}

中断模式的使用示例

static csi_uart_t g_uart;
static volatile uint8_t rx_async_flag = 0;
static volatile uint8_t tx_async_flag = 0;
static uint8_t recv_buf[16];
static uint8_t send_buf[128];

#define EXAMPLE_UART_BAUDRATE   115200
#define UART_CHECK_RETURN(ret)                      \
        do {                                        \
            if (ret != CSI_OK) {                    \
                return -1;                          \
            }                                       \
        } while(0);

static void uart_event_cb(csi_uart_t *uart, csi_uart_event_t event, void *arg)
{
    switch (event) {
        case UART_EVENT_SEND_COMPLETE:
            tx_async_flag = 1;
            break;

        case UART_EVENT_RECEIVE_COMPLETE:
            rx_async_flag = 1;
            break;

        default:
            break;
    }
}

/* use console uart to show how to use intr mode */
int example_uart_intr()
{
    csi_error_t ret;

    /* init uart, EXAMPLE_UART_IDX == 0 */
    ret = csi_uart_init(&g_uart, EXAMPLE_UART_IDX);
    UART_CHECK_RETURN(ret);

    /* set uart baudrate */
    ret = csi_uart_baud(&g_uart, EXAMPLE_UART_BAUDRATE);
    UART_CHECK_RETURN(ret);

    /* set uart format */
    ret = csi_uart_format(&g_uart, UART_DATA_BITS_8, UART_PARITY_NONE, UART_STOP_BITS_1);
    UART_CHECK_RETURN(ret);

    /* attach callback to uart device */
    ret = csi_uart_attach_callback(&g_uart, uart_event_cb, NULL);
    UART_CHECK_RETURN(ret);

    strcpy(send_buf, "hello world\n\r");

    ret = csi_uart_send_async(&g_uart, send_buf, strlen(send_buf));
    UART_CHECK_RETURN(ret);

    while(1) {
        if (tx_async_flag) {
            tx_async_flag = 0;
            break;
        }
    }

    ret = csi_uart_receive_async(&g_uart, recv_buf, sizeof(recv_buf));
    UART_CHECK_RETURN(ret);

    while(1) {
        if (rx_async_flag) {
            rx_async_flag = 0;
            break;
        }
    }

    /* Detach the uart callback */
    csi_uart_detach_callback(&g_uart);

    /* Uninit the uart device */
    csi_uart_uninit(&g_uart);
    return 0;
}

results matching ""

    No results matching ""