实现基于VisualC 70的多线程串口通信_第1页
实现基于VisualC 70的多线程串口通信_第2页
实现基于VisualC 70的多线程串口通信_第3页
实现基于VisualC 70的多线程串口通信_第4页
实现基于VisualC 70的多线程串口通信_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、收稿日期:2001-11-11实现基于Visual C +710的多线程串口通信李东晓,李晓明,肖鲲,张发忠,彭家银(武汉大学电力工程系,湖北武汉430072摘要:串口通信程序多是用微软提供的MSC omm 控件实现的,但MSC omm 控件实现方法很难加入多线程技术提高程序的执行效率,尤其对微机与多台智能设备之间同时进行通信,这种方法的单线程局限性就更明显。为此,深入介绍了32位串口通信的结构体和Windows API 函数及多线程编程技术,并结合面向对象的编程思想,将Windows API 函数、结构体及多线程技术进行了封装,形成新的串口通信类CC ommunication ,该类可以完成

2、MSC omm 控件的所有功能,用该类开发的程序比用MSC omm 控件开发的程序的执行速度快。应用该类可很方便地实现基于Visual C +7.0多线程串口通信,且具有通用性好、使用性强等优点。关键词:Visual C +7.0;Windows API ;结构体;多线程;串口通信中图分类号:T N 91519文献标识码:A 文章编号:1006-6047(200209-0013-04本文深入介绍了如何实现基于Visual C +7.0的Win 32的多线程串口通信,用此方法实现了上位机与P LC (Omron C200H 之间的串口通信,应用到火电厂翻车机输煤实时监控系统中,具有稳定、可靠、实

3、用性强的特点。1实现方案Visual C +7.0作为面向对象编程语言的代表,与其他面向对象编程语言相比,Visual C +7.0不仅具有程序执行速度快(相当于汇编语言的优点,而且还可以与Windows API 函数实现无缝连接。因此,选用Visual C +7.0作为串口通信开发平台。用Visual C +7.0开发串口通信通常有4种方案。a.调用函数inp (和outp (直接读写串口。b.使用Visual C +7.0提供的串行通信控件MSC omm 。c.用单线程的方法实现自定义串口通信类,用这些类封装Windows API 提供的串口通信函数。d.用多线程的方法实现自定义串行通信类

4、,在单线程方法的基础之上加入多线程。本文深入研究多线程方法,基于Visual C +7.0的多线程串口通信,如何编写class CC ommunication 。111结构体1开发串口通信程序用到的结构体主要有DC B ,C OM MST ART 和OVER LAPPE D 三种。a.结构体DC B 用于经由SetC ommState (函数设置端口的参数。结构DC B 有一个很大的成员列表,这些成员包括端口的波特率、数据位、停止位、校验码、握手信息、控制信息等,详见文献1。b.结构体C OM MST ART 由G etC ommError (函数填充,包括BY TE status ,UI N

5、T cbInQue 和UI NT cbOutQue 三个成员函数。Status 包含一组标志,用于设置流控制信息(如设置CSTF CTSH O LD 标志,即表明在发送一个字符之前,发送器正在等待CTS 线变高;cbInQue 用于指明接收缓冲区中当前共有多少个字符;cbOutQue 指明在当前传送缓冲区中共有多少个字符。c.ReadFile (和WriteFile (将使用结构体OVER LAPPE D 管理重叠的I/O 。把这个结构体传递给函数,直到异步I/O 完成才释放它。再把同一结构体传递给G etOverlappedResult (,以获得I/O 操作的最后数据。112函数Micro

6、s oft 标识通信的API 函数有20多个。可分为打开串口、初始化串口、读写串口和关闭串口4个部分。a.打开串口,相关函数为CreateFile 函数。该函数用于创建或打开文件、通道、通信资源,并返回一个句柄,它是W in 32环境下打开端口的唯一方法。H AND LE CreateFile (LPCTSTR lpFileName ,DW O RD dwDesiredAccess ,DW ORD dwShareM ode ,LPSEC UR ITY ATTRI BUTES lpSecuity ,DW ORD dwCreationDisp osition ,DW ORD dwFlagsAndA

7、ttributes ,H AND LE hT em p lateFile lpFileName 为要打开的端口名,格式为C OMxx ;dwDesiredAccess 为端口的打开方式,有GE NERIC RE AD 和GE NERIC WRITE 。当打开通信端口时,只有同时使用两者才有意义;dwShareM ode 为文件的共享方式,一般将此参数设为0;lpSecurity 为安全级别,一般将此参数设为0;dwCreationDisposition 为文件存在方式,使用通信设备时,串口是存在的,总把此参数设为OPE N EXISTI NG;dwF1agsAndAttributes 为串口打

8、开的标志,其中,FI LE ATTRI BUTE NOR 2M A L 是必需的,FI LE F LAG OVER LAPPE D 用于指明将要使用文件完成重叠I/O ,若用多线程实现串口通信,此参数应设置为FI LE A TTRI BUTE NOR M A L |31第22卷第9期2002年9月电力自动化设备Electric P ower Automation Equipment FI LE F LAG OVER LAPPE D;hT em plateFile,对于串口通信,此参数没有任何意义,设为0。若函数成功调用,则返回打开串口的句柄,否则,返回值I NVA LI D H AND LE

9、VA LUE。b.初始化串口,主要包括函数G etC ommState, SetC ommState,SetupC omm,G etC ommProperties,G etC om2 mT imeouts,SetC ommT imeouts,这些函数用于设置串口通信所需的各类参数。BOO L G etC ommState(H AND LE hFile,LPDC B lpDC B用于设置结构体DC B的所有成员。hFile为通信设备句柄;lpDC B是指向结构体DC B的指针。调用成功返回TRUE,否则返回FA LSE。BOO L SetC ommState(H AND LE hFile,LPD

10、C B lpD2 C B用结构体DC B设置串口的所有可配置参数。hFile为通信设备句柄;lpDC B是指向结构体DC B的指针。调用成功返回TRUE,否则返回FA LSE。BOO L SetupC omm(H AND LE hFile,DW ORD dwIn2 Queue,DW ORD dwOutQueue设置驱动程序输入和输出缓冲区的大小,hFile 为通信设备句;dwInQueue为输入缓冲区的大小, dwOutQueue为输出缓冲区的大小。调用成功返回TRUE,否则返回FA LSE。BOO L G etC ommT imeouts(H AND LE hFile,LPC OMMTI M

11、 OUTS lpC ommT imeouts读入端口的当前超时值,设置结构体C OM MTIME OUTS的所有成员。hFile为通信设备句柄;LPC OM MTI M OUTS是指向结构体C OM MTI ME OUTS的指针。成功返回TRUE,否则返回FA LSE。BOO L SetC ommT imeouts(H AND LE hFile,LPC OMMTI M OUTS lPC Ommtimeouts用结构体C OM MTI ME OUTS设置端口的当前超时值。hFile为通信设备句柄;LPC OM MTI M OUTS是指向结构体C OM MTI ME OUTS的指针。成功返回TRU

12、E,否则返回FA LSE。BOO L PurgeC omm(H AND LE hFile,DW ORD dwFlags用于终止当前打开端口正在进行的输入和输出操作。hFile为通信设备句柄;dwFlags为命令掩码中设置的位,能够确定由这个函数调用完成的确切操作。成功返回TRUE,否则返回FA LSE。c.读写串口,包括函数ReadFile,WriteFile,Set2 C omm Mask和WaitC ommEvent,这些函数用于对串口进行读写和监控操作。BOO L ReadFile(H AND LE hFile,LPVOI D lpBu ffer, DW ORD nNumberO fBy

13、tesT oRead,LPDW ORD lpNumber2 O fBytesRead,LPOVER LAPPE D,lpOverlapped从串口读取数据的唯一函数。hFile用于读操作的端口句柄,由CreateFile函数创建;lpBu ffer指向接收缓冲区的指针;nNumberO fBytesT oRead为读入的字节数,应小于接收缓冲区的大小;lpNumber2O f2 BytesRead为接收函数调用期间读取的字节数;lpOverlapped指向一个OVER LAPPE D结构,异步读写时,更新此结构。成功返回TRUE,否则返回FA LSE。BOO L WriteFile(H AND

14、 LE hFile,LPVOI D lpBu ffer, DW ORD nNumberO fBytesT oRead,LPDW ORD lpNumber2 O fBytesRead,LPOVER LAPPE D,lpOverlapped向串口写数据的唯一函数。hFile用于读操作的端口句柄,由CreateFile函数创建;lpBu ffer指向发送缓冲区的指针;nNumberO fBytesT oRead为发送的字节数,应小于发送缓冲区的大小;lpNumberO fBytesRead 为写函数调用期间发送的字节数;lpOverlapped指向一个OVER LAPPE D结构,异步读写时,更新此

15、结构,成功返回TRUE,否则返回FA LSE。BOO L SetC omm Mask(H AND LE hFile,DW ORD dw2 EvMask设置一个打开的通信端口,当某些异步事件由WaitC ommEvent调用发生时,来报告这些事件。hFile 为要使用的端口句柄;dwEvMask为端口事件掩码,可以是下列事件的任意组合:E V BRE AK,E V CTS, E V DSR,E V ERR,E V RI NG,E V RI NG TE,E VR LS D,E V RX80FU LL,E V RXCH AR,E V RXF LAG, E V TXE MPTY。成功返回TRUE,否则

16、返回FA LSE。BOO L WaitC ommEvent(H AND LE hFile,LPDW ORD lpEvtMask LPOVER LAPPE D lpOverlapped等待从串口读入事件,hFile为要监视的端口句柄,lpEvtMask指向接收标志发生事件类型掩码的32位的变量,lpOverlapped指向一个OVER LAPPE D结构。成功返回TRUE,否则返回FA LSE。d.关闭串口,函数CloseHandle,关闭已打开的串口,停止一切输入和输出。BOO L CloseHand(Handle hObjecthObject指向已打开的通信端口句柄。成功返回TRUE,否则返

17、回FA LSE。113多线程Windows98/NT操作系统CPU的时间按一定的算法分配给多个任务,轮流处理各个任务,这就是并行多任务。在设计计算机通信程序时,需要采用并行编程机制完成各种任务。并行编程机制主要有多进程和多线程,与多进程相比,多线程能更充分地利用计算机的CPU,具有更高的效率。用Visual C+ 7.0的MFC(Micros oft F oundation Class实现多线程,要解决好构造线程、线程内通信和同步的问题。a.如何构造线程。在程序中调用函数A fx BeginThread(创建一个新线程。CW inThread3A fx BeginThread(AFX THRE

18、 ADPROC pfnThreadProc,LPVOI D pParam,int nPriority= THRE AD PRI ORITY NORM A L,UI NT nStackSize=0, DW ORD dwCreateFlags=0,LPSEC URITY ATTRI BUTES lpSecurityAttrs=NU LL其中,pfnThreadProc是线程函数名称,pParam是传递给线程的参数,nPriority为线程的优先级,一般来讲线程的优先级越高,线程获得CPU的时间越长。b.如何实现线程内部的通信。有多种方法实现进程中不同线程之间的通信,最好的方法是采用41电力自动化设

19、备2002年Windows消息映射和事件对象。c.如何实现线程的同步。实现线程通信同步有临界区、互斥体和信号灯3种方法。本文采取临界区技术,线程通过临界区技术安全访问数据。在程序中通过函数InitializeCriticalSection初始化临界区,函数EnterCriticalSection进入临界区,通过函数LeaveCriticalSection释放临界区,实现对临界区的控制。114封装类2在用Visual C+7.0开发串口通信软件时,可直接调用Windows API通信函数,实现串口通信,而更为有效的方法是将Windows API通信函数封装成类。本文将结构体和Windows AP

20、I通信函数封装成类CC ommunication。具体封装见类CC ommunication 的实现函数。11411初始化函数初始化函数用于封装打开串口和初始化串口Windows API函数。BOO L CC ommunication:Init(CWnd3pP ortOwner, UI NT port,UI NT baud,char parity,UI NT data bit,UI NT stop bit,DW ORD dwC ommEvents,UI NT readbu ffersize, UI NT writebu ffersize,BOO L bBinary,UI NT handShak

21、ing, BOO L bRTS,BOO L bDTRInitializeCriticalSection(&m csC ommunicationSy2 nc;初始化临界区EnterCriticalSection(&m csC ommunicationSync;进入临界区m hC omm=CreateFile(P ort,GE NERIC RE AD| GE NERIC WRITE,0,NU LL,OPE N EXISTI NG,FI LE F LAG OVER LAPPE D,0;创建文件句柄设置通信参数m C ommT imeouts.ReadIntervalT imeout=

22、1000;m C ommT imeouts.ReadT otalT imeoutMultiplier= 1000m C ommT imeouts.ReadT otalT imeoutC onstant= 1000;m C ommT imeouts.WriteT otalT imeoutMultiplier= 1000;m C ommT imeouts.WriteT otalT imeoutC onstant= 1000;if(SetC ommT imeouts(m hC omm,&m C omm2T ime2 outsif(SetC omm Mask(m hC omm,dwC ommE

23、ventsif(G etC ommState(m hC omm,&m dcbif(BuildC ommDC B(Baud,&m dcbif(SetC ommState(m hC omm,&m dcbelseProcessErrorMessage(“error”;PurgeC omm(m hC omm,PURGE RXC LE AR| PURGE TXC LE AR|PURGE RX ABORT|PURGE TX ABORT;终止串口操作LeaveCriticalSection(&m csC ommunicationSync;离开临界区return TRUE;11

24、412线程处理函数UI NT CC ommunication:C ommThread(LPVOI D pParam CC ommunication3pP ort=(CC ommunication3pPa2 ram;if(pP ort2>m hC ommPurgeC omm(port2>m hC omm,PURGE RX2 C LE AR|PURGE TXC LE AR|PURGE RX ABORT| PURGE TX ABORT;for(;无限期循环bResult=WaitC ommEvent(port2>m hC omm, &Event,&port2>

25、m ov;等待通信事件if(!bResultswitch(dwError=G etLastError(等待触发线程事件Event=WaitF orMultipleObjects(3,port2>m hEventArray,FA LSE,I NFI NITE;switch(Event case0:;异常case1:;读串口if(C ommEvent&E V RXCH ARReceiveChar(port,comstat;调用读串口函数break;case2:;写串口WriteChar(port;调用写串口函数break;11413读串口函数,完成串口的读操作v oid CC omm

26、unication:Receivechar(CC ommunication3 port,C OMST AT comstatfor(;无限循环bResult=ReadFile(port2>m hC omm,&RX Bu ff, 1,&BytesRead,&port2>m ov;:SendMessage(pP ort2>m pOwner2>m51第9期李东晓,等:实现基于Visual C+710的多线程串口通信hWnd,W M C OM M RXCH AR,(WPARAMRX Bu ff, (LPARAMport2>m nP ortNr;114

27、14调用线程函数,开始一个新的线程BOO L CC ommunication:StartThread(if(!(m Thread=A fx BeginThread(C ommThread, thisreturn FA LSE;return TRUE;11415挂起线程函数,挂起正在运行的线程BOO L CC ommunication:StopThread(m Thread2>SuspendThread(;return TRUE;11416写串口函数v oid CC ommunication:WriteChar(CC ommunication3 portResetEvent(port2&g

28、t;m hWriteEvent;触发线程的写事件EnterCriticalSection(&port2>m csC ommunic2ation2 Sync;if(bWrite串口写操作bResult=WriteFile(port2>m hC omm, port2>WriteBu ffer,strlen(char3port2>WriteBu ffer, &BytesSent,&port2>m ov;if(!bWrite异步处理bResult=G etOverlappedResult(port2>m hC omm,&port2&g

29、t;m ov,&BytesSent,TRUE;LeaveCriti2 calSection(&port2>m csC ommunicationSync;释放临界区2应用实例基于类CC ommunication的串口通信程序,应用到火电场翻车机实时监控系统中(上位机每隔一定的时间向P LC发送命令,并从P LC中读出数据,经现场运行使用,该通信程序能快速、准确地完成数据采集任务。在类CC ommunication的基础之上封装对M O2 DE M的控制函数,从而实现了远程智能设备的串口通信,基于类CC ommunication的通信程序应用于电能量数据采集系统中,充分发挥了

30、多线程的优势,能够快速、准确地完成对大量电能量数据的采集。参考文献:京:中国水利电力出版社,2000.NE LS ON M.Serial communication programmingM.T ranslat2 ed by X iaoxiang w orking studio.Beijing:Hydraulic and E lectric P ower Press,2000.2K RUG LI NSKI D J.Visual C+6.0技术内幕M.希望图书创作室译.第5版.北京:北京希望电子出版社,1999.K RUG LI NSKI D J.Visual C+6.0ProgrammingM.T rans2 lated by H ope book w orking studio.5thed.Beijing:BeijingH ope E lectronic Press,1999.(责任编辑:汪仪珍作者简介:李东晓(1975-,男,河南南阳人,硕士研究生,研究方向为电力系统运行与控制(E2mail:lnldx;李晓明(1955-,男,湖北应城人,教授,从事电力系统及其自动化专业的科研和教学工作;肖鲲(1978-,男,湖北荆州人,硕士研究生,研究方向为电力系统运行与控制;张发忠(1978-,男,湖北随州人,硕士研究

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论