admin管理员组

文章数量:1550527

访问串口设备

应用程序通过 RT-Thread提供的 I/O 设备管理接口来访问串口硬件,相关接口如下所示:

函数 描述
rt_device_find() 查找设备
rt_device_open() 打开设备
rt_device_read() 读取数据
rt_device_write() 写入数据
rt_device_control() 控制设备
rt_device_set_rx_indicate() 设置接收回调函数
rt_device_set_tx_complete() 设置发送完成回调函数
rt_device_close() 关闭设备

查找串口设备

应用程序根据串口设备名称获取设备句柄,进而可以操作串口设备,查找设备函数如下所示,

rt_device_t rt_device_find(const char* name);
参数 描述
name 设备名称
返回 ——
设备句柄 查找到对应设备将返回相应的设备句柄
RT_NULL 没有找到相应的设备对象
一般情况下,注册到系统的串口设备名称为 uart0,uart1等,使用示例如下所示:

#define SAMPLE_UART_NAME “uart2”
static rt_device_t serial; /* 串口设备句柄 /
/
查找串口设备 */
serial = rt_device_find(SAMPLE_UART_NAME);

打开串口设备

通过设备句柄,应用程序可以打开和关闭设备,打开设备时,会检测设备是否已经初始化,没有初始化则会默认调用初始化接口初始化设备。通过如下函数打开设备:

rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflags);
参数 描述
dev 设备句柄
oflags 设备模式标志
返回 ——
RT_EOK 设备打开成功
-RT_EBUSY 如果设备注册时指定的参数中包括 RT_DEVICE_FLAG_STANDALONE 参数,此设备将不允许重复打开
其他错误码 设备打开失败
oflags 参数支持下列取值 (可以采用或的方式支持多种取值):

#define RT_DEVICE_FLAG_STREAM 0x040 /* 流模式 /
/
接收模式参数 /
#define RT_DEVICE_FLAG_INT_RX 0x100 /
中断接收模式 /
#define RT_DEVICE_FLAG_DMA_RX 0x200 /
DMA 接收模式 /
/
发送模式参数 /
#define RT_DEVICE_FLAG_INT_TX 0x400 /
中断发送模式 /
#define RT_DEVICE_FLAG_DMA_TX 0x800 /
DMA 发送模式 */
串口数据接收和发送数据的模式分为 3 种:中断模式、轮询模式、DMA 模式。在使用的时候,这 3 种模式只能选其一,若串口的打开参数 oflags 没有指定使用中断模式或者 DMA 模式,则默认使用轮询模式。

以中断接收及轮询发送模式使用串口设备的示例如下所示:
#define SAMPLE_UART_NAME “uart2” /* 串口设备名称 /
static rt_device_t serial; /
串口设备句柄 /
/
查找串口设备 */
serial = rt_device_find(SAMPLE_UART_NAME);

/* 以中断接收及轮询发送模式打开串口设备 */
rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);

控制串口设备

通过控制接口,应用程序可以对串口设备进行配置,如波特率、数据位、校验位、接收缓冲区大小、停止位等参数的修改。控制函数如下所示:

rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void* arg);
参数 描述
dev 设备句柄
cmd 命令控制字,可取值:RT_DEVICE_CTRL_CONFIG
arg 控制的参数,可取类型: struct serial_configure
返回 ——
RT_EOK 函数执行成功
-RT_ENOSYS 执行失败,dev 为空
其他错误码 执行失败
控制参数结构体 struct serial_configure 原型如下:

struct serial_configure
{
rt_uint32_t baud_rate; /* 波特率 /
rt_uint32_t data_bits :4; /
数据位 /
rt_uint32_t stop_bits :2; /
停止位 /
rt_uint32_t parity :2; /
奇偶校验位 /
rt_uint32_t bit_order :1; /
高位在前或者低位在前 /
rt_uint32_t invert :1; /
模式 /
rt_uint32_t bufsz :16; /
接收数据缓冲区大小 /
rt_uint32_t reserved :4; /
保留位 */
};
RT-Thread 提供的默认串口配置如下,即 RT-Thread 系统中默认每个串口设备都使用如下配置:

#define RT_SERIAL_CONFIG_DEFAULT
{
BAUD_RATE_115200, /* 115200 bits/s /
DATA_BITS_8, /
8 databits /
STOP_BITS_1, /
1 stopbit /
PARITY_NONE, /
No parity /
BIT_ORDER_LSB, /
LSB first sent /
NRZ_NORMAL, /
Normal mode /
RT_SERIAL_RB_BUFSZ, /
Buffer size */
0
}

若实际使用串口的配置参数与默认配置参数不符,则用户可以通过应用代码进行修改。修改串口配置参数,如波特率、数据位、校验位、缓冲区接收 buffsize、停止位等的示例程序如下:

#define SAMPLE_UART_NAME “uart2” /* 串口设备名称 /
static rt_device_t serial; /
串口设备句柄 /
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /
初始化配置参数 */

/* step1:查找串口设备 */
serial = rt_device_find(SAMPLE_UART_NAME);

/* step2:修改串口配置参数 */
config.baud_rate = BAUD_RATE_9600; //修改波特率为 9600
config.data_bits = DATA_BITS_8; //数据位 8
config.stop_bits = STOP_BITS_1; //停止位 1
config.bufsz = 128; //修改缓冲区 buff size 为 128
config.parity = PARITY_NONE; //无奇偶校验位

/* step3:控制串口设备。通过控制接口传入命令控制字,与控制参数 */
rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);

/* step4:打开串口设备。以中断接收及轮询发送模式打开串口设备 */
rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);

/*
 * 程序清单:这是一个 串口 设备使用例程
 * 例程导出了 uart_sample 命令到控制终端
 * 命令调用格式:uart_sample uart2
 * 命令解释:命令第二个参数是要使用的串口设备名称,为空则使用默认的串口设备
 * 程序功能:通过串口输出字符串"hello RT-Thread!",然后错位输出输入的字符
*/

#include <rtthread.h>

#define SAMPLE_UART_NAME       "uart2"

/* 用于接收消息的信号量 */
static struct rt_semaphore rx_sem;
static rt_device_t serial;

/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
    /* 串口接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */
    rt_sem_release(&rx_sem);

    return RT_EOK;
}

static void serial_thread_entry(void *parameter)
{
    char ch;

    while (1)
    {
        /* 从串口读取一个字节的数据,没有读取到则等待接收信号量 */
        while (rt_device_read(serial, -1, &ch, 1) != 1)
        {
            /* 阻塞等待接收信号量,等到信号量后再次读取数据 */
            rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
        }
        /* 读取到的数据通过串口错位输出 */
        ch = ch + 1;
        rt_device_write(serial, 0, &ch, 1);
    }
}

static int uart_sample(int argc, char *argv[])
{
    rt_err_t ret = RT_EOK;
    char str[] = "hello RT-Thread!\r\n";
    /* 查找系统中的串口设备 */
    serial = rt_device_find("uart2");
    if (!serial)
    {
        rt_kprintf("find %s failed!\n", "uart2");
        return RT_ERROR;
    }

    /* 初始化信号量 */
    rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
    /* 以中断接收及轮询发送模式打开串口设备 */
    rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
    /* 设置接收回调函数 */
    rt_device_set_rx_indicate(serial, uart_input);
    /* 发送字符串 */
    rt_device_write(serial, 0, str, (sizeof(str) - 1));

    /* 创建 serial 线程 */
    rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
    /* 创建成功则启动线程 */
    if (thread != RT_NULL)
    {
        rt_thread_startup(thread);
    }
    else
    {
        ret = RT_ERROR;
    }

    return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(uart_sample, uart device sample);

本文标签: 设备RTTUART