CANoe不能自动识别串口号?那就封装个DLL让它必须行

Posted 蚂蚁小兵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CANoe不能自动识别串口号?那就封装个DLL让它必须行相关的知识,希望对你有一定的参考价值。

📘前言

  • 🍅 比如程控电源,每个同事都需要,但是工程是同一个,那么每个同事在运行工程前,都要选择不同的串口,这就很麻烦,能否让CANoe自动识别程控电源连接在电脑上的串口号呢

  • 🍅 CAPL操作串口的内置函数是无法自动识别串口号,经过查找资料,调用Windows 的设备 API是可以实现的,那么就想到了封装个DLL,在CANoe中调用DLL去实现目的。

  • 🍅 演示软硬件环境 Win10 x64CANoe 11 SP2 x64Visual Studio 2019

目录

📙 C++调试工程

1️⃣ 老规矩,封装DLL之前咱先新建一个控制台工程用来调试代码


2️⃣ 下图,是我电脑上连着的COM

  • 其中程控电源连接到电脑上的描述是 USB Serial Device (COMxx),那么 我就可以通过 关键字符串 USB Serial Device来实现筛选,从而返回COM号


3️⃣ 全部代码,如下:

// PrintDeviceInfo.cpp : 定义控制台应用程序的入口点。
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <Windows.h>
#include <setupapi.h>
#pragma comment(lib, "setupapi.lib")



int getSpecialComNum(const char* s, const char* t)

	char n = t[0];
	int l ,i,j, sourlen, tarlen;
	char temp[200] =  0 ;
	char out[200] =  0 ;

	sourlen = strlen(s);
	tarlen = strlen(t);


	for (i = 0; i < sourlen - tarlen + 1; i++)
	
		for (j = 0; j < tarlen; j++)
		

			if (s[i + j] != t[j])
			
				break;
			
		
		if (j == tarlen)
		

			return i+7; //find it
		
	
return -1;


//从设备信息中 获取特定串口号  @return <=0无效
int  getSpecialComNumFromDevInfo(char ComList[][200] ,  const char* SpecialCom ,int *ComNum)

	HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
	if (hDevInfo == INVALID_HANDLE_VALUE)
	
		printf("SetupDiGetClassDevs Err:%d", GetLastError());
		return -2;
	;

	SP_CLASSIMAGELIST_DATA _spImageData =  0 ;
	_spImageData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
	SetupDiGetClassImageList(&_spImageData);

	SP_DEVINFO_DATA spDevInfoData =  0 ;
	spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	int k;
	k = 0;

	for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
	
		char  szBuf[MAX_PATH] =  0 ;
		int  wImageIdx = 0;
		short  wItem = 0;
		char szBuf_byteToChar[256] =  0 ;
		int j;
		
		if (!SetupDiGetDeviceRegistryPropertyA(hDevInfo, &spDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, MAX_PATH, 0))
		
			continue;
		;
		if (strcmp(szBuf, "Ports") != 0) //只取端口
					
			continue;
		
		
		//printf("Class1:%s\\r\\n", szBuf);
		if (SetupDiGetClassImageIndex(&_spImageData, &spDevInfoData.ClassGuid, &wImageIdx))
		
			char  szName[MAX_PATH] =  0 ;
			DWORD  dwRequireSize;

			if (!SetupDiGetClassDescription(&spDevInfoData.ClassGuid, (PWSTR)szBuf, MAX_PATH, &dwRequireSize))
			
				continue;
			;
			//wprintf(L"Class:%s\\r\\n", szBuf);

			if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
			
				//wprintf(L"FriendlyName:%s\\r\\n\\r\\n", szName);

				sprintf_s(szBuf_byteToChar, "");
				for (j = 0; j < sizeof(szName); j++)
				
					sprintf_s(szBuf_byteToChar, "%s%c", szBuf_byteToChar, szName[j]);
				
			
				strcpy_s(ComList[k], szBuf_byteToChar);
				int comNum = getSpecialComNum(szBuf_byteToChar, SpecialCom);

				//wprintf(L"comNum:%s\\r\\n\\r\\n", comNum);
				k++;
				*ComNum = k;
				if (comNum > 0)
				
					return comNum;
				
			
			else  if (SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, SPDRP_DEVICEDESC, NULL, (PBYTE)szName, MAX_PATH - 1, 0))
			
				wprintf(L"Device:%s\\r\\n\\r\\n", szName);
			
		
	
	SetupDiDestroyClassImageList(&_spImageData);
	return -1;


int  main(int  argc, char* argv[])


	char comList[50][200];
	char SpecialCom[100] = "USB Serial Device";
	int serialPortsNum;


	//printf("Locale is: %s\\n", setlocale(LC_ALL, "chs"));
	printf("根据描述 %s,查找的串口号:%d\\n", SpecialCom,getSpecialComNumFromDevInfo(comList, SpecialCom, &serialPortsNum));
	printf("串口号数量: %d\\n", serialPortsNum);
	for (int i = 0; i < serialPortsNum; i++)
	
		printf("%d: %s\\n", i,comList[i]);
	
	//PrintDevicesInfo2();
	getchar();
	return  0;


4️⃣ Debug 下工程看下结果,返回了我们想要的结果


📙 封装成DLL


📙 CANoe 调用DLL 演示

1️⃣ 新建个NetWork Module Node


2️⃣ can 脚本种的代码如下,:

核心函数:dllGetSeriesPorts(comList,SpecialComDescribtion,serialPortsNum);

  • comList :返回的所有的Port口的描述
  • SpecialComDescribtion: 输入参数,选择指定Port口的描述, 比如 程控电源的COM描述是USB Serial Device
  • serialPortsNum : 输入参数,返回所有Ports 口的统计数
/*@!Encoding:936*/
includes

  #pragma library("autoSerialPort.dll") 



int connectSerialPort(char  SpecialComDescribtion[])

 	char comList[50][200];	
	long serialPortsNum;
  long retCom;
  int i ,RetVal;
  
  retCom =  dllGetSeriesPorts(comList,SpecialComDescribtion,serialPortsNum);
    
  write("Return COM Port:%d",retCom);
  
  write("Total COM Ports Number:%d",serialPortsNum);
  
  for ( i = 0; i < serialPortsNum; i++)
	
		write("%d: %s", i,comList[i]);
	
  RetVal = RS232Open(retCom);
  
  if (RetVal == 1 )
    write("Open port %d Ok.",retCom);
  else
    write("Open port %d failed.",retCom);
  
  RetVal = RS232Configure(retCom,9600,8,1,0 ); 

    if (RetVal == 1 )
    write("Configure port %d Ok.",retCom);
  else
    write("Configure port %d failed.",retCom);
  
 return RetVal;


on key 'k'

  connectSerialPort("USB Serial Device");




3️⃣ 测试结果如下,实现目的

End

🌎总结


  • 🚩要有最朴素的生活,最遥远的梦想,即使明天天寒地冻,路遥马亡!

  • 🚩 有微信的小伙伴可以关注下浪哥车载诊断,一个行业内小小圈子,群里有网盘资料源码还有各路大神 闲时交流交流技术,聊聊工作机会啥的。

  • 🚩如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。

以上是关于CANoe不能自动识别串口号?那就封装个DLL让它必须行的主要内容,如果未能解决你的问题,请参考以下文章

CANoe DLL编程—— Visual Studio 创建DLL以及动态调用

CANoe DLL编程——SendKey DLL的CANoe应用

CANoe DLL编程—— 创建CANoe适用的DLL以及调用

CANoe DLL编程——通过VS 生成 SendKey.dll

CANoe DLL编程——DLL和回调函数

c 获取串口号 c 自动获取串口号