RTT设备和驱动(2)UART 设备

  • Post author:
  • Post category:其他




访问串口设备

应用程序通过 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);



版权声明:本文为weixin_44532706原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。