⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 1585.htm

📁 对于学习很有帮助
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<TABLE border=0 cellPadding=0 cellSpacing=0 width=750>
  <TBODY>
  <TR>
    <TD width=144><img src=/images/sina_kjsd.gif width=144 height=34 alt=科技时代></TD>
    <TD background=/images/tech_bg.gif vAlign=bottom width=606>
      <TABLE background="" border=0 cellPadding=0 cellSpacing=0 width="100%">
        <TBODY>
        <TR>
          <TD bgColor=#004dc0 width=6><IMG height=21 
            src="/images/c1.gif" width=6></TD>
          <TD bgColor=#004dc0 class=sb width=600><IMG height=4 
            src="/images/c1.gif" width=1><BR><A 
            class=tech1 href="http://www.sina.com.cn/">新浪首页</A> &gt; <A       
            class=tech1 href="http://tech.sina.com.cn/">科技时代</A> &gt; <A       
            class=tech1 href="http://tech.sina.com.cn/introduction/">网上学园</A> 
            &gt; <A class=tech1 href="/introduction/prog.shtml">高级编程</A>      
            &gt; <A class=tech1 href="http://www.swm.com.cn">软件世界</A>      
            &gt;       
          正文</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><!--结束:table 1--><!--开始:新闻内容-->
<TABLE border=0 cellPadding=0 cellSpacing=0 width=750>
  <TBODY>
  <TR>
    <TD colSpan=5 height=25></TD></TR>
  <TR vAlign=top>
    <TD align=middle vAlign=top width=109>
      <TABLE border=0 cellPadding=0 cellSpacing=0 width="100%">
        <TBODY>
        <TR>
          <TD align=middle height=250 vAlign=top><A 
            href="http://www.swm.com.cn"><img src="/images/meiti_logo/logo_softwareworld.gif" border="0" width=100 height=43></A><BR><BR><BR><BR> <BR></TD></TR>
        <TR>
          <TD class=title12 height=18>
          </TD></TR></TBODY></TABLE></TD>
    <TD bgColor=#000000 width=1><BR></TD>
    <TD width=8><BR></TD>
    <TD vAlign=top width=520>
<CENTER><FONT COLOR=#000066 size=5><B>Windows 95/98下高效率串行通信的实现</B></FONT><br>

<HR WIDTH=520 ALIGN="center" SIZE=1>
<FONT FACE="Arial" SIZE=2>http://tech.sina.com.cn 2001/03/12&nbsp;11:06 </FONT><FONT COLOR="#990000" class=title12>软件世界</FONT>&nbsp;<FONT COLOR="#000000" class=title12>韩磊 徐磊</FONT></center><font class=confont>   
      <p>  1. 引言<p>  由于串行通信具有结构简单、可靠性高等优点,因而在工业监控、数据采集等实时系统中得到了广泛的应用。目前,PC与PC之间,PC与单片机之间大都采用这种通信方式。而在Windows下通信程序的设计与在DOS下有着显著的不同,Windows 95/98操作系统将底层的硬件进行了封装,不允许程序员直接对其进行操作,而是提供了大量的WIN32 API函数来作为用户程序与通信硬件的接口。由于在实际的应用中,对串行通信的可靠性、实时性有着较高的要求,因而本文在简单阐述在Windows 95/98平台下实现串行通信的基本方法的基础上,着重介绍如何利用Windows 95/98的多线程机制和重叠I/O实现高效率的串行通信。<p><p>  2. Windows 95/98下重叠I/O(异步)串行通信的实现<p>  Windows 95/98系统为串行通信提供了全新的服务。它以WIN32 API作为其应用程序的编程接口,提供了打开及关闭通信资源句柄及读写的基本操作。更为重要的是,它支持重叠式(即异步)输入输出。在用WIN32 API函数读写串口时,既可以同步执行,也可以重叠(异步)执行。同步执行时,函数直到操作完成后才返回,这就有可能导致线程的阻塞,从而使效率下降;重叠执行时,即使操作还未完成,函数也会立即返回,I/O操作将在后台进行,从而极大地提高了CPU的利用率和程序的执行效率。<p>  下面,就分步详细介绍一下如何实现重叠I/O。<p>  (1)串口的打开和关闭<p>  在WIN 32系统中串口的打开是用API函数CreateFile实现的,该函数的声明为:<p>  HANDLE CreateFile(<p>  LPCTSTR lpFileName,//文件名<p>  DWORD dwDesiredAcess,//访问模式<p>  DWORD dwShareMode,//共享模式<p>  LPSECURITY_ATTRIBUTES lpSecurityAttributes,//通常为NULL<p>  DWORD dwCreationDistribution,//创建方式<p>  DWORD dwFlagsAndAttributes,//文件属性和标志<p>  HANDLE hTemplateFile,//临时文件句柄,通常为NULL<p>  );<p>  对于I/O方式,必须指定串口的FILE_FLAG_OVERLAPPED属性。使用完串口后应用CloseHandle函数关闭串口。<p>  (2)串口的初始化<p>  串口打开后,需要做一些初始化工作,例如:波特率、数据位数、奇偶校验、停止位数等。这些信息都包含在一个DCB结构中。要得到当前的串口配置,可使用GetCommState函数,该函数的声明为:BOOL GetCommState(HANDLE hFile,LPDCB lpDCB),它把当前的配置添充到一个DCB结构中。然后可以根据需要来设置DCB结构中的成员变量,再调用SetCommState函数用该DCB结构来设置串口。此外,程序还需设置I/O缓冲区的大小和超时。输入和输出缓冲区的大小通过调用SetupComm函数来实现,该函数的声明为:BOOL SetupComm(HANDLE hFile,DWORD dwInQueue,DWORD dwOutQueue),其中dwInQueue和dwOutQueue分别为输入和输出缓冲区的大小。超时的查询和设置则通过GetCommTimeouts、SetCommTimeouts函数和COMMTIMEOUTS结构来实现。本文中,为了讨论上的方便,我们不使用超时设置。下面就以一段程序为例,来看一下如何打开并初始化串口。<p>  HANDLE hCom;<p>  DWORD dwError;<p>  DCB dcb;<p>  COMMTIMEOUTS timeOuts;<p>  If(hCom=CreateFile("COM1",//打开COM1口<p>  GENERIC_READ|GENERIC_WRITE,//允许读写<p>  0,//独占方式<p>  NULL,<p>  OPEN_EXITING,//打开而不是创建<p>  FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,<p>  //重叠方式<p>  NULL)==INVALID_HANDLE_VALUE)<p>  dwError=GetLastError();<p>  ...... //处理错误<p>  SetCommTimeouts(hCom,&timeouts);<p>  //不使用超时,将timeouts结构设置为零<p>  SetupComm(hCom,1024,1024);//设置缓冲区大小<p>  GetCommState(hCom,&dcb);<p>  dcb.BaudRate=CBR_9600;//设置波特率<p>  dcb.ByteSize=8;<p>  ......<p>  SetCommState(hCom,&dcb);<p>  (3)串口的读写<p>  串口的读写分别用ReadFile和WriteFile函数实现。前面已经指出,串口的读写既可以同步进行,也可以重叠(异步)执行,下面我们就以读串口为例,来讨论一下重叠I/O的实现方法。<p>  ReadFile函数的声明为: <p>  BOOL ReadFile(<p>  HANDLE hFile, //要读取的串口句柄<p>  LPVOID lpBuffer, //读缓冲区<p>  DWORD nNumberOfBytesToRead, //要求读入的字节数<p>  LPDWORD lpNumberOfBytesRead,//实际读入的字节数<p>  LPOVERLAPPED lpOverlapped <p>  //指向一个OVERLAPPED结构的指针 <p>  );<p>  要使用重叠I/O,除了要在CreateFile函数中指定FILE_FLAG_OVERLAPPED标志外,线程还需为ReadFile函数创建一OVERLAPPED结构,该结构包含一个事件对象句柄hEvent,它是读写函数是否完成的标志。如果读写操作还未完成,函数就返回,就把hEvent置于无信号状态,操作完成后,再将它设置成有信号的。为此,线程还要用CreateEvent函数创建一手工重置事件。<p>  读写操作完成后(包括超时),函数返回TRUE,否则返回FALSE。需要注意的是,在使用重叠I/O时,读写操作还未完成,函数就有可能返回,此时函数返回FALSE,但操作并未失败。因此,当函数返回FALSE时,应立即调用GetLastError函数分析返回的结果。若返回结果为ERROR_IO_PENDING,则说明重叠操作还未完成,这时线程可以调用GetOverlappedResult结构等待操作完成。该函数的声明为:<p>  BOOL GetOverLappedResult(<p>  HANDLE hFile,<p>  LPOVERLAPPED lpOverlapped,<p>  LPDWORD lpNumberOfBytesTransferred,<p>  //实际传输的字节数<p>  BOOL bWait<p>  );<p>  将bWait设置为TRUE,函数就会等待lpOverLapped所指向的OVERLAPPED结构的hEvent事件,并报告实际传输的字节数等信息。<p>  下面我们就以一程序为例,来看一下以重叠方式读串口的基本方法:<p>  OVERLAPPED overlapped;<p>  DWORD dwWantLength,dwRealLength,dwErrorFlags;<p>  COMSATE ComSate;<p>  overlapped.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);<p>  if(!ReadFile(hCom,lpBuffer,dwWantLength,<p>  &dwRealLength,&overlapped));//读取串口<p>  ///返回FALSE<p>  {<p>  if(GetLastError()==ERROR_IO_PENDING) <p>  //重叠操作正在进行 <p>  while(GetOverlappedResult(hCom,<p>  &overlappedresult, //等待重叠操作 <p>  &dwLength,TRUE))<p>  AfxMessageBox("Reading has finished!");<p>  else //发生错误<p>  {<p>  dwLength=0;<p>  ClearCommError(hCom,&dwErrorFlags,&ComSate);<p>  If(dwErrorFlags>0)<p>  AfxMessageBox("Reading error!");<p>  ......//处理错误<p>  }<p>  else<p>  {......}<p><p>  3. 使用多线程机制<p>  在实际的串行通信应用中,通信请求的产生往往是随机的、突发性的。而Windows系统在接收到通信请求后,只和通信缓冲区进行数据交换,并不通知用户进程。这样,用户进程只能通过定时查询串口等方式进行通信,但往往会由于对通信请求反应的不及时而造成通信的错误及不可靠。<p>  Windows 95/98中,WIN32应用程序组采取的抢占式多任务方式与Windows 3.1下WIN16应用程序的协同多任务方式不同,它可以同时执行多个进程和多个线程。线程是一个代码单元,在操作系统运行时标志着代码运行流。每个进程都有私有的虚拟地址空间,并可以拥有多个线程,进程的所有线程共享同一地址空间。每个线程被CPU分配一个时间片,一旦被激活,它正常运行到时间片耗尽并被挂起,然后操作系统选择另一线程进行工作。通过时间片轮转,又由于时间片很小,大约20毫秒级,就像多个线程在同时运行,这样可以充分挖掘CPU的潜力,增强用户进程的反应能力,以及进行后台处理,从而提高用户进程的效率。<p>  为此,我们可以利用Windows 95/98系统的抢占式多任务的特点,在用户进程的主线程之外,再建立一个通信监视线程,来监视通信事件的发生。<p>  在WIN32应用程序中,线程被分为两类:工作线程(Worker Thread)和用户界面线程(User Interface Thread)。前者常用于处理后台任务,执行这些后台任务并不会耽搁用户对应用程序的使用。鉴于工作线程的这些特点,我们就利用它来监视串口。工作线程的建立分两步来进行:首先编写线程控制函数,然后再启动线程。控制函数定义了线程。通常线程启动时,这个函数就被执行了。该函数的声明为:<p>  UINT CommProc(LPVOID pParam);<p>  线程的启动可使用全局函数AfxBeginThread。在调用该函数的时候,需要将控制函数的名称和控制函数的参数作为参数传递给它。<p>  还有一点需要声明,当我们建立专门的线程来监视串口时,需要指定被监视事件,即建立事件屏蔽。这就要调用SetCommMask函数。如果要得到当前的被监视变量,则可调用GetCommMask函数。然后,线程调用WaitCommEvent函数来监视被指定的事件。当指定范围内的某一事件发生后,线程就结束等待并把该事件的屏蔽码设置到事件屏蔽变量中。需要注意的是,WaitCommEvent只检测调用该函数后发生的事件。<p>  在具体的编程中,我们可以把串口的初始化、事件屏蔽变量的建立及启动监视线程的工作放在主线程中进行,监视线程主要负责监视串口事件并向主线程发送消息(读写工作也可放在监视线程中)。这样,要实现多线程异步输入输出,首先需要在串口的初始化代码中加入如下代码(这里,我们只以读串口为例):<p>  SetCommMask(hCom,EV_ERR|EV_RXCHAR);<p>  //监视错误和输入缓冲区接收到新字符事件<p>  在初始化代码的最后添加:<p>  AfxBeginThread(WatchProc,pParam);<p>  然后,再构建线程控制函数:<p>  UINT WatchProc(LPVOID pParam)<p>  { DWORD dwEventMask=0;//事件屏蔽变量<p>  WaitCommEvent(hCom,&dwEventMask,NULL);<p>  //等待指定事件的发生<p>  if((dwEventMask & EV_RXCHAR)==EV_RXCHAR)<p>  {......}//读缓冲区<p>  if((dwEventMask &EV_ERR)==EV_ERR)<p>  {......}//处理错误<p>  return 0;<p>  }<p><p>  4. 结束语<p>  以上给出了利用多线程机制和重叠I/O在Windows 95/98平台下实现串行通信的基本思想。在实际的工程应用中,如果能够灵活地加以利用,则对增强应用程序的灵活性、实时反应能力,以及提高程序的运行效率有很大的帮助。<p></font>
	 <table width=90% border=0 align=center>
	 <tr></tr>
	 </table>
	 <br>
      <DIV align=right class=title12>【<a href=http://comment.sina.com.cn/cgi-bin/news/release1/news_face1?Windows%2095%2F98%CF%C2%B8%DF%D0%A7%C2%CA%B4%AE%D0%D0%CD%A8%D0%C5%B5%C4%CA%B5%CF%D6+http://tech.sina.com.cn/c/1585.html+1585+1>发表评论</a>】【<a href=http://bbs2.sina.com.cn/show.shtml?tech:newbie>初学者园地</a>】【<a href=http://chat27.sina.com.cn/cgi-bin/chat/go?channel=科技聊天室>科技聊天</a>】【<A 
      href="javascript:window.close()">关闭窗口</A>】</DIV><BR>
      <table width=100% border=0 cellspacing=0 cellpadding=0><tr><td bgcolor=#455ca2><table width=100% border=0 cellspacing=1 cellpadding=3><tr><td bgcolor=#dcdcdc class=title12> 相关链接</td></tr><tr><td bgcolor=#ffffff class=title14><a href=http://tech.sina.com.cn/it2/55882.shtml target=_blank>Cypress推出了EZ-USB&#8482;SX2智能串行接口引擎</a><font COLOR=#6666cc> (2001/03/01 14:21)</font><br><a href=http://tech.sina.com.cn/news/computer/2000-02-16/17537.shtml target=_blank>经验杂谈:如何寻找丢失的串口</a><font COLOR=#6666cc> (2000/02/16 11:50)</font><br><a href=http://games.sina.com.cn/handbook/9908/081284.shtml target=_blank>答疑解难:CM3怎么联机玩?我用串口,谢谢!</a><font COLOR=#6666cc> (1999/08/12 00:00)</font></td></tr></table></td></tr></table>
      <P>
      <!--广告--><!--广告结束--><!--
<div align=right><a href=http://tech.sina.com.cn/hotnews/cnnic/index.shtml target=_blank><font size=2 color=red>资料:中国互联网权威管理机构CNNIC</font></a><div>
--></TD>
    <TD width=112><BR></TD></TR></TBODY></TABLE><!--结束:新闻内容-->
<CENTER>
<!--标准尾-->
<p class=tail12><a href=http://home.sina.com.cn/intro/intro.shtml >网站简介</a> | <a href=http://members.sina.com.cn>用户注册</a> | <a href=http://home.sina.com.cn/intro/ads.shtml>广告服务</a> | <a href=http://www.sina.com.cn/intro/recruit.shtml>招聘信息</a> | <a href=http://home.sina.com.cn/intro/chinesereading.shtml>中文阅读</a> | <a href=http://richwin.sina.com.cn>Richwin</a> | <a href=http://home.sina.com.cn/intro/contacts.shtml>联系方式</a> | <a href=http://home.sina.com.cn/intro/help.shtml>帮助信息</a> | <a href=http://home.sina.com.cn/intro/lawfirm.shtml>网站律师</a>
<p class=tail12>Copyright &copy; 1996 - 2001 SINA.com, Stone Rich Sight. All Rights Reserved<br><br><img src=http://image2.sina.com.cn/home/image/c.gif
 width=1 height=1><a href=http://home.sina.com.cn/intro/copyright.shtml target=_blank>版权所有</a> 四通利方 新浪网</center><LAYER       
height="60" width="468" visibility="hidden" 
onLoad="moveToAbsolute(layer1.pageX,layer1.pageY);clip.height=60;clip.width=468; visibility='show';" 
SRC="http://ad.cn.doubleclick.net/adl/tech.sina.com.cn/;;num=364658647415139.2?"></LAYER></CENTER></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -