Qt篇——获取Windows系统上插入的串口设备的物理序号

news2024/10/9 11:25:31

        先右键【此电脑-管理- 设备管理器-端口(COM和LPT)】中找到我们插入的某个设备的物理序号,如下图红色矩形框出的信息,这个就是已插入设备的物理序号(就是插在哪个USB口的意思)。

        在Linux下我们可以通过往/etc/udev/rules.d文件夹中放入串口绑定规则文件,将指定物理序号devpath上的设备绑定一个固定名称(参考我的文章Linux绑定串口名称),而在windows下没有这种方式。

        那么当我们在Qt开发过程中,需要获取windows系统下特定物理USB口的序号(如Port_#0001.Hub_#0002)和串口名称(如COM3),把它作为某个设备的专用启动位置,就可以按下面的方法得到(我用的Qt5.14.2,是直接可以用的,这是windows的api,理论上受Qt版本影响不大)。 (QSerialPort本身不提供相关的接口,所以我们要使用windows api)。

#include <windows.h>
#include <setupapi.h>
#include <regstr.h>

// 定义全局变量
GUID GuidSerialPort = { 0x4d36e978, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } };

// 使用SetupDiGetDeviceRegistryProperty获取设备属性
bool GetDeviceProperty(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, LPWSTR Buffer, DWORD BufferLength, PDWORD RequiredSize) {
    DWORD DataT;
    LONG Result;

    DeviceInfoData->cbSize = sizeof(SP_DEVINFO_DATA);

    // 获取属性
    Result = SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, DeviceInfoData, Property, &DataT, (PBYTE)Buffer, BufferLength, RequiredSize);

    if (Result) {
        return true;
    } else {
        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
            return false;
        } else {
            return false;
        }
    }
}

void serialPortListFresh(){
    HDEVINFO DeviceInfoSet = INVALID_HANDLE_VALUE;
    SP_DEVINFO_DATA DeviceInfoData;
    DWORD i;
    WCHAR Buffer[256];
    DWORD RequiredSize;
    QString portName;
    QString locationInfo;

    DeviceInfoSet = SetupDiGetClassDevs(&GuidSerialPort, 0, 0, DIGCF_PRESENT);
    if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
        qDebug() << "Error getting device information set";
    }

    for (i = 0; i < 10; i++) {
        // 清空缓冲区
        ZeroMemory(Buffer, sizeof(Buffer));
        RequiredSize = sizeof(Buffer);

        // 获取设备实例路径
        if (GetDeviceProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_LOCATION_INFORMATION, Buffer, sizeof(Buffer), &RequiredSize)) {
            locationInfo = QString::fromWCharArray(Buffer);
            qDebug() << "Location Info:" << locationInfo;

            // 获取设备描述(通常是串口名,如"COM1")
            ZeroMemory(Buffer, sizeof(Buffer));
            RequiredSize = sizeof(Buffer);
            if (GetDeviceProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_DEVICEDESC, Buffer, sizeof(Buffer), &RequiredSize)) {
                portName = QString::fromWCharArray(Buffer);
                qDebug() << "Port Name:" << portName;

                // 输出配对信息
                qDebug() << portName << " is located at" << locationInfo;
            }
            if (GetDeviceProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_FRIENDLYNAME, Buffer, sizeof(Buffer), &RequiredSize)) {
                portName = QString::fromWCharArray(Buffer);
                qDebug() << "Port Name:" << portName << "\n";
                QString portCom = portName.mid(portName.indexOf("("), portName.indexOf(")") - portName.indexOf("("));
                portlist.append(portCom);
                ui->comboBox_SerialName_Rail->addItem(ports.at(i).portName());
                if(locationInfo == "Port_#0001.Hub_#0002") {
                    ui->comboBox_SerialName_Rail->setCurrentIndex(i);        //选取
                }
                ui->comboBox_Lidar_SerialName_1->addItem(ports.at(i).portName());
                if(locationInfo == "Port_#0006.Hub_#0002") {
                    ui->comboBox_Lidar_SerialName_1->setCurrentIndex(i);        //选取
                }
            }
        }

        if (!SetupDiEnumDeviceInfo(DeviceInfoSet, i, &DeviceInfoData)) {
            break;
        }
    }

    SetupDiDestroyDeviceInfoList(DeviceInfoSet);

}

可以得到如下打印:

这样我们就知道插到Port_#0001.Hub_#0002(举例)的USB口上的设备的端口号是COM3了,那么接下来就可以用QSerialPort打开COM3设备进行通信了。

注:更多串口信息参数详见微软官网:

SetupDiGetDeviceRegistryPropertyA 函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1863313.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MQTT自动回复消息工具

点击下载《MQTT自动回复消息工具V1.0.0》 1. 前言 在进行IoT系统开发时&#xff0c;各个小组成员通常是同步进行项目开发&#xff0c;经常会遇到设备端和前后端开发人员开发进度不协调的情况&#xff0c;此时接口还没开发完&#xff0c;也没有可以调试的环境&#xff0c;只能…

natsort 自然排序

1、安装 pip install natsort 2、为什么使用natsort 而不是sorted 在python中只需要调用sorted函数就可以了&#xff0c;但是这个函数有一个缺点&#xff0c;就是它是按照从第一位开始的顺序排列的。意思是&#xff1a; wav_file [1.wav, 13.wav, 9.wav, 2.wav,"23.wav…

C++STL 6大组件—你必知必会的编程利器

课程总目录 文章目录 一、vector容器二、deque和list容器三、vector、deque、list横向对比四、详解容器是配置stack、queue、priority_queue五、无序关联容器六、有序关联容器七、迭代器八、函数对象九、泛型算法和绑定器 一、vector容器 底层数据结构是动态开辟的数组&#x…

牛客周赛 F 小红的迷宫行走

原题链接&#xff1a;F-小红的迷宫行走​​​​​​ 题目大意&#xff1a;给大小的图&#xff0c;小红初始在&#xff0c;小红想要去&#xff0c;小红可以向下或者向右走&#xff0c;每次花费1代价&#xff0c;并且每个点上面有一个数字&#xff0c;小红可以瞬移到和这个数字不…

ES6模板字符串详解

ES6是JavaScript语言的一次重大更新&#xff0c;引入了许多新特性和语法改进&#xff0c;其中模板字符串是一个非常实用和灵活的语法特性。它可以让我们从数组或对象中提取值&#xff0c;并赋给对应的变量&#xff0c;让代码变得更加简洁和易读。 本文将深入探讨ES6解构赋值的语…

数据结构:栈(stack)详解 c++信息学奥赛基础知识讲解

目录 一、栈的定义 二、栈的操作 三、代码实操 四、栈的实现 1、string实现stack 2、vector实现stack 3、deque实现栈 一、栈的定义 stack是一个比较简单易用的数据结构&#xff0c;stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff…

泰勒斯威夫特2022年纽约大学毕业典礼演讲:NYU‘s 2022 Commencement Speaker Taylor Swift

NYU’s 2022 Commencement Speaker Taylor Swift Link: https://www.youtube.com/watch?vOBG50aoUwlI Singer, songwriter, producer, and director Taylor Swift received a Doctor of Fine Arts, honoris causa, at the Commencement for the Class of 2022 and delivered …

Java | Leetcode Java题解之第198题打家劫舍

题目&#xff1a; 题解&#xff1a; class Solution {public int rob(int[] nums) {if (nums null || nums.length 0) {return 0;}int length nums.length;if (length 1) {return nums[0];}int first nums[0], second Math.max(nums[0], nums[1]);for (int i 2; i <…

图形编辑器基于Paper.js教程04: Paper.js中的基础知识

背景 了解paper.js的基础知识&#xff0c;在往后的开发过程中会让你如履平地。 基础知识 paper.js 提供了两种编写方式&#xff0c;一种是纯粹的JavaScript编写&#xff0c;还有一种是使用官方提供的PaperScript。 区别就是在于&#xff0c;调用paper下的字对象是否需要加pa…

吉他练琴软件哪个好 Guitar Pro如何辅助练琴

在现代音乐学习和创作中&#xff0c;吉他打谱软件的作用越来越为人们所重视。随着技术的不断发展&#xff0c;各种吉他练琴软件也如雨后春笋般涌现&#xff0c;为吉他爱好者提供了更多选择。下面我们来看看吉他练琴软件哪个好&#xff0c;Guitar Pro如何辅助练琴的相关内容。 一…

出现 defineProps is a compiler macro and no longer needs to be imported. 解决方法

目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 执行前端代码的时候,出现如下问题: [@vue/compiler-sfc] defineProps is a compiler macro and no longer needs to be imported.[@vue/compiler-sfc] defineEmits is a compiler macro and no longer needs to be impo…

在线客服源码系统全端通用 源码完全开源可以二次开发 带完整的安装代码包以及搭建教程

系统概述 在线客服源码系统采用了先进的技术架构&#xff0c;包括前端界面、后端服务、数据库等部分。前端界面采用了响应式设计&#xff0c;能够自适应不同的设备屏幕尺寸&#xff0c;为用户提供良好的使用体验。后端服务采用了高性能的服务器架构&#xff0c;确保系统的稳定…

【安全审核】音视频审核开通以及计费相关

融云控制台音视频审核入口&#xff1a;音视频审核 1 音视频审核文档&#xff1a;融云开发者文档 1 提示&#xff1a; 开发环境&#xff1a; 免费体验 7 天&#xff08;含 21 万分钟音频流和 420 万张视频审核用量&#xff09;&#xff0c;免费额度用尽后&#xff0c;将关停服务…

echarts 折线图柱状图增加点击事件

单折线图&#xff0c;可以直接监听click事件&#xff08;只有点击到折线才会触发&#xff09; this.chart.on(click, () > {console.log(点击,.s)})但很多时候&#xff0c;我们是要求点击折线图任意位置触发点击事件 而且要注意隐藏折线的操作按钮 this.chart.getZr().on…

C++ | Leetcode C++题解之第191题位1的个数

题目&#xff1a; 题解&#xff1a; class Solution { public:int hammingWeight(uint32_t n) {int ret 0;while (n) {n & n - 1;ret;}return ret;} };

RabbitMQ实践——搭建多人聊天服务

大纲 用户登录创建聊天室监听Stream&#xff08;聊天室&#xff09;发送消息实验登录Tom侧Jerry侧 创建聊天室Jerry侧Tom侧 进入聊天室Jerry侧Tom侧 发送消息Jerry发送消息Jerry侧聊天室Tom侧聊天室 Tom发送消息Jerry侧聊天室Tom侧聊天室 代码工程参考资料 在《RabbitMQ实践——…

LongRAG:增强长上下文大语言模型的检索增强生成

这篇论文的标题是《LongRAG: Enhancing Retrieval-Augmented Generation with Long-context LLMs》&#xff0c;由滑铁卢大学的Ziyan Jiang、Xueguang Ma和Wenhu Chen撰写。论文主要探讨了在传统的检索增强生成&#xff08;RAG&#xff09;框架中存在的一些问题&#xff0c;并提…

Linux基础 - 存储结构与管理硬盘

目录 零. 简介 一. 文件系统 Ubuntu 文件系统结构&#xff1a; 路径: 二. 硬盘管理 零. 简介 Linux 文件系统是一种用于组织和存储文件、目录以及相关数据的架构。 常见的 Linux 文件系统有&#xff1a; Ext4&#xff08;Fourth Extended File System&#xff09;&#…

数据结构:队列详解 c++信息学奥赛基础知识讲解

目录 一、队列概念 二、队列容器 三、队列操作 四、代码实操 五、队列遍历 六、案例实操 题目描述&#xff1a; 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; 详细代码&#xff1a; 一、队列概念 队列是一种特殊的线性…

了解负载均衡器

现代系统变得越来越复杂&#xff0c;但这种复杂性确保了处理大量的网络流量和请求。 简单来说&#xff0c;负载均衡器的主要思想就像它的名字一样&#xff0c;它跨服务器提供直接的客户端请求。换句话说&#xff0c;负载均衡器是在多台服务器之间分配网络或应用程序流量的系统…