sos ...!! 串口通讯问题!!!分数不够可以再加。(100分)

  • 主题发起人 主题发起人 ggscw
  • 开始时间 开始时间
G

ggscw

Unregistered / Unconfirmed
GUEST, unregistred user!
初次接触不知如何下手(最好有详细源码):
定时从串口(下位机)取数据,处理,过滤;写入数据库供查询使用。。。。
向串口写数据(对下位机进行参数设置)
注:下位机设备我没见过。只有如下资料

命令格式:$xxxxzyyyy $:命令引导符 ,xxxx:编号,z: 命令,yyyy:参数
请各位大侠指点迷津!!!谢谢。。。。


 
ggscw@sohu.com
或是给兄弟指条明路说个网址!!不胜感激。
 
清华大学曾出版过一本<Delphi与RS-232 通信>的书籍呢.讲的很详细的.去看看吧
我这有一篇关于串口的应用呢.留个地址发给你;
 
很简单嘛,你就定时用串口控件读数据(mscomm.input)
然后在分析你得到的数据的格式是不是你想要的格式,
然后再处理
 
对串口感兴趣的学友,能否交流一下,
我的QQ号码:22330699
 
yuanwl ,我的地址:ggscw@sohu.com 谢谢!

以前没接触过这方面的编程。。。近期准备向单片机方面发展,希望多多指教
qq :26480886 (很少上)
 
yanghai0437,给个具体一点的例子行吗?
 
最今刚好在搞这种项目,很简单的。
看看
人民邮电出版社的
《delphi串口通信编程》
第三章 很详细的。并且,看一下后面的crc检验也比较好。
 
看来我只有自己慢慢的看书了,可是由于时间的问题还是希望有人给个例子,关键是取回来以后的处理
和对下位机的参数设置。。。。
 
我也要啊,我不知道用什么控件啊,有那个ACtiveX,也就是人民邮电出版的书,但是,如果按书上说的,就可以了么?
我想做一个考勤机系统啊
谢谢,能不能聊了啊
 
可以用spcomm和mscomm控件,它时多线程的,设置它的端口号,波特率,奇偶校验等
Delphi 是新一代可视化开发工具,它具有功能强大、简便易用和代码执行速度快等特点,Delphi系列开发工具在国际各媒体上曾获得过三十多项大奖,是全球公认的快速应用开发工具技术的先驱者,他越来越在构架企业信息系统方面发挥着重要作用。

它的功能很强大,但在对串口通信的控制上Delphi的帮助文档和其他书籍中很少提及,可这是在开发应用系统时会经常遇到却又令人头痛的事情。下面介绍三种解决方案,以实现接收和发送数据的功能。

一、 使用ActiveX控件

由于Delphi中没有串口控件可用,所以首先需要把ActiveX控件MSCOMM加到元件选项板上。这是一个非常好的控件它不仅能对串口进行操作,而且还可以对Modem进行控制。下面结合一个具体的实例来说明如何用MSCOMM控件开发出串口通信程序。

创建一个Communication.dpr工程,把窗体的Name属性变为CommForm,将标题改为The Communication Test,选择File/Save As将新的窗体存储为CommFrm.pas,接下来参照图1和图2将控件添加到主窗体中。

图1 图2

由图1和图2我们可以看出,通过设置页可选定进行数据传输的通信端口和端口的波特率、奇偶校验、数据位和停止位,通信时每传输一个字符都将触发响应事件,在通信页“传输显示”位置可看到当前正在进行传输的数据。同时当出现回车换行符时将整行内容显示在memDisplay新的一行中,而全部接收的内容还将存在一个文件中。部分源代码如下:

变量说明

var

CommForm: TCommForm;

ss :string;

savef,readf :file of char;

i,j :longint;

初始化

procedure TCommForm.FormCreate(Sender: TObject);

begin

mscomm.commport:=1;

mscomm.settings:='9600,n,8,1';

mscomm.inputlen:=1;

mscomm.inbuffercount:=0;

mscomm.portopen:=true;

ss:='';

i:=0;

j:=0;

assignfile(savef,'save1');

rewrite(savef);

assignfile(readf,'read1');

reset(readf);

end;

设置确定

procedure TCommForm.btnConfirmClick(Sender: TObject);

begin

if mscomm.portopen then

mscomm.portopen:=false;

mscomm.commport:=strtoint(edtCommport.text);

mscomm.settings:=edtCommsetting.Text;

end;

传输事件

procedure TCommForm.MSCommComm(Sender: TObject);

var

filenrc :char;

buffer :variant;

s1:string;

c :char;

begin

case mscomm.commEvent of

comEvSend:

begin

while not(eof(readf)) do

begin

read(readf,filenrc);

mscomm.output:=filenrc;

j:=j+1;

lblDisplay.caption:=inttostr(j);

if mscomm.outbuffercount>=2 then

break;

end;

end;

comEvReceive:

begin

buffer:=mscomm.Input;

s1:=buffer;

c:=s1[1];

ss:=ss+c;

i:=i+1;

lblDisplay.caption:=c+inttostr(i);

write(savef,c);

if (c=chr(10))or(c=chr(13)) then

begin

lblDisplay.caption:='cr'+inttostr(i);

memDisplay.lines.add(ss);

ss:='';

end;

end;

end;

end;

当然还有许多串口控制的ActiveX控件,有控件用是方便,但是是否说没有控件就不能用Delphi本身解决问题呢。那么就请来看一下下面的解决方案:

二、使用行间汇编

对于硬件的控制,汇编语言是最方便的了,而Delphi中又允许使用行间汇编那么来看一下怎样使用行间汇编接收下位机传来的数据,在下面的例子中我们简化了问题,比如我们通过COM2接收400个传来的字符并将这些内容保存在AAA.DAT文件中当接收完毕后显示‘Receive end’。但是为什么说我们简化了问题呢,因为实际情况中双方通信可能是约定传送字符的个数,也可能约定的是规定好的起始字符和结束字符,或是多种条件同时约定待各种条件全部满足时才表示完成一次成功的接收否则如有一个条件未满足都表示接收失败需要重新传送。这些约定在使用了行间汇编的Delphi程序中都可实现。下面的程序就是按一个按钮进入的一个简化的串口接收程序。

procedure TForm1.Button1Click(Sender: TObject);

var ca:array[1..400]of char;

c:char;

i,j:integer;

f1:file of char;

label loop1;

begin

i:=1;

asm

mov dx,0001

mov ax,005eh

int 14h

end;

for j:=1 to 400 do

begin

asm

loop1: mov dx,0001

mov ah,02

int 14h

test ah,80h

jnz loop1

mov c,al

end;

ca:=c;

i:=i+1;

end;

assignfile(f1,'aaa.dat');

rewrite(f1);

for j:=1 to i-1 do

write(f1,ca[j]);

closefile(f1);

label1.caption:='receive end';

end;

三、用Delphi调用可执行应用程序

采用其它编程技术编制的串口通信程序在完成数据传输后将数据保存到磁盘上,然后用Delphi对数据内容进行处理。通过在Delphi中与其他编程技术协同工作也不失为一种解决问题的好方法。
  用Delphi开发串口通信软件一般有两种方法:一是利用Windows的通信API函数,另一种是采用Microsoft的MSComm控件。利用API编写串口通信程序较为复杂,需要掌握大量通信知识,其优点是实现的功能强大,应用面广泛,适合于编写较为复杂的低层次通信程序。而利用MSComm控件则相对较简单,该控件具有丰富的与串口通信密切相关的属性及事件,提供了对串口的各种操作。
  一、MSComm控件的主要属性及事件
  (1)CommPort:设置或返回串行端口号,缺省值1。
  (2)Setting:设置或返回串口通信参数,格式为“波特率,奇偶校验位,数据位,停止位”。例如:MSComm1.Setting:=′9600,n,8,1′
  (3)PortOpen:打开或关闭串行端口,格式为:MSComm1.PortOpen:={True|False}
  (4)InBufferSize:设置或返回接收缓冲区的大小,缺省值为1024字节。
  (5)InBufferCount:返回接收缓冲区内等待读取的字节数,可通过设置该属性为0来清空接收缓冲区。
  (6)RThreshold:该属性为一阀值,它确定当接收缓冲区内的字节个数达到或超过该值后就产生代码为ComEvReceive的OnComm事件。
  (7)SThreshold:该属性为一阀值,它确定当发送缓冲区内的字节个数少于该值后就产生代码为ComEvSend的OnComm事件。
  (8)InputLen:设置或返回接收缓冲区内用Input读入的字节数,设置该属性为0表示Input读取整个缓冲区的内容。
  (9)Input:从接收缓冲区读取一串字符。
  (10)OutBufferSize:设置或返回发送缓冲区的大小,缺省值为512字节。
  (11)OutBufferCount:返回发送缓冲区内等待发送的字节数,可通过设置该属性为0来清空缓冲区。
  (12)OutPut:向发送缓冲区传送一串字符。
  如果在通信过程中发生错误或事件,就会触发OnComm事件,并由CommEvent属性代码反映错误类型,在通信程序的设计中可根据该属性值来执行不同的操作。CommEvent属性值及其含义如下:
  (1)ComEvSend:值为1,发送缓冲区的内容少于SThreshold指定的值。
  (2)ComEvReceive:值为2,接收缓冲区内字符数达到RThreshold指定的值。
  (3)ComEvFrame:值为1004,硬件检测到帧错误。
  (4)ComEvRxOver:值为1008,接收缓冲区溢出。
  (5)ComEvTxFull:值为1010,发送缓冲区溢出。
  (6)ComEvRxParity:值为1009,奇偶校验错误。
  (7)ComEvEOF:值为7,接收数据中出现文件尾(ASCII码为26)字符。
  二、程序样例
  在Delphi3.0中无法使用MSComm控件,笔者使用的是Delphi5.0。MSComm控件是VB中的OCX控件,首先需要将其添加到Delphi中,选择菜单“Component”→“Import ActiveX Control”,在“Import ActiveX”页内选择“Microsoft Comm Control”,点击“Install”安装,安装后在“ActiveX”组件板中出现MSComm图标,即可被使用。有一点要注意,在Object Inspector中MSComm控件的Input和Output属性是不可见的,但它们仍然存在,这两个属性的类型是OleVariant(Ole万能变量)。
  下面是一接收程序的样例(主要部分),大家可根据实际需要进行完善。
  在Form中放置一Memo控件用于显示接收的数据,Combobox1选择通信参数(Setting属性值),Combobox2选择串口(CommPort属性值),按Button1开始接收数据,按Button2停止接收。
  procedure TForm1.FormCreate(Sender: TObject);
  begin
  Mscomm1.InBufferCount :=0; // 清空接收缓冲区
  Mscomm1.InputLen :=0; // Input读取整个缓冲区内容
  Mscomm1.RThreshold :=1; // 每次接收到字符即产生OnComm事件
  end;
  procedure TForm1.Button1Click(Sender: TObject);
  begin
  Mscomm1.Settings :=ComboBox1.Text;
  if ComboBox2.Text =′com1′ then // 假设只考虑COM1和COM2两种情况
Mscomm1.CommPort :=1
  else
    Mscomm1.CommPort :=2;
  Mscomm1.PortOpen :=true; // 打开串口
  Mscomm1.DTREnable :=true; // 数据终端准备好
  Mscomm1.RTSEnable :=true; // 请求发送
  end;
  procedure TForm1.Button2Click(Sender: TObject);
  begin
  Mscomm1.PortOpen :=false; // 关闭串口
   Mscomm1.DTREnable :=false;
  Mscomm1.RTSEnable :=false;
  end;
  procedure TForm1.MSComm1Comm(Sender: TObject);
  var
  recstr:Olevariant;
  begin
   if Mscomm1.CommEvent = 2 then
    begin
  recstr := Mscomm1.Input ;
  Memo1.text := Memo1.Text + recstr;
  end;
end;

Delphi是一种具有功能强大、简便易用和代码执行速度快等优点的可视化快速应用开发工具,它在构架企业信息系统方面发挥着越来越重要的作用,许多程序员愿意选择 Delphi作为开发工具编制各种应用程序。但是,美中不足之处是 Delphi没有自带的串口通信控件,在它的帮助文档里也没有提及串口通信,这就给编制通信程序的开发人员带来许多不便。

目前,利用 Delphi实现串口通信的常用的方法有 3种:一是利用控件,如 MSCOMM控件和 SPCOMM控件;二是使用 API函数;三是调用其他串口通信程序。其中利用 API编写串口通信程序较为复杂,需要掌握大量的通信知识。相比较而言,利用 SPCOMM控件则相对较简单,并且该控件具有丰富的与串口通信密切相关的属性及事件,提供了对串口的各种操作,而且还支持多线程。下面本文结合实例详细介绍 SPCOMM控件的使用。

SPCOMM的安装

1.选择下拉菜单 Component中的 Install Component选项,弹出如图 1所示的窗口。


图 1

在 Unit file name处填写 SPCOMM控件所在的路径,其他各项可用默认值,点击 OK按钮。

2.安装后,在 System控件面板中将出现一个红色控件 COM。现在就可以像 Delphi自带控件一样使用 COM控件了。

SPCOMM的属性、方法和事件

1.属性

●CommName:表示 COM1、 COM2等串口的名字;

●BaudRate:根据实际需要设定的波特率,在串口打开后也可更改此值,实际波特率随之更改;

●ParityCheck:表示是否需要奇偶校验;

●ByteSize:根据实际情况设定的字节长度;

●Parity:奇偶校验位;

●StopBits:停止位;

●SendDataEmpty:这是一个布尔型属性,为 true时表示发送缓存为空,或者发送队列里没有信息;为 false时表示发送缓存不为空,或者发送队列里有信息。

2.方法

●Startcomm方法用于打开串口,当打开失败时通常会报错。错误主要有 7种:⑴串口已经打开;⑵打开串口错误;⑶文件句柄不是通信句柄;⑷不能够安装通信缓存;⑸不能产生事件;⑹不能产生读进程;⑺不能产生写进程;

●StopComm方法用于关闭串口,没有返回值;

●WriteCommData(pDataToWrite: PChar;dwSizeofDataToWrite:Word )方法是个带有布尔型返回值的函数,用于将一个字符串发送到写进程,发送成功返回 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)后 8051能收到一帧( F0,01,FF,FF,01,F0),表示数据通信握手成功,两者之间就可以按照协议相互传输数据。

创建一个新的工程 COMM.DPR,把窗体的 NAME属性定为 FCOMM,把窗体的标题定义为测试通信,按照图 2添加控件 (图 2中黑色矩形围住的控件即为 COMM1)。



图 2

1.设定 COMM1属性:

●波特率: 4800;

●奇偶校验位:无;

●字节长度: 8;

●停止位: 1;

●串口: COM1。

Memo1中将显示发送和接收的数据。将新的窗体存储为 Comm.pas。

2.编写源代码

//变量说明

var

fcomm: TFCOMM;

viewstring:string;

i:integer;

rbuf,sbuf:array[16] 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($ f0); //帧尾

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 01 F0和接收到 F0 01 FF FF 01 F0,这表示串口已正确地发送出数据并正确地接收到数据,则串口通信成功。




 
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 01 F0和接收到 F0 01 FF FF 01 F0,这表示串口已正确地发送出数据并
正确地接收到数据,则串口通信成功。

这个例子的最后一段中的
move(buffer^,pchar(@rbuf^),bufferlength);
有问题。编译出错。
 
>move(buffer^,pchar(@rbuf^),bufferlength);
少了一个括号,改为:
move(buffer^,pchar((@rbuf)^),bufferlength);
 
感谢大家的关注,有些代码我可以自己找到,可是我希望有一个具体一点的。。。。

还有如果能告知哪里有 《delph 与rs232 通信〉或是 《delphi 串口通信编程〉的电子版的下载也不胜感激
 
你还是到书店去看看<<delph 与rs232 通信>>
我一个体会,希望对你有帮助的!

就是用控件有一个Bug,数据多了会出现乱码!
建议用API

还有,程序调试的时候,你必须要有一根窜口线(Null Modem),就是2,3引脚互换的那种
而且两头必须是母头,然后一端接到Com1,一端接到Com2,
调试的时候,用处Com1向Com2发消息就好了,
注意不能同时用同一个Com口

清华的那本 <<delph 与rs232 通信>> 很好!!
 
我觉得清华的那本不如邮电那本。
 
谢谢,大家!! 希望大家多给我一些宝贵的意见和建议,避免我再犯低级的错误
至少别给delphi 抹黑 :)
说实话,我昨天到书店看了一下《delphi 与rs 232 通信〉〉 感觉和我想的不太一样
开始几章讲的都是一些基础的控件应用,本来书就不是很厚。。。。。
邮电的那本没见到。。。
zxbyh,u100可以介绍的详细一点吗?


 
我觉得邮电的那本有用的东西多一点。清华的废话太多了[:D]指的是它有很大的篇幅在介绍
Delphi的基本使用,这有点不值得了,而且还贵。不过我两本都买了。如果你刚开始作串口
我觉得还是清华的吧,用来入门很不错。我现在也在作串口通讯的项目,很高兴和你一起探
讨。
 
U100 留个地址吧! 有问题一定向你请教 [^]。。。

大家多指教。
 
后退
顶部