全部文档
OneOS简介 硬件支持 快速开发指南 编译构造工具 API参考文档 高级语言 用户编程手册 OnePos定位 应用笔记 FAQ

Serial设备


API列表

接口 说明
os_device_find() 查找设备
os_device_open() 打开设备
os_device_read() 读取数据
os_device_write() 写入数据
os_device_control() 控制设备
os_hw_serial_isr_rxdone() 设置接收回调函数
os_hw_serial_isr_txdone() 设置发送完成回调函数
os_device_close() 关闭设备

os_device_find

该函数根据串口名查找对应的串口设备,函数原型如下:

os_device_t *os_device_find(const char *name);
参数 说明
name 串口名(uart1,uart2 等)
返回 说明
设备指针 成功返回对应的设备指针
OS_NULL 没有找到指定的串口

os_device_open

该函数用于打开设备,第一次打开设备会调用设备初始化接口,函数原型如下:

os_err_t os_device_open(os_device_t *dev, os_uint16_t oflag);
参数 说明
dev 设备指针
oflag 设备模式标志
返回 说明
OS_EOK 设备打开成功
OS_EBUSY 设备忙,即:带有独占属性的设备不允许被重复打开
其他错误码 设备打开失败

oflag 参数支持下列取值 (串口收发支持轮询、中断、DMA,如果不指定标志,默认使用轮询模式):

#define OS_DEVICE_FLAG_INT_RX           0x100           /**< INT mode on Rx */
#define OS_DEVICE_FLAG_DMA_RX           0x200           /**< DMA mode on Rx */
#define OS_DEVICE_FLAG_INT_TX           0x400           /**< INT mode on Tx */
#define OS_DEVICE_FLAG_DMA_TX           0x800           /**< DMA mode on Tx */

os_device_read

该函数用于从串口中读取数据,函数原型如下:

os_size_t os_device_read(os_device_t *dev, os_off_t pos, void *buffer, os_size_t size);
参数 说明
dev 设备指针
pos 读取数据偏移量,此参数串口设备未使用
buffer 缓冲区指针,读取的数据将会被保存在缓冲区中
size 读取数据的大小
返回 说明
读到数据的实际大小 如果是字符设备,返回大小以字节为单位
0 需要读取当前线程的 errno 来判断错误状态

os_device_write

该函数用于向串口中写入数据,函数原型如下:

os_size_t os_device_write(os_device_t *dev, os_off_t pos, const void *buffer, os_size_t size);
参数 说明
dev 设备指针
pos 写入数据偏移量,此参数串口设备未使用
buffer 内存缓冲区指针,放置要写入的数据
size 写入数据的大小
返回 说明
写入数据的实际大小 如果是字符设备,返回大小以字节为单位;
0 需要读取当前线程的 errno 来判断错误状态

os_device_control

该函数用于对串口设备进行配置,如波特率、数据位、校验位、接收缓冲区大小、停止位等参数,函数原型如下:

os_err_t os_device_control(os_device_t *dev, int cmd, void *arg);
参数 说明
dev 设备指针
cmd 命令控制字,可取值:OS_DEVICE_CTRL_CONFIG
arg 控制的参数,可取类型: struct serial_configure
返回 说明
OS_EOK 函数执行成功
OS_ENOSYS 执行失败,设备不支持 control 接口
其他错误码 执行失败

控制参数结构体 struct serial_configure 原型如下:

struct serial_configure
{
    os_uint32_t baud_rate;

    os_uint32_t data_bits               :4;
    os_uint32_t stop_bits               :2;
    os_uint32_t parity                  :2;
    os_uint32_t bit_order               :1;
    os_uint32_t invert                  :1;
    os_uint32_t rx_bufsz                :16;
    os_uint32_t tx_bufsz                :16;
    os_uint32_t reserved                :6;
};

配置参数可取值如下:

#define BAUD_RATE_2400                  2400
#define BAUD_RATE_4800                  4800
#define BAUD_RATE_9600                  9600
#define BAUD_RATE_19200                 19200
#define BAUD_RATE_38400                 38400
#define BAUD_RATE_57600                 57600
#define BAUD_RATE_115200                115200
#define BAUD_RATE_230400                230400
#define BAUD_RATE_460800                460800
#define BAUD_RATE_921600                921600
#define BAUD_RATE_2000000               2000000
#define BAUD_RATE_3000000               3000000

#define DATA_BITS_5                     5
#define DATA_BITS_6                     6
#define DATA_BITS_7                     7
#define DATA_BITS_8                     8
#define DATA_BITS_9                     9

#define STOP_BITS_1                     0
#define STOP_BITS_2                     1
#define STOP_BITS_3                     2
#define STOP_BITS_4                     3

os_hw_serial_isr_rxdone

该函数用于设置数据接收回调,当串口收到数据时,通知上层应用线程有数据到达,函数原型如下:

os_err_t os_hw_serial_isr_rxdone(struct os_serial_device *serial, int count);
参数 说明
serial serial设备指针
count 接收字符字节计数
返回 说明
OS_EOK 设置成功

os_hw_serial_isr_txdone

该函数用于设置数据发送完毕回调,当串口数据发送完毕时,通知上层应用线程,函数原型如下:

void os_hw_serial_isr_txdone(struct os_serial_device *serial);
参数 说明
seria serial设备指针
返回 说明
viod

os_device_close

该函数用于关闭设备,函数原型如下:

os_err_t os_device_close(os_device_t *dev);
参数 说明
dev 设备指针
返回 说明
OS_EOK 关闭设备成功
OS_ERROR 设备已经完全关闭,不能重复关闭设备
其他错误码 关闭设备失败

使用示例

串口轮询收发数据

本例中将测试串口 uart2 的 tx rx 信号线还回,进行自收自发。

#include <drv_cfg.h>
#include <os_clock.h>
#include <os_memory.h>
#include <os_mailbox.h>
#include <stdint.h>
#include <stdlib.h>
#include <shell.h>
#include <serial/serial.h>

static int32_t  rx_thread_status = 0;
static int32_t  rx_done_cnt      = 0;
static int32_t  rx_total_cnt     = 0;
static uint16_t rx_crc           = 0;
static os_mailbox_t rx_mb;
static os_uint32_t  mb_pool[4];

static os_err_t rx_done(os_device_t *uart, struct os_device_cb_info *info)
{
    rx_done_cnt++;
    os_mb_send(&rx_mb, (os_uint32_t)info->size, OS_IPC_WAITING_NO);
    return 0;
}

static void rx_thread(void *parameter)
{
    int            rx_cnt;
    unsigned char *rx_buff = os_malloc(OS_SERIAL_RX_BUFSZ);
    os_uint32_t    size;
    os_device_t   *uart = (os_device_t *)parameter;

    OS_ASSERT(rx_buff);

    while (rx_thread_status == 0)
    {
        if (os_mb_recv(&rx_mb, &size, OS_TICK_PER_SECOND) != OS_EOK)
            continue;

        while (size)
        {
            rx_cnt = os_device_read(uart, 0, rx_buff, min(OS_SERIAL_RX_BUFSZ, size));
            if (rx_cnt == 0)
                break;

            rx_total_cnt += rx_cnt;

            os_kprintf("<%d>rx cnt:%d\r\n", os_tick_get(), rx_cnt);
            hex_dump(rx_buff, rx_cnt);
            rx_crc = crc16(rx_crc, rx_buff, rx_cnt);
            size -= rx_cnt;
        }

        size = 0;

        os_kprintf("<%d>rx done(%d) total:%d\r\n", os_tick_get(), rx_done_cnt, rx_total_cnt);
    }

    /* Last pack */
    rx_total_cnt += os_device_read(uart, 0, rx_buff, OS_SERIAL_RX_BUFSZ);

    os_free(rx_buff);

    rx_thread_status = 2;
}

static int tx_complete;
static int tx_done_cnt;

static os_err_t tx_done(os_device_t *uart, struct os_device_cb_info *info)
{
    os_kprintf("<%d>tx done %d\r\n", os_tick_get(), tx_done_cnt++);
    tx_complete = 1;
    return 0;
}

static unsigned char tx_buff[OS_SERIAL_RX_BUFSZ];

static int serial_test(int argc, char *argv[])
{
    int           ret;
    int           tx_cnt;
    int           rx_cnt;
    unsigned char rx_buff[32];
    os_device_t  *uart;
    const char   *dev_name;

    if (argc != 2)
    {
        os_kprintf("usage: serial_test <dev> \r\n");
        os_kprintf("       serial_test uart2 \r\n");
        return -1;
    }

    dev_name = argv[1];

    uart = os_device_find(dev_name);
    OS_ASSERT(uart);

    /* Open serial device with rx nopoll flag */
    os_device_open(uart, OS_SERIAL_FLAG_RX_NOPOLL | OS_SERIAL_FLAG_TX_NOPOLL | OS_DEVICE_OFLAG_RDWR);

    struct serial_configure config = OS_SERIAL_CONFIG_DEFAULT;
    config.baud_rate = BAUD_RATE_115200;
    ret = os_device_control(uart, OS_DEVICE_CTRL_CONFIG, &config);
    if (ret != 0)
    {
        os_kprintf("serial control fail %d\r\n", ret);
        return -1;
    }

    os_task_msleep(100);

    /* Tx */
    tx_cnt = os_device_write(uart, 0, "Hello World!\n", sizeof("Hello World!\n"));

    /* Wait rx complete */
    os_task_msleep(100);

    /* Rx */
    rx_cnt = os_device_read(uart, 0, rx_buff, sizeof(rx_buff));

    os_kprintf("tx_cnt: %d, rx_cnt: %d\n", tx_cnt, rx_cnt);

    if (rx_cnt == sizeof("Hello World!\n"))
    {
        os_kprintf("rx buff:%s\n", rx_buff);
    }
    else
    {
        os_kprintf("rx failed\n");
    }

    os_device_close(uart);

}
SH_CMD_EXPORT(serial_test, serial_test, "serial_test");

运行结果如下:

sh />serial_test uart2
tx_cnt: 14, rx_cnt: 14
rx buff:Hello World!

串口中断收发数据

本例中将测试串口 uart1 的中断接收功能。

#include <drv_cfg.h>
#include <os_clock.h>
#include <os_memory.h>
#include <os_mailbox.h>
#include <stdint.h>
#include <stdlib.h>
#include <shell.h>
#include <serial/serial.h>

static int32_t  rx_thread_status = 0;
static int32_t  rx_done_cnt      = 0;
static int32_t  rx_total_cnt     = 0;
static uint16_t rx_crc           = 0;
static os_mailbox_t rx_mb;
static os_uint32_t  mb_pool[4];

static os_err_t rx_done(os_device_t *uart, struct os_device_cb_info *info)
{
    rx_done_cnt++;
    os_mb_send(&rx_mb, (os_uint32_t)info->size, OS_IPC_WAITING_NO);
    return 0;
}

static void rx_thread(void *parameter)
{
    int            rx_cnt;
    unsigned char *rx_buff = os_malloc(OS_SERIAL_RX_BUFSZ);
    os_uint32_t    size;
    os_device_t   *uart = (os_device_t *)parameter;

    OS_ASSERT(rx_buff);

    while (rx_thread_status == 0)
    {
        if (os_mb_recv(&rx_mb, &size, OS_TICK_PER_SECOND) != OS_EOK)
            continue;

        while (size)
        {
            rx_cnt = os_device_read(uart, 0, rx_buff, min(OS_SERIAL_RX_BUFSZ, size));
            if (rx_cnt == 0)
                break;

            rx_total_cnt += rx_cnt;

            os_kprintf("<%d>rx cnt:%d\r\n", os_tick_get(), rx_cnt);
            hex_dump(rx_buff, rx_cnt);
            rx_crc = crc16(rx_crc, rx_buff, rx_cnt);
            size -= rx_cnt;
        }

        size = 0;

        os_kprintf("<%d>rx done(%d) total:%d\r\n", os_tick_get(), rx_done_cnt, rx_total_cnt);
    }

    /* Last pack */
    rx_total_cnt += os_device_read(uart, 0, rx_buff, OS_SERIAL_RX_BUFSZ);

    os_free(rx_buff);

    rx_thread_status = 2;
}

static int tx_complete;
static int tx_done_cnt;

static os_err_t tx_done(os_device_t *uart, struct os_device_cb_info *info)
{
    os_kprintf("<%d>tx done %d\r\n", os_tick_get(), tx_done_cnt++);
    tx_complete = 1;
    return 0;
}

static unsigned char tx_buff[OS_SERIAL_RX_BUFSZ];

static int serial_rx_test(int argc, char *argv[])
{
    int            ret;
    int            rx_cnt;
    unsigned char *rx_buff;
    os_device_t   *uart;
    const char    *dev_name;

    if (argc != 2)
    {
        os_kprintf("usage: serial_rx_test <dev> \r\n");
        os_kprintf("       serial_rx_test uart2 \r\n");
        return -1;
    }

    dev_name = argv[1];

    os_mb_init(&rx_mb, "rx_test_mb", mb_pool, sizeof(mb_pool) / sizeof(mb_pool[0]), OS_IPC_FLAG_FIFO);

    uart = os_device_find(dev_name);
    OS_ASSERT(uart);

    struct os_device_cb_info cb_info = 
    {
        .type = OS_DEVICE_CB_TYPE_RX,
        .cb   = rx_done,
    };

    os_device_control(uart, IOC_SET_CB, &cb_info);

    os_device_open(uart, OS_SERIAL_FLAG_RX_NOPOLL | OS_SERIAL_FLAG_TX_NOPOLL | OS_DEVICE_OFLAG_RDWR);

    struct serial_configure config = OS_SERIAL_CONFIG_DEFAULT;
    config.baud_rate = BAUD_RATE_115200;
    ret = os_device_control(uart, OS_DEVICE_CTRL_CONFIG, &config);
    if (ret != 0)
    {
        os_kprintf("serial control fail %d\r\n", ret);
        return -1;
    }

    rx_buff = os_malloc(128);
    OS_ASSERT(rx_buff);

    while (1)
    {
        os_uint32_t size;

        os_mb_recv(&rx_mb, &size, OS_IPC_WAITING_FOREVER);

        do
        {
            rx_cnt = os_device_read(uart, 0, rx_buff, 128);

            if (rx_cnt == 0)
                break;

            if (rx_cnt < 0)
                goto end;

            os_kprintf("rx_cnt: %d\n", rx_cnt);

            hex_dump(rx_buff, rx_cnt);
        } while (1);
    }

end:
    os_free(rx_buff);
    os_device_close(uart);

    return 0;
}
SH_CMD_EXPORT(serial_rx_test, serial_rx_test, "serial_rx_test");

通过串口发送字符串:hello world! 运行结果如下:

sh />serial_rx_test uart1
rx_cnt: 15
00000000: 0d 68 65 6c 6c 6f 20 77  6f 72 6c 64 21 0d 0a

results matching ""

    No results matching ""

    返回顶部