使用MSComm控件时遇到的问题 ( 积分: 20 )

  • 主题发起人 主题发起人 TENTODBV
  • 开始时间 开始时间
T

TENTODBV

Unregistered / Unconfirmed
GUEST, unregistred user!
在我写的一个用MSComm控件实现与仪表通讯的程序中,MSComm控件的OnComm事件过程框架代码如下:
procedure TfrmMain.MSCommComm(Sender: TObject);
var
i,InputLen:integer;
UpperCaseBuff:string;
begin
if MSComm.CommEvent=ComEvReceive then
begin
sleep(300);
InputLen:=MSComm.InBufferCount;
InputString:=MSComm.Input;

i:=1;
while i<=InputLen do
begin
......省略部分代码
if InputString=#4 then //EOT
begin
UpperCaseBuff:=UpperCase(Buff);
RichEdit1.Text:=Buff;//全局变量,这个就是我想得到的结果
bOK:=true;//全局变量
exit;
end;
end;
end;



//发送命令按钮的代码框架如下:
procedure TfrmMain.Button2Click(Sender: TObject);
var
Sample,Cycle:integer;
tempstr:string;
begin
bGet:=true;
SLTest:=TStringList.Create;
Len:=0;
Count:=0;
Buff:='';
bOK:=false;
LinkString:='';
with frmMain.MSComm do
begin
if not PortOpen then
begin
CommPort:=ComNum;
Settings:=ComSetting;
PortOpen:=true;
end;
SendCommand('test ?');
//Timer1.Enabled:=false;//启动定时器定时刷新显示
end;

Sleep(2000);
ShowMessage(RichEdit1.Text);
//返回结果处理代码段
if bOK then
begin
//SLTest.Text:=Buff;
SLTest.Text:=RichEdit1.Text;
if SLTest.Count>0 then
begin
tempstr:=SLTest[0];
tempstr:=AnsiReplaceStr(tempstr,' ','');
tempstr:=AnsiReplaceStr(tempstr,'=','');
tempstr:=AnsiReplaceStr(tempstr,'SAMPLE','');
Sample:=StrToInt(tempstr);
Edit2.Text:=IntToStr(Sample);
end;
end;
end;

以上代码SendCommand('test ?');是通过串口发送命令给仪表,然后仪表会返回字符串值到全局变量Buff
问题是:如果没有前面所示的返回结果处理代码段
if bOK then
begin
......
end;
结果Buff确实是可以正确返回到RichEdit1框显示的。我加上返回结果处理代码段的目的是为了确定在已经接收到返回值时,对接收结果字符串进行处理。调试状态下,在MSCommComm中跟踪显示Buff值正确,bOK为true。按理来说执行返回结果处理代码段时,全局变量bOK值应该为true,且RichEdit1.Text的值不为空才对。

可是实际跟踪发现,执行到if bOK then时 bOK值总是是false,可是调试状态下,在MSCommComm中跟踪显示Buff值正确,bOK也已经是true了呀。bOK和Buff都是全局变量。

后来我又在返回结果处理代码段之前加上延时和显示代码
Sleep(2000);
ShowMessage(RichEdit1.Text);
明显看出无论延时多长时间,总是先显示ShowMessage(RichEdit1.Text);的空白结果然后RichEdit1才接收到返回字符串。

请问问题出在哪里?
 
在我写的一个用MSComm控件实现与仪表通讯的程序中,MSComm控件的OnComm事件过程框架代码如下:
procedure TfrmMain.MSCommComm(Sender: TObject);
var
i,InputLen:integer;
UpperCaseBuff:string;
begin
if MSComm.CommEvent=ComEvReceive then
begin
sleep(300);
InputLen:=MSComm.InBufferCount;
InputString:=MSComm.Input;

i:=1;
while i<=InputLen do
begin
......省略部分代码
if InputString=#4 then //EOT
begin
UpperCaseBuff:=UpperCase(Buff);
RichEdit1.Text:=Buff;//全局变量,这个就是我想得到的结果
bOK:=true;//全局变量
exit;
end;
end;
end;



//发送命令按钮的代码框架如下:
procedure TfrmMain.Button2Click(Sender: TObject);
var
Sample,Cycle:integer;
tempstr:string;
begin
bGet:=true;
SLTest:=TStringList.Create;
Len:=0;
Count:=0;
Buff:='';
bOK:=false;
LinkString:='';
with frmMain.MSComm do
begin
if not PortOpen then
begin
CommPort:=ComNum;
Settings:=ComSetting;
PortOpen:=true;
end;
SendCommand('test ?');
//Timer1.Enabled:=false;//启动定时器定时刷新显示
end;

Sleep(2000);
ShowMessage(RichEdit1.Text);
//返回结果处理代码段
if bOK then
begin
//SLTest.Text:=Buff;
SLTest.Text:=RichEdit1.Text;
if SLTest.Count>0 then
begin
tempstr:=SLTest[0];
tempstr:=AnsiReplaceStr(tempstr,' ','');
tempstr:=AnsiReplaceStr(tempstr,'=','');
tempstr:=AnsiReplaceStr(tempstr,'SAMPLE','');
Sample:=StrToInt(tempstr);
Edit2.Text:=IntToStr(Sample);
end;
end;
end;

以上代码SendCommand('test ?');是通过串口发送命令给仪表,然后仪表会返回字符串值到全局变量Buff
问题是:如果没有前面所示的返回结果处理代码段
if bOK then
begin
......
end;
结果Buff确实是可以正确返回到RichEdit1框显示的。我加上返回结果处理代码段的目的是为了确定在已经接收到返回值时,对接收结果字符串进行处理。调试状态下,在MSCommComm中跟踪显示Buff值正确,bOK为true。按理来说执行返回结果处理代码段时,全局变量bOK值应该为true,且RichEdit1.Text的值不为空才对。

可是实际跟踪发现,执行到if bOK then时 bOK值总是是false,可是调试状态下,在MSCommComm中跟踪显示Buff值正确,bOK也已经是true了呀。bOK和Buff都是全局变量。

后来我又在返回结果处理代码段之前加上延时和显示代码
Sleep(2000);
ShowMessage(RichEdit1.Text);
明显看出无论延时多长时间,总是先显示ShowMessage(RichEdit1.Text);的空白结果然后RichEdit1才接收到返回字符串。

请问问题出在哪里?
 
//接收
procedure TForm1.MSComm1Comm(Sender: TObject);
var
i,j:integer;
rxbuf:Variant;
a:array of byte;
s:string;
begin
if (Mscomm1.CommEvent=2) then
while Mscomm1.inbuffercount<>0 do
begin
a:=mscomm1.input;
Memo1.SelStart:=Length(Memo1.Text);
if CheckBox4.Checked //HEX show
then Memo1.SelText:=StrToHex(char(a[0]))
else Memo1.SelText:=Char(a[0]);
end;
end;
 
能不能给各mscomm控件?
cmqlovell@163.com
对通讯编成关注中^^^^
谢谢TENTODBV,maxim88两位大虾了!
 
我用的mscomm控件就是微软的Visual Studio 6.0里面自带的 那个Comm Control
 
结果处理代码段
if bOK then
begin
......
end;
应该加到MSCommComm中,在发送命令按钮中处理接收的结果在逻辑上说不通,再说Sleep函数不释放程序控制权,串口接收事件不能处理数据,送你一个延时函数吧
procedure Delay(msecs:word);
var
FirstTickCount:cardinal;
begin
FirstTickCount:=timeGetTime;
repeat
Application.ProcessMessages;
until ((timeGetTime-FirstTickCount) >= msecs);
end;
 
加:
application.processmessage ;//或者:
richedit1.reflash ;//看看哪个得罢
// Sleep(2000);
// ShowMessage(RichEdit1.Text);
//返回结果处理代码段
if bOK then
begin
//SLTest.Text:=Buff;
SLTest.Text:=RichEdit1.Text;
估计是运行时全在你的代码里了,RichEdit1未收到消息,调试状态下已处理过消息了
 
用su37的方法解决了问题。
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
900
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
后退
顶部