调用.net DLL让CANoe自动识别串口号

article/2025/6/10 5:09:24

1.前言

CANoe9.0用CAPL控制数控电源_canoe读取程控电源电流值-CSDN博客

之前做CAPL通过串口控制数控电源,存在一个缺点:更换电脑需要改串口号

CSDN上有类似的博客,不过要收费,本文根据VID和PID来自动获取串口号,代码少,使用起来更方便

本文可以告诉大家

(1)C#中如何根据VID和PID来获取串口号

(2)CAPL如何调用C#的DLL

(3)如何获取设备的VID和PID

(4)如何创建C#的DLL

2.开发环境

2.1硬件环境

科睿源 KA3005P

2.2软件环境

Win10 + CANoe12.0 + VS2013

3.参考资料

CANoe Help文档

4.自动识别串口原理

4.1方案一

枚举所有串口,分别询问每个串口是否是指定设备,优点是通用,缺点是速度慢

4.2方案二

根据设备的VID和PID获取串口号,优点是速度快,缺点是只适合USB转串口,如果存在多个同类设备,仍然需要每个询问

由于KA3005P是USB接口的虚拟串口,因此我这里选择方案二

5.创建C# DLL

5.1 注意事项

5.2 创建DLL工程

5.3 代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.IO.Ports;
using UCANHelper;namespace SerialPortAutoDetect
{public class SerialPortAutoDetect{public static int GetAllPorts(int[] ports, int maxLength){var port_names = SerialPort.GetPortNames();int i = 0;for (i = 0; i < ports.Length && i < maxLength; i++){string num = port_names[i].Replace("COM", "");ports[i] = Convert.ToInt32(num);}return i;}public static int GetPortsByVidPid(int[] ports, int maxLength, ushort vid, ushort pid){List<string> names = USB_Help.ComPortNames(vid.ToString("X4"), pid.ToString("X4"));int i = 0;for (i = 0; i < names.Count && i < maxLength; i++){string num = names[i].Replace("COM", "");ports[i] = Convert.ToInt32(num);}return i;}}
}

USB_Help.cs

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;namespace UCANHelper
{class USB_Help{#region 根据VID PID通过注册表获取端口号public static List<string> ComPortNames(String VID, String PID){//https://cloud.tencent.com/developer/ask/sof/115144954RegistryKey rk1 = Registry.LocalMachine;RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum");String pattern = String.Format("^VID_{0}.PID_{1}", VID, PID);Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase);List<string> ports = new List<string>();string[] pc_com_ports = SerialPort.GetPortNames();foreach (String s3 in rk2.GetSubKeyNames()){RegistryKey rk3 = rk2.OpenSubKey(s3);foreach (String s in rk3.GetSubKeyNames()){if (_rx.Match(s).Success){RegistryKey rk4 = rk3.OpenSubKey(s);foreach (String s2 in rk4.GetSubKeyNames()){RegistryKey rk5 = rk4.OpenSubKey(s2);RegistryKey rk6 = rk5.OpenSubKey("Device Parameters");string port_name = (string)rk6.GetValue("PortName");if (port_name != null && pc_com_ports.Contains<string>(port_name)){ports.Add(port_name);}}}}}return ports;}#endregion}
}

编译,生成SerialPortAutoDetect.dll

6.获取设备的VID和PID

在设备管理器中,找到端口,右击属性

7.CAPL中访问

仅有初始化部分,其他的参考之前的博客

includes
{#pragma netlibrary("..\DLL\SerialPortAutoDetect.dll")
}variables
{// GLOBALconst int kBUFFER_SIZE = 1000;const int kINFO        = 1;const int kWARN        = 2;const int kERROR       = 3;const int kHANDSHAKE_DISABLED = 0;const int kHANDSHAKE_RTSCTS   = 33;// define for dp serial port com9dword port = 6;const dword baudrate = 9600;const dword dataBits = 8;const dword stopBits = 1;const dword parity = 0;//0:none 1:even 0:odd// data is copied from callback buffer to gReceiverBuffer (collects data)byte gReceiverCallbackBuffer[kBUFFER_SIZE];byte gReceivedBuffer[kBUFFER_SIZE];dword gReceivedIndex= 0;// state variablebyte gSending = 0;byte gGetValueSt = 0;byte gSetValueSt = 0;msTimer t100ms;msTimer t20ms;dword vid = 0x0416;dword pid = 0x5011;
}on preStart
{InitSerialPort();  
}on start
{setTimer(t100ms,100);
}
//RS232 Init
InitSerialPort()
{long ports[10];long count=0;count=SerialPortAutoDetect::SerialPortAutoDetect::GetPortsByVidPid(ports,10,vid,pid);if(count > 0){port=ports[0];writeLineEx(0,kINFO,"Find %d serial port, use first serial port: %d.", count, port);}else{writeLineEx(0,kINFO,"Can not find any serial port, use default serial port %d.", port);}    // close serial port (port may have changed, former port shall not remain open)if(Rs232Close(port)!=1)writeLineEx(0,kERROR,"An error occurred during closing of the serial port %d.", port);    // set state (close aborts all open requests)gSending = 0;// open the serial port (comes up with Windows defaults)if(Rs232Open(port)==1)writeLineEx(0,kINFO, "Serial port %d successfully opened.", port);    elsewriteLineEx(0,kERROR,"An error occurred during opening of the serial port %d.", port);    // configure the serial port// - just take the panel contentif(Rs232Configure(port,baudrate,dataBits,stopBits,parity)==1)writeLineEx(0,kINFO, "Serial port %d successfully initialized.", port);    elsewriteLineEx(0,kERROR,"An error occurred during initialization of the serial port %d.", port);    // port, handshake, xonLim, xoffLim, xonChar, xoffChar, writeTimeout// without last timeout parameter: use default timeout// for transmission of small amounts of data one may not need to use handshake ! // e.g. 33 for RTS/CTS as second parameter for large volumes of data, 0 for small volumesif(Rs232SetHandshake(port, kHANDSHAKE_DISABLED, 0, 0, 0, 0))writeLineEx(0,kINFO, "Handshake parameters for serial port %d successfully configured.", port);    elsewriteLineEx(0,kERROR,"An error occurred during the serial port %d configuration of handshake parameters.", port);// set buffer for reception (otherwise callback would not work)if(Rs232Receive(port, gReceiverCallbackBuffer, kBUFFER_SIZE))writeLineEx(0,kINFO, "Receiver buffer for serial port %d successfully set.", port);    elsewriteLineEx(0,kERROR,"An error occurred during setting the receiver buffer for serial port %d.", port);
}

8.测试

可以正确识别到串口3


http://www.hkcw.cn/article/hDZGTpBogb.shtml

相关文章

C++中锁与原子操作的区别及取舍策略

文章目录 锁与原子操作的基本概念锁&#xff08;Lock&#xff09;原子操作&#xff08;Atomic Operations&#xff09; 锁与原子操作的区别1. **功能**2. **性能**3. **复杂性**4. **适用场景** 锁与原子操作的取舍策略1. **简单变量操作**2. **复杂共享资源**3. **性能敏感场景…

知识拓展卡———————RSTP与MSTP的简要说明

我们在之前的学习过程中了解了STP&#xff08;生成树协议&#xff09;的各个端口角色选举的相关概念&#xff0c;今天我们再来拓展一下关于STP的扩展性知识点MSTP与RSTP。 目录 RSTP&#xff08;Rapid Spanning Tree Protocol,快速生成树协议&#xff09;: 端口角色&#xf…

NSSCTF [LitCTF 2025]test_your_nc

[复现]绕过学的还是太差了&#xff0c;多积累吧 ​​​​​​题目 题目: 给了一个python文件 #!/bin/python3 import osprint("input your command")blacklist [cat,ls, ,cd,echo,<,${IFS},sh,\\]while True:command input()for i in blacklist:if i in com…

(10)Fiddler抓包-Fiddler如何设置捕获Firefox浏览器的Https会话

1.简介 经过上一篇对Fiddler的配置后&#xff0c;绝大多数的Https的会话&#xff0c;我们可以成功捕获抓取到&#xff0c;但是有些版本的Firefox浏览器仍然是捕获不到其的Https会话&#xff0c;需要我们更进一步的配置才能捕获到会话进行抓包。 2.环境 1.环境是Windows 10版…

持续领跑中国异地组网路由器市场,贝锐蒲公英再次登顶销量榜首

作为国产远程连接SaaS服务的创领者&#xff0c;贝锐持续引领行业发展&#xff0c;旗下贝锐蒲公英异地组网路由器&#xff0c;凭借出色的技术实力和市场表现&#xff0c;斩获2024年线上电商平台市场销量份额中国第一的佳绩&#xff0c;充分彰显了其在网络解决方案与异地组网领域…

Redis底层数据结构之深入理解跳表(2)

上一篇文章中我们详细讲述了跳表的增添、查找和修改的操作&#xff0c;这篇文章我们来讲解一下跳表在多线程并发时的安全问题。在Redis中&#xff0c;除了网络IO部分和大文件的后台复制涉及到多线程外&#xff0c;其余任务执行时全部都是单线程&#xff0c;这也就意味着在Redis…

振动力学:有阻尼单自由度系统(简谐力激励的受迫振动)

本文讨论外力作用下的单自由度系统的受迫振动&#xff0c;特别是详细讨论了系统的共振特性。 1. 受迫振动的解及其组成 根据文章1和2的描述&#xff0c;此时简谐力外力 f ( t ) f 0 sin ⁡ ( ω t ) f(t) f_0 \sin(\omega t) f(t)f0​sin(ωt)。因此振动方程为&#xff1a;…

Vert.x学习笔记-EventLoop与Handler的关系

Vert.x学习笔记 一、底层机制&#xff1a;事件驱动的核心引擎二、协作流程&#xff1a;事件分发与执行三、线程安全&#xff1a;EventLoop与Handler的约束四、性能优化&#xff1a;最佳实践与注意事项五、典型场景与架构设计六、总结 在Vert.x中&#xff0c;**EventLoop&#x…

DevEco Studio的使用

IDE环境的搭建 快速开始 因为本版本的DevEco Studio为一体化版本&#xff0c;已经包含了SDK&#xff0c;构建插件&#xff0c;ohpm等工具&#xff0c;所以您 在安装完成后即可开箱即用&#xff0c;进行工程开发&#xff0c;无需配置环境。首先看一下安装DevEco Studio的相关流…

手动删除网页上的禁止复制事件

以Edge浏览器为环境、以网络上一个文档为例。 右击页面&#xff0c;打开【检查】工具。选择元素&#xff0c;打开【事件侦听器】&#xff1a; 展开copy&#xff0c;删除里面的事件&#xff1a; 选中文字&#xff0c;进行复制

【MATLAB去噪算法】基于CEEMD联合小波阈值去噪算法(第三期)

02.去噪算法原理 1.引言 传统EMD方法存在模态混叠问题&#xff0c;即信号成分在不同IMF分量中出现碎片化分布。为改进这一问题&#xff0c;Huang等&#xff08;1999&#xff09;提出间歇性测试算法&#xff0c;但效果有限。Wu和Huang&#xff08;2009&#xff09;发展的集合经…

Semi-Supervised Neuron Segmentation via Reinforced Consistency Learning

perturbed counterpart x u ′ ^{u} u′ waterz环境不好满足&#xff0c;不建议复现

R语言使用随机过采样(Random Oversampling)平衡数据集

随机过采样&#xff08;Random Oversampling&#xff09;是一种用于平衡数据集的技术&#xff0c;常用于机器学习中处理类别不平衡问题。当某个类别的样本数量远少于其他类别时&#xff08;例如二分类中的正负样本比例悬殊&#xff09;&#xff0c;模型可能会偏向多数类&#x…

pcie 日常问答-20250528

问题均来自工作总结&#xff0c;面经问题&#xff1b;多为发散性问题&#xff1b;大多均会结合S IP rtl实现进行细致分析。 1. dllp包有哪些类型&#xff1f;dllp主要功能是干甚呢的&#xff1f; dllp是一个点到点的传输&#xff08;传输过程中没有任何标识&#xff09;&#…

ADK实战-基于ollama+qwen3实现外部工具串行调用

0 环境准备 1 开发环境准备 1.1 创建项目python环境 1.2 在pycharm创建项目 1.3 安装项目依赖 2 资源准备 3 adk agent构建 3.1 新建adk_agent_tool_serial python包 3.2 编辑__init__.py文件 4 配置env 4.1 新建.env文件 4.2 编辑.env文件 5 agent逻辑实现 5.1 …

降本增效的新引擎:GEO如何提升企业营销ROI

在当前经济环境下&#xff0c;企业面临着前所未有的成本压力和效率挑战。深耕数字营销二十余年&#xff0c;我们见证了从传统广告到数字营销&#xff0c;再到如今生成式AI时代的每一次效率变革。在这个新阶段&#xff0c;生成式引擎优化&#xff08;GEO&#xff09;正在成为企业…

Blinko智能笔记系统实现跨平台同步与隐私保护的完整技术方案解析

文章目录 前言1. Docker Compose一键安装2. 简单使用演示3. 安装cpolar内网穿透4. 配置公网地址5. 配置固定公网地址 推荐 ​ 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。 点击跳转到网站 前言 是否…

OpenCV CUDA模块特征检测------创建Harris角点检测器的GPU实现接口cv::cuda::createHarrisCorner

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数创建一个 基于 Harris 算法的角点响应计算对象&#xff0c;专门用于在 GPU 上进行高效计算。 它返回的是一个 cv::Ptrcv::cuda::Cornernes…

013旅游网站设计技术详解:打造一站式旅游服务平台

旅游网站设计技术详解&#xff1a;打造一站式旅游服务平台 在互联网与旅游业深度融合的时代&#xff0c;旅游网站成为人们规划行程、预订服务的重要工具。一个功能完备的旅游网站&#xff0c;通过用户管理、订单管理等核心模块&#xff0c;实现用户与管理员的高效交互。本文将…

Linux运维笔记:1010实验室电脑资源规范使用指南

文章目录 0. 检查资源使用情况&#xff0c;避免冲突检查在线用户检查 CPU 使用情况检查 GPU 使用情况协作建议 1. 备份重要文件和数据2. 定期清理硬盘空间3. 退出 ThinLinc 时注销&#xff0c;释放内存4. 校外使用时配置 VPN注意事项总结 实验室的电脑配备了 CPU 和 GPU 资源&a…