本帖最后由 群发软件 于 2017-8-13 23:49 编辑
Delphi程序的串口通信亲你有没有玩过绝招
是新一代可视化开发工具,它具有功能强大、简便易用和代码执行速度快等特点,是全球公认的快速应用开发工具技术的先驱者,它越来越在构架企业信息系统方面发挥着重要作用。由于Delphi 这些显著特点,许多程序员选择Delphi作为开发工具编制各种应用程序。但是,令人惋惜的是Delphi没有自带串口通讯的控件,在它的帮助文档里也没有提及串口通讯,这就给编制通讯程序的开发人员带来众多麻烦,影响了开发进度,下面就这一技术进行讨论。
用Delphi 实现串口通讯,常用的几种方法为:使用控件如MSCOMM和SPCOMM,使用API函数或者在Delphi 中调用其它串口通讯程序。利用API编写串口通信程序较为复杂,需要掌握大量通信知识,其优点是可实现的功能更强大,应用面更广泛,更适合于编写较为复杂的低层次通信程序。相比较而言,利用SPComm控件则相对较简单,该控件具有丰富的与串口通信密切相关的属性及事件,提供了对串口的各种操作。
使用控件这一方法容易掌握,而SPCOMM支持多线程,所以SPCOMM控件的应用更加广泛。结合实例详细介绍SPCOMM的使用。
一.SPCOMM控件的安装
1.选择下拉菜单Component的第二项Install Component 。
图1
弹出图1所示的窗口,在Unit file name 处填写控件SPCOMM控件所在路径,其它可用默认值,点击OK按纽。
2.安装成功后,system控件面板中将出现一个红色控件COMM。现在使用COMM控件可以象Delphi自带控件一样使用.。
二.SPCOMM的主要属性,方法和事件
1.属性
CommName:填写COM1,COM2…等串口的名字,在打开串口前,必须填写好此值。
BaudRate:设定波特率9600,4800等,根据实际需要来定,在串口打开后也可更改波特率,实际波特率随之更改。
ParityCheck:奇偶校验。
ByteSize:字节长度_5,_6,_7,_8等,根据实际情况设定。
Parity:奇偶校验位
pBits:停止位
SendDataEmpty:这是一个布尔属性,为true时表示发送缓存为空,或者发送队列里没有信息;为False时表示表示发送缓存不为空,或者发送队列里有信息。
2.方法
Startcomm过程用于打开串口,当打开失败时通常会报错,错误主要有7种:
⑴串口已经打开 ;
⑵打开串口错误 ;
⑶文件句柄不是通讯句柄;
⑷不能够安装通讯缓存;
⑸不能产生事件 ;
⑹不能产生读进程;
⑺不能产生写进程;
StopComm过程用于关闭串口,没有返回值。
函数WriteCommData(pDataToWrite: PChar;dwSizeofDataToWrite:Word ): boolean 用于发送一个字符串到写线程,发送成功返回true,发送失败返回false, 执行此函数将立即得到返回值,发送操作随后执行。函数有两个参数,其中 pdatatowrite是要发送的字符串,dwsizeofdatatowrite 是发送的长度。
3.事件
OnReceiveData : procedure (Sender: TObject;Buffer: Pointer;BufferLength: Word) of object
当输入缓存有数据时将触发该事件,在这里可以对从串口收到的数据进行处理。Buffer中是收到的数据,bufferlength是收到的数据长度。
OnReceiveError : procedure(Sender: TObject; EventMask : DWORD)
当接受数据时出现错误将触发该事件。
三.SPCOMM的使用
下面,我们结合一个串口通讯的例子来说明SPCOMM的使用。
为了实现PC与单片机8051之间的通讯,首先要调通它们之间的握手信号,假定它们之间的通讯协议是,PC到8051一帧数据6个字节,8051到PC一帧数据也为6个字节,当PC发出(F0,01,FF,FF,01,F0)后能收到这样一帧(F0,01,FF,FF,01,F0),表示数据通信握手成功,两者之间就可以按照协议相互传输数据。在PC方要发送及接受数据需要以下步骤:
1.创建一个新的工程COMM.DPR,把窗体的NAME属性改为FCOMM,把窗体的标题改为测试通讯,添加控件。
对COMM1(黑色矩形围住的控件)进行属性设计,设波特率4800,校验位无,字节长度_8,停止位_1,串口选择COM1。Memo1中将显示发送和接受的数据。选择File/Save As将新的窗体存储为Comm.pas。
2.编写源代码
变量说明
var
FCOMM: TFCOMM;
Viewstring:string;
i:integer;
rbuf,sbuf:array[1..6] of byte;
打开串口
procedure TFCOMM.FormShow(Sender: TObject);
begin
comm1.StartComm;
end;
关闭串口
procedure TFCOMM.FormClose(Sender: TObject; var Action: TCloseAction);
begin
comm1.StopComm;
end;
发送数据
自定义的发送过程
procedure senddata;
var
i:integer;
commflg:boolean;
begin
viewstring:="";
commflg:=true;
for i:=1 to 6 do
begin
if not fcomm.comm1.writecommdata(@sbuf,1) then
begin
commflg:=false;
break;
end;
sleep(2); {发送时字节间的延时}
viewstring:=viewstring+inttohex(sbuf,2)+" ";
end;
viewstring:="发送"+viewstring;
fcomm.memo1.lines.add(viewstring);
fcomm.memo1.lines.add("");
if not commflg then messagedlg("发送失败!",mterror,[mbyes],0);
end;
procedure TFCOMM.Btn_sendClick(Sender: TObject);{发送按钮的点击事件}
begin
sbuf[1]:=byte($f0); {帧头}
sbuf[2]:=byte($01); {命令号}
sbuf[3]:=byte($ff);
sbuf[4]:=byte($ff);
sbuf[5]:=byte($01);
sbuf[6]:=byte($0f); {帧尾}
senddata;{调用发送函数}
end;
接收过程
procedure TFCOMM.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
i:integer;
begin
viewstring:="";
move(buffer^,pchar(@rbuf^),bufferlength);
for i:=1 to bufferlength do
viewstring:=viewstring+inttohex(rbuf,2)+" ";
viewstring:="接受"+viewstring;
memo1.lines.add(viewstring);
memo1.lines.add("");
end;
如果memo1上显示发送F0 01 FF FF 0F 和 接受F0 01 FF FF F0
这表示串口已正确的发送出数据并正确的接受到数据,串口通讯成功。
由Borland公司开发的Delphi语言是一种新生代的面向对象的可视化编程语言,它以其简洁的代码、精美的界面、易学易懂的特点深受人们的喜爱。相对传统测控系统开发语言如C、C++、VC、VB及汇编语言,Delphi的最大特点就是界面制作更加简单和美观、数据库功能更加强大,它支持Oracle、SQL、
功能完备的可视组件库——Server等大型数据库。同时由于它具有强大的BDE数据库引擎和种类齐全、
VCL,直接调用WindowsAPI函数以及直接嵌入式汇编语言等特点,使其在测控系统中应用越来越广泛。Delphi的多线程技术使数据采集和现场控制速度更加快捷。在Delphi中多线程为TThread对象,通过创建线程,合理安排CPU的时序,从而大大提高CPU的使用效率。但令人惋惜的是Delphi没有自带的串行口通讯控件,这就给编制通讯程序带来众多麻烦,影响了开发进度。不过,现在已经有许多公司的硬件产品支持Delphi,它们提供了Delphi的驱动程序库函数。开发人员可以通过调用这些函数实现串行口通讯。由于提供这些库函数的硬件并不普及,而且这些函数专用性较强,不能满足开发者的全部要求。
对于测控系统来说,数据采集是关键的一环,数据采集技术在工业控制及自动化等领域中发挥着重要的作用。数据采集的一般过程是这样的:??向采集卡发出通道选择指令,选择要采集的通道号。??启动A/D转换。 等待,直到转换完成。!从采集卡读出数据。而数据采集也无非是对总线上的I/O端口进行操作,现场检测元件(各类传感器)通过RS232或直接将模拟量通过二次仪表转换后送给工控机或微机串行口,而串行口需快速连续的读写串行口数据,并进行换算,将转换结果显示,对I/O的读写必须编制输入输出程序实现对硬件的操作。在Delphi中有三种不同的方法可以制作成输入输出子程序,以便在程序中调用。利用Delphi开发测控系统的三种不同串行口通信方法是:一是在Delphi程序中嵌入汇编语言;二是调用WindowsAPI函数实现串行口通讯;三是利用Delphi提供的ActivX通讯控件如MSCOMM或SP-COMM。下面分别详细介绍它们的具体应用方法。
2 Delphi串行口通讯的三种不同实现方法
2.1 利用嵌入式汇编语言
Delphi的嵌入式汇编语言支持所有的8086/8087和80386/80387指令,可放在程序可执行部分的收文日期:2001-06-08
(,(,
第3期李志合等
elphi程序中实现串行口通讯的三种方法—53—任何地方。汇编语言模块必须以关键字ASM开头、END结束,以便和其他语句分开。在其范围内的变量都可以直接调用。与以前的TurboAssember不同,标号、注释、变量声明都遵循Delphi规则,系统可以直接对这些语句进行编译,无需安装额外的汇编编译系统。开发者不必了解程序中现场保护或变量调用等细节,这一切均由系统自动完成。用嵌入式汇编进行串行口通讯的基本的输入输出子程序如下。
ProcedureOutport(addressout:word;valueout:byte); //定义数据输出子程序,实现串行口写操作
Begin
Asm//嵌入汇编开始标示符
Moval,valuout//送控制字
Movdx,addressout //送地址
Outdx,al //向地址写控制字
End; //嵌入式汇编结束标示符
End;
ProcedureInport(addressin:word):byte; //定义数据输入子程序
Begin
Asm
Movdx,addressin //送地址
Inal,dx
Mov@result,al //读数据
End;
End;
定义了以上两个输入输出子程序以后,就可以在程序中调用它,实现对串行口的读写操作。利用嵌入式汇编代码简单、效率高,是数据采集和自动控制优先选用的方法。
2.2 利用windows提供的API函数
Delphi作为编程语言,可以方便的调用CreateFile、ReadFile、WriteFile、SetupComm、BuildCommD-CB、SetCommState等WindowsAPI函数,实现对串行口的输入输出控制操作。在Windows环境下,对于串行口通讯的控制是通过中断机制驱动的,由系统自行处理。Windows禁止应用程序直接和硬件打交道,程序员只能使用Windows提供的标准函数通过通讯驱动程序与硬件接口。首先,用CreateFile()函数打开通讯端口,然后通过SetupComm()函数给通讯的输入输出队列分配一定大小的内存缓冲区,接着通过BuildCommDCB()函数和SetCommState()等函数对主要通讯参数进行设置。初始化完成后就可以利用
下面列出串行口操作的几个函数和串行ReadFile()函数和WriteFile()函数对通讯端口进行读写操作了。
口初始化函数:
FunctionComOpen(sPara:String):Thandle; //定义串行口初始化函数
VarPparaa:array[0..20]ofChar, //变量生明
Hcom:Thandle;
DCB:TDCB;
CommTimesout:TcommTimeouts;
Begin
Result:=0;
StrPCopy(pPara,sPara);
BuildCommDCB(pPara,DCB);
WithCommTimeoutsdo
Begin
ReadIntervalTimeout:=MAXDWORD;
ReadTotalTimeoutMultiplier:=200;
ReadTotalTimeConstant:=5000
WriteTotaltimeoutConstant:=200;
Hcom:=CreateFile(Pchar(Copy(sPara,1,4)),GENERRIC_READ+GENERRIC_WRITE,FILE_FLAG_OVERLAPPEDD,0);
WriteTotaltimeoutConstant:=5000;
IfSetCommState(hcom,DCB)then
Begin
Showmessage(’串行口初始化成功!’);
End;
End;
End;
数据发送函数::;s
;
—54— 山 东 工 程 学 院 学 报2001年 DwWritten
WORD;
Ssend:array[0..80]ofchar;
Begin
StrPCopy(sSend,s);
Result:=WriteFile(hcom,SSend,length(s),DwWritten,nil);
End;
数据读取函数:
FunctionComRead(hcom:Thandle;s:string):Boolean;
Var
DwReadln
WWORD;
Sget:array[0..80]ofchar;
Begin
StrPcopy(Sget,s);
Result:=ReadFile(hcom,Sget,length(s),DwReadln,nil);
End;
以上只是几个对串行口操作的基本函数,定义了这几个函数后(包括串行口初始化、数据读写函数),可以利用它们方便快速的对串行口进行读写操作。这样数据采集的关键一步在Delphi环境下就解决了。
2.3 用ActiveX控件
从本质上讲,ActiveX控件是一个Ac-ActiveX控件是充分利用OLE和ActiveX技术的自定义控件。
tiveX服务器,它所有的OLE自动化与所有的ActiveX服务器一样,ActiveX控件需要在系统注册表中进行注册。ActiveX控件可以用许多产品来开发,包括Delphi、BorlandC++Builder、VisualC++以及Vi-sualBasic。这里我们采用Delphi5.0自带的MSComm和SPcomm通讯控件即VisualBasic6.0中的MSComm进行串行口通讯。这里主要就SPComm控件进行说明,MSComm控件和SPComm控件大同小异,用法基本相同。
2.3.1 SPComm控件的主要属性见附表。
附表 SPComm控件的主要属性
属性CommName
BaudRate
ParityCheck
ByteSize
Parity
StopBitsSend-
DataEmpty属 性 说 明填写COM1,COM2…等串行口的名字,在打开串行口前,必须填写好此值设定波特率9600,4800等,根据实际需要来定,在串行口打开后也可更改波特率,实际波特率随之更改奇偶校验字节长度5,6,7,8等,根据实际情况设定奇偶校验位停止位这是一个布尔属性,为true时表示发送缓存为空,或者发送队列里没有信息;为False时表示表示发送缓存不为空,或者发送队列里有信息
2.3.2 SPComm的主要方法:Startcomm过程用于打开串行口,当打开失败时通常会报错,错误主要有7种
1)串行口已经打开;(2)打开串行口错误;(3)文件句柄不是通讯句柄;(4)不能够安装通讯缓存;
(5)不能产生事件;(6)不能产生读进程;(7)不能产生写进程。StopComm过程用于关闭串行口,没有返回值。函数WriteCommData(pDataToWrite
Char;dwSizeofDataToWrite:Word):boolean用于发送一个字符串到写线程,发送成功返回true,发送失败返回false,执行此函数将立即得到返回值,发送操作随后执行。函数有两个参数,其中pdatatowrite是要发送的字符串,dwsizeofdatatowrite是发送的长度。
2.3.3 SPComm的主要事件:OnReceiveData:procedure(Sender:TObject;Buffer
ointer;Buffer-Length:Word)ofobject。当输入缓存有数据时将触发该事件,在这里可以对从串行口收到的数据进行处理。Buffer中是收到的数据,bufferlength是收到的数据长度。
OnReceiveError:procedure(Sender:TObject;EventMask
WORD);当接受数据时出现错误将触发该事件。
我们已经知道了这些属性、方法、事件,以后所要做的就是对属性进行设置,对事件编程序。由于Ac-tiveX控件封装了许多复杂的环节,使编程大为简单化。
2.3.4 MSComm控件有几个重要属性、方法和事件与SPComm控件基本相同,只是名称稍不同读者可
第3期李志合等
elphi程序中实现串行口通讯的三种方法—55—
另外需要指出的是Activex控件能够无缝地集成到Delphi的IDE中,但它不象Delphi组件那样能够直接建在程序的可执行文件中,它是通过COM与应用程序通讯的,而Delphi组件是直接与应用程序进行通讯。所以,它比Delphi组件运行的慢些。但在大多数情况下,这种差别是微不足道的。另外,还要注意这样一个问题,当发布使用带有ActiveX的应用程序时,要把控件及相关的文件一并拷贝发布使用:必须附带ActiveX控件的OCX或DLL文件,因为OCX与DLL文件在设计时没有链接到应用程序的可执行文件中。一旦脱离Delphi设计环境而又缺少这些文件则程序将无法运行;必须在系统注册表中注册ActiveX控件。关于ActiveX控件的注册请参考有关书籍。
3 结论
通过以上介绍,可以知道Delphi在编制测控分析软件中串行口通讯的三种编程方法为:利用嵌入式汇编语言、WindowsAPI函数和ActiveX的SPComm和MSComm通讯控件,它们都能实现对串行口的读写操作。利用嵌入式汇编代码简单、效率高,是数据采集和自动控制优先选用的方法;利用Windows