首页 > 代码库 > Windows自动识别串口的实现

Windows自动识别串口的实现

<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);
	}




Windows自动识别串口的实现