我在使用SPCOMM的时候无意间发现一个问题,我写了一个Demo程序,代码很简单,我只是接收的地方写了一句代码,
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
receivebuf:array[1..255] of byte;
begin
move(buffer^,pchar(@rbuf)^,bufferlength);
end;电脑和另外一台机器的串口是连着的,我在另外一台机器用串口调试程序手动发送,如果一下下点,差不多间隔1000ms,是没问题的,如果鼠标连续快速点发送的话,这个程序是出错:access violation at 0x01b1d2b7: read of address 0x01b1d2b7.
我想应该是内存溢出了,但是为什么会出现这种情况呢,难道SPCOMM内部机制没有对种情况作相应的处理吗?我又用了COMPORT,代码也很简单:
procedure TForm1.ComPortRxChar(Sender: TObject; Count: Integer);
var
Str: String;
begin
ComPort.ReadStr(Str, Count);
Memo.Text := Memo.Text + Str;
end;
我用串口调试程序发送,无论我鼠标怎么快的点都没问题,我想这样应该是正常的。因为人工鼠标点才多快啊!!!请教各位,如果知道的话,请告诉我一声好吗?谢谢
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
receivebuf:array[1..255] of byte;
begin
move(buffer^,pchar(@rbuf)^,bufferlength);
end;电脑和另外一台机器的串口是连着的,我在另外一台机器用串口调试程序手动发送,如果一下下点,差不多间隔1000ms,是没问题的,如果鼠标连续快速点发送的话,这个程序是出错:access violation at 0x01b1d2b7: read of address 0x01b1d2b7.
我想应该是内存溢出了,但是为什么会出现这种情况呢,难道SPCOMM内部机制没有对种情况作相应的处理吗?我又用了COMPORT,代码也很简单:
procedure TForm1.ComPortRxChar(Sender: TObject; Count: Integer);
var
Str: String;
begin
ComPort.ReadStr(Str, Count);
Memo.Text := Memo.Text + Str;
end;
我用串口调试程序发送,无论我鼠标怎么快的点都没问题,我想这样应该是正常的。因为人工鼠标点才多快啊!!!请教各位,如果知道的话,请告诉我一声好吗?谢谢
procedure TForm1.Button1Click(Sender: TObject);
begin
Comm.CommName:=ComboBox1.Text;
Comm.BaudRate:=StrToInt(Edit2.Text);
try
Comm.StartComm;
except
raise Exception.Create('打开串口错误');
end;
StatusBar1.Panels[0].Text :=Comm.CommName+'已打开';
StatusBar1.Refresh;
end;procedure TForm1.Button3Click(Sender: TObject);
begin
Comm.StopComm;
StatusBar1.Panels[0].Text :=Comm.CommName+'已关闭';
StatusBar1.Refresh;
end;procedure TForm1.Button2Click(Sender: TObject);
var
str:PChar ;
count:Integer ;
i:Integer;
sbuf:array[1..6] of byte;
viewstr:string ;
begin
//以HEX发送
sbuf[1]:=byte($5B);
sbuf[2]:=byte($53);
sbuf[3]:=byte($00);
sbuf[4]:=byte($43);
sbuf[5]:=byte($01);
sbuf[6]:=byte($5D);
viewstr:='';
for i:=1 to 6 do
begin
if not Comm.WriteCommData(@sbuf[i],1) then
break;
sleep(2);
viewstr:=viewstr+inttohex(sbuf[i],2)+'';
end;
//Memo1.Lines.Add('已发送字符'+'-->'+viewstr);
{
//以ASCII发送
str:=PChar(Edit1.Text);
count :=Length(str);
//if Comm.WriteCommData(str,count) then
if Comm.WriteCommData(PChar('[RS]'),4) then
Memo1.Lines.Add('已发送'+inttostr(count)+'个字符'+'-->'+Edit1.Text)
else
raise Exception.Create('发送错误'); }
end;
procedure TForm1.CommReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
strRecv:string;
i:Integer ;
rbuf:array[1..6] of byte;
viewstr1:string ; Channel:array[1..4] of string ;
begin
{//1-ASC接收
SetLength(strRecv,BufferLength);
Move(Buffer^,PChar(strRecv)^,BufferLength);
Memo1.Lines.Add('已收到:'+IntToStr(BufferLength)+'字节的数据');
Memo1.Lines.Add(strRecv);
Memo1.Invalidate; }
//2-HEX接收
viewstr1:='';
Move(Buffer^,PChar(@rbuf)^,BufferLength);
for i:=1 to bufferlength do
viewstr1:=viewstr1+inttohex(rbuf[i],2)+'';
Memo1.Lines.Add(viewstr1); if Copy(viewstr1,1,12)='5B530043015D' then
begin
Channel[1]:=Copy(viewstr1,13,4);
Channel[2]:=Copy(viewstr1,17,4);
Channel[3]:=Copy(viewstr1,21,4);
Channel[4]:=Copy(viewstr1,25,4);
//ShowMessage(Channel[1]+' '+Channel[2]+' '+Channel[3]+' '+Channel[4]); ShowMessage(IntToStr(StrToInt('$'+Channel[1])));
end;
end;
谢谢你的回答因为我不了解SPCOMM所以才怀疑是不是他内部机制问题,但是我知道这种可能性很小。我的发送端是用“串口调试助手V2.2”,不知道是不是这个调试程序的问题,接收端的代码我已经给出了,很简单,因为我只是做测试,但是鼠标快速发送还会有同样的问题,不知道为什么
bufferlength肯定是大于255了,会出现越界写的情况,就会报错。 move(buffer^,pchar(@rbuf)^,bufferlength);
这里面的rbuf,不要用静态数组,要根据bufferlength动态申请内存(处理完后记得释放,不然就是内存泄露了)。
是你说的原因,我给写一下,结果发现连续快速发送的话,接收到的数据有些是两条数据一起发送的,有些甚至是3条,我想就是这么情况造成的错误。 但是我还有个问题,为什么SPCOMM会有这么问题呢?是发送端的问题吗?为什么我用COMPORT来做就没这么问题了,无论发送多快都没问题的。是不是SPCOMM对发送端有要求?
COMPORT没有问题么?
我目前测试下来好象COMPORT没有问题,起码我测试的时候没问题,现在我把rbuf改为动态申请了,出现的问题也解决了,汗一下。
不过既然有这个问题,那么对发送端就有要求了,不是只管发送就可以了,如果时间没控制好,那么会出现这种情况,原来发送两条指令,结果由于时间太短,两条指令一起发送了
会么?自己写的发送端?不会吧,一条就是条,还会出现一起发送两条?应该不至于这样,是不是参数设置的问题,我想Spcomm还不至于这样吧!
bufferLength的大小你根本不知道,你怎么能够保证他不出问题。
bufferlength是word类型的,那么最大长度可以是2^16-1的。
SPCOMM好像可以设置事件触发条件的,你可以选择数据到了多少的时候触发OnRecieve不就行了?
一般这种情况,如果你知道发送端数据量和本地处理速度的情况下,选择一个足够大的缓冲区做接受,或者就动态申请缓冲区好了。
这个根本就不是spcomm的问题,是个基本的内存使用问题!!!!