[攻城狮计划]|RT-Thread—详解UART设备(基于RA2E1)
🚀🚀开启攻城狮的成长之旅!这是我参与的由 CSDN博客专家 架构师李肯和 瑞萨MCU 联合发起的「 致敬未来的攻城狮计划 」的第4天,点击查看活动计划详情
🚀🚀首先非常感谢李老师能给我参加这个计划的机会,让我有机会接触到许多的开发板,同时也感谢瑞萨官方 为我们提供的开发板。在参加活动的期间,结识了许多的大佬,让我收获了许多的知识,我感觉短短的几天,收获的知识与开发经验比自己独自学习几个月的收获还要多。所以,希望各位大佬们也能加入李老师的这个活动,而且,李老师水平真的很高,而且非常耐心,谁来谁知道!!!!
🚀🚀好了,接下来我们开始进入今天的主题,如何在RA2E1上基于RT-Thread优雅地使用UART设备!
🚀🚀本文将会详细介绍有关RT-Thread的UART设备,但是考虑到可能有部分和我一样的初学者,所以有些具体细节并未介绍。其实本文中的内容并不仅仅适用于一款开发板,只要运行了RT-Thread操作系统的开发板,都是一样的。
UART简介
🚀🚀接下来,我们来详细介绍一下UART设备(Universal Asynchronous Receiver/Transmitter,通用异步收发传输器),我们一般也叫其为串口。
🚀🚀UART 是异步串口通信协议的一种,工作原理就是是将传输数据的每个字符一位接一位地传输。它的特点是将数据一位一位地顺序传送,只要 2 根传输线就可以实现双向通信,一根线(TX)发送数据的同时用另一根线(RX)接收数据。UART 串口通信有几个重要的参数:
- 起始位:表示数据传输的开始,电平逻辑为 “0” 。
- **数据位:**可能值有 5、6、7、8、9,表示传输这几个 bit 位数据。一般取值为 8,因为一个 ASCII 字符值为 8 位。
- 停止位: 表示一帧数据的结束。电平逻辑为 “1”。
- **奇偶校验位:**用于接收方对接收到的数据进行校验,校验 “1” 的位数为偶数 (偶校验) 或奇数(奇校验),以此来校验数据传送的正确性,使用时不需要此位也可以。
- **波特率:**串口通信时的速率,它用单位时间内传输的二进制代码的有效位 (bit) 数来表示,其单位为每秒比特数 bit/s(bps)。常见的波特率值有 4800、9600、14400、38400、115200 等,数值越大数据传输的越快,波特率为 115200 表示每秒钟传输 115200 位数据。
🚀🚀对于两个使用 UART 串口通信的端口,这些参数必须匹配,否则将无法通信。UART 串口传输的数据格式如下图所示:
串口设备管理
🚀🚀在RT-Thrread中,应用程序可通过通用I/O设备管理接口来访向串口硬件,可以按照轮询、中断或DMA等方式进行串口数据收发,也可以设置串口的波特率、数据位等。
🚀🚀串口设备驱动框架中定义了串口的设备模型,代码如下所示:
struct rt_serial_device
{
struct rt_device parent; /* 继承 rt_device */
const struct rt_uart_ops *ops; /* 串口设备的操作方法 */
struct serial_configure config; /* 串口设备的配置参数 */
void *serial_rx;
void *serial_tx;
struct rt_device_notify rx_notify; /* 通知结构 */
};
🚀🚀注:串口设备驱动程序根据串口设备模型定义,创建出具备硬件访问能力的串口设备实例,将该设备通过rt_ hw_serial_register()接口注册到串口设备驱动框架中。
🚀🚀我们主要的就是需要去实现这些操作方法,我们在下面会介绍。
创建和注册串口设备
🚗创建
🚀🚀接下来,我们需要来创建一个串口设备,而主要需要做的就是实现串口设备的操作方法,也就是将其实例化。
/**
* uart operators
*/
struct rt_uart_ops
{
rt_err_t (*configure)(struct rt_serial_device *serial,
struct serial_configure *cfg);
rt_err_t (*control)(struct rt_serial_device *serial,
int cmd,
void *arg);
int (*putc)(struct rt_serial_device *serial, char c);
int (*getc)(struct rt_serial_device *serial);
rt_size_t (*transmit)(struct rt_serial_device *serial,
rt_uint8_t *buf,
rt_size_t size,
rt_uint32_t tx_flag);
};
方法名称 | 方法描述 |
---|---|
configure | 串口配置操作函数 |
control | 串口控制函数 |
putc | 发送一个字符数据 |
getc | 接收一个字符数据 |
transmit | 多字节数据的的发送 |
🚀🚀这部分的实现在drv_usart_v2.c文件里面能看到。
🚀🚀串口设备被创建后,使用如下接口注册到串口设备驱动框架中:文章来源:https://www.toymoban.com/news/detail-635401.html
rt_err_t rt_hw_serial_register ( struct rt_serial_device * serial,
const char * name,
rt_uint32_t flag,
void * data
)
参数 | 描述 |
---|---|
serial | 串口设备句柄 |
name | 串口设备名称 |
flag | 串口设备模式标志 |
data | 串口设备私有数据 |
返回 | 描述 |
---|---|
RT_EOK | 成功 |
-RT_ERROR | 注册失败,已有其他驱动使用该name注册 |
访问串口设备
🚀🚀应用程序通过 RT-Thread提供的 I/O 设备管理接口来访问串口硬件,相关接口如下所示:文章来源地址https://www.toymoban.com/news/detail-635401.html
函数 | 描述 |
---|---|
rt_device_open() | 打开设备 |
rt_device_read() | 读取数据 |
rt_device_write() | 写入数据 |
rt_device_control() | 控制设备 |
rt_device_close() | 关闭设备 |
示例代码
#include <rtthread.h>
#define SAMPLE_UART_NAME "uart9" /* 串口设备名称 */
/* 用于接收消息的信号量 */
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 uart_name[RT_NAME_MAX];
char str[] = "hello RT-Thread!\r\n";
if (argc == 2)
{
rt_strncpy(uart_name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX);
}
/* 查找串口设备 */
serial = rt_device_find(uart_name);
if (!serial)
{
rt_kprintf("find %s failed!\n", uart_name);
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);
到了这里,关于[攻城狮计划]RT-Thread—详解UART设备(基于RA2E1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!