调用.net DLL让CANoe自动识别串口号
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
相关文章:

调用.net DLL让CANoe自动识别串口号
1.前言 CANoe9.0用CAPL控制数控电源_canoe读取程控电源电流值-CSDN博客 之前做CAPL通过串口控制数控电源,存在一个缺点:更换电脑需要改串口号 CSDN上有类似的博客,不过要收费,本文根据VID和PID来自动获取串口号,代码…...
第5章:Cypher查询语言进阶
在掌握了Cypher的基础知识后,本章将深入探讨更高级的查询技术。这些进阶技能将帮助您构建更复杂、更高效的查询,解决实际业务中的复杂问题,并充分发挥Neo4j的图数据处理能力。 5.1 复杂查询构建 随着业务需求的复杂性增加,查询也…...
【Python进阶】元类编程
目录 🌟 前言🏗️ 技术背景与价值🩹 当前技术痛点🛠️ 解决方案概述👥 目标读者说明 🧠 一、技术原理剖析📊 核心概念图解💡 核心作用讲解🔧 关键技术模块说明⚖️ 技术选…...

算法(蓝桥杯学习C/C++版)
up: 溶金落梧桐 溶金落梧桐的个人空间-溶金落梧桐个人主页-哔哩哔哩视频 蓝桥杯三十天冲刺系列 BV18eQkY3EtP 网站: OI Wiki OI Wiki - OI Wiki 注意 比赛时,devc勾选c11(必看) 必须勾选c11一共有两个方法,任用…...

Docker镜像无法拉取问题解决办法
最近再学习RabbitMQ,需要从Docker镜像中拉取rabbitMQ,但是下拉失败 总的来说就是无法和docker镜像远程仓库建立连接 我又去尝试ping docker.io发现根本没有反应,还是无法连接找了许多办法还是没有办法解决,最后才发现是镜像问题&a…...

ZephyrOS 嵌入式开发Black Pill V1.2之Debug调试器
版本和环境信息如下: PC平台: Windows 11 专业版 Zephyr开发环境:v4.1.0 Windows 下搭建 Zephyr 开发环境 WeAct BlackPill V1.2开发板: WeAct STM32F411CEU6 BlackPill 核心板 Debug调试器: ST-LINK V2: ST-LINK V2 S…...
# 主流大语言模型安全性测试(二):英文越狱提示词下的表现与分析
主流大语言模型安全性测试(二):英文越狱提示词下的表现与分析 在上一篇文章中,我们对多个主流大语言模型(LLM)进行了中文诱导性提示词的越狱测试,评估其是否能够在面对非法、有害或危险内容请求…...
SAP 在 AI 与数据统一平台上的战略转向
在 2025 年 SAP Sapphire 大会上,SAP 展示了其最新的产品战略和技术整合方向,与以往不同的是,今年的讨论更加务实、聚焦客户实际需求。SAP 强调,ERP 的转型不再是“一刀切”或破坏性的,而是可以根据客户现状࿰…...

服务器磁盘空间被Docker容器日志占满处理方法
事发场景: 原本正常的服务停止运行了,查看时MQTT服务链接失败,查看对应的容器服务发现是EMQX镜像停止运行了,重启也是也报错无法正常运行,报错如下图: 报错日志中连续出现两个"no space left on devi…...

c++学习-this指针
1.基本概念 非静态成员函数都会默认传递this指针(静态成员函数属于类本身,不属于某个实例对象),方便访问对象对类成员变量和 成员函数。 2.基本使用 编译器实际处理类成员函数,this是第一个隐藏的参数,类…...

交易所系统攻坚:高并发撮合引擎与合规化金融架构设计
交易所系统攻坚:高并发撮合引擎与合规化金融架构设计 ——2025年数字资产交易平台的性能与合规双轮驱动 一、高并发撮合引擎:从微秒级延迟到百万TPS 核心架构设计 订单簿优化:数据结构创新:基于红黑树与链表混合存储,…...

OpenCV计算机视觉实战(10)——形态学操作详解
OpenCV计算机视觉实战(10)——形态学操作详解 0. 前言1. 腐蚀与膨胀1.1 为什么要做腐蚀与膨胀1.2 OpenCV 实现 2. 开运算与闭运算2.1 开运算与闭运算原理2.2 OpenCV 实现 3. 形态学梯度与骨架提取3.1 形态学梯度3.2 骨架提取 小结系列链接 0. 前言 形态…...
libiec61850 mms协议异步模式
之前项目中使用到libiec61850库,都是服务端开发。这次新的需求要接收服务端的遥测数据,这就涉及到客户端开发了。 客户端开发没搞过啊,挑战不少,但是人不就是通过战胜困难才成长的嘛。通过查看libiec61850的客户端API发现…...

[论文阅读] 人工智能 | 利用负信号蒸馏:用REDI框架提升LLM推理能力
【论文速读】利用负信号蒸馏:用REDI框架提升LLM推理能力 论文信息 arXiv:2505.24850 cs.LG cs.AI cs.CL Harnessing Negative Signals: Reinforcement Distillation from Teacher Data for LLM Reasoning Authors: Shuyao Xu, Cheng Peng, Jiangxuan Long, Weidi…...

基于 NXP + FPGA+Debian 高可靠性工业控制器解决方案
在工业系统开发中,**“稳定”**往往比“先进”更重要。设备一旦部署,生命周期动辄 5~10 年,系统重启或异常恢复成本高昂。 这时候,一套“值得托付”的软硬件组合,就显得尤为关键。 ✅ NXP —— 提供稳定、长期供货的工…...
CSS 选择器全解析:分组选择器/嵌套选择器,从基础到高级
一、CSS 选择器基础:从单个元素到多个元素 CSS 选择器是用来定位 HTML 元素的工具,就像 “元素的地址”。最基础的选择器有: 元素选择器(按标签名定位) css p { color: red; } /* 所有<p>标签 */ div { b…...
uniapp 对接腾讯云IM群公告功能
UniApp 实战:腾讯云IM群公告功能 一、前言 在即时通讯场景中,群公告是信息同步的重要渠道。本文将基于uniapp框架,结合腾讯云IM SDK,详细讲解如何实现群公告的发布、修改、历史记录查询等核心功能。 群公告的数据结构设计权限校…...

垂起固定翼无人机应用及技术分析
一、主要应用行业 1. 能源基础设施巡检 电力巡检:适用于超高压输电线路通道的快速巡查,实时回传数据提升智能运检效率。 油田管道监测:利用长航时特性(1.5-2小时)对大范围管道进行隐患排查,减少人力巡…...
Python Robot Framework【自动化测试框架】简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

vite配置@别名,以及如何让IDE智能提示路经
1.配置路径(vite.config.js) // vite.config.js import { defineConfig } from "vite"; import vue from "vitejs/plugin-vue"; import path from "path";// https://vite.dev/config/ export default defineConfig({server: {port: 8080,},plu…...
c#bitconverter操作,不同变量类型转byte数组
缘起:串口数据传输的基础是byte数组,write(buff,0,num)或者writeline(string),如果是字符串传输就是string变量就可以了,但是在modbus这类hex传递时,就要遇到转换了,拼凑byte数组时需要各种变量的值传递,解…...

【Linux】LInux下第一个程序:进度条
前言: 在前面的文章中我们学习了LInux的基础指令 【Linux】初见,基础指令-CSDN博客【Linux】初见,基础指令(续)-CSDN博客 学习了vim编辑器【Linux】vim编辑器_linux vim insert-CSDN博客 学习了gcc/g【Linux】编译器gc…...

RPA+AI:自动化办公机器人开发指南
RPAAI:自动化办公机器人开发指南 系统化学习人工智能网站(收藏):https://www.captainbed.cn/flu 文章目录 RPAAI:自动化办公机器人开发指南摘要引言技术融合路径1. 传感器层:多模态数据接入2. 决策层&…...
daz3d + PBRSkin (MDL)+ SSS
好的,我们来解释一下 Daz3D 中的 PBRSkin (MDL) Shader。 简单来说,PBRSkin (MDL) 是 Daz Studio 中一种基于物理渲染(PBR)技术、专门用于创建高度逼真人物皮肤效果的着色器(Shader)。 它利用 NVIDIA 的材…...
计算矩阵A和B的乘积
根据矩阵乘法规则,编程计算矩阵的乘积。函数fix_prod_ele()是基本方法编写,函数fix_prod_opt()是优化方法编写。 程序代码 #define N 3 #define M 4 typedef int fix_matrix1[N][M]; typedef int fix_matrix2[M][N]; int fix_prod_ele(f…...

Houdini POP入门学习05 - 物理属性
接下来随着教程学习碰撞部分,当粒子较为复杂或者下载了一些粒子模板进行修改时,会遇到一些较奇怪问题,如粒子穿透等,这些问题实际上可以通过调节参数解决。 hip资源文件:https://download.csdn.net/download/grayrail…...

每日Prompt:双重曝光
提示词 新中式,这幅图像将人体头像轮廓与山水中式建筑融为一体,双重曝光,体现了反思、内心平静以及人与自然相互联系的主题,靛蓝,水墨画,晕染,极简...
sendDefaultImpl call timeout(rocketmq)
rocketmq 连接异常 senddefaultimpl call timeout-腾讯云开发者社区-腾讯云 第一种情况: 修改broker 的配置如下,注意brokerIP1 这个配置必须有,不然 rocketmq-console 显示依然是内网地址 caused by: org.apache.rocketmq.remoting.excep…...

【LLM】多智能体系统 Why Do Multi-Agent LLM Systems Fail?
note 构建一个成功的 MAS,不仅仅是提升底层 LLM 的智能那么简单,它更像是在构建一个组织。如果组织结构、沟通协议、权责分配、质量控制流程设计不当,即使每个成员(智能体)都很“聪明”,整个系统也可能像一…...

CSS 定位:原理 + 场景 + 示例全解析
一. 什么是CSS定位? CSS中的position属性用于设置元素的定位方式,它决定了元素在页面中的"定位行为" 为什么需要定位? 常规布局(如 display: block)适用于主结构 定位适用于浮动按钮,弹出层,粘性标题等场景帮助我们精确控制元素在页面中的位置 二. 定位类型全…...