winCE中实现虚拟串口的方法

转载请标明是引用于 http://blog.csdn.net/chenyujing1234 

欢迎大家拍砖!

 

环境:wince6.0+ARM+Freescell

 

一、目的

设计一个读GPS串口数据的驱动,并注册为COM口。

二、实现过程

1、COM_Init

注册表中读出GPS COM口号及是否Debug,创建共享数据区,创建读取数据的线程,打开GPS真实的COM口;

开一线程MonitorCommEventProc读取GPS口数据,并用DecodeGpsBuf解析读取到的数据。

这里注意在WinCE驱动中的XXX_Init中的入口参数DWORD dwContext通过

LPCTSTR regKeyPath = (LPCTSTR)dwContext;HKEY hKey = OpenDeviceKey(regKeyPath);可以转化为其所在驱动的.reg注册的HKEY。

 

  1. DWORD COM_Init(DWORD dwContext)     
  2. {     
  3.     DWORD dwPare,dwReturn;  
  4.     LPCTSTR regKeyPath = (LPCTSTR)dwContext;  
  5.     HKEY hKey = OpenDeviceKey(regKeyPath);  
  6.   
  7.     DWORD size = 4;  
  8.     DWORD index;  
  9.   
  10.     MyPDebugStringW(L"Enter Com_Init");  
  11.     if ( hKey == NULL )  
  12.     {  
  13.         MyPDebugStringW(L"Fun:%s; hKey == NULL", __FUNCTIONW__);  
  14.         //return NULL;   
  15.     }  
  16.     if (ERROR_SUCCESS != RegQueryValueEx(hKey,_T("GpsCom"), 0, NULL, (LPBYTE)&g_GsmPort, &size))  
  17.     {  
  18.     //  RETAILMSG(TRUE,(TEXT("We get original com index :%d ......\r\n"),g_GsmPort));   
  19.     }  
  20.     if (ERROR_SUCCESS != RegQueryValueEx(hKey,_T("Dbg"), 0, NULL, (LPBYTE)&g_bDbg, &size))  
  21.     {  
  22.     //  RETAILMSG(TRUE,(TEXT("We get original com index :%d ......\r\n"),g_GsmPort));   
  23.     }  
  24. #if 0   
  25.     if (ERROR_SUCCESS != RegQueryValueEx(hKey,_T("Index"), 0, NULL, (LPBYTE)&index, &size))  
  26.     {  
  27.         RegCloseKey(hKey);  
  28.         return NULL;  
  29.     }  
  30.   
  31.     GetFromVirtalRegistry((BYTE *)&g_GsmPort,&size, NULL, HKEY_LOCAL_MACHINE, _T("virtalSerial"), _T("Index"));  
  32. #endif   
  33.     RegCloseKey(hKey);  
  34.   
  35.     MyPDebugStringW(L"The apply port is com%d", g_GsmPort);  
  36.     InitializeCriticalSection(&g_csOpen);     
  37.     InitializeCriticalSection(&g_csRead);     
  38.     InitializeCriticalSection(&g_csWrite);     
  39.       
  40.     g_dwWM_PEKSUNNY  = RegisterWindowMessage(L"WM_PEKSUNNY");  
  41.     if(!g_hEventComm)  
  42.         g_hEventComm = CreateEvent(NULL,TRUE,FALSE,NULL);     
  43.   
  44. #if 0   
  45.     //给GSM模块上电   
  46.     dwPare=(0<<16)|(21<<8)|(1);  
  47.     KernelIoControl(IOCTL_HAL_SET_GPIO_HIGH_LOW,&dwPare,sizeof(DWORD),NULL,0,&dwReturn);  
  48.     dwPare=(0<<16)|(26<<8)|(1);  
  49.     KernelIoControl(IOCTL_HAL_SET_GPIO_HIGH_LOW,&dwPare,sizeof(DWORD),NULL,0,&dwReturn);  
  50. #endif   
  51.     g_pGpsDataMem = (PGPSDATA)ReadShareArea();  
  52.   
  53.     g_pGpsDataMem->iSatNum = 67;  
  54.   
  55.     return OpenTransmitThr();  
  56.     
  57. }     
DWORD COM_Init(DWORD dwContext)   
{   
	DWORD dwPare,dwReturn;
	LPCTSTR regKeyPath = (LPCTSTR)dwContext;
	HKEY hKey = OpenDeviceKey(regKeyPath);

	DWORD size = 4;
	DWORD index;

	MyPDebugStringW(L"Enter Com_Init");
	if ( hKey == NULL )
	{
		MyPDebugStringW(L"Fun:%s; hKey == NULL", __FUNCTIONW__);
		//return NULL;
	}
	if (ERROR_SUCCESS != RegQueryValueEx(hKey,_T("GpsCom"), 0, NULL, (LPBYTE)&g_GsmPort, &size))
	{
	//	RETAILMSG(TRUE,(TEXT("We get original com index :%d ......\r\n"),g_GsmPort));
	}
	if (ERROR_SUCCESS != RegQueryValueEx(hKey,_T("Dbg"), 0, NULL, (LPBYTE)&g_bDbg, &size))
	{
	//	RETAILMSG(TRUE,(TEXT("We get original com index :%d ......\r\n"),g_GsmPort));
	}
#if 0
	if (ERROR_SUCCESS != RegQueryValueEx(hKey,_T("Index"), 0, NULL, (LPBYTE)&index, &size))
	{
		RegCloseKey(hKey);
		return NULL;
	}

	GetFromVirtalRegistry((BYTE *)&g_GsmPort,&size, NULL, HKEY_LOCAL_MACHINE, _T("virtalSerial"), _T("Index"));
#endif
	RegCloseKey(hKey);

	MyPDebugStringW(L"The apply port is com%d", g_GsmPort);
	InitializeCriticalSection(&g_csOpen);   
	InitializeCriticalSection(&g_csRead);   
	InitializeCriticalSection(&g_csWrite);   
	
	g_dwWM_PEKSUNNY  = RegisterWindowMessage(L"WM_PEKSUNNY");
	if(!g_hEventComm)
		g_hEventComm = CreateEvent(NULL,TRUE,FALSE,NULL);   

#if 0
	//给GSM模块上电
	dwPare=(0<<16)|(21<<8)|(1);
	KernelIoControl(IOCTL_HAL_SET_GPIO_HIGH_LOW,&dwPare,sizeof(DWORD),NULL,0,&dwReturn);
	dwPare=(0<<16)|(26<<8)|(1);
	KernelIoControl(IOCTL_HAL_SET_GPIO_HIGH_LOW,&dwPare,sizeof(DWORD),NULL,0,&dwReturn);
#endif
	g_pGpsDataMem = (PGPSDATA)ReadShareArea();

	g_pGpsDataMem->iSatNum = 67;

	return OpenTransmitThr();
  
}   
  1. BOOL OpenTransmitThr()  
  2. {  
  3.     TCHAR szPort[12];  
  4.     swprintf(szPort, L"COM%u:", g_GsmPort);  
  5.   
  6.     g_hCom = CreateFile(szPort, GENERIC_READ | GENERIC_WRITE , 0, NULL, OPEN_EXISTING, 0, NULL);  
  7.     if(g_hCom == INVALID_HANDLE_VALUE )     
  8.     {     
  9.         MyPDebugStringW(L"Fun:%s; CreateFile %s failed", __FUNCTIONW__, szPort);    
  10.         return FALSE;     
  11.     }     
  12.     else    
  13.     {     
  14.         MyPDebugStringW(L"Fun:%s; CreateFile %s success", __FUNCTIONW__, szPort);     
  15.     }   
  16.   
  17. #if 1   
  18.     if(!InitComDcb(g_hCom,CBR_9600))  
  19.     {  
  20.         MyPDebugStringW(L"Fun:%s; Line:%d; InitComDcb failed", __FUNCTIONW__, __LINE__);  
  21.     }  
  22.         //goto SET_SUCCEED_FLAG;   
  23.     if(!InitComTimeOuts(g_hCom))  
  24.     {  
  25.         MyPDebugStringW(L"Fun:%s; Line:%d; InitComTimeOuts failed", __FUNCTIONW__, __LINE__);  
  26.     }  
  27.         //goto SET_SUCCEED_FLAG;   
  28.     SetupComm(g_hCom, 1024,1024);  
  29.     PurgeComm(g_hCom, PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_RXABORT|PURGE_TXABORT);  
  30.   
  31.     //设置端口上指定信号的状态   
  32.     // SETDTR: 发送DTR (data terminal ready)信号   
  33.     // SETRTS: 发送RTS (request to send)信号   
  34.     EscapeCommFunction(g_hCom,SETDTR);  
  35.     EscapeCommFunction(g_hCom,SETRTS);  
  36. #endif   
  37.   
  38.     InterlockedExchange((LPLONG)(&g_bExitMonitorProc),FALSE);     
  39.     g_hReadThread =CreateThread(NULL,NULL,MonitorCommEventProc,NULL,NULL,NULL);   
  40.     return TRUE;  
  41. }  
BOOL OpenTransmitThr()
{
	TCHAR szPort[12];
	swprintf(szPort, L"COM%u:", g_GsmPort);

	g_hCom = CreateFile(szPort, GENERIC_READ | GENERIC_WRITE , 0, NULL, OPEN_EXISTING, 0, NULL);
	if(g_hCom == INVALID_HANDLE_VALUE )   
	{   
		MyPDebugStringW(L"Fun:%s; CreateFile %s failed", __FUNCTIONW__, szPort);  
		return FALSE;   
	}   
	else  
	{   
		MyPDebugStringW(L"Fun:%s; CreateFile %s success", __FUNCTIONW__, szPort);   
	} 

#if 1
	if(!InitComDcb(g_hCom,CBR_9600))
	{
		MyPDebugStringW(L"Fun:%s; Line:%d; InitComDcb failed", __FUNCTIONW__, __LINE__);
	}
		//goto SET_SUCCEED_FLAG;
	if(!InitComTimeOuts(g_hCom))
	{
		MyPDebugStringW(L"Fun:%s; Line:%d; InitComTimeOuts failed", __FUNCTIONW__, __LINE__);
	}
		//goto SET_SUCCEED_FLAG;
	SetupComm(g_hCom, 1024,1024);
	PurgeComm(g_hCom, PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_RXABORT|PURGE_TXABORT);

	//设置端口上指定信号的状态
	// SETDTR: 发送DTR (data terminal ready)信号
	// SETRTS: 发送RTS (request to send)信号
	EscapeCommFunction(g_hCom,SETDTR);
	EscapeCommFunction(g_hCom,SETRTS);
#endif

	InterlockedExchange((LPLONG)(&g_bExitMonitorProc),FALSE);   
	g_hReadThread =CreateThread(NULL,NULL,MonitorCommEventProc,NULL,NULL,NULL); 
	return TRUE;
}



 

  1. DWORD MonitorCommEventProc(LPVOID pParam)     
  2. {     
  3.     TCHAR wcDebug[1024] = {0};  
  4.   
  5.     MyPDebugStringW(L"Enter MonitorCommEventProc");  
  6.     SetCommMask(g_hCom, EV_RXCHAR);  
  7.     while(!g_bExitMonitorProc)     
  8.     {      
  9.         DWORD   dwErrorFlags;  
  10.         COMSTAT ComStat;  
  11.         DWORD dwLength;  
  12.         DWORD dwEvtMask = 0;     
  13.         DWORD dwRead = 0;  
  14.   
  15.         BOOL bWaitRes = WaitCommEvent(g_hCom, &dwEvtMask, NULL);   
  16.         //      RETAILMSG(TRUE,(TEXT("VSP comm event come %d ,last set is %d\r\n"),dwEvtMask,g_dwWaitMask));   
  17.         //MyPDebugStringW(L"Gps com has event come up");   
  18.         if(dwEvtMask==0)  
  19.         {  
  20.             //wait error   
  21.             Sleep(30);  
  22.   
  23.             if(g_dwWaitMask)  
  24.             {  
  25.                 continue//Last set is not null,give up,because exit read thread need null event   
  26.             }  
  27.         }  
  28.   
  29.         if(bWaitRes == FALSE)     
  30.         {     
  31.             continue;     
  32.         }       
  33.   
  34.         if(dwEvtMask & EV_RXCHAR)     
  35.         {     
  36.             Sleep(20);  
  37.   
  38.             EnterCriticalSection(&g_csRead);      
  39.   
  40.             ClearCommError(g_hCom,&dwErrorFlags,&ComStat);  
  41.             dwLength=ComStat.cbInQue;  
  42.   
  43.             if(/*dwLength>0*/1)  
  44.             {  
  45.                 ZeroMemory(g_vtBufRead, sizeof(g_vtBufRead));  
  46.                 ReadFile(g_hCom, &g_vtBufRead, sizeof(g_vtBufRead), &dwRead, NULL);  
  47.   
  48.                 mbstowcs(wcDebug,  (char*)g_vtBufRead, strlen((char*)g_vtBufRead));  
  49.             //  OutputErrorInfo(L"Read data:%s\r\n", wcDebug);   
  50.             //  DecodeGpsNema((char*)g_vtBufRead);   
  51.                 DecodeGpsBuf((char*)g_vtBufRead);  
  52.   
  53.                 g_dwLenReadBuf=dwRead;  
  54.   
  55.                 if(g_pChanle1)  
  56.                 {  
  57.                     g_pChanle1->iIndex = 0;  
  58.                     g_pChanle1->iTolLen = dwRead;  
  59.                     memcpy(g_pChanle1->cReadBuf,g_vtBufRead,dwRead);  
  60.                 }  
  61.                 if(g_pChanle2)  
  62.                 {  
  63.                     g_pChanle2->iIndex = 0;  
  64.                     g_pChanle2->iTolLen = dwRead;  
  65.                     memcpy(g_pChanle2->cReadBuf,g_vtBufRead,dwRead);  
  66.                 }  
  67.                 if(g_pChanle3)  
  68.                 {  
  69.                     g_pChanle3->iIndex = 0;  
  70.                     g_pChanle3->iTolLen = dwRead;  
  71.                     memcpy(g_pChanle3->cReadBuf,g_vtBufRead,dwRead);  
  72.                 }  
  73.   
  74.             }  
  75.             else  
  76.             {  
  77.                 RETAILMSG(g_bDbg,(L"[VSP]:ClearCommError(%d): dwLength is 0,continue ......\r\n",dwErrorFlags));  
  78.                 //  LeaveCriticalSection(&g_csRead);   
  79.                 //  continue;   
  80.             }  
  81.   
  82.             LeaveCriticalSection(&g_csRead);     
  83.         }     
  84. #if 0   
  85.         //if(dwEvtMask == EV_RXCHAR && ((g_dwWaitMask & EV_RXCHAR) == 0 || dwRead == 0))      
  86.         if(dwEvtMask == EV_RXCHAR && ((g_dwWaitMask & EV_RXCHAR) == 0 ))     
  87.         {     
  88.             //The return event mask is only EV_RXCHAR and there is not EV_RXCHAR in the wait mask.      
  89.             RETAILMSG(g_bDbg,(L"Skip send event C......\r\n"));  
  90.             continue;     
  91.         }     
  92. #endif   
  93.         InterlockedExchange((LPLONG)(&g_dwEvtMask),dwEvtMask);     
  94.         PulseEvent(g_hEventComm);  
  95.         //  RETAILMSG(TRUE,(TEXT("PulseEvent %d\r\n"),g_dwEvtMask));   
  96.   
  97.         //Sleep for other thread to respond to the event      
  98.         //  Sleep(100);      
  99.         Sleep(20);   
  100.   
  101.         DEBUGMSG(g_bDbg,(TEXT("[VSP]:PulseEvent! The event-mask is 0x%x\r\n"),dwEvtMask));      
  102.   
  103.     }     
  104.   
  105.     MyPDebugStringW(L"Fun:%s; over MonitorCommEventProc", __FUNCTIONW__);  
  106.   
  107.     return 0;     
  108. }     
DWORD MonitorCommEventProc(LPVOID pParam)   
{   
	TCHAR wcDebug[1024] = {0};

	MyPDebugStringW(L"Enter MonitorCommEventProc");
	SetCommMask(g_hCom, EV_RXCHAR);
	while(!g_bExitMonitorProc)   
	{    
		DWORD   dwErrorFlags;
		COMSTAT ComStat;
		DWORD dwLength;
		DWORD dwEvtMask = 0;   
		DWORD dwRead = 0;

		BOOL bWaitRes = WaitCommEvent(g_hCom, &dwEvtMask, NULL); 
		//		RETAILMSG(TRUE,(TEXT("VSP comm event come %d ,last set is %d\r\n"),dwEvtMask,g_dwWaitMask));
		//MyPDebugStringW(L"Gps com has event come up");
		if(dwEvtMask==0)
		{
			//wait error
			Sleep(30);

			if(g_dwWaitMask)
			{
				continue; //Last set is not null,give up,because exit read thread need null event
			}
		}

		if(bWaitRes == FALSE)   
		{   
			continue;   
		}     

		if(dwEvtMask & EV_RXCHAR)   
		{   
			Sleep(20);

			EnterCriticalSection(&g_csRead);    

			ClearCommError(g_hCom,&dwErrorFlags,&ComStat);
			dwLength=ComStat.cbInQue;

			if(/*dwLength>0*/1)
			{
				ZeroMemory(g_vtBufRead, sizeof(g_vtBufRead));
				ReadFile(g_hCom, &g_vtBufRead, sizeof(g_vtBufRead), &dwRead, NULL);

			 	mbstowcs(wcDebug,  (char*)g_vtBufRead, strlen((char*)g_vtBufRead));
			//	OutputErrorInfo(L"Read data:%s\r\n", wcDebug);
			//	DecodeGpsNema((char*)g_vtBufRead);
				DecodeGpsBuf((char*)g_vtBufRead);

				g_dwLenReadBuf=dwRead;

				if(g_pChanle1)
				{
					g_pChanle1->iIndex = 0;
					g_pChanle1->iTolLen = dwRead;
					memcpy(g_pChanle1->cReadBuf,g_vtBufRead,dwRead);
				}
				if(g_pChanle2)
				{
					g_pChanle2->iIndex = 0;
					g_pChanle2->iTolLen = dwRead;
					memcpy(g_pChanle2->cReadBuf,g_vtBufRead,dwRead);
				}
				if(g_pChanle3)
				{
					g_pChanle3->iIndex = 0;
					g_pChanle3->iTolLen = dwRead;
					memcpy(g_pChanle3->cReadBuf,g_vtBufRead,dwRead);
				}

			}
			else
			{
				RETAILMSG(g_bDbg,(L"[VSP]:ClearCommError(%d): dwLength is 0,continue ......\r\n",dwErrorFlags));
				//	LeaveCriticalSection(&g_csRead);
				//	continue;
			}

			LeaveCriticalSection(&g_csRead);   
		}   
#if 0
		//if(dwEvtMask == EV_RXCHAR && ((g_dwWaitMask & EV_RXCHAR) == 0 || dwRead == 0))   
		if(dwEvtMask == EV_RXCHAR && ((g_dwWaitMask & EV_RXCHAR) == 0 ))   
		{   
			//The return event mask is only EV_RXCHAR and there is not EV_RXCHAR in the wait mask.   
			RETAILMSG(g_bDbg,(L"Skip send event C......\r\n"));
			continue;   
		}   
#endif
		InterlockedExchange((LPLONG)(&g_dwEvtMask),dwEvtMask);   
		PulseEvent(g_hEventComm);
		//	RETAILMSG(TRUE,(TEXT("PulseEvent %d\r\n"),g_dwEvtMask));

		//Sleep for other thread to respond to the event   
		//	Sleep(100);   
		Sleep(20); 

		DEBUGMSG(g_bDbg,(TEXT("[VSP]:PulseEvent! The event-mask is 0x%x\r\n"),dwEvtMask));    

	}   

	MyPDebugStringW(L"Fun:%s; over MonitorCommEventProc", __FUNCTIONW__);

	return 0;   
}   
2、COM_Open

为了让上层的应用程序能实现三次打开此设备而初始化三块COM_DEV内存。

  1. typedef struct  
  2. {  
  3.     int iIndex;  
  4.     int iTolLen;  
  5.     BYTE cReadBuf[READ_BUFFER_LENGTH];  
  6. }COM_DEV,*PCOM_DEV;  
typedef struct
{
	int iIndex;
	int iTolLen;
	BYTE cReadBuf[READ_BUFFER_LENGTH];
}COM_DEV,*PCOM_DEV;


 

  1. DWORD COM_Open(DWORD dwData, DWORD dwAccess, DWORD dwShareMode)     
  2. {     
  3.     PCOM_DEV pComDev = NULL;  
  4.   
  5.     MyPDebugStringW(L"Enter %s", __FUNCTIONW__);  
  6.     EnterCriticalSection(&g_csOpen);     
  7.     if(!g_pChanle1)  
  8.     {  
  9.         g_pChanle1 = new COM_DEV;  
  10.         g_pChanle1->iTolLen = g_pChanle1->iIndex = 0;  
  11.         pComDev = g_pChanle1;  
  12.     }  
  13.     else if(!g_pChanle2)  
  14.     {  
  15.         g_pChanle2 = new COM_DEV;  
  16.         g_pChanle2->iTolLen=g_pChanle2->iIndex =0;  
  17.         pComDev = g_pChanle2;  
  18.     }  
  19.     else if(!g_pChanle3)  
  20.     {  
  21.         g_pChanle3 = new COM_DEV;  
  22.         g_pChanle3->iTolLen=g_pChanle3->iIndex =0;  
  23.         pComDev = g_pChanle3;  
  24.     }  
  25.     else  
  26.     {  
  27.         return 0;  
  28.     }  
  29.   
  30. #if 1   
  31.     //The variable      
  32.     if(g_uiOpenCount >= MAX_OPEN_CNT)  
  33.         return 0;  
  34.   
  35.     g_uiOpenCount ++;    
  36.     pComDev->iIndex = 0;  
  37.     //  dwResult = dwData;      
  38.   
  39. LEAVE_CRITICAL_SECTION:      
  40. #endif   
  41.     LeaveCriticalSection(&g_csOpen);   
  42.     return (DWORD)pComDev;     
  43. }     
DWORD COM_Open(DWORD dwData, DWORD dwAccess, DWORD dwShareMode)   
{   
	PCOM_DEV pComDev = NULL;

	MyPDebugStringW(L"Enter %s", __FUNCTIONW__);
	EnterCriticalSection(&g_csOpen);   
	if(!g_pChanle1)
	{
		g_pChanle1 = new COM_DEV;
		g_pChanle1->iTolLen = g_pChanle1->iIndex = 0;
		pComDev = g_pChanle1;
	}
	else if(!g_pChanle2)
	{
		g_pChanle2 = new COM_DEV;
		g_pChanle2->iTolLen=g_pChanle2->iIndex =0;
		pComDev = g_pChanle2;
	}
	else if(!g_pChanle3)
	{
		g_pChanle3 = new COM_DEV;
		g_pChanle3->iTolLen=g_pChanle3->iIndex =0;
		pComDev = g_pChanle3;
	}
	else
	{
		return 0;
	}

#if 1
	//The variable   
	if(g_uiOpenCount >= MAX_OPEN_CNT)
		return 0;

	g_uiOpenCount ++;  
	pComDev->iIndex = 0;
	//	dwResult = dwData;   

LEAVE_CRITICAL_SECTION:    
#endif
	LeaveCriticalSection(&g_csOpen); 
	return (DWORD)pComDev;   
}   

3、COM_Deinit

主要是关闭读线程,反初始化资源;

关闭线程的方法有几种:

(1)是直接CloseHandle真实的COM口,然后在线程中会WaitCommEvent失败,然后退出,这这种方法太间接;

(2)设备全局变量,采用原子操作函数来变化它的标识。

A、定义变量:BOOL g_bExitMonitorProc = FALSE;   ;

B、在线程中:

  1. DWORD MonitorCommEventProc(LPVOID pParam)     
  2. {     
  3.  TCHAR wcDebug[1024] = {0};  
  4.   
  5.  MyPDebugStringW(L"Enter MonitorCommEventProc");  
  6.  SetCommMask(g_hCom, EV_RXCHAR);  
  7.  while(!g_bExitMonitorProc)     
  8.  {    
DWORD MonitorCommEventProc(LPVOID pParam)   
{   
 TCHAR wcDebug[1024] = {0};

 MyPDebugStringW(L"Enter MonitorCommEventProc");
 SetCommMask(g_hCom, EV_RXCHAR);
 while(!g_bExitMonitorProc)   
 {  

C、在创建线程前使它为FLASE:

  1. InterlockedExchange((LPLONG)(&g_bExitMonitorProc),FALSE);     
InterlockedExchange((LPLONG)(&g_bExitMonitorProc),FALSE);   

D、在要关闭线程时:

  1. BOOL CloseTransmitThr()  
  2. {  
  3.     DWORD dwMask = 0;   
  4.     //Notify the monitor thread to exit.       
  5.     InterlockedExchange((LPLONG)(&g_bExitMonitorProc),TRUE);     
BOOL CloseTransmitThr()
{
	DWORD dwMask = 0; 
	//Notify the monitor thread to exit.    
	InterlockedExchange((LPLONG)(&g_bExitMonitorProc),TRUE);   

4、COM_IOControl

为了使应用程序能像使用真实COM口一样的使用虚拟COM口,我们需要给出COM_IOControl,并去case需要的IOCODE,

(1)IOCTL_SERIAL_SET_TIMEOUTS
应用程序设备虚拟COM口的此接口,我们就给真实的COM口通过系统API SetCommTimeouts来设置:

  1. SetCommTimeouts(g_hCom,(LPCOMMTIMEOUTS)(pBufIn));     
SetCommTimeouts(g_hCom,(LPCOMMTIMEOUTS)(pBufIn));   

(2)IOCTL_SERIAL_GET_TIMEOUTS

类似于(1)

(3)IOCTL_SERIAL_SET_DCB

类似于(1)

(4)IOCTL_SERIAL_GET_DCB

类似于(1)

(5)IOCTL_SERIAL_WAIT_ON_MASK

(5、1)因为我们的读线程中有调用了WaitCommEvent,所以这里我们得做好同步,同步的方法是:

A、初始化事件

  1. g_hEventComm = CreateEvent(NULL,TRUE,FALSE,NULL);     
g_hEventComm = CreateEvent(NULL,TRUE,FALSE,NULL);   

B、在读取完数据后让事件激活

  1. PulseEvent(g_hEventComm);  
PulseEvent(g_hEventComm);

C、在case IOCTL_SEARIAL_WAIT_ON_MASK时去等待

  1. case IOCTL_SERIAL_WAIT_ON_MASK:     
  2.         {        
  3.             MyPDebugStringW(L"receive IOCTL_SERIAL_WAIT_ON_MASK");  
  4.             if(dwBufOutSize < sizeof(DWORD) ||  WaitForSingleObject(g_hEventComm,INFINITE) == WAIT_TIMEOUT)     
  5.             {     
case IOCTL_SERIAL_WAIT_ON_MASK:   
		{      
			MyPDebugStringW(L"receive IOCTL_SERIAL_WAIT_ON_MASK");
			if(dwBufOutSize < sizeof(DWORD) ||  WaitForSingleObject(g_hEventComm,INFINITE) == WAIT_TIMEOUT)   
			{   

(5、2)把读线程WaitCommEvent返回的结果返回给应用程序

A、

  1. BOOL bWaitRes = WaitCommEvent(g_hCom, &dwEvtMask, NULL);   
BOOL bWaitRes = WaitCommEvent(g_hCom, &dwEvtMask, NULL); 

B、

  1. InterlockedExchange((LPLONG)(&g_dwEvtMask),dwEvtMask);     
InterlockedExchange((LPLONG)(&g_dwEvtMask),dwEvtMask);   


C、在case IOCTL_SEARIAL_WAIT_ON_MASK等待成功时

  1. InterlockedExchange((LPLONG)(pBufOut),g_dwEvtMask);     
InterlockedExchange((LPLONG)(pBufOut),g_dwEvtMask);   

 

(6)IOCTL_SERIAL_SET_WAIT_MASK

  1. g_dwWaitMask = *(DWORD*)(pBufIn);     
  2.             RETAILMSG(g_bDbg,(TEXT("VSP : Set wait mask : %d ......\r\n"),g_dwWaitMask));  
  3.             return SetCommMask(g_hCom,g_dwWaitMask | EV_RXCHAR); //The driver need the EV_RXCHAR notify event.     
g_dwWaitMask = *(DWORD*)(pBufIn);   
			RETAILMSG(g_bDbg,(TEXT("VSP : Set wait mask : %d ......\r\n"),g_dwWaitMask));
			return SetCommMask(g_hCom,g_dwWaitMask | EV_RXCHAR); //The driver need the EV_RXCHAR notify event.   

也是调用了系统的SetCommMask,不过对入口设置的标志或上了EV_RXHCAR,因为我们的驱动需要EX_RXCHAR 通知事件。

 

(7)IOCTL_SERIAL_GET_WAIT_MASK

(8)IOCTL_SERIAL_GET_COMMSTATUS

(9)

 

 

三、实现机制要点

(1)采用文件映射实现共享数据。

(1、1)共享的数据为GPS数据,在COM_Init中去创建文件映射:

  1. g_pGpsDataMem = (PGPSDATA)ReadShareArea();  
  2.   
  3. g_pGpsDataMem->iSatNum = 67;  
	g_pGpsDataMem = (PGPSDATA)ReadShareArea();

	g_pGpsDataMem->iSatNum = 67;


映射文件的大小由SHARE_MEM_SIZE指定,为256。

  1. PVOID ReadShareArea()     
  2. {     
  3.     PBYTE pShareMem=NULL;  
  4.     HANDLE hMySharedFile=  
  5.         CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,SHARE_MEM_SIZE,SHARE_MEM_NAME);  
  6.     if(hMySharedFile!=NULL)  
  7.         pShareMem =(PBYTE)MapViewOfFile(hMySharedFile,FILE_MAP_ALL_ACCESS,0,0,0);  
  8.     CloseHandle(hMySharedFile);  
  9.   
  10.     return pShareMem;    
  11. }  
PVOID ReadShareArea()   
{   
	PBYTE pShareMem=NULL;
	HANDLE hMySharedFile=
		CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,SHARE_MEM_SIZE,SHARE_MEM_NAME);
	if(hMySharedFile!=NULL)
		pShareMem =(PBYTE)MapViewOfFile(hMySharedFile,FILE_MAP_ALL_ACCESS,0,0,0);
	CloseHandle(hMySharedFile);

	return pShareMem;  
}


(1、2)在COM _Open中为应用程序分析三个内存用于存储在读线程中得到的数据。

其中存储线程中得到的数据为:

  1. DecodeGpsBuf((char*)g_vtBufRead);  
  2.   
  3.                 g_dwLenReadBuf=dwRead;  
  4.   
  5.                 if(g_pChanle1)  
  6.                 {  
  7.                     g_pChanle1->iIndex = 0;  
  8.                     g_pChanle1->iTolLen = dwRead;  
  9.                     memcpy(g_pChanle1->cReadBuf,g_vtBufRead,dwRead);  
  10.                 }  
  11.                 if(g_pChanle2)  
  12.                 {  
  13.                     g_pChanle2->iIndex = 0;  
  14.                     g_pChanle2->iTolLen = dwRead;  
  15.                     memcpy(g_pChanle2->cReadBuf,g_vtBufRead,dwRead);  
  16.                 }  
  17.                 if(g_pChanle3)  
  18.                 {  
  19.                     g_pChanle3->iIndex = 0;  
  20.                     g_pChanle3->iTolLen = dwRead;  
  21.                     memcpy(g_pChanle3->cReadBuf,g_vtBufRead,dwRead);  
  22.                 }  
DecodeGpsBuf((char*)g_vtBufRead);

				g_dwLenReadBuf=dwRead;

				if(g_pChanle1)
				{
					g_pChanle1->iIndex = 0;
					g_pChanle1->iTolLen = dwRead;
					memcpy(g_pChanle1->cReadBuf,g_vtBufRead,dwRead);
				}
				if(g_pChanle2)
				{
					g_pChanle2->iIndex = 0;
					g_pChanle2->iTolLen = dwRead;
					memcpy(g_pChanle2->cReadBuf,g_vtBufRead,dwRead);
				}
				if(g_pChanle3)
				{
					g_pChanle3->iIndex = 0;
					g_pChanle3->iTolLen = dwRead;
					memcpy(g_pChanle3->cReadBuf,g_vtBufRead,dwRead);
				}


(1、3)在导出给应用程序的接口ReadGpsFromCom中把映射的数据拷到形参中

  1. BOOL ReadGpsFromCom(PVOID pReadBuf)  
  2. {  
  3.     MyPDebugStringW(L"Enter %s", __FUNCTIONW__);  
  4.     PGPSDATA pGpsDataMem= (PGPSDATA)ReadShareArea();;  
  5.     memcpy(pReadBuf,pGpsDataMem,sizeof(GPSDATA));  
  6.     if(pGpsDataMem)  
  7.         UnmapViewOfFile(pGpsDataMem);  
  8.     return TRUE;  
  9. }  
BOOL ReadGpsFromCom(PVOID pReadBuf)
{
	MyPDebugStringW(L"Enter %s", __FUNCTIONW__);
	PGPSDATA pGpsDataMem= (PGPSDATA)ReadShareArea();;
	memcpy(pReadBuf,pGpsDataMem,sizeof(GPSDATA));
	if(pGpsDataMem)
		UnmapViewOfFile(pGpsDataMem);
	return TRUE;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值