前言
下面介绍两种方法去搜索WCH串口通过调用CH343PT库接口来实现,第一种方法枚举串口(需打开串口)搜索到PC上插入的WCH串口。第二种搜索WCH串口方法,需要传入串口的端口号字符串参数就可以做到。
方法1:搜索WCH串口(需要打开串口)
使用的CH343PT库的函数接口:
BOOL WINAPI CH343PT_HandleIsCH34x( // 检查已经打开的端口是否为CH341端口
HANDLE iPortHandle ); // 指定已经打开的端口句柄
代码实现:
//搜索WCH串口
VOID SerachWchUARTA()
{
//打开串口
if(!OpenCom())
{
MessageBox(NULL,"打开串口失败!","SearchWchUart",MB_ICONWARNING);
return;
}
//方法1:判断是否为WCH串口
if(CH343PT_HandleIsCH34x(hCom))
SetDlgItemText(AfxMainHwnd,IDC_SerachResult, "当前选中的串口是WCH串口");
else
SetDlgItemText(AfxMainHwnd,IDC_SerachResult, "当前选中的串口不是WCH串口");
//关闭串口
CloseCom();
return;
}
方法2:搜索WCH串口
代码实现:
//搜索WCH串口
VOID SerachWchUARTB()
{
CHAR TempBuf[64] = {0};
INT i,BegainSer,EndSer,Len;
std::string strTemp,strComName;
CHAR ComName[16] = "";
CHAR tempBuf[256] = "";
CHAR buf[256] = "";
//提取设备友好名称中的COM号
GetDlgItemText(AfxMainHwnd,IDC_Com,tempBuf,sizeof(tempBuf));
Len =strlen(tempBuf);
strTemp = tempBuf;
BegainSer = strTemp.find('(');
EndSer = strTemp.find(')');
for(i=0; i<EndSer-BegainSer-1; i++)
{
ComName[i] = tempBuf[BegainSer+1+i];
}
strComName += "\\\\.\\";
strComName += ComName;
//方法2:判断是否为WCH串口
if(CH343PT_NameIsCH34x((PUCHAR)strComName.c_str())) //传入端口号字符串,如:"\\\\.\\COMXX"
SetDlgItemText(AfxMainHwnd,IDC_SerachResult, "当前选中的串口是WCH串口");
else
SetDlgItemText(AfxMainHwnd,IDC_SerachResult, "当前选中的串口不是WCH串口");
return;
}
该方法需要传入COM端口号,且该端口必须未被占用(指未被其它程序打开)。
软件实现
使用VC++6.0创建一个对话框,如下图所示。
点击“搜索WCH串口(方法1)”按钮后输出结果,如下图所示:
点击“搜索WCH串口(方法2)”按钮后输出结果,如下图所示:
代码实现:
//Main.c
#include "Main.h"
#include <Windows.h>
#include <string>
//全局变量
HANDLE hCom; //串口句柄
//获取串口友好名称friendlyName
VOID GetComFriendlyName()
{
INT wImageIdx = 0;
SHORT wItem = 0;
CHAR szBuf[MAX_PATH] = { 0 };
TCHAR szComName[MAX_PATH] = { 0 };
SendDlgItemMessage(AfxMainHwnd,IDC_Com,CB_RESETCONTENT,0,0); //清除组合框列表
HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES); //构建系统存在的所有设备列表
if (hDevInfo == INVALID_HANDLE_VALUE)
{
return;
};
SP_DEVINFO_DATA SpDevInfoData = { 0 };
SpDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &SpDevInfoData); i++)
{
if (!SetupDiGetDeviceRegistryProperty(hDevInfo, &SpDevInfoData, SPDRP_CLASS, NULL, (PBYTE)szBuf, sizeof(szBuf), 0))
{
continue;
}
else
{
if (strcmp(szBuf, "Ports") != 0) //过滤端口,只取COM
{
continue;
}
}
if (SetupDiGetDeviceRegistryProperty(hDevInfo, &SpDevInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)szComName, sizeof(szComName), 0))
{
ComCounts++;
SendDlgItemMessage(AfxMainHwnd,IDC_AllCom,CB_ADDSTRING,0,(LPARAM)szComName); //向组合框中添加获取的设备友好名称
}
}
SendDlgItemMessage(AfxMainHwnd,IDC_AllCom,CB_SETCURSEL,0,0);
if(hDevInfo)
SetupDiDestroyDeviceInfoList(hDevInfo); //释放资源
}
//打开串口
BOOL OpenCom()
{
CHAR TempBuf[64] = {0};
INT i,BegainSer,EndSer,Len;
std::string strTemp,strComName;
CHAR ComName[16] = "";
CHAR tempBuf[256] = "";
CHAR buf[256] = "";
//提取设备友好名称中的COM号
GetDlgItemText(AfxMainHwnd,IDC_Com,tempBuf,sizeof(tempBuf));
Len =strlen(tempBuf);
strTemp = tempBuf;
BegainSer = strTemp.find('(');
EndSer = strTemp.find(')');
for(i=0; i<EndSer-BegainSer-1; i++)
{
ComName[i] = tempBuf[BegainSer+1+i];
}
strComName += "\\\\.\\";
strComName += ComName;
hCom = CreateFile((LPCTSTR)strComName.c_str(),GENERIC_READ|GENERIC_WRITE,
0,NULL,OPEN_EXISTING,
NULL,
NULL);
if(hCom == INVALID_HANDLE_VALUE)
{
return FALSE;
}
return TRUE;
}
//关闭串口
BOOL CloseCom()
{
if (INVALID_HANDLE_VALUE != hCom)
{
CloseHandle(hCom);
hCom = INVALID_HANDLE_VALUE;
}
return TRUE;
}
//方法1:判断是否为WCH串口
VOID SerachWchUARTA()
{
//打开串口
if(!OpenCom())
{
MessageBox(AfxMainHwnd,"打开串口失败!","SearchWchUart",MB_ICONWARNING);
return;
}
//方法1:判断是否为WCH串口
if(CH343PT_HandleIsCH34x(hCom))
SetDlgItemText(AfxMainHwnd,IDC_SerachResult, "当前选中的串口是WCH串口");
else
SetDlgItemText(AfxMainHwnd,IDC_SerachResult, "当前选中的串口不是WCH串口");
//关闭串口
CloseCom();
return;
}
//方法2:判断是否为WCH串口
VOID SerachWchUARTB()
{
CHAR TempBuf[64] = {0};
INT i,BegainSer,EndSer,Len;
std::string strTemp,strComName;
CHAR ComName[16] = "";
CHAR tempBuf[256] = "";
CHAR buf[256] = "";
//提取设备友好名称中的COM号
GetDlgItemText(AfxMainHwnd,IDC_Com,tempBuf,sizeof(tempBuf));
Len =strlen(tempBuf);
strTemp = tempBuf;
BegainSer = strTemp.find('(');
EndSer = strTemp.find(')');
for(i=0; i<EndSer-BegainSer-1; i++)
{
ComName[i] = tempBuf[BegainSer+1+i];
}
strComName += "\\\\.\\";
strComName += ComName;
//方法2:判断是否为WCH串口
if(CH343PT_NameIsCH34x((PUCHAR)strComName.c_str()))
SetDlgItemText(AfxMainHwnd,IDC_SerachResult, "当前选中的串口是WCH串口");
else
SetDlgItemText(AfxMainHwnd,IDC_SerachResult, "当前选中的串口不是WCH串口");
return;
}
//应用程序入口
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
return DialogBox(hInstance, (LPCTSTR)IDD_MainWnd, 0, (DLGPROC)WndProc);
}
//主窗体进程
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
switch (message)
{
case WM_INITDIALOG:
{
AfxMainHwnd = hWnd;
HICON hicon;
hicon = (HICON)LoadIcon(AfxMainIns,(LPCTSTR)IDI_Main);
PostMessage(AfxMainHwnd,WM_SETICON,ICON_BIG,(LPARAM)(HICON)hicon);
PostMessage(AfxMainHwnd,WM_SETICON,ICON_SMALL,(LPARAM)(HICON)hicon);
//串口初始化
GetComFriendlyName();
}
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
case IDC_SearchWchUartA:
SerachWchUARTA();
break;
case IDC_SearchWchUartB:
SerachWchUARTB();
break;
case WM_DESTROY:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return 0;
}
总结
可以通过上述两种方法来确定所选的串口是否为WCH串口,前提要安装VCP驱动才可以使用,使用上述两种方法可以过滤WCH串口,从而方便串口的后续操作。