




已阅读5页,还剩2页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
/=/TITLE:/ WinXP与WinCE串口的运行机制之比较/AUTHOR:/ norains/DATE:/ Saturday 11-November-2006/Passed Environment:/ PC:WinXP+VC6.0/ CE:WinCE4.2+EVC4.0/= 查看微软相关的串口通信文档,可以发现在桌面操作系统中,串口通信分为两种模式:同步和异步.而WinCE只有一种,但文档中却没标明归属哪种模式.实际 上,WinCE的串口通信模式更像介于同步和异步之间. 在此先简要地介绍何为同步和异步.所谓的同步,指得是对同一个设备或文件(在文中只的是串口COM1)的读或写操作必须要等待上一个操作完成才能进行.比 如说,调用ReadFile()函数读取串口,但由于上一个WriteFile()操作没完成,ReadFile()的操作就被阻塞,直到 WriteFile()完成后才能运行.而异步,则无论上一个操作是否完成,都会执行目前调用的操作.还是拿前面举的例子,在异步模式下,即使 WriteFile()没有执行完成,ReadFile()也会立刻执行. 1.CreateFile()参数的 差异 首先说明一下WinCE和WinXP打开串口时参数的差异.以打开串口COM1为例子,WinCE下的名字为COM1:,而WinXP 为COM1,两者的唯一区别仅仅在于WinCE下多个分号. 例如: HANDLE hd = CreateFile(TEXT(COM1:),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); /WinCE HANDLE hd = CreateFile(TEXT(COM1),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); /WinXP 在这稍微多说一下,在默认的环境下,TEXT宏在WinCE下会编译为双字节,而WinXP为单字节.换句话说,TEXT(COM1)在WinCE下 相当于LCOM1,而WinXP则为COM1. 2.单线程比较 还是用代码做例子来说明比较形象.这是一段单线程的代码,先对串口进行写操作,然后再读.对于WinXP来说,这是同步模式.(与主题无关的代码省 略) int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) . HANDLE hCom = CreateFile(TEXT(COM1:),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); /WinCE /HANDLE Com = CreateFile(TEXT(COM1),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); /WinXP . DWORD dwBytes; if(WriteFile(hCom,TEXT(COM1:),5,&dwBytes,NULL) = FALSE) /WinCE /if(WriteFile(hCom,TEXT(COM1),5,&dwBytes,NULL) = FALSE) /WinXP return 0x05; . DWORD dwRead; char szBufMAX_READ_BUFFER; if(ReadFile(hCom,szBuf,MAX_READ_BUFFER,&dwRead,NULL) = FALSE) return 0x10; . 经过实验,可以发现这段代码在WinCE和WinXP下都能正常工作,并且其表现也相同,都是在WriteFile()函数返回后才执行 ReadFile(). 由于异步模式在单线程中也能正常运作,唯一的不同只是在执行WriteFile()时可能也会执行ReadFile()(依WriteFile()函数执 行的时间而定),所在此不表. 3.多线程比较 单线程两者表现相同,那多线程呢?下面这段代码采用多线程,先是创建一个读的线程,用来监控串口是否有新数据到达,然后在主线程中对串口写出数据. 这里假设是这么一个情况,有两台设备,分别为A和B,下面的代码运行于设备A,设备B仅仅只是应答而已.换句话说,只有A向B发送数据,B才会返回应答信 号. /主线程 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) . CreateThread(NULL,0,ReadThread,0,0,&dwThrdID); /创建一个读的线程. . HANDLE hCom = CreateFile(TEXT(COM1:),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); /WinCE /HANDLE Com = CreateFile(TEXT(COM1),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); /WinXP . DWORD dwBytes; if(WriteFile(hCom,ATrn,4,&dwBytes,NULL) = FALSE) /WinCE /if(WriteFile(hCom,ATrn,5,&dwBytes,NULL) = FALSE) /WinXP return 0x05; . /读线程 DWORD WINAPI ReadThread() . SetCommMask(hCom),EV_RXCHAR); DWORD dwCommStatus = 0; if(WaitCommEvent(hCom),&dwCommStatus,NULL) = FALSE) /Clear the error flag DWORD dwErrors; COMSTAT comStat; memset(&comStat,0,sizeof(comStat); ClearCommError(hCom,&dwErrors,&comStat); return 0x15; . char szBufMAX_READ_BUFFER=0; DWORD dwRead; if(ReadFile(hCom),szBuf,MAX_READ_BUFFER,&dwRead,NULL) = FALSE | dwRead = 0) return 0x20; . 这段代码在WinCE下运行完全正常,读线程在监听收到的数据的同时,主线程顺利地往外发数据. 然而同样的代码,在WinXP下则根本无法完成工作.运行此代码,我们将发现CPU的占用率高达99%.通过单步调试,发现两个线程分别卡在 WaitCommEvent()和WriteFile()函数中.因为根据同步模式的定义,当前对设备的操作必须要等待上一个操作完毕方可执行.在以上代 码中,因为设备B没接到设备A的命令而不会向设备A发送应答,故WaitCommEvent()函数因为没有检测到接受数据而一直在占用串口;而 WaitCommEvent()一直占据串口使得WriteFile()没有得到串口资源而处于阻塞状态,这就造成了死锁. 而这种情况没有在WinCE上出现,只要WaitCommEvent()和WriteFile()不在同一个线程,就可以正常工作.这应该和系统的调度方 式有关. 如果要在PC上同时进行WaitCommEvent()和WriteFile()操作,需要把串口的模式改写为异步模式. 更改后的代码如下: /主线程 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) . CreateThread(NULL,0,ReadThread,0,0,&dwThrdID); /创建一个读的线程. . HANDLE Com = CreateFile(TEXT(COM1),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,FILE_FLAG_OVERLAPPED); . OVERLAPPED olWrite; memset(&olWrite,0,sizeof(m_olWrite); olWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); DWORD dwBytes; if(WriteFile(hCom,ATrn,4,&dwBytes,&olWrite) = FALSE) if(GetLastError() != ERROR_IO_PENDING) return 0x20; if(GetOverlappedResult(hCom,&olWrite,&dwBytes,TRUE) = FALSE) return 0x25; . /读线程 DWORD WINAPI ReadThread() . memset(&olWaite,0,sizeof(olWaite); olWaite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); SetCommMask(hCom),EV_RXCHAR); DWORD dwCommStatus = 0; WaitCommEvent(hCom,&dwCommStatus,olWaite); DWORD dwByte; /norains:It is only suitable for the GetOverlappedResult(),not undefined here. if(GetOverlappedResult(hCom,olWaite,&dwByte,TRUE) = FALSE) if(GetLastError() != ERROR_IO_PENDING) return 0x30; /Clear the error flag DWORD dwErrors; COMSTAT comStat; memset(&comStat,0,sizeof(comStat); ClearCommError(hCom,&dwErrors,&comStat); return 0x35; . memset(&olRead,0,sizeof(olRead); olRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); char szBufMAX_READ_BUFFER=0; DWORD dwRead; if(ReadFile(hCom,szBuf,MAX_READ_BUFFER,&dwRead,olRead) =FALSE) if(GetLastError() != ERROR_IO_PENDING) return 0x40; if(GetOverlappedResult(hCom,olRead,&dwRead,TRUE) = FALSE) return 0x45; if(dwRead = 0) return 0x50; . 测试经过更改后的代码,可以发现在WinXP下终于可以同时调用WaitCommEvent()和WriteFile()而不造成死锁. 在这里可以发现WinCE和WinXP的串口调度的差异性:单线程中,WinCE的串口工作方式和WinXP串口的同步工作模式相符;而多线程 中,WinCE串口工作方式却又和WinXP的异步方式吻合.虽然无法确切比较WinCE的单一串口模式是否比WinXP的双模式更为优越,但可以确认的 是,WinCE的这种串口调用方式给程序员带来了极大的便利. 4.WinXP异步模式两种判断操作是否成功的方 法 因为在WinXP的异步模式中,WriteFile(),ReadFile()和WaitCommEvent()大部分情况下都是未操作完毕就返回,所以 不能简单地判断返回值是否为TRUE或FALSE来判断. 以ReadFile()函数做例子. 一种是上文所用的方法: if(ReadFile(hCom,szBuf,MAX_READ_BUFFER,&dwRead,olRead) =FALSE) if(GetLastError() != ERROR_IO_PENDING) return 0x40; if(GetOverlappedResult(hCom,olRead,&dwRead,TRUE) = FALSE) return 0x45; if(dwRead = 0) return 0x50; 如果ReadFile()返回为TRUE,则表明读文件已经完成.但这种情况几乎不会出现,因为对外设的读写相对于内存的读写来说非常慢,所以一般在 ReadFile()函数还没执行完毕,程序已经执行到下一个语句. 当ReadFile()返回为FALSE时,需要采用GetLastError()函数判断读操作是否在后台进行.如果在后台进行,则调用 GetOverlappedResult()函数获取ReadFile()函数的结果.在这里要注意的是,GetOverlappedResult()函 数的最后一个参数必须设置为TRUE,表明要等ReadFile()函数在后台运行完毕才返回.如果最后一个参数设置为FALSE,则即使 ReadFile()还在后台执行,GetOverlappedResult()函数也会立刻返回,从而造成判断错误. 另一种是调用WaitForSingleObject函数达
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 航空货运业务中的冷链物流质量控制考核试卷
- 自行车电助力技术发展趋势考核试卷
- 谈判口才训练谈判口才技巧
- 货币经纪公司交易系统操作技巧考核试卷
- 水产养殖技术培训与指导考核试卷
- 抖音直播运营与规范指南
- 《三级公共政策分析教学课件》
- 室内设计的程序与方法
- 《围棋艺术》课件
- 巡察采购领用环节重点与经验分享
- 交通运输安全风险评估
- 互联网技术支持的新型健康管理模式对慢病人群的应用研究
- FZT 74005-2016 针织瑜伽服行业标准
- 2024年湖北省武汉市高考数学一调试卷
- 愿站成一棵树金波
- 2022年10月自考00372公安信息学试题及答案含解析
- 脱贫攻坚战在2024年取得全面胜利
- 高中音乐 人音版《音乐鉴赏》家国情怀的民族乐派(单元教学设计)
- GB/T 43701-2024滑雪场地滑雪道安全防护规范
- 制片人与导演的权力斗争与权力关系
- 国家开放大学《人际沟通》形考任务1-4参考答案
评论
0/150
提交评论