使用 select 进行 UART 通信的注意事项
文章目录
- 引言
- UART 通信中的 `select` 函数
- `select` 函数的工作原理
- 使用 `select` 进行 UART 通信的注意事项
- 示例代码
引言
UART(Universal Asynchronous Receiver/Transmitter)是一种用于异步串行通信的硬件协议,常用于计算机和外设之间的数据交换。在嵌入式系统中,UART 通信非常常见,用于连接传感器、微控制器、调制解调器等设备。为了实现高效的 UART 通信,通常需要使用非阻塞式 I/O 操作,这时候 select 函数就派上用场了。
UART 通信中的 select 函数
select 函数允许我们同时监控多个文件描述符,并在这些文件描述符变为可读、可写或发生错误时通知程序。这样可以避免程序在等待 I/O 操作时被阻塞,提高系统的响应速度和效率。
select 函数的工作原理
- 监控文件描述符:
select接受一组文件描述符,并监控这些文件描述符的状态。 - 阻塞等待:可以设置阻塞等待或非阻塞等待,直到文件描述符变为可读、可写或发生错误,或者达到超时时间。
- 返回事件:
select返回后,程序可以检查哪些文件描述符变为可读、可写或发生错误,并进行相应的处理。
使用 select 进行 UART 通信的注意事项
在使用 select 进行 UART 通信时,有几个关键点需要注意:
- 正确初始化文件描述符集
每次调用 select 之前,需要重新初始化文件描述符集(fd_set),因为 select 调用会修改这个集合:
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
- 设置超时值
在每次调用 select 之前,需要设置超时值(struct timeval)。同样,select 会修改这个结构体,因此每次调用前都需要重新设置:
struct timeval tv;
tv.tv_sec = timeout_us / 1000000;
tv.tv_usec = timeout_us % 1000000;
- 处理
select的返回值
检查 select 的返回值以确定是否有文件描述符变为可读、可写或出错:
int ret = select(fd + 1, &rfds, NULL, NULL, &tv);
if (ret == -1) {// Handle error
} else if (ret == 0) {// Handle timeout
} else {if (FD_ISSET(fd, &rfds)) {// Handle readable data}
}
- 避免文件描述符泄漏
确保在程序结束或不再需要文件描述符时关闭它们,防止资源泄漏:
close(fd);
- 多线程环境下的文件描述符使用
如果在多线程环境下使用文件描述符,需要确保对文件描述符的操作是线程安全的。使用互斥锁(mutex)保护对文件描述符的操作,避免竞态条件。
- 检查文件描述符的有效性
在调用 select 之前检查文件描述符是否有效,确保文件描述符在整个生命周期中是有效的:
int check_fd_valid(int fd) {return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
}
- 处理边界情况
处理 read 返回 0 的情况,这通常表示文件结束或没有数据可用:
ssize_t bytesRead = read(fd, buff, len);
if (bytesRead == -1) {// Handle read error
} else if (bytesRead == 0) {// Handle EOF or no data
}
示例代码
以下是综合了上述注意事项的改进代码示例:
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <stdarg.h>
#include <fcntl.h>
#include <pthread.h>void ota_info(const char *fmt, ...) {va_list args;va_start(args, fmt);vprintf(fmt, args);printf("\n");va_end(args);
}int check_fd_valid(int fd) {return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
}int uart_read(int fd, uint8_t *buff, int len, int timeout_us)
{int ret;struct timeval tv;fd_set rfds;memset(buff, 0, len);// Debug log to print fd value before selectota_info("uart_read: fd=%d, timeout_us=%d, thread_id=%ld", fd, timeout_us, pthread_self());// Check if fd is validif (!check_fd_valid(fd)) {ota_info("Invalid file descriptor: %d", fd);return -1;}FD_ZERO(&rfds);FD_SET(fd, &rfds);memset(&tv, 0, sizeof(tv));tv.tv_sec = timeout_us / 1000000;tv.tv_usec = timeout_us % 1000000;ret = select(fd + 1, &rfds, NULL, NULL, &tv);if (ret == -1) {// Select itself failedota_info("select() failed. ret %d, errno %d, %m", ret, errno);return -1;} else if (ret == 0) {// Timeout occurred without any file descriptor becoming readyota_info("select() timed out.");return 0; // Indicate timeout}if (FD_ISSET(fd, &rfds)) {ssize_t bytesRead = read(fd, buff, len);if (bytesRead == -1) {// Error during readota_info("read() failed. errno %d, %m", errno);return -1;} else if (bytesRead == 0) {// EOF reached or no data availableota_info("read() returned 0, no data available or EOF reached.");return 0;}// Return actual bytes readota_info("read() succeeded. bytesRead=%ld, thread_id=%ld", bytesRead, pthread_self());return bytesRead;} else {// This branch should not be reachable given the checks aboveota_info("select() returned with no file descriptor ready.");return 0;}
}int main() {// Example usageint fd = 0; // Example file descriptor, should be initialized properlyuint8_t buffer[256];int len = 256;int timeout_us = 5000000; // 5 secondsint result = uart_read(fd, buffer, len, timeout_us);if (result > 0) {printf("Read %d bytes\n", result);} else if (result == 0) {printf("Timeout or no data available\n");} else {printf("Error occurred\n");}return 0;
}
通过遵循这些注意事项,可以确保在使用 select 函数进行 UART 通信时,代码更加健壮和可靠,减少出现难以复现的错误的可能性。希望这篇博客能帮助你在项目中更好地使用 select 函数进行 UART 通信。
相关文章:
使用 select 进行 UART 通信的注意事项
文章目录 引言UART 通信中的 select 函数select 函数的工作原理使用 select 进行 UART 通信的注意事项示例代码 引言 UART(Universal Asynchronous Receiver/Transmitter)是一种用于异步串行通信的硬件协议,常用于计算机和外设之间的数据交换…...
干货 | 2024低空经济产业发展白皮书(免费下载)
【1】关注本公众号,转发当前文章到微信朋友圈 【2】私信发送 2024低空经济产业发展白皮书 【3】获取本方案PDF下载链接,直接下载即可。 如需下载本方案PPT/WORD原格式,诚挚邀请您微信扫描以下二维码加入方案驿站知识星球,获取上…...
打开nginx连接的php页面报错502
目录 问题描述: 原因: 1. 使用 Unix 域套接字(Unix Socket) 区别和优势: 2. 使用 TCP/IP 套接字 区别和优势: 如何选择 扩展:Rocky_Linux9.4安装PHP的步骤: 使用Remi存储库…...
Qt之文件操作(QFile、QFileInfo、QTemporaryFile)
文章目录 前言QFile如何使用 QFile QFileInfo如何使用 QFileInfo QTemporaryFile如何使用 QTemporaryFile QFile常用函数QFileInfo常用函数QTemporaryFile常用函数总结 前言 在开发 Qt 应用程序时,我们经常需要进行文件操作,如读取文件、写入文件、获取…...
Python爬虫初试
在Python中,我们可以使用一些强大的库来编写一个功能强大的爬虫, Python 首先安装必要的库(如果尚未安装) pip install requests beautifulsoup4 import requests from bs4 import BeautifulSoup import osdef download_images(…...
ARM-V9 RME(Realm Management Extension)系统架构之系统初始化流程
安全之安全(security)博客目录导读 目录 一、重置取消 二、应用处理单元(PE)初始启动 三、MSD初始化 四、GPT初始化 五、初始启动退出(由所有应用PE执行) 六、RMSD初始化 七、PE进入丢失上下文的低功耗状态 本博客提供了R…...
软件工程考试题备考
文章目录 前言一、二、1.2 总结 前言 一、 B D C 类图、对象图、包图 其他系统及用户 功能需求 用例 人、硬件或其他系统可以扮演的角色7. D C 数据 原型/系统原型;瀑布 A 功能;功能需求 D 数据存储;圆形/圆角矩形;矩形 C T;T;F C C B C D C …...
一款基于WordPress开发的高颜值的自适应主题Puock
主题特性 支持白天与暗黑模式 全局无刷新加载 支持博客与CMS布局 内置WP优化策略 一键全站变灰 网页压缩成一行 后台防恶意登录 内置出色的SEO功能 评论Ajax加载 文章点赞、打赏 支持Twemoji集成 支持QQ登录 丰富的广告位 丰富的小工具 自动百度链接提交 众多页面模板 支持评论…...
浙教版 七年级下册 科学复习干货
七年级下册 浙教版科学 复习干货 文章目录 七年级下册 浙教版科学 复习干货第 I 章人类 H u m a n Human Human人类生殖系统胚胎发育、娩出过程青春期 动物 A n i m a l Animal Animal生长时期有性生殖无性生殖 植物 P l a n t Plant Plant种子结构种子萌发芽花有性生殖无性…...
罗盘时钟lua迷你世界
--罗盘时钟 --星空露珠工作室制作 --作者:韩永旗 --数字换中文 local zhChar {一,二,三,四,五,六,七,八,九} function formatNumber( num ) if type(num)~number then return num..is not a num end if num>99 then return num..不是两位数 end if num0 then return 零 el…...
【Java】Java基础语法
一、注释详解 1.1 注释的语法: // 单行注释/*多行注释 *//**文档注释 */ 1.2 注释的特点: 注释不影响程序的执行,在Javac命令进行编译后会将注释去掉 1.3 注释的快捷键 二、字面量详解 2.1 字面量的概念: 计算机是用来处理…...
利用golang_Consul代码实现Prometheus监控目标的注册以及动态发现与配置
文章目录 前言一、prometheus发现方式二、监控指标注册架构图三、部分代码展示1.核心思想2.代码目录3、程序入口函数剖析4、settings配置文件5、初始化配置文件及consul6、全局变量7、配置config8、公共方法目录common9、工具目录tools10、service层展示11、命令行参数12、Make…...
Python爬虫介绍
Python 作为一种广泛应用的编程语言,在 Web 开发、大数据开发、人工智能开发和嵌入式开发等领域都有着重要的应用。 Python 的易学性、清晰性和可移植性等特点使它得到很多技术人士的喜爱。对于数据科学和机器学习领域的程序员来说,Python 提供了强大的…...
Linux 进程管理
一、查看进程 使用ps -aux进行查看,其中a表示列出所有进程信息,u以用户格式显示进程信息,x显示后台进程参数,也可以使用| grep 进行进程的筛选 以下是显示进程后的示意 USER为进程执行的用户 PID为进程号 %CPU为该进程的cpu占用…...
【车载测试】CAN协议、CAN- FD协议和FlexRay协议 区别
【上半场电动化,下半场智能化】 一、CAN协议 和 CAN- FD协议的区别 CAN(Controller Area Network)协议是一种广泛用于汽车和工业控制系统等领域的现场总线协议。CAN- FD(Flexible Data Rate)协议是对CAN协议的扩展&am…...
对日期的处理
对日期的处理 对编码进行统一,在脚本最开始: # -*- coding: utf-8 -*-这里涉及到两个操作,一个是将数据进行标准化,比如有些日期是2024/05/06这并不符合日期的标准格式,需要转换成这样的2024-05-06 def tran_std(st…...
赵丽颖纯白茉莉绽放温柔之美
赵丽颖纯白茉莉,绽放温柔之美在这个繁忙喧嚣的娱乐圈,赵丽颖以其独特的魅力,成为了无数人心中的白月光。近日,赵丽颖工作室发布了一组live图,她身着一袭温柔白裙,宛如一朵盛开的纯白茉莉花,美得…...
软考高级论文真题“论湖仓一体架构及其应用”
论文真题 随着5G、大数据、人工智能、物联网等技术的不断成熟,各行各业的业务场景日益复杂,企业数据呈现出大规模、多样性的特点,特别是非结构化数据呈现出爆发式增长趋势。在这一背景下,企业数据管理不再局限于传统的结构化OLTP…...
CentOS系统查看版本的各个命令
cat /etc/centos-release 查看CentOS版本 uname -a 命令的结果分别代表:当前系统的内核名称、主机名、内核发型版本、节点名、系统时间、硬件名称、硬件平台、处理器类型以及操作系统名称 cat /proc/version 命令用于查看Linux内核的版本信息。执行该命令后…...
[保姆级教程]uniapp实现底部导航栏
文章目录 前置准备工作安装HBuilder-X新建uniapp项目教程使用HBuilder-X启动uniapp项目教程 实现底部导航栏package.json中配置导航栏详细配置内容 前置准备工作 安装HBuilder-X 详细步骤可看上文》》 新建uniapp项目教程 详细步骤可看上文》》 使用HBuilder-X启动uniapp项…...
植物基肉类替代品市场的增长与投资机会
植物基肉类替代品市场的增长与投资机会 关键词:植物基肉类替代品、市场增长、投资机会、消费趋势、行业发展 摘要:本文聚焦于植物基肉类替代品市场,深入分析其市场增长的驱动因素、现状及未来趋势,同时探讨了该领域蕴含的投资机会。通过对核心概念的阐释、相关算法原理的介…...
TM1620驱动数码管的8个常见坑点及解决方案(基于STM32实战)
TM1620驱动数码管的8个常见坑点及解决方案(基于STM32实战) 当你在STM32项目中使用TM1620驱动数码管时,可能会遇到各种令人头疼的问题。本文将深入探讨8个最常见的坑点,并提供经过实战验证的解决方案,帮助开发者快速定位…...
LeRobot数据采集全流程解析:从环境配置到动作回放(SO-100实战)
LeRobot数据采集全流程实战:从环境搭建到动作复现的SO-100深度指南 当我们需要让机器人学会新技能时,数据采集是构建智能系统的第一步。LeRobot作为Hugging Face推出的机器人学习平台,通过标准化流程降低了开发门槛。本文将带你完整走通SO-10…...
深入解析LCD面板Gamma校准:从原理到自动化调试实践
1. Gamma校准的前世今生:从CRT到LCD的视觉革命 第一次接触Gamma校准时,我正对着两台显示器发愣——同样的设计稿在CRT显示器上色彩饱满,到了LCD屏幕却像蒙了层灰。这个困扰无数设计师的问题,背后正是Gamma值在作祟。早年的CRT显示…...
FanControl深度指南:智能散热系统的架构解析与实战优化
FanControl深度指南:智能散热系统的架构解析与实战优化 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/f…...
保姆级教程:在若依框架里给你的系统加个AI客服(通义千问+流式响应)
企业级智能客服系统集成实战:若依框架与通义千问的完美结合 1. 智能客服系统架构设计 在当今数字化转型浪潮中,智能客服已成为企业提升服务效率、降低人力成本的关键工具。基于若依框架与通义千问构建的智能客服系统,能够无缝集成到现有企业应…...
Python Decouple 的测试策略:如何确保配置的正确性
Python Decouple 的测试策略:如何确保配置的正确性 【免费下载链接】python-decouple Strict separation of config from code. 项目地址: https://gitcode.com/gh_mirrors/py/python-decouple 在软件开发中,配置管理的正确性直接影响应用的稳定性…...
从0到1落地智能仓储:C#上位机+Modbus RTU实现AGV集群调度与货物自动分拣
本文是纯实战、可直接落地的智能仓储完整方案,基于C# .NET 6 + Modbus RTU/Modbus TCP + AGV调度 + 自动分拣,从零搭建一套轻量级、低成本、高可靠的智能仓储系统,适用于电商仓库、工厂原料仓、成品仓、立体库。 无废话、无虚架构,代码可直接复制运行,适合新手从0到1上手智…...
Acetic Acid-PEG-OPSS,分子链两端分别带有吡啶基二硫化物和乙酸基团
一.名称英文名称:AA-PEG-OPSS,Acetic Acid-PEG-OPSS,OPSS-PEG-AA,OPSS-PEG-Acetic Acid中文名称:乙酸聚乙二醇二巯基吡啶,乙酸PEG二巯基吡啶分子量:1k,2k,3.4k࿰…...
Liquibase,数据库无关的版本控制工具!
在现代软件开发中,数据库的版本控制往往比代码版本控制更具挑战性。不同的开发环境、测试环境、生产环境可能使用不同的数据库产品(如开发用H2、测试用MySQL、生产用PostgreSQL),而传统的SQL脚本往往包含特定数据库的方言…...
