Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
UART
串口
二、RT-Thread Uart设备学习
发布于 2022-03-13 21:33:29 浏览:1691
订阅该版
[tocm] Uart设备就是串口设备,单片机的Usart和Uart都是这个设备,包括RS232和RS485也都是Uart设备。在RTT中CAN是单独的设备,不属于Uart。 在操作系统中将底层抽象成一个设备,一定要理解这一点,你在写代码的时候操作的都是操作系统给你的API而不是直接操作硬件的API。RTOS开发一定要理解这一点,至于操作系统是怎么调用硬件API的这点不用管,开发操作系统的人都给你实现好了,这个就叫BSP:板级支持包。 ## 1. Uart设备常用函数 ### 1. 查找串口设备 串口设备可以通过定义字符串设备名字来查找绑定设备。 ```c rt_device_t rt_device_find(const char* name); ``` **const char* name** 为设备名 字符串 这个API会返回 对应设备名的设备句柄,需要接收。 **调用Demo** ```c #define SAMPLE_UART_NAME "uart2" /* 串 口 设 备 名 称 */ static rt_device_t serial; /* 串 口 设 备 句 柄 */ /* 查 找 串 口 设 备 */ serial = rt_device_find(SAMPLE_UART_NAME); ``` ### 2. 打开串口设备 通过查找获取的句柄 应用程序可以打开和关闭设备,当打开设备的时候会自动检测设备有没有初始化,如果没有初始化的话会自动帮你初始化这个设备。 ```c rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflags); ``` **rt_device_t dev** 这个是获取到的设备句柄 **rt_uint16_t oflags** 设备模式标志,用来设置串口工作的模式 | RT_DEVICE_FLAG_STREAM | 流模式 | | :-------------------: | :----------: | | RT_DEVICE_FLAG_INT_RX | 中断接收模式 | | RT_DEVICE_FLAG_DMA_RX | DMA接收模式 | | RT_DEVICE_FLAG_INT_TX | 中断发送模式 | | RT_DEVICE_FLAG_DMA_TX | DMA发送模式 | 如果设备打开成功会返回**RT_EOK**,如果打开失败会返回**RT_EBUSY** 流模式没用过,不过好像是RS232和RS485需要用的,然后DMA模式就根据项目需求啦,如果数据量大的话就用DMA吧。 **调用Demo** ```c #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); ``` 轮询就是 正常一行接一行的发送,没有其他什么操作,CPU权限到发送这个任务才会去发送。 ### 3. 控制串口设备 控制串口 主要是配置串口参数, 比如波特率、数据位等等关键参数。 这个头文件是 RTT设备的接口,需要调用这个头文件 ``` #include
``` 如果需要更改 波特率参数,需要调用这个头文件。这个包含设备驱动 ```c rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void* arg); ``` **rt_device_t dev** 这个是设备句柄 **rt_uint8_t cmd** 设备命令控制字,选择可以如下,这里是配置设备 | RT_DEVICE_CTRL_RESUME | 恢复设备 | | ---------------------- | -------- | | RT_DEVICE_CTRL_SUSPEND | 挂起设备 | | RT_DEVICE_CTRL_CONFIG | 配置设备 | | RT_DEVICE_CTRL_CLOSE | 关闭设备 | **arg** 是设备控制的参数,可取类型:struct serial_configure ```c 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; /* 保 留 位 */ }; ``` 默认提供了一个 configure,**RT_SERIAL_CONFIG_DEFAULT** ```c #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 } ``` 其他参数可以自行创建结构体然后赋值变量。 如果使用终端接收模式打开,系统会分配一个64字节的数据缓冲区,如果没有及时读取数据将被覆盖,这时候可以调大缓冲区内存。 **串口配置Demo** ```c #define SAMPLE_UART_NAME "uart2" /* 串 口 设 备 名 称 */ static rt_device_t serial; /* 串 口 设 备 句 柄 */ struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 配 置 默 认 参 数 */ /* 查 找 串 口 设 备 */ serial = rt_device_find(SAMPLE_UART_NAME); /* 以 中 断 接 收 及 轮 询 发 送 模 式 打 开 串 口 设 备 */ rt_device_open(serial, RT_DEVICE_FLAG_INT_RX); //通过config结构体来配置 串口参数 config.baud_rate = BAUD_RATE_115200; config.data_bits = DATA_BITS_8; config.stop_bits = STOP_BITS_2; config.parity = PARITY_NONE; /* 打 开 设 备 后 才 可 修 改 串 口 配 置 参 数 */ rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config); ``` ### 4. 串口发送数据 这里发送数据和裸机发送数据基本一样,多的只是填写设备句柄。 ```c rt_size_t rt_device_write(rt_device_t dev, rt_off_t pos, const void* buffer,rt_size_t size); ``` **rt_device_t dev** 设备句柄 **rt_off_t pos** 写入数据偏移量,如果不偏移就填0 **const void* buffer** 要写入数据的指针 **rt_size_t size** 要写入数据的内存大小,单位是字节 发送数据时这个API会返回写入数据的实际大小,如果返回0就是发送错误了。 **发送数据Demo** ```c #define SAMPLE_UART_NAME "uart2" /* 串 口 设 备 名 称 */ static rt_device_t serial; /* 串 口 设 备 句 柄 */ char str[] = "hello RT-Thread!\r\n"; /* 要发送的数据 */ struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 配 置 参 数 */ /* 查 找 串 口 设 备 */ serial = rt_device_find(SAMPLE_UART_NAME); /* 以 中 断 接 收 及 轮 询 发 送 模 式 打 开 串 口 设 备 */ rt_device_open(serial, RT_DEVICE_FLAG_INT_RX); /* 发 送 字 符 串 */ rt_device_write(serial, 0, str, (sizeof(str) - 1)); ``` ### 5. 设置发送回调函数 RTT提供了发送数据完成后的回调函数,如果没有这个需求可以不用, 当数据发送完成后系统会自动调用这个函数。 ```c rt_err_t rt_device_set_tx_complete(rt_device_t dev, rt_err_t (*tx_done)(rt_device_tdev,void *buffer)); ``` **rt_device_t dev** 设备句柄 **rt_err_t (*tx_done)** 回调函数的指针 当发送完数据后系统自动调用这个函数 参数中的回调函数,函数需要由用户自定义。 ### 6. 设置接收回调函数 与发送回调函数一样,接收回调函数就是接收到数据后系统自动调用的函数,如果没有调用这个设置就不会有接收回调产生。 ```c rt_err_t rt_device_set_rx_indicate(rt_device_t dev, rt_err_t (*rx_ind)(rt_device_tdev,rt_size_t size)); ``` **rt_device_t dev** 设备句柄 **rt_err_t (*rx_ind)** 接收回调函数指针 如果打开串口是以**中断**接收方式打开,当串口接收到数据产生中断后就会回调这里设置的中断回调函数。 一般接收回调函数会发送一个信号量或者事件通知串口数据处理线程有数据到达。 **接收回调函数Demo** ```c #define SAMPLE_UART_NAME "uart2" /* 串 口 设 备 名 称 */ 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; } ``` **发现一个BUG** 现在没有用串口接收数据,如果不处理接收的数据当缓冲区存满后会出现警告,数据再无法存入。 **发现一个BUG** 串口在读写的时候 size这个变量似乎没办法控制数据大小,但是发送16进制不受影响,或者是实际保存的就一个字节大小,但是发送出来的FIFO里的数据。 ### 7. 串口接收数据 RTT提供专门的接收数据的API来读取串口接收到的函数 ```c rt_size_t rt_device_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size); ``` **rt_device_t dev** 设备句柄 **rt_off_t pos** 读取数据偏移量,一般都是0 **void* buffer** 接收缓冲区指针,数据会被保存在这里 **rt_size_t size** 接收字节数 该API会返回读到数据的实际大小,单位是字节,如果返回0就读取错误了。 这里提供一个RT-Thread通过串口接收16进制的Demo吧, 这段代码通过命令行调用打开串口4中断,并启动串口接收线程,在接收回调函数中释放一个信号量,在任务线程中获取一个信号量,然后判断接收的数据是否0X0A。 ```c #include
#include
struct serial_configure config; /* 配 置 默 认 参 数 */ #define SAMPLE_UART_NAME "uart4" /* 串 口 设 备 名 称 */ static rt_device_t serial; /* 串 口 设 备 句 柄 */ static struct rt_semaphore rx_sem; /* 用 于 接 收 消 息 的 信 号 量 */ char str[] = "hello RT-Thread!\r\n"; /* 接 收 数 据 回 调 函 数 */ static rt_err_t uart_input(rt_device_t dev, rt_size_t size) { /* 串 口 接 收 到 数 据 后 产 生 中 断, 调 用 此 回 调 函 数, 然 后 发 送 接 收 信 号 量 */ rt_sem_release(&rx_sem); return RT_EOK; } void serial_thread_entry(void) { char ch; while(1) { /* 阻 塞 等 待 接 收 信 号 量, 等 到 信 号 量 后 再 次 读 取 数 据 */ rt_sem_take(&rx_sem, RT_WAITING_FOREVER); rt_device_read(serial, 0, &ch, 1); //如果不读取数据,FIFO不会清空,缓冲区会爆 if(ch == 0X0A) //判断16进制数据 { rt_device_write(serial, 0, str, sizeof(str)-1); } } } static void uart_sample2(int argc, char *argv[]) { rt_thread_t thread; serial = rt_device_find(SAMPLE_UART_NAME); /* 初 始 化 信 号 量 */ rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO); /* 以 中 断 接 收 及 轮 询 发 送 模 式 打 开 串 口 设 备 */ rt_device_open(serial, RT_DEVICE_FLAG_INT_RX); config.baud_rate = BAUD_RATE_115200; config.data_bits = DATA_BITS_8; config.stop_bits = STOP_BITS_1; config.parity = PARITY_NONE; /* 打 开 设 备 后 才 可 修 改 串 口 配 置 参 数 */ rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config); /* 设 置 接 收 回 调 函 数 */ rt_device_set_rx_indicate(serial, uart_input); thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 15, 10); rt_thread_startup(thread); } /* 导 出 到 msh 命 令 列 表 中 */ MSH_CMD_EXPORT(uart_sample2, uart device sample); ``` ### 8. 关闭串口设备 应用程序完成串口操作后可以关闭串口。 ```c rt_err_t rt_device_close(rt_device_t dev); ``` **rt_device_t dev** 设备句柄 返回值为 **RT_EOK** / **RT_ERROR** ,关闭成功 / 设备已经关闭,其他错误代码为设备关闭失败。
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
乐乐爱学习
这家伙很懒,什么也没写!
文章
8
回答
3
被采纳
0
关注TA
发私信
相关文章
1
rt thread 2.0.2 usart 接收缓存问题
2
关于STM32串口通信的问题
3
STM32F1+RTT串口接收终端数据丢失问题
4
UART TX丢数据?
5
RTT打开串口的时候如何自定义波特率呢?
6
STM32F4的USART数据接收问题
7
串口1234使用问题
8
串口接收回调函数
9
LPC18xx UART问题讨论
10
x1000串口配置的失败问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
a1012112796
10
个答案
1
次被采纳
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
YZRD
2
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部