访问串口设备
应用程序通过 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);