c++通过serial库进行上下位机通信
编辑
风紊
现役大学牲,半退休robomaster视觉队员
写在前面
本文章主要介绍的是如何通过开源的serial库和虚拟串口实现上位机和下位机通信。
需求
假设下位机有这样一个数据报发送给上位机
struct DataRecv {char start = 's';TeamColor color = TeamColor::Blue;Mode mode = Mode::Armor;float speed = 20;float euler[3] = {}; //(0,1,2) = (yaw,roll,pitch)char shoot_bool = 0;char RuneFlag = 0; char unused[10] = {};char end = 'e';
}//TeamColor是一个char类型的迭代类,Mode也是一个char类型的迭代类
其他数据我都不需要,只需要欧拉角,也就是一个浮点数数组,euler[3]
解决方法
serial库的github仓库
先clone下来,安装,得到头文件和动态库。
我们来看看serial库的构造函数:
class Serial {
public:/*!* Creates a Serial object and opens the port if a port is specified,* otherwise it remains closed until serial::Serial::open is called.** \param port A std::string containing the address of the serial port,* which would be something like 'COM1' on Windows and '/dev/ttyS0'* on Linux.** \param baudrate An unsigned 32-bit integer that represents the baudrate** \param timeout A serial::Timeout struct that defines the timeout* conditions for the serial port. \see serial::Timeout** \param bytesize Size of each byte in the serial transmission of data,* default is eightbits, possible values are: fivebits, sixbits, sevenbits,* eightbits** \param parity Method of parity, default is parity_none, possible values* are: parity_none, parity_odd, parity_even** \param stopbits Number of stop bits used, default is stopbits_one,* possible values are: stopbits_one, stopbits_one_point_five, stopbits_two** \param flowcontrol Type of flowcontrol used, default is* flowcontrol_none, possible values are: flowcontrol_none,* flowcontrol_software, flowcontrol_hardware** \throw serial::PortNotOpenedException* \throw serial::IOException* \throw std::invalid_argument*/Serial (const std::string &port = "" //需要打开的端口uint32_t baudrate = 9600, //设置波特率,缺省值位9600Timeout timeout = Timeout(), //打开超时的时间,缺省值时间为0bytesize_t bytesize = eightbits, //字节大小,缺省值位8位parity_t parity = parity_none, //奇偶校验位,默认无奇偶校验stopbits_t stopbits = stopbits_one, //停止位,缺省值为1位flowcontrol_t flowcontrol = flowcontrol_none);//流控制,默认五流控制,可选择软件流控制和硬件流控制
选项都设置好后,直接调用对象的open()方法就能打开串口通信。
读数据的方法:
size_t
Serial::read (uint8_t *buffer, size_t size)
{ScopedReadLock lock(this->pimpl_);return this->pimpl_->read (buffer, size);
}
所以我们只需要将数据包转为uint8_t的类型的存储格式指针,传给函数,并指定字节数size就能读取数据了。
通信实现文件test.cpp的代码
#include <serial/serial.h>
#include <iostream>struct data_package
{char start = 's';char unused1[2];float speed = 20;float euler[3] = {}; //(0,1,2) = (yaw,roll,pitch)char shoot_bool = 0;char RuneFlag = 0; //char unused2[10] = {};char end = 'e';
} __attribute__((packed));
static_assert(sizeof(data_package) == 32);data_package data;
int main()
{std::cout << "helloworld" << std::endl;serial::Serial ser; // 实例化一个串口的对象ser.setPort("/dev/serial_sdk"); // 设置串口设备ser.setBaudrate(115200); // 设置波特率try{ser.open(); // 打开串口while (true){std::cout << "number" << ser.available() << std::endl; // 读取到缓存区数据的字节数ser.read(reinterpret_cast<uint8_t *>(&data), 32);//将data_package类型结构体强制转换位uint8_t类型的指针,来接收32字节的数据std::cout << data.start << data.unused1[0] << data.unused1[1] << std::endl;std::cout << "(yaw,pitch,roll)" << data.euler[0] << " " << data.euler[1] << " " << data.euler[2] << std::endl;}}catch (std::exception &e){std::cerr << e.what() << std::endl;}
}
使用g++编译代码失败的话,可以参考关于库不在默认搜索路径时,g++链接库时找不到函数实现的问题。
如果要给设备起别名,可以参考Linux下给外部挂载的设备起别名,而不使用内核名称
Notice
如果结构体最后不接 attribute((packed)),经笔者测试,数据包大小变为36位。
相关文章:
c++通过serial库进行上下位机通信
编辑 风紊 现役大学牲,半退休robomaster视觉队员 写在前面 本文章主要介绍的是如何通过开源的serial库和虚拟串口实现上位机和下位机通信。 需求 假设下位机有这样一个数据报发送给上位机 struct DataRecv {char start s;TeamColor color TeamColor::Blu…...
【傻瓜级JS-DLL-WINCC-PLC交互】7.C#直连PLC并读取PLC数据
思路 JS-DLL-WINCC-PLC之间进行交互,思路,先用Visual Studio创建一个C#的DLL控件,然后这个控件里面嵌入浏览器组件,实现JS与DLL通信,然后DLL放入到WINCC里面的图形编辑器中,实现DLL与WINCC的通信。然后PLC与…...
指针常量和常量指针的区别
文章目录 指针常量常量指针即是指针常量又是常量指针 指针常量 指针常量的本质是常量,表示的是 这个指针所指向的地址不能发生改变。即指针变量的值(即地址值)不能发生修改。但是指针所指向的那块内存里的值是可以修改的。 注意:…...
离散化算法总结
离散化是将大范围的数字映射到小范围的区间内,适用于稀疏的区间。 两个问题需要考虑: 1. 原数组中可能有重复元素,需要去重。 2. 如何算出离散化后的值(离散化后保序,使用二分)。 题目链接: …...
【海思SS528 | VO】MPP媒体处理软件V5.0 | VO模块编程总结
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…...
逻辑卷管理器lvm
啥意思,个人理解就是可以将物理分区合并一起组成大的磁盘,也可以移除其中的某个分区。 有四个概念需要了解下 PV,物理卷,VG 卷用户组,PE物理扩展块,LV逻辑卷 p物理,v卷,g用户组&a…...
函数声明后的“ - >”是什么?
这种语法的优势之一是可以在函数的返回类型中使用函数参数,使得返回类型更灵活。 先来看一个使用尾返回类型的例子: #include <iostream> auto add(int a, int b) -> int {return a b; }int main() {std::cout << add(3, 4) <<…...
51爱心流水灯32灯炫酷代码
源代码摘自远眺883的文章,大佬是30个灯的,感兴趣的铁汁们可以去看看哦~(已取得原作者的许可):基于STC89C51单片机设计的心形流水灯软件代码部分_单片机流水灯代码_远眺883的博客-CSDN博客 由于博主是个小菜鸡ÿ…...
将不同时间点的登录状态记录转化为不同时间段的相同登录状态SQL求解
题目 有不同时间点的登录状态记录表state_log如下 请使用sql将其转化为如下表的不同时间段的相同登录状态记录 思路分析: 此类问题需要用到lag或lead函数取上下行对应的数据,然后对前后结果做比较打标签(0或1),再…...
正则表达式与SQL数据库教程
使用正则表达式通过用例查询 Postgres 数据库: 正则表达式(又名 Regex) 正则表达式是一个强大的工具,广泛用于模式匹配和文本操作。 几乎所有编程语言都支持它们,并且经常用于文本提取、搜索和匹配文本等用例。 正则…...
HTML_web扩展标签
1.表格标签 2.增强表头表现 4.表格属性(实际不常用) 结构标签: 合并单元格: 更多请查看主页...
论文阅读:Distributed Initialization for VVIRO with Position-Unknown UWB Network
前言 Distributed Initialization for Visual-Inertial-Ranging Odometry with Position-Unknown UWB Network这篇论文是发表在ICRA 2023上的一篇文章,本文提出了一种基于位置未知UWB网络的一致性视觉惯性紧耦合优化测距算法( DC-VIRO )的分布式初始化方法。 对于…...
scrapy爬虫中间件和下载中间件的使用
一、关于中间件 之前文章说过,scrapy有两种中间件:爬虫中间件和下载中间件,他们的作用时间和位置都不一样,具体区别如下: 爬虫中间件(Spider Middleware) 作用: 爬虫中间件主要负…...
手敲单链表,简单了解其运行逻辑
1. 链表 1.1 结构组成 链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。 链表的结构如下图所示,是由很多个节点相互通过引用来连接而成的;每一个节点由两部分组成,分别数据域&…...
Redis RDB
基于内存的 Redis, 数据都是存储在内存中的。 那么如果重启的话, 数据就会丢失。 为了解决这个问题, Redis 提供了 2 种数据持久化的方案: RDB 和 AOF。 RDB 是 Redis 默认的持久化方案。当满足一定条件的时候, 会把当前内存中的数据写入磁盘, 生成一个快照文件 dump.rdb。Redi…...
Elasticsearch一些函数查询
1. 根据价格分组统计数量,每组区间为2000, filter_pathaggregations 设置查询结果只展示函数结果 也有date_histogram函数根据日期分组等等 GET order/_search?filter_pathaggregations {"aggs": {"hist_price": {"histogr…...
竞赛选题 : 题目:基于深度学习的水果识别 设计 开题 技术
1 前言 Hi,大家好,这里是丹成学长,今天做一个 基于深度学习的水果识别demo 这是一个较为新颖的竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/pos…...
Linux expect命令详解
在Linux系统中,expect 是一款非常有用的工具,它允许用户自动化与需要用户输入进行交互的程序。本文将深入探讨expect命令的基本语法、使用方法以及一些最佳实践。 什么是Expect命令? expect 是一个用于自动化交互式进程的工具。它的主要功能…...
ubuntu18编译Android8的Failed to contact Jack server问题
环境 ubuntu18.04 Android8.1.0 步骤 安装环境 apt install git-core apt install gnupg apt install flex apt install bison apt install gperf apt install build-essential apt install curl apt install libc6-dev apt install libssl-dev apt install libncurses5-dev:…...
FindSecBugs支持的检测规则
很多SAST集成了FindSecBugs这个开源工具,其好处是直接对Class文件进行检测,也就是直接检测二进制问题,可以直接检测war、jar,还是非常方便的。虽然误报率较高,但是这些检测出来的安全漏洞很多是安全从业人员耳熟能详的…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...
第八部分:阶段项目 6:构建 React 前端应用
现在,是时候将你学到的 React 基础知识付诸实践,构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段,你可以先使用模拟数据,或者如果你的后端 API(阶段项目 5)已经搭建好,可以直接连…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...
Java后端检查空条件查询
通过抛出运行异常:throw new RuntimeException("请输入查询条件!");BranchWarehouseServiceImpl.java // 查询试剂交易(入库/出库)记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...
【iOS】 Block再学习
iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...
