<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">* Windows自动识别串口的实现,以下是基于MFC开发的,以下所说都是建立在串口注册表上说的</span>
*实现Windows系统下自动识别串口需要调用三个Windows API函数,它们是:
//主要用于打开串口
1. LONG RegOpenKeyEx( <span style="white-space:pre"> </span> HKEY hKey,<span style="white-space:pre"> </span>//主键,即串口信息存放的文件夹 <span style="white-space:pre"> </span> LPCTSTR lpSubKey,<span style="white-space:pre"> </span>//子键,串口所在的具体文件夹 <span style="white-space:pre"> </span> DWORD ulOptions,<span style="white-space:pre"> </span>//保留值,不用管,必须设置为0 REGSAM samDesired,<span style="white-space:pre"> </span>//访问权限 PHKEY phkResult<span style="white-space:pre"> </span>//返回的串口句柄,以下两个函数使用 <span style="white-space:pre"> </span> );
//主要用于获得在当前串口注册表中有多少个串口
2. LONG RegQueryInfoKey( <span style="white-space:pre"> </span>HKEY hKey,<span style="white-space:pre"> </span>//RegOpenKeyEx的五个参数返回的子键句柄 <span style="white-space:pre"> </span>LPTSTR lpClass,<span style="white-space:pre"> </span>//NULL <span style="white-space:pre"> </span>LPDWORD lpcClass,<span style="white-space:pre"> </span>//NULL <span style="white-space:pre"> </span>LPDWORD lpReserved,<span style="white-space:pre"> </span>//NULL <span style="white-space:pre"> </span>LPDWORD lpcSubKeys,<span style="white-space:pre"> </span>//子键的数量 <span style="white-space:pre"> </span>LPDWORD lpcMaxSubKeyLen,<span style="white-space:pre"> </span>//最大子键的长度 <span style="white-space:pre"> </span>LPDWORD lpcMaxClassLen,<span style="white-space:pre"> </span>//NULL <span style="white-space:pre"> </span>LPDWORD lpcValues,<span style="white-space:pre"> </span>//串口的数量 <span style="white-space:pre"> </span>LPDWORD lpcMaxValueNameLen,<span style="white-space:pre"> </span>//最大值名的长度 <span style="white-space:pre"> </span>LPDWORD lpcMaxValueLen,<span style="white-space:pre"> </span>//最大串口的长度 <span style="white-space:pre"> </span>LPDWORD lpcbSecurityDescriptor,<span style="white-space:pre"> </span>//NULL <span style="white-space:pre"> </span>PFILETIME lpftLastWriteTime<span style="white-space:pre"> </span>//NULL <span style="white-space:pre"> </span>);
//主要用于获得串口名,如"COM3"等
3. LONG RegEnumValue( <span style="white-space:pre"> </span> HKEY hKey,<span style="white-space:pre"> </span>//串口子键句柄 <span style="white-space:pre"> </span> DWORD dwIndex,<span style="white-space:pre"> </span>//在注册表中的索引 <span style="white-space:pre"> </span> LPTSTR lpValueName,<span style="white-space:pre"> </span>//值名 <span style="white-space:pre"> </span> LPDWORD lpcValueName,<span style="white-space:pre"> </span>//值名的长度 <span style="white-space:pre"> </span> LPDWORD lpReserved,<span style="white-space:pre"> </span>//NULL <span style="white-space:pre"> </span> LPDWORD lpType,<span style="white-space:pre"> </span>//串口的数据类型 <span style="white-space:pre"> </span> LPBYTE lpData,<span style="white-space:pre"> </span>//串口名 <span style="white-space:pre"> </span> LPDWORD lpcbData<span style="white-space:pre"> </span>//串口名的长度 <span style="white-space:pre"> </span> );
自动识别串口的实现:
struct UartInfo { DWORD UartNum; WCHAR UartName[20]; }; //获取串口列表 BOOL EnumComs(struct UartInfo **UartCom, LPDWORD UartComNumber, CnuprogDlg *pMainDlg) { //LPCTSTR 即const char * *UartComNumber = 0; HKEY hNewKey; LONG lResult=RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_ALL_ACCESS, &hNewKey); if(lResult != ERROR_SUCCESS) { pMainDlg->AddToInfOut(_T("打开COM注册表失败!!!"),1,1); return FALSE; } else { pMainDlg->AddToInfOut(_T("打开COM注册表成功!!!"),1,1); } //DWORD即unsigned long DWORD ValuesNumber; DWORD MaxValueNameLen; DWORD MaxValueLen; CString str; //检索指定的子键下有多少个值项 lResult = RegQueryInfoKey( hNewKey, NULL, NULL, NULL, NULL, NULL, NULL, &ValuesNumber, &MaxValueNameLen, &MaxValueLen, NULL, NULL ); if(lResult != ERROR_SUCCESS) { RegCloseKey(hNewKey); //pMainDlg->AddToInfOut(_T("检索连接在PC上的串口数量失败!!!"),1,1); return FALSE; } else { // str.Format(_T("连接在PC上的串口数量是:%ld"), ValuesNumber); // pMainDlg->AddToInfOut(str,1,1); *UartCom =(struct UartInfo *)malloc( ValuesNumber * sizeof(struct UartInfo)); } DWORD index; DWORD uartindex = 0; //CHAR ValueName[MAX_VALUE_NAME]; WCHAR ValueName[100]; //DWORD ValueNameSize = MAX_VALUE_NAME; DWORD ValueNameSize; DWORD DataType; BYTE DataBuffer[100]; DWORD DataLen = 100; //LPTSTR 即 char *, LPBYTE即 char * //检索每个值项,获取值名,数据类型,数据 for(index = 0; index < ValuesNumber; index++) { memset(ValueName, 0, sizeof(ValueName)); memset(DataBuffer, 0, sizeof(DataBuffer)); ValueNameSize = 100; DataLen = 100; lResult = RegEnumValue(hNewKey,index,ValueName,&ValueNameSize,NULL, &DataType, DataBuffer, &DataLen); if (lResult == ERROR_SUCCESS ) { switch(DataType) { case REG_NONE: // No value type (0) break; case REG_SZ: //Unicode nul terminated string (1) break; case REG_EXPAND_SZ: // Unicode nul terminated string (2) break; case REG_BINARY: // Free form binary (3) break; case REG_DWORD: // 32-bit number (4) break; case REG_MULTI_SZ: // Multiple Unicode strings (7) break; default: break; } memcpy((*UartCom)[uartindex].UartName, DataBuffer, DataLen); (*UartCom)[uartindex].UartNum = ValuesNumber; uartindex++; } else if(lResult == ERROR_NO_MORE_ITEMS) { //pMainDlg->AddToInfOut(_T("检索串口完毕!!!"),1,1); } else { DWORD dw = GetLastError(); // str.Format(_T("检索串口出错: 0x%08x"), dw); // pMainDlg->AddToInfOut(str,1,1); return FALSE; } } *UartComNumber = uartindex; return TRUE; }
在主函数中的调用:
DWORD UartComNumber = 0; struct UartInfo *pUartCom; BOOL bResult; bResult = EnumComs(&pUartCom, &UartComNumber, pMainDlg); DWORD index; if(bResult) { pMainDlg->AddToInfOut(_T("获取串口列表成功"),1,1); } else { pMainDlg->AddToInfOut(_T("获取串口列表失败"),1,1); } for( index= 0;index < UartComNumber; index++) { pMainDlg->m_ComboBox.AddString(pUartCom[index].UartName); }