none
Win CE 6.0 USB转串口,神奇诡异的“两次”问题,设备需要二次打开 RRS feed

  • 问题

  • //串口读线程函数
    DWORD CCESeries::ReadThreadFunc(LPVOID lparam)
    {
    	CCESeries *ceSeries = (CCESeries*)lparam;
    	
    	DWORD	evtMask;
    	BYTE * readBuf = NULL;//读取的字节
    	DWORD actualReadLen=0;//实际读取的字节数
    	DWORD willReadLen;
    	
    	DWORD dwReadErrors;
    	COMSTAT	cmState;
    	
    	// 清空缓冲,并检查串口是否打开。
    	ASSERT(ceSeries->m_hComm !=INVALID_HANDLE_VALUE); 
    	
    	
    	//清空串口
    	if (!PurgeComm(ceSeries->m_hComm, PURGE_RXCLEAR|PURGE_TXCLEAR ))
    	{
    		TRACE(_T("PurgeComm() failed. %d"), GetLastError());
    			return 1;
    	}
    	//Sleep(3000);
    	if (!SetCommMask (ceSeries->m_hComm, EV_RXCHAR|EV_TXEMPTY|EV_CTS|EV_DSR|EV_RLSD|EV_RING ))
    	{
    		TRACE(_T("SetCommMask() failed. %d"), GetLastError());
    		return 1;
    	}
    	while (TRUE)
    	{  	
    		if (WaitCommEvent(ceSeries->m_hComm, &evtMask, 0))
    		{			
    			SetCommMask (ceSeries->m_hComm, EV_RXCHAR|EV_TXEMPTY|EV_CTS|EV_DSR|EV_RLSD|EV_RING );
    			//表示串口收到字符		
    			if (evtMask & EV_RXCHAR) 
    			{
    				ClearCommError(ceSeries->m_hComm, &dwReadErrors, &cmState);
    				willReadLen = cmState.cbInQue ;
    				if (willReadLen <= 0)
    				{
    					continue;
    				}
    				
    				//分配内存
    				readBuf = new BYTE[willReadLen];
    				ZeroMemory(readBuf,willReadLen);
    				//读取串口数据
    				ReadFile(ceSeries->m_hComm, readBuf, willReadLen, &actualReadLen,0);
    				
    				//如果读取的数据大于0,
    				if (actualReadLen>0)
    				{
    					//触发读取回调函数
    					if (ceSeries->m_OnSeriesRead != NULL)
    					{
    						ceSeries->m_OnSeriesRead(ceSeries->m_pOwner, readBuf, actualReadLen);
    					}
    				}
    
    				//释放内存
    				delete[] readBuf;
    				readBuf = NULL;
    			}
    		}
    		else
    		{
    			// WaitCommEvent() failed
    			TRACE(_T("WaitCommEvent() failed. error code: %d"), GetLastError());
    		}
    		//如果收到读线程退出信号,则退出线程
    		if (WaitForSingleObject(ceSeries->m_hReadCloseEvent,500) == WAIT_OBJECT_0)
    		{
    			break;
    		}
    	}
    	return 0;
    }
    

    以上代码为读取数据的线程。

    问题现象如下:

    设备插入usb口后加载usbser.dll驱动,设备识别为com设备。

    通过在应用层的软件中使用createfile打开设备,该设备上的芯片上的firmware会往出送数据。但是第一次createfile后线程接收不到数据,然后我closehandle关闭设备,第二次createfile,这个时候线程就收到数据了。

    在应用程序中往file handle中写数据,第一次写的数据设备收不到,第二次以后写的数据设备才能收到。(设备收到数据firmware会解析,会通过往出送的数据表现出来)。

     

    在xp下使用usbser.sys这个驱动也可以将设备识别为com,然后在超级终端不会出现“两次”问题。

     

    经过调试,发现程序在第一次打开设备文件句柄后,创建的接受线程会停在WaitCommEvent出不来,第二次WaitCommEvent就不会阻塞住。

    我调试了很久,没有结果。

    还请各位相助啊~  

    Thanks!

    2011年2月18日 8:51

答案

  • 您好,

    关于这个问题,问题原因应该不是出在应用程序层面,您可以尝试将此测试程序在别的平台上进行测试,看是否有问题。并且,您提及了该测试程序在板载串口下正常工作,说明程序本身问题。

    接下来,如果要进一步查看此问题,仅提供以下想法供您参考:

    1. 该问题是出现在Win CE的系统平台上,针对于XP上的行为,并不具备特别严格的参考性,从设计之初来讲,这是两个完全不同的OS,虽然有些API应用相似,但是其内部机制并不相同。

    2. 针对于这个问题,如果您是OEM厂商本身,建议您可以开启设备上相应的调试机制,比如说KITL,debug版本的模块等,或者加一些debug日志在USB-Serial流驱动的IO中。通过抓取调试日志或者进行一系列的KITL命令调试动作,可以进一步研究此问题。

    3. 如果您只是负责串口程序本身的应用开发,还希望您可以联系相应的设备提供商一起来查看问题,由于资源的限制,您可能没有很多的调式手段来进一步跟踪查看问题,这就需要设备提供商的参与写作。

    谢谢!希望以上信息可以帮到您!

    祝工作愉快!

    2011年2月23日 3:35

全部回复

  • 您好,

    第一次打开的时候会报错么 用 GetLastError()

    致礼


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年2月22日 8:29
    版主
  • 打开设备(CreateFile)可以顺利打开,不会报错。

    只是第奇数次打开无法读写数据;

          第偶数次则可以读数据,写数据第一次的无效(写不进去,丢了,但是WriteFile执行成功了),第二次往后可以写进去。

     

    这种问题我觉得和我测试程序无关,例如从机器重启后开始计算, 我测试程序(应用层)执行,然后打开设备(算第一次),无法读取。然后关掉测试程序,再打开测试程序,然后在测试程序中打开设备(第二次),就可以读写,当然,写操作第二次有效。

    因此,”两次“问题我觉得不在测试程序,测试程序在板载串口测试正常。就在这个usb转串口上有这个问题。

    2011年2月22日 8:38
  • 您好,

    关于这个问题,问题原因应该不是出在应用程序层面,您可以尝试将此测试程序在别的平台上进行测试,看是否有问题。并且,您提及了该测试程序在板载串口下正常工作,说明程序本身问题。

    接下来,如果要进一步查看此问题,仅提供以下想法供您参考:

    1. 该问题是出现在Win CE的系统平台上,针对于XP上的行为,并不具备特别严格的参考性,从设计之初来讲,这是两个完全不同的OS,虽然有些API应用相似,但是其内部机制并不相同。

    2. 针对于这个问题,如果您是OEM厂商本身,建议您可以开启设备上相应的调试机制,比如说KITL,debug版本的模块等,或者加一些debug日志在USB-Serial流驱动的IO中。通过抓取调试日志或者进行一系列的KITL命令调试动作,可以进一步研究此问题。

    3. 如果您只是负责串口程序本身的应用开发,还希望您可以联系相应的设备提供商一起来查看问题,由于资源的限制,您可能没有很多的调式手段来进一步跟踪查看问题,这就需要设备提供商的参与写作。

    谢谢!希望以上信息可以帮到您!

    祝工作愉快!

    2011年2月23日 3:35
  • 您好,

    关于这个问题,问题原因应该不是出在应用程序层面,您可以尝试将此测试程序在别的平台上进行测试,看是否有问题。并且,您提及了该测试程序在板载串口下正常工作,说明程序本身问题。

    接下来,如果要进一步查看此问题,仅提供以下想法供您参考:

    1. 该问题是出现在Win CE的系统平台上,针对于XP上的行为,并不具备特别严格的参考性,从设计之初来讲,这是两个完全不同的OS,虽然有些API应用相似,但是其内部机制并不相同。

    2. 针对于这个问题,如果您是OEM厂商本身,建议您可以开启设备上相应的调试机制,比如说KITL,debug版本的模块等,或者加一些debug日志在USB-Serial流驱动的IO中。通过抓取调试日志或者进行一系列的KITL命令调试动作,可以进一步研究此问题。

    3. 如果您只是负责串口程序本身的应用开发,还希望您可以联系相应的设备提供商一起来查看问题,由于资源的限制,您可能没有很多的调式手段来进一步跟踪查看问题,这就需要设备提供商的参与写作。

    谢谢!希望以上信息可以帮到您!

    祝工作愉快!

    谢谢你的回复。

    我是属于第2条。通过打开环境变量sysgen_usb_ser生成含有usbser.dll驱动的nk。测试程序只是为了验证设备工作。具体表现已经叙述。

    从KITL的打印来看两次打开设备log是一样的。仅从log上我现在分析不出来问题。在流驱动io中加debug日志我试下,以前做的是应用层软件,现在做嵌入式驱动一些调试技术以及解决问题的方法还不成熟。

    另:我想请教一下,从usb设备插入插口开始,os执行的具体步骤是怎样的?从哪个模块到哪个模块这样子。

    2011年2月23日 3:45
  • m_OnSeriesRead 函数的代码能复制出来吗?

    你是同步读取吧


    我运行怎么卡在WaitCommEvent这里了,看错都不好看
    2011年5月19日 12:11
  • m_OnSeriesRead 函数的代码能复制出来吗?

    你是同步读取吧


    我运行怎么卡在WaitCommEvent这里了,看错都不好看

    ce不能异步。

    那只是一个回调函数,处理接收到的数据的。我只是简单的显示。

    该主题中描述的问题已经解决。不是我代码的问题,也不是ce的问题。更新单片机的labrary,重新编译firmware,烧写就行。 使用pic18系列的应该注意这个问题。

    2011年5月20日 0:26