我这里有一个完整的例子,你看看,比较长<br>Delphi中串行通信的实现<br><br>随着现代信息技术的发展以及计算机网络的广泛使用,计算机通信技术已经日臻成熟<br>,但串行通信作为一种灵活、方便、可靠的通信方式,仍不失为有效的通信手段,被广泛应<br>用于工业控制中。在工业生产实践中,用PC机对工程实现实时监控,通常要求PC机能在用<br>户界面上具有数据采集、数据处理以及控制信号的产生与传输等功能。在这种特定的环<br>境下,PC机要与过程控制的实时信号相联系,就要求能实现对PC机的串行端口直接操作。<br>Borland公司推出的Delphi是一种功能强大的高级编程语言,其可视化面向对象的特性,适<br>于在Windows环境下图形界面和用户程序的编制。本文介绍基于Windows 95/NT操作系统<br>用Delphi来实现PC机与下层PLC控制器之间的串口通信方法。<br>基于Windows 95/NT的串行通信机制<br>Windows操作系统禁止应用程序直接访问计算机硬件,但它为程序员提供了一系列标<br>准API函数,使得应用程序的编制更加方便,并且免除了对有关硬件调试的麻烦。在Windo<br>ws 95/NT中,原来Windows 3.X的WM_COMMNOTIFY消息已被取消,操作系统为每个通信设备<br>开辟了用户可定义大小的读/写缓冲区,数据进出通信口均由操作系统后台完成,应用程序<br>只需对读/写缓冲区操作即可。Windows 95/NT中几个常用的串行通信操作函数如下:<br>@@0474300.JPG;表1@@<br>除上述几个函数外,还要经常用到一个重要的记录DCB(设备控制块)。DCB中记录有可<br>定义的串行口参数,设置串行口参数时必须先用GetCommState函数将系统默认值填入DCB<br>控制块,然后才可设定用户想改变的自定义值。<br>在Windows 95/NT中实现串行通信除了要了解基本的通信操作函数外,还要掌握多线<br>程编程。线程是进程内部执行的路径,是操作系统分配CPU时间的基本实体,每个进程都由<br>单线程开始完成应用程序的执行。串行通信需要利用多线程技术实现,其主要的处理逻辑<br>可以表述如下:进程一开始先由主线程做一些必要的初始化工作,然后主线程根据需要在<br>适当时候建立线程监视通信口,当指定的串行口事件发生时,向主线程发送WM_COMMNO<br>FY消息(由于Windows 95取消了WM_COMMNOTIFY消息,因此程序员必须自己创建),主线程<br>对其进行处理。若不需要WM_COMMNOTIFY消息,则主线程终止通信监视线程。<br>多线程同时执行可能会引起对共享资源的冲突,为避免冲突,需要用同步多线程对共<br>享资源进行访问。Windows 95提供了许多保持线程同步的方法,笔者采用创建事件对象来<br>保持线程同步。通过CreateEvent()创建事件对象,使用SetEvent()或PulseEvent()函数<br>将事件对象设置成信号同步。在应用程序中,利用WaitSingleObject()函数等待同步的触<br>发,等到指定的事件被其它线程设置为有信号时,才继续向下执行程序。<br>Delphi下的具体实现方法<br>Delphi的强大功能和支持多线程的面向对象编程技术,使得实现串行通信非常简单方<br>便。它通过调用外部的API函数来实现,主要步骤如下。<br>1. 利用CreateFile函数打开串行口,以确定本应用程序对此串行口的占有权,并封锁<br>其它应用程序对此串口的操作;<br>2. 通过GetCommState函数填充设备控制块DCB,再通过调用SetCommState函数配置串<br>行口的波特率、数据位、校验位和停止位;<br>3. 创建串行口监视线程监视串行口事件,在此基础上就可以在相应的串口上操作数<br>据的传输;<br>4. 用CloseHandle函数关闭串行口(具体的程序如下)。本程序用Delphi3.0编写,在<br>Windows 95环境下调试通过,已投入实际应用中,供广大读者参考。<br>程序:<br>unit comdemou;<br>interface<br>uses<br> Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialo<br>gs;<br>const<br>Wm_commNotify=Wm_User+12;<br>type<br> TForm1 = class(TForm)<br>procedure FormCreate(Sender: TObject);<br> private<br>Procedure comminitialize;<br><br>Procedure MsgcommProcess(Var Message:Tmessage); Message Wm_commnotify;<br><br>{ Private declarations }<br><br> public<br><br>{ Public declarations }<br><br> end;<br><br> //线程声明<br><br> TComm=Class(TThread)<br><br> protected<br><br>procedure Execute;override;<br><br> end;<br><br>var<br><br> Form1: TForm1;<br><br> hcom,Post_Event:Thandle;<br><br> lpol
overlapped;<br><br>implementation<br><br>{$R *.DFM}<br><br>Procedure TComm.Execute;<br><br>//线程执行过程<br><br>var<br><br>dwEvtMask
word;<br><br>Wait:Boolean;<br><br>Begin<br><br>fillchar(lpol,sizeof(toverlapped),0);<br><br>While True do Begin<br><br> dwEvtMask:=0;<br><br> Wait:=WaitCommEvent(hcom,dwevtmask,lpol);<br><br> //等待串行口事件;<br><br> if Wait Then Begin<br><br>waitforsingleobject(post_event,infinite); //等待同步事件置位;<br><br>resetevent(post_event);<br><br>//同步事件复位;<br><br>PostMessage(Form1.Handle,WM_COMMNOTIFY,0,0);//发送消息;<br><br>end;<br><br> end;<br><br>end;<br><br>procedure Tform1.comminitialize;<br><br>//串行口初始化<br><br>var<br><br>lpdcb:Tdcb;<br><br>Begin<br><br>hcom:=createfile(‘com2’,generic_read or generic_write,0,nil,open_exist<br><br>ing,<br><br> file_attribute_normal or file_flag_overlapped,0);//打开串行口<br><br>if hcom=invalid_handle_value then<br><br>else<br><br>setupcomm(hcom,4096,4096);<br><br> //设置输入、输出缓冲区皆为4096字节<br><br>getcommstate(hcom,lpdcb);<br><br>//获取串行口当前默认设置<br><br>lpdcb.baudrate:=2400;<br><br>lpdcb.StopBits:=1;<br><br>lpdcb.ByteSize:=8;<br><br>lpdcb.Parity:=EvenParity;<br><br>//偶校验<br><br>Setcommstate(hcom,lpdcb);<br><br>setcommMask(hcom,ev_rxchar);<br><br> //指定串行口事件为接收到字符;<br><br>end;<br><br>Procedure TForm1.MsgcommProcess(Var Message:Tmessage);<br><br>var<br><br>Clear:Boolean;<br><br>Coms:Tcomstat;<br><br>cbNum,ReadNumber,lpErrors:Integer;<br><br>Read_Buffer:array[1..100]of char;<br><br>Begin<br><br>Clear:=Clearcommerror(hcom,lpErrors,@Coms);<br><br>if Clear Then Begin<br><br> cbNum:=Coms.cbInQue;<br><br> ReadFile(hCom,Read_Buffer,cbNum,ReadNumber,lpol);<br><br> //处理接收数据<br><br> SetEvent(Post_Event);<br>//同步事件置位<br> end;<br>end;<br>procedure TForm1.FormCreate(Sender: TObject);<br>begin<br>comminitialize;<br>post_event:=CreateEvent(nil,true,true,nil); //创建同步事件;<br>Tcomm.Create(False);<br>//创建串行口监视线程;<br>end;<br>end.<br>