需要链接这两个库
setupapi
uuid
添加链接库后下面的程序可以直接拷贝运行
终端需要设置为utf8以适应中文
我的环境是mingw+gcc,只要链接库添加好vs也是一样的
windows相关api文档:https://learn.microsoft.com/zh-cn/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertya
- cv即可,相关细节从上面的api文档检索
#include <stdio.h>
#include <windows.h>
#include <setupapi.h>
#include <devguid.h>
#include <regstr.h>
#pragma comment(lib, "setupapi.lib")
void searchSerialPorts()
{
HDEVINFO hDevInfo;
SP_DEVINFO_DATA devInfoData;
DWORD index = 0;
// 获取串口类设备列表
hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, NULL, NULL, DIGCF_PRESENT);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
printf("无法获取串口设备列表\n");
return;
}
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
while (SetupDiEnumDeviceInfo(hDevInfo, index, &devInfoData))
{
char deviceInstanceId[MAX_PATH];
if (SetupDiGetDeviceInstanceIdA(hDevInfo, &devInfoData, deviceInstanceId, sizeof(deviceInstanceId), NULL))
{
printf("设备号:%s\n", deviceInstanceId);
}
char portDetails[256];
if (SetupDiGetDeviceRegistryPropertyA(hDevInfo, &devInfoData, SPDRP_DEVICEDESC, NULL, (PBYTE)portDetails, sizeof(portDetails), NULL))
{
// 将设备描述转换为UTF-8编码
int utf8Len = MultiByteToWideChar(CP_ACP, 0, portDetails, -1, NULL, 0);
wchar_t* wideStr = (wchar_t*)malloc(utf8Len * sizeof(wchar_t));
MultiByteToWideChar(CP_ACP, 0, portDetails, -1, wideStr, utf8Len);
int utf8Size = WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, NULL, 0, NULL, NULL);
char* utf8Str = (char*)malloc(utf8Size);
WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, utf8Str, utf8Size, NULL, NULL);
printf("设备描述:%s\n", utf8Str);
free(wideStr);
free(utf8Str);
}
else
{
printf("无法获取设备描述\n");
}
// 获取串口号
char portName[10];
HKEY hKey = SetupDiOpenDevRegKey(hDevInfo, &devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
if (hKey != INVALID_HANDLE_VALUE)
{
DWORD portNameSize = sizeof(portName);
if (RegQueryValueExA(hKey, "PortName", NULL, NULL, (LPBYTE)portName, &portNameSize) == ERROR_SUCCESS)
{
printf("串口号:%s\n", portName);
}
else
{
printf("无法获取串口号\n");
}
RegCloseKey(hKey);
}
else
{
printf("无法打开注册表键\n");
}
printf("\n");
index++;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
}
int main()
{
searchSerialPorts();
return 0;
}
- 结果正确
- 再贴一个初级的方法,就是挨着打开一个范围的串口号,能打开就是有,不能获取更多设备信息:
void searchSerialPorts()
{
char portName[10];
HANDLE hSerial;
for (int i = 1; i <= 40; i++)
{
sprintf(portName, "COM%d", i);
// 尝试打开串口
hSerial = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hSerial != INVALID_HANDLE_VALUE)
{
printf("找到串口:%s\n", portName);
CloseHandle(hSerial);
}
else
{
// 尝试在串口名称前添加"\\\\.\\"后再次打开
sprintf(portName, "\\\\.\\COM%d", i);
hSerial = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hSerial != INVALID_HANDLE_VALUE)
{
printf("找到串口:%s\n", portName);
CloseHandle(hSerial);
}
}
}
}
-
串口号搜索也可以,就是没有其他信息了
-
另外,一个退出处理:
BOOL WINAPI consoleHandler(DWORD signal)
{
if (signal == CTRL_C_EVENT || signal == CTRL_BREAK_EVENT)
{
// 关闭串口
if (hSerial != INVALID_HANDLE_VALUE)
{
CloseHandle(hSerial);
}
printf("程序已退出\n");
ExitProcess(0);
return TRUE;
}
return FALSE;
}
int main()
{
// 设置控制台信号处理函数
if (!SetConsoleCtrlHandler(consoleHandler, TRUE))
{
printf("无法设置控制台信号处理函数\n");
return -1;
}
}