<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>https://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>https://jackxiang.com/post//</link>
<title><![CDATA[WINDOWS CE下串口编程与WINDOWS下的比较]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Sun, 11 Oct 2009 15:01:17 +0000</pubDate> 
<guid>https://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	 //========================================================================<br/>//TITLE:<br/>//&nbsp;&nbsp;&nbsp;&nbsp;WinXP与WinCE串口的运行机制之比较<br/>//AUTHOR:<br/>//&nbsp;&nbsp;&nbsp;&nbsp;norains<br/>//DATE:<br/>//&nbsp;&nbsp;&nbsp;&nbsp;Saturday&nbsp;&nbsp;11-November-2006<br/>//Passed Environment:<br/>//&nbsp;&nbsp;&nbsp;&nbsp;PC:WinXP+VC6.0<br/>//&nbsp;&nbsp;&nbsp;&nbsp;CE:WinCE4.2+EVC4.0<br/>//========================================================================<br/>&nbsp;&nbsp;&nbsp;&nbsp;查看微软相关的串口通信文档,可以发现在桌面操作系统中,串口通信分为两种模式:同步和异步.而WinCE只有一种,但文档中却没标明归属哪种模式.实际上,WinCE的串口通信模式更像介于同步和异步之间.<br/>&nbsp;&nbsp;&nbsp;&nbsp;在此先简要地介绍何为同步和异步.所谓的同步,指得是对同一个设备或文件(在文中只的是串口COM1)的读或写操作必须要等待上一个操作完成才能进行.比如说,调用ReadFile()函数读取串口,但由于上一个WriteFile()操作没完成,ReadFile()的操作就被阻塞,直到 WriteFile()完成后才能运行.而异步,则无论上一个操作是否完成,都会执行目前调用的操作.还是拿前面举的例子,在异步模式下,即使 WriteFile()没有执行完成,ReadFile()也会立刻执行.<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp; <br/>1.CreateFile()参数的差异<br/>&nbsp;&nbsp;&nbsp;&nbsp;首先说明一下WinCE和WinXP打开串口时参数的差异.以打开串口COM1为例子,WinCE下的名字为"COM1:",而WinXP为"COM1",两者的唯一区别仅仅在于WinCE下多个分号.<br/>&nbsp;&nbsp;&nbsp;&nbsp;例如:<br/>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE hd = CreateFile(TEXT("COM1:"),GENERIC_READ&#124;GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); //WinCE<br/>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE hd = CreateFile(TEXT("COM1"),GENERIC_READ&#124;GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); //WinXP<br/>&nbsp;&nbsp;&nbsp;&nbsp;在这稍微多说一下,在默认的环境下,TEXT宏在WinCE下会编译为双字节,而WinXP为单字节.换句话说,TEXT("COM1")在WinCE下相当于L"COM1",而WinXP则为"COM1".<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp; <br/>2.单线程比较<br/>&nbsp;&nbsp; 还是用代码做例子来说明比较形象.这是一段单线程的代码,先对串口进行写操作,然后再读.对于WinXP来说,这是同步模式.(与主题无关的代码省略)&nbsp;&nbsp; <br/>&nbsp;&nbsp; int WINAPI WinMain( HINSTANCE hInstance,<br/>&nbsp;&nbsp;&nbsp;&nbsp; HINSTANCE hPrevInstance,<br/>&nbsp;&nbsp;&nbsp;&nbsp; LPTSTR&nbsp;&nbsp;&nbsp;&nbsp;lpCmdLine,<br/>&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nCmdShow)<br/>&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; ...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLE hCom = CreateFile(TEXT("COM1:"),GENERIC_READ&#124;GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); //WinCE<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//HANDLE Com = CreateFile(TEXT("COM1"),GENERIC_READ&#124;GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); //WinXP<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWord dwBytes;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(WriteFile(hCom,TEXT("COM1:"),5,&dwBytes,NULL) == FALSE) //WinCE<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//if(WriteFile(hCom,TEXT("COM1"),5,&dwBytes,NULL) == FALSE) //WinXP<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0x05;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWord dwRead;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char szBuf[MAX_READ_BUFFER];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(ReadFile(hCom,szBuf,MAX_READ_BUFFER,&dwRead,NULL) == FALSE)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0x10;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;经过实验,可以发现这段代码在WinCE和WinXP下都能正常工作,并且其表现也相同,都是在WriteFile()函数返回后才执行ReadFile().<br/>&nbsp;&nbsp;&nbsp;&nbsp;由于异步模式在单线程中也能正常运作,唯一的不同只是在执行WriteFile()时可能也会执行ReadFile()(依WriteFile()函数执行的时间而定),所在此不表.<br/>&nbsp;&nbsp; <br/>3.多线程比较<br/>&nbsp;&nbsp;&nbsp;&nbsp;单线程两者表现相同,那多线程呢?下面这段代码采用多线程,先是创建一个读的线程,用来监控串口是否有新数据到达,然后在主线程中对串口写出数据.<br/>&nbsp;&nbsp;&nbsp;&nbsp;这里假设是这么一个情况,有两台设备,分别为A和B,下面的代码运行于设备A,设备B仅仅只是应答而已.换句话说,只有A向B发送数据,B才会返回应答信号.<br/>&nbsp;&nbsp;&nbsp;&nbsp;//主线程<br/>&nbsp;&nbsp;&nbsp;&nbsp;int WINAPI WinMain( HINSTANCE hInstance,<br/>&nbsp;&nbsp;&nbsp;&nbsp; HINSTANCE hPrevInstance,<br/>&nbsp;&nbsp;&nbsp;&nbsp; LPTSTR&nbsp;&nbsp;&nbsp;&nbsp;lpCmdLine,<br/>&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nCmdShow)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CreateThread(NULL,0,ReadThread,0,0,&dwThrdID); //创建一个读的线程.<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLE hCom = CreateFile(TEXT("COM1:"),GENERIC_READ&#124;GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); //WinCE<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//HANDLE Com = CreateFile(TEXT("COM1"),GENERIC_READ&#124;GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); //WinXP<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD dwBytes;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(WriteFile(hCom,"AT&#92;r&#92;n",4,&dwBytes,NULL) == FALSE) //WinCE<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//if(WriteFile(hCom,"AT&#92;r&#92;n",5,&dwBytes,NULL) == FALSE) //WinXP<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0x05;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;//读线程<br/>&nbsp;&nbsp;&nbsp;&nbsp;DWORD WINAPI ReadThread()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetCommMask(hCom),EV_RXCHAR);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD dwCommStatus = 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(WaitCommEvent(hCom),&dwCommStatus,NULL) == FALSE)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; //Clear the error flag<br/>&nbsp;&nbsp;&nbsp;&nbsp; DWORD dwErrors;<br/>&nbsp;&nbsp;&nbsp;&nbsp; COMSTAT comStat;<br/>&nbsp;&nbsp;&nbsp;&nbsp; memset(&comStat,0,sizeof(comStat));<br/>&nbsp;&nbsp;&nbsp;&nbsp; ClearCommError(hCom,&dwErrors,&comStat);<br/>&nbsp;&nbsp;&nbsp;&nbsp; return 0x15;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;char szBuf[MAX_READ_BUFFER]=&#123;0&#125;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;DWORD dwRead;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(ReadFile(hCom),szBuf,MAX_READ_BUFFER,&dwRead,NULL) == FALSE &#124;&#124; dwRead == 0)<br/>&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;return 0x20;<br/>&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp; ...<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;这段代码在WinCE下运行完全正常,读线程在监听收到的数据的同时,主线程顺利地往外发数据.<br/>&nbsp;&nbsp;&nbsp;&nbsp;然而同样的代码,在WinXP下则根本无法完成工作.运行此代码,我们将发现CPU的占用率高达99%.通过单步调试,发现两个线程分别卡在WaitCommEvent()和WriteFile()函数中.因为根据同步模式的定义,当前对设备的操作必须要等待上一个操作完毕方可执行.在以上代码中,因为设备B没接到设备A的命令而不会向设备A发送应答,故WaitCommEvent()函数因为没有检测到接受数据而一直在占用串口;而WaitCommEvent()一直占据串口使得WriteFile()没有得到串口资源而处于阻塞状态, 这就造成了死锁.<br/>&nbsp;&nbsp;&nbsp;&nbsp;而这种情况没有在WinCE上出现,只要WaitCommEvent()和WriteFile()不在同一个线程,就可以正常工作.这应该和系统的调度方式有关. <br/>如果要在PC上同时进行WaitCommEvent()和WriteFile()操作,需要把串口的模式改写为异步模式.<br/>&nbsp;&nbsp;&nbsp;&nbsp;更改后的代码如下:<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;//主线程<br/>&nbsp;&nbsp;&nbsp;&nbsp;int WINAPI WinMain( HINSTANCE hInstance,<br/>&nbsp;&nbsp;&nbsp;&nbsp; HINSTANCE hPrevInstance,<br/>&nbsp;&nbsp;&nbsp;&nbsp; LPTSTR&nbsp;&nbsp;&nbsp;&nbsp;lpCmdLine,<br/>&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nCmdShow)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CreateThread(NULL,0,ReadThread,0,0,&dwThrdID); //创建一个读的线程.<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLE Com = CreateFile(TEXT("COM1"),GENERIC_READ&#124;GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,FILE_FLAG_OVERLAPPED);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OVERLAPPED olWrite;<br/>&nbsp;&nbsp;&nbsp;&nbsp; memset(&olWrite,0,sizeof(m_olWrite));<br/>&nbsp;&nbsp;&nbsp;&nbsp; olWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD dwBytes;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp; if(WriteFile(hCom,"AT&#92;r&#92;n",4,&dwBytes,&olWrite) == FALSE)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(GetLastError() != ERROR_IO_PENDING)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0x20;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp; if(GetOverlappedResult(hCom,&olWrite,&dwBytes,TRUE) == FALSE)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0x25;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;//读线程<br/>&nbsp;&nbsp;&nbsp;&nbsp;DWORD WINAPI ReadThread()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp; memset(&olWaite,0,sizeof(olWaite));&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp; olWaite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetCommMask(hCom),EV_RXCHAR);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD dwCommStatus = 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;WaitCommEvent(hCom,&dwCommStatus,olWaite);<br/>&nbsp;&nbsp;&nbsp;&nbsp;DWORD dwByte; //norains:It is only suitable for the GetOverlappedResult(),not undefined here.<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(GetOverlappedResult(hCom,olWaite,&dwByte,TRUE) == FALSE)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; if(GetLastError() != ERROR_IO_PENDING)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0x30;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp; //Clear the error flag<br/>&nbsp;&nbsp;&nbsp;&nbsp; DWORD dwErrors;<br/>&nbsp;&nbsp;&nbsp;&nbsp; COMSTAT comStat;<br/>&nbsp;&nbsp;&nbsp;&nbsp; memset(&comStat,0,sizeof(comStat));<br/>&nbsp;&nbsp;&nbsp;&nbsp; ClearCommError(hCom,&dwErrors,&comStat);<br/>&nbsp;&nbsp;&nbsp;&nbsp; return 0x35;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;...<br/>&nbsp;&nbsp;&nbsp;&nbsp;memset(&olRead,0,sizeof(olRead));<br/>&nbsp;&nbsp;&nbsp;&nbsp;olRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);<br/>&nbsp;&nbsp;&nbsp;&nbsp;char szBuf[MAX_READ_BUFFER]=&#123;0&#125;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;DWORD dwRead;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(ReadFile(hCom,szBuf,MAX_READ_BUFFER,&dwRead,olRead) ==FALSE)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; if(GetLastError() != ERROR_IO_PENDING)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0x40;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp; if(GetOverlappedResult(hCom,olRead,&dwRead,TRUE) == FALSE)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0x45;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp; if(dwRead == 0)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0x50;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp; ...<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;测试经过更改后的代码,可以发现在WinXP下终于可以同时调用WaitCommEvent()和WriteFile()而不造成死锁.<br/>&nbsp;&nbsp;&nbsp;&nbsp;在这里可以发现WinCE和WinXP的串口调度的差异性:单线程中,WinCE的串口工作方式和WinXP串口的同步工作模式相符;而多线程中,WinCE串口工作方式却又和WinXP的异步方式吻合.虽然无法确切比较WinCE的单一串口模式是否比WinXP的双模式更为优越,但可以确认的是,WinCE的这种串口调用方式给程序员带来了极大的便利.<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp; <br/>4.WinXP异步模式两种判断操作是否成功的方法<br/>&nbsp;&nbsp;&nbsp;&nbsp;因为在WinXP的异步模式中,WriteFile(),ReadFile()和WaitCommEvent()大部分情况下都是未操作完毕就返回,所以不能简单地判断返回值是否为TRUE或FALSE来判断.<br/>&nbsp;&nbsp;&nbsp;&nbsp;以ReadFile()函数做例子.<br/>&nbsp;&nbsp;&nbsp;&nbsp;一种是上文所用的方法:<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(ReadFile(hCom,szBuf,MAX_READ_BUFFER,&dwRead,olRead) ==FALSE)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; if(GetLastError() != ERROR_IO_PENDING)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0x40;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp; if(GetOverlappedResult(hCom,olRead,&dwRead,TRUE) == FALSE)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0x45;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp; if(dwRead == 0)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0x50;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;如果ReadFile()返回为TRUE,则表明读文件已经完成.但这种情况几乎不会出现,因为对外设的读写相对于内存的读写来说非常慢,所以一般在ReadFile()函数还没执行完毕,程序已经执行到下一个语句.<br/>&nbsp;&nbsp;&nbsp;&nbsp;当ReadFile()返回为FALSE时,需要采用GetLastError()函数判断读操作是否在后台进行.如果在后台进行,则调用 GetOverlappedResult()函数获取ReadFile()函数的结果.在这里要注意的是,GetOverlappedResult()函数的最后一个参数必须设置为TRUE,表明要等ReadFile()函数在后台运行完毕才返回.如果最后一个参数设置为FALSE,则即使 ReadFile()还在后台执行,GetOverlappedResult()函数也会立刻返回,从而造成判断错误.<br/>&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;另一种是调用WaitForSingleObject函数达到此目的:<br/>&nbsp;&nbsp;&nbsp;&nbsp;if(ReadFile(hCom,szBuf,MAX_READ_BUFFER,&dwRead,olRead) ==FALSE)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; if(GetLastError() != ERROR_IO_PENDING)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0x40;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp; if(WaitForSingleObject(olRead.hEvent,INFINITE) != WAIT_OBJECT_0)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp; return 0x55;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp; if(GetOverlappedResult(hCom,olRead,&dwRead,FALSE) == FALSE)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0x45;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp; if(dwRead == 0)<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0x50;<br/>&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&nbsp;&nbsp;&nbsp;&nbsp;因为ReadFile()在后台执行完毕以后,会发送一个event,所以在这里可以调用WaitForSingleObject()等待 ReadFile()执行完毕,然后再调用GetOverlappedResult()获取ReadFile()的最终结果.在这里需要注意的是,GetOverlappedResult()的最后一个参数一定要设置为FALSE,因为WaitForSingleObject()已经捕获了 ReadFile()发出的event,再也没有event传递到GetOverlappedResult()函数.如果此时 GetOverlappedResult()最后一个参数设置为TRUE,则线程会一直停留在GetOverlappedResult()函数而不往下执行.
]]>
</description>
</item><item>
<link>https://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] WINDOWS CE下串口编程与WINDOWS下的比较]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>https://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>