SPCOMM控件的CommReceiveData()过程(50分)

  • 主题发起人 主题发起人 carrie4002
  • 开始时间 开始时间
TO tty0819:
谢谢。我的代码里一直有延时的。如下:
k2000v(); //调用读过程
Sleep(200); //延时200ms
k2000v(); //再次调用读过程
Sleep(200); //同样延时200ms
............
断点调试结果不变。
急啊.........
 
用线程进行k200v(),
procedure Trs232.Execute;
begin
while not Terminated do
begin
try
k2000v();
except
end;
sleep(100);
end;
end;
 
我对线程不了解。不知道该怎么用??
 
请阅读本人BLOG
http://qianghua.greatweb.cn/blog/read.php?22

有完整的程序源码示例,照做即可
 
谢谢你。太复杂了。
谁能帮我看看下列代码为何实现不了“边读边写”:
k2000v(); //调用读过程
Sleep(200); //延时200ms
k2000v(); //再次调用读过程
Sleep(200); //同样延时200ms
............
问题到底在哪里呢?
 
CommReceiveData()与
k2000v(); //调用读过程
Sleep(200); //延时200ms
k2000v(); //再次调用读过程
Sleep(200);
在同一窗体。为同一线程。
所以
k2000v(); //调用读过程
Sleep(200); //延时200ms
k2000v(); //再次调用读过程
Sleep(200);
完成后才会到CommReceiveData(),也就是你现在的这种情况。
所以另开一个线程进行k2000v().
 
200 只有1/5秒啊,最起码要500 这样串口才会认为是两条消息,SPCOMM和定时器连起来用的,定时器interval 500 以上
 
用time控件不是很好。建议看一下线程资料,也很简单。
 
TO tty0819:
谢谢你理解了我的调试结果和我的想法。
你的意思是在上述代码的每一处读过程“k2000v()”都改为:
procedure Trs232.Execute;
begin
while not Terminated do
begin
try
k2000v();
except
end;
sleep(100);
end;
end;
吗?
实在不懂线程,可老板催得急啊
 
汗!
给你一个我以前写的一个读卡器测试程序你看看。
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, SPComm, StdCtrls, ExtCtrls,Registry, OoMisc, AdPort;

type
tdkq = record
dkqadd:string;
idh,idl:string;
sendtime:TDateTime;
id:integer;
idok:integer;
idokc:integer;
ide:integer;
idr:integer;
idtime:integer;
rs:boolean;
end;
type
Trs232 = class(TThread)
Commd: TComm;
private

protected
procedure Execute; override;
public
constructor Create(dqkComm: TComm);
end;
type
TForm1 = class(TForm)
Panel1: TPanel;
Memo1: TMemo;
Memo2: TMemo;
Comm1: TComm;
ComboBox1: TComboBox;
Button1: TButton;
Button2: TButton;
Edit1: TEdit;
Button3: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
function totime(time1:TDatetime):integer;
private
loaddkq:Trs232;
sendt:integer;//发送延时
loadtype:integer;
dkqco:integer;//读卡器数量
icdkq:array of tdkq;
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}
function TForm1.totime(time1:TDatetime):integer;
var
Hour,Min,Sec,MSec:Word;
begin
//time3:=time1-time2;
decodetime(time1,Hour,Min,Sec,MSec);
result:=Hour*3600+Min*60+Sec;
end;

constructor Trs232.Create(dqkComm: TComm);
begin
form1.loadtype:=2;
//form1.idc:=1;//初始化读卡次数
//form1.noid:=0; //无数据次数
//form1.yid:=1;
commd:=dqkcomm;
commd.CommName:=Form1.ComboBox1.Text;
commd.BaudRate:=19200;
commd.StartComm;
inherited Create(False);
end;

procedure Trs232.Execute;
var
sendtxt:string;
i,j,k:integer;
bbc:string;
bbc1,bbc2:char;
str:pchar;
begin
while not Terminated do
begin
//
for k:=0 to high(Form1.icdkq) do
begin
i:=strtoint(Form1.icdkq[k].idh);
j:=strtoint(Form1.icdkq[k].idl);
if ((form1.totime(time())-form1.totime(form1.icdkq[k].sendtime))>50) or form1.icdkq[k].rs then
begin
form1.icdkq[k].rs:=false;
form1.icdkq[k].id:=form1.icdkq[k].id+1;
sleep(form1.sendt);
bbc:=inttohex($09 xor StrToInt('$'+inttohex(ord(chr(i)),2)) xor StrToInt('$'+inttohex(ord(chr(j)),2)) xor $46,2);
sendtxt:=#09+inttostr(i)+inttostr(j)+'F'+bbc+#13;
str:=pchar(sendtxt);
if Commd.WriteCommData(str,length(str)) then
begin
sleep(20);
end;
if ((form1.totime(time())-form1.totime(form1.icdkq[k].sendtime))>50) then
begin
form1.icdkq[k].idtime:=form1.icdkq[k].idtime+1;
form1.Memo2.Lines.Add(inttostr(i)+inttostr(j)+'读卡器未回应!超时');
end;
end; //丢包

end;//end for
//form1.idc:=form1.idc+1;
sleep(form1.sendt);
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
reg : TRegistry;
ts : TStrings;
i : integer;
begin
sendt:=100;
reg := TRegistry.Create;
reg.RootKey := HKEY_LOCAL_MACHINE;
reg.OpenKey('hardware/devicemap/serialcomm',
false);
ts := TStringList.Create;
reg.GetValueNames(ts);
self.ComboBox1.Clear;
for i := 0 to ts.Count -1 do begin
self.ComboBox1.Items.Add(reg.ReadString(ts.Strings));
self.ComboBox1.Text:=reg.ReadString(ts.Strings);
end;
ts.Free;
reg.CloseKey;
reg.free;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
sendtxt:string;
i,j:integer;
bbc:string;
bbc1,bbc2:char;
str:pchar;
begin
loadtype:=1;
dkqco:=0;
self.Comm1.CommName:=self.ComboBox1.Text;
self.Comm1.BaudRate:=19200;
self.Comm1.StartComm;
for i:=0 to 9 do
begin
for j:=0 to 9 do
begin
Application.ProcessMessages;
sleep(sendt);
bbc:=inttohex($09 xor StrToInt('$'+inttohex(ord(chr(i)),2)) xor StrToInt('$'+inttohex(ord(chr(j)),2)) xor $46,2);
sendtxt:=#09+inttostr(i)+inttostr(j)+'F'+bbc+#13;
str:=pchar(sendtxt);
self.Memo1.Lines.Add(inttostr(i)+inttostr(j));
if Comm1.WriteCommData(str,length(str)) then
begin
sleep(sendt);
end;
end;
end;
self.Comm1.StopComm;
self.Memo2.Lines.Add('共找到'+inttostr(self.dkqco)+'个读卡器!');
end;

procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
const
CR = #13;
LF = #10;
var
strrecv:String;
start,stop,strleng:integer;
k:integer;
tc:integer;
kh:string;
khi:integer;
begin
setlength(strrecv,BufferLength);
strleng:=length(strrecv);
move(buffer^,pchar(strrecv)^,bufferlength);
start := Pos(LF, strrecv);
Stop := Pos(CR, strrecv);
self.Memo1.Lines.Add(strrecv);
tc:=stop-start;
if (start>0) and (tc>0) then
begin
Application.ProcessMessages;
if self.loadtype=1 then
begin
self.dkqco:=dkqco+1;
self.Memo2.Lines.Add('找到读卡器:'+copy(strrecv,start+1,2));
setlength(icdkq,dkqco);
if strleng>10 then
icdkq[dkqco-1].dkqadd:=copy(strrecv,start+4,8)
else
icdkq[dkqco-1].dkqadd:=inttostr(dkqco);
icdkq[dkqco-1].sendtime:=time();
icdkq[dkqco-1].id:=0; //发送指令次数
icdkq[dkqco-1].idok:=0;
icdkq[dkqco-1].idokc:=0;
icdkq[dkqco-1].ide:=0; //读卡错误
icdkq[dkqco-1].idr:=0; //响应次数
icdkq[dkqco-1].idtime:=0;//超时
icdkq[dkqco-1].rs:=true;
icdkq[dkqco-1].idh:=copy(strrecv,start+1,1);
icdkq[dkqco-1].idl:=copy(strrecv,start+2,1);
end;//寻读卡器
if self.loadtype=2 then
begin
for k:=0 to high(form1.icdkq) do
begin
if (form1.icdkq[k].idh=copy(strrecv,start+1,1)) and (form1.icdkq[k].idl=copy(strrecv,start+2,1)) then
begin
SetLength(kh, 4);
if (strleng-start)>8 then
begin
if (stop-start)>6 then
begin
kh:=copy(strrecv,start+7,5);
end

else
begin
{kh:='';
khi:=0;
while khi<6 do
begin
if khi=4 then
khi:=khi+1;
kh:=kh+strrecv[stop+khi];
khi:=khi+1;
end; }

kh:=copy(strrecv,stop+1,5);
end;

if form1.icdkq[k].dkqadd<>kh then//读卡不一致
begin
self.Memo2.Lines.Add('读卡器'+form1.icdkq[k].idh+form1.icdkq[k].idl+'回应数据:'+strrecv+' 延时:'+inttostr(totime(time())-totime(form1.icdkq[k].sendtime))+' 读取卡号:'+kh+' 不匹配上次');
form1.icdkq[k].ide:=form1.icdkq[k].ide+1;
icdkq[k].dkqadd:=kh;
self.Memo2.Lines.Add(inttostr(stop-start));
end
else
begin
self.Memo2.Lines.Add('读卡器'+form1.icdkq[k].idh+form1.icdkq[k].idl+'回应数据:'+strrecv+' 延时:'+inttostr(totime(time())-totime(form1.icdkq[k].sendtime))+' 读取卡号:'+kh+' 匹配');
form1.icdkq[k].idok:=form1.icdkq[k].idok+1;

end;
form1.icdkq[k].idokc:=form1.icdkq[k].idokc+1;

end
else
self.Memo2.Lines.Add('读卡器'+form1.icdkq[k].idh+form1.icdkq[k].idl+'回应数据:'+strrecv+' 延时:'+inttostr(totime(time())-totime(form1.icdkq[k].sendtime)));
form1.icdkq[k].sendtime:=time();
form1.icdkq[k].rs:=true;
form1.icdkq[k].idr:=form1.icdkq[k].idr+1;
end;//对应读卡器
end;
end;//测试读卡器
end;//end 读卡器回应
end;

procedure TForm1.Button2Click(Sender: TObject);
var
k:integer;
rcout:string;
begin
if self.Button2.Tag=0 then
begin
if length(Form1.icdkq)>0 then
begin
loaddkq:=trs232.Create(comm1);
self.Button2.Tag:=1;
self.Button2.Caption:='停止';
end
else
showmessage('必须先查找读卡器!');
end
else
begin
self.Button2.Tag:=0;
self.Button2.Caption:='测试';
loaddkq.Terminate;
self.Comm1.StopComm;
loaddkq.Free;
for k:=0 to high(form1.icdkq) do
begin
rcout:='读卡器:'+form1.icdkq[k].idh+form1.icdkq[k].idl+' 发送数据:'+inttostr(form1.icdkq[k].id)+' ';
rcout:=rcout+'接收数据:'+inttostr(form1.icdkq[k].idr)+' ';
rcout:=rcout+'读卡次数:'+inttostr(form1.icdkq[k].idokc)+' ';
rcout:=rcout+'读卡正确次数:'+inttostr(form1.icdkq[k].idok)+' ';
rcout:=rcout+'读卡错误:'+inttostr(form1.icdkq[k].ide)+' ';
rcout:=rcout+'超时错误:'+inttostr(form1.icdkq[k].idtime)+' ';
self.Memo2.Lines.Add(rcout);
end;
end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
self.sendt:=strtoint(self.Edit1.Text);
end;

end.
 
一个思路:
在线程里监控串口事件,有ONREAD事件就发消息给主线程,主线程读缓冲区数据再处理
 
谢谢二位。我先看看。
TO tty0819,能加你QQ就好了,关于这个问题。呵呵
 
to carrie4002:
88091743
 
to 楼主:
其实关于你收到00的问题我个人认为很简单的问题,那就是你定义了一个固定长度的数组
RBuf:array[0..64] of char; 的问题,因为数组初始化为0 ,而你接受到数据后显示的时候如果比收到的数据的个数多,那么多出来的就是0了很简单啊,否则你可以定义动态数组
RBuf:array of byte 然后用setlength()函数确定其长度就可以了
 
TO longskyliu:
谢谢。'00'字符的问题我已经解决了。是别的串口返回的数据。
我现在的问题就是:我做不到在需要的地方调用线程来读数据。线程读出的数据不正确。
如果线程能在需要的地方象“过程”一样被调用就好了。
 
不知道楼主用的什么,是否有硬件的问题
具体就是是否设备和测试机共地没有。将设备用导线连接。
不在同一等势面,会有问题。
 
TO xinwsw:
谢谢你。你说的那些问题都早已解决,不再是问题。
我很急迫地想知道,我的串口数据为何不能输出到线程所在的窗口里?(因实际需要,线程必须在该窗口里)
 
多人接受答案了。
 
后退
顶部