spcomm中,如果串口不停发数据,该如何处理为好?(100分)

  • 主题发起人 主题发起人 linying
  • 开始时间 开始时间
L

linying

Unregistered / Unconfirmed
GUEST, unregistred user!
我用spcomm读一个串口的数据,DTE只有两根线,即“信号地”和“发送数据”,
而且DTE是不停发数据的,所以receivedata事件无法停止,我用了一个定时器来
打开串口,程序如下,不知可行否。程序运行过,可以读数,但是不是很稳定。
DTE发的数据是以7个字节为循环的,波特率为1200。

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, SPComm, DdeMan;

type
TForm1 = class(TForm)
Comm1: TComm;
Memo1: TMemo;
Timer1: TTimer;
Memo2: TMemo;
procedure Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
view:string;//存读来的数据

implementation

{$R *.DFM}

procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
i,j:integer;
view1,view2:string;
rbuff:array[1..14] of byte;

begin

sleep(1000);
move(buffer^,pchar(@rbuff)^,bufferlength);
comm1.stopcomm;
memo2.lines.Add(inttostr(bufferlength));
if bufferlength=7 then
begin
for i:=1 to (bufferlength-1) do
begin
view1:=inttohex(rbuff,2)+ inttohex(rbuff[i+1],2);
if view1='1DE2' then j:=i;//判断要取的数据的位置,数据是跟在'1DE2'后的两个字节
end;
if j<=(bufferlength-3) then
view2:=inttohex(rbuff[j+2],2)+'.'+ inttohex(rbuff[j+3],2);
view:=view2;
end;


memo1.lines.add(view);



end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
comm1.stopcomm;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
comm1.stopcomm;
comm1.StartComm;

end;

end.
 
怎么没有人帮帮我呢?
 
两个办法,
1)是禁止receivedata事件,而在定时器上直接读取端口
2)去掉定时器,在receivedata事件上判断有足够的数据到时,读出并处理
 
to iie:
1 如何在定时器中直接读端口呢?难道SPCOMM控件只要收到数据就放置于buffer中,我在定时器
读buffer里的数就可以了吗?也就是说把在receivedata事件中的程序放于定时器里(去掉开关
串口的语句)?
2 不用定时器好象不行吧?因为总有数来,receivedata事件总是被触发,以至于程序都无法停
止。
 
1)就是这样,我没有用过SPCOMM,但串口工作原理就是这样,一定要有缓冲区的,
所以你可以用读方法来操作串口,事实上串口处理API就是把串口作为数据文件
处理的
2)不会的,事件触发后,你不处理,它不会再次触发,你判断数据足够后处理就行
 
to iie:
你说的第二种我还是不太明白,我原来的程序就是没有用定时器的,结果程序无法停止下来。
因为发送数据的测量仪器是一帧发7个字节,不停地循环发。所以我只要读到如果发的是7个字
节,就开始取数,这样一处理完(而这个取数处理的时间很短的),receivedata事件又被触
发了。难道设一个长时间的sleep语句?
请问哪有讲串口工作原理比较好的书?
谢谢。
 
用ComPort Library version 2.62可以轻松解决你的问题。
 
不能循环发,再发的条件有两个:
1)定时器判定发送延时若干时间后没有收到回送;
2)接收到回送后处理完毕或回送错误
 
在receivedata事件處理有用信息,無用就不用處理了
 
串口通信速率的上限也就是115200,机器处理速度肯定可以跟得上的,
千万不要用sleep这样的延时
 
应该数据同步接受的问题吧?如果有同步标志位的就监测,或者要别的控件(比如mscomm)
配合可以监测监测串口收发控制信号的数据线(不是一般3线的)------一种想法,我也在弄
 
各位:
那个仪器只有两条信号线,一个为信号地,一个为发送数据,所以我根本无法控制它,它是
不停地发数据(24小时工作),所以我才不知如何解决好,才加上定时器,定时打开串口并
关闭串口(可看我所附的程序)。
to iie:
我如果不用sleep,那程序运行的周期时间岂不是更短,程序会太忙的,以至于你的鼠标点击
关闭窗口都无法进行。
 
不会的,反而是sleep会增加系统负担,造成你所说的现象
 
如果正在读串口数据的时候关闭串口,可能会造成程序没有响应。
特别是数据传输速率高的时候,必死。

我以前用SPCOMM的时候,它好象要读到一定量的数据的时候才触发ReceiveData的啊?
 
我监视过BUFFERLENGTH,也就是7个字节,有时不稳,会波动。
看来我原来在ReceiveData事件中关闭串口是不可取的了?可是我真的不知如何让程序停下
来。
我在ReceiveData事件中加SLEEP是因为觉得刚开串口就关,时间太短了,所以才用的。
该程序是用于外地现场的,目前无法调试,我想现在弄明白一些,到时出差好尽快解决。
 
SPComm有个属性ReadIntervalTimeOut,用于设定接收连续两个字节之间的最长时间。
超过这个时间,则认为是两个数据块。
 
我最近不知怎么老是上不来,还望见谅。
TO YYGW:该如何使用这个ReadIntervalTimeOut属性呢?该属性在README里好象没有说明。
“设定接收连续两个字节的时间长度”,那么是说每隔这么长的时间,ReceiveData事件就
被触发吗?


 
我的意思是:
假设串口在第1和第21毫秒时发送过来两个字节的数据,如果ReadIntervalTimeOut设
为10毫秒,则这两个字节会被当作两个数据块处理,各产生一次ReceiveData事件。
每次一字节。如果设为30毫秒,则会被认为是一个数据块,只产生一次事件,两个字
节。当然,如果该值设得较大,而发送速度快,则在缓冲区满后将产生事件。
(我用的控件是V2.5版的SPComm。)
 
后退
顶部