请教有关SPCOMM控件的一个问题,急

时间:2022-11-26 04:11:40
日前在使用SPCOMM的过程中遇到一个难点,在接收数据的时候有两个数据接收不到,
$11和$13,编写了一个程序,从$01到$FF顺序发送,只有$11和$13不能正常接收,请问各位高手这是怎么回事儿,是SPCOMM的BUG,还是其他原因,急。

18 个解决方案

#1


不会的,你看看是不是其他的原因
我用spcomm进行串口通讯没有发生过问题
spcomm很好用的。
你把你的程序发过来给我,或者贴出来。。
我的email:yangyugw@163.net
大家一起探讨。

#2


我也用Spcomm控件,请问这样的问题怎么解决
构造一个函数,其返回值有多个内容的。应该怎么构造??
比如说我要构造一个得到门禁机信息的函数。其返回值应该包括这个门禁机的号码(Address),板号(boardID),出入记录多少(nCord),人员信息多少(nPerson)及系统时间(SysTime)。。
我用了一个发送过程Transmit和一个接收过程ReadData,发送的是字符串,接收的也是一个整的字符串。。我构造的函数如下:
Function GetDoorInf(Address:integer):shortstring;//提取门禁机的信息
var
   i:integer;
   a,b,c,d:shortstring;
begin
    i:=4;
while i>0 do
begin
   bagsize:=chr($03);
   s0:=start;//同步字符
   s1:=start;
   s2:=chr($81);//命令字符
   s3:=chr(Address);
   s4:=bagsize;
   send:=s0+s1+s2+s3+s4;//发送字符串
   Transmit;//发送命令

   ReadData;//接收命令
   Result:=Receive;//接收字符串Receive
   Raddress:=r3;
   r0:=copy(Receive,1,1);
   r1:=copy(Receive,2,1);
   r2:=copy(Receive,3,1);
   r3:=copy(Receive,4,1);
   bagnumber:=copy(Receive,5,2);
   r4:=copy(Receive,7,9);
 if r2=chr($91) then//数据处理与分离
    BoardID:=StrToInt(copy(r4,1,1));
    a:=copy(r4,2,1);
    nperson:=ord(a[1]);
    b:=copy(r4,3,2);
    nOpenCount:=ord(b[1])*ord(b[2]);
    c:=copy(r4,5,2);
    MDelay:=inttostr(ord(c[1]))+inttostr(ord(c[2]));
    d:=copy(r4,7,3);
    SupOrder:=inttostr(ord(d[1]))+inttostr(ord(d[2]))+inttostr(ord(d[3]));
    if r2=chr($C1) then
          i:=i-1;
    end
end;
请问为什么我调用的时候就错了,这样构造对不?要不要把发送和接收分开,不在同一个函数里啊?接收另外判断吗??


~~~~~~~~~~~~~~~~~~~~~~~~  
 世界因为你我而年轻!
☆★○●◎◇◆□■△▲※

#3


gz

#4


接收和发送应该分开处理。
Function GetDoorInf(Address:integer):shortstring;//提取门禁机的信息
var
   i:integer;
   a,b,c,d:shortstring;
begin
...
   //Transmit;//发送命令
   comm1.writecommdate(pchar(send),length(send));
end;

在comm1的onreceivedate事件中处理;
   //Result:=Receive;//接收字符串Receive
   receive:=pchar(buffer);
   len:=integer(bufferlength);//接收字符串的长度
   
   Raddress:=r3;
   r0:=copy(Receive,1,1);
   r1:=copy(Receive,2,1);
...
end;



#5


我的Transmit和ReadData就是按照你这样做的啊 。。。我有一个函数成功了啊。。不过那个返回值是BOOL的。。判断少一些。。呵呵

~~~~~~~~~~~~~~~~~~~~~~~~  
 世界因为你我而年轻!
☆★○●◎◇◆□■△▲※

#6


关键是你不能把Transmit和readdata两个函数放在同一个过程里,因为writecommdata是主动发送,可以写在transmit中,返回值是true和false,表示发送成功或失败。readdata(也就是receivedata)是被动接收,只有当com口有数据到达的时候才执行,不能放在GetDoorInf函数中主动执行。

#7


那按照师兄的意思就是说我要分开写吧,一个单单用来发送,
然后所有的接收就一起判断,对不对啊

~~~~~~~~~~~~~~~~~~~~~~~~  
 世界因为你我而年轻!
☆★○●◎◇◆□■△▲※

#8


不管怎么说,谢谢师兄了

~~~~~~~~~~~~~~~~~~~~~~~~  
 世界因为你我而年轻!
☆★○●◎◇◆□■△▲※

#9


搂主,人家的问题你分析清楚了
你的问题呢出在那里
0-ff发送,任何一个都可以收到
不知道你为什么不行啊
你是如何显示,你收到的数据的,把那一段数据贴一下
呵呵
************
* 努力学习 *
*   全为   *
*¥人民币¥*
************

#10


yangyugw你好,我已经把源程序发送到你的信箱中了,你可以看看。

发送程序如下:
procedure TForm1.BitBtn5Click(Sender: TObject);
var tmp:string;
    pDataToWrite:Pchar;
    dwSizeofDataToWrite:Word;
begin
  tmp:=memo2.Text;
  dwSizeofDataToWrite:=length(tmp);
  pDataToWrite:=pchar(tmp);
  Comm1.WriteCommData(pDataToWrite,dwSizeofDataToWrite);
  sleep(1000);
end;

接收程序如下:
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
  BufferLength: Word);
var buff:string;
    count:integer;
begin
  ////////////////////////////////////
  //开始接收数据
  //////////////////////////////////////////////
  buff:=PChar(buffer);
  count:=integer(bufferlength);
  buff:=copy(buff,1,count);
  tbuff:=tbuff+buff;
  memo1.Text:=tbuff;
end;

在memo2中写入字符,发送后应该在memo1中显示相同的字符,在uedit中编辑一个字符串,其中包含十六进制的字符$11和$13,将整个字符串拷贝到memo2中,发送后将memo1中收到的字符串拷贝到uedit中,十六进制显示中没有$11和$13这两个字符,其他字符都有。

#11


老哥,你的程序怎么发11,13啊,我不明白
我给你段我的程序吧,你看看

var
r_b:ARRAY oF CHAR ;

begin

setlength(r_b,bufferlength);
   
move(buffer^,r_b,bufferlength);   

memo1.Text:=r_b

end;
我用你的程序无法发送$11,$13啊
************
* 努力学习 *
*   全为   *
*¥人民币¥*
************

#12


哦,用uedit是么,我明白了
#13,是回车,你要显示什么呢

************
* 努力学习 *
*   全为   *
*¥人民币¥*
************

#13


你把 memo1.txt:=r_b;改成
for i:=0 to bufferlength-1 do
memo1.text:=memo1.text+IntToHex(ord(r_b[i]))
************
* 努力学习 *
*   全为   *
*¥人民币¥*
************

#14


不是#13,是$13,在键盘上是PAUSE键。
我试过了,用SPCOMM控件不能发送$11和$13,在连续发送$01到$FF时,结果只显示0102030405060708090A0B0C0D0E0F10121415161718191A1B1C(十六进制),后面没有显示,而且可能是接收了一个PAUSE的命令,再次发送无响应,必须重新打开端口才能发送。
只要字符串中不包含$11和$13,所有字符串都能发送和接收,
只要包含$13,发送接收后必须重新打开端口才能再次发送。
包含$11,能多次发送,但是不能接收到$11。
有兴趣的人可以试一试,昨天回去查了一下,只要用一个9针的串口,将2和3短接,就可以实现同一端口的发送和接收。
改用MSCOMM控件没有问题,所有字符都可以发送和接收,这可能是SPCOMM的BUG吧。

#15


兄弟,我就是用一台计算机发送的啊
com1-com2啊,呵呵,一直这么用啊2,3交换,5直接连接
短接不太好。那样,你自己发的东西也回来了。

#16


厉害喔,现在小弟的问题用起来没有错了,就是没有真的传输过。。

哈哈哈,还是理论啊

~~~~~~~~~~~~~~~~~~~~~~~~  
 世界因为你我而年轻!
☆★○●◎◇◆□■△▲※

#17


我找到原因了 outx_xonxoffflow:=flase;
spcom的这个属性改成 flase就可以了
************
* 努力学习 *
*   全为   *
*¥人民币¥*
************

#18


一切都OK了,谢谢小杨兄的帮助。

#1


不会的,你看看是不是其他的原因
我用spcomm进行串口通讯没有发生过问题
spcomm很好用的。
你把你的程序发过来给我,或者贴出来。。
我的email:yangyugw@163.net
大家一起探讨。

#2


我也用Spcomm控件,请问这样的问题怎么解决
构造一个函数,其返回值有多个内容的。应该怎么构造??
比如说我要构造一个得到门禁机信息的函数。其返回值应该包括这个门禁机的号码(Address),板号(boardID),出入记录多少(nCord),人员信息多少(nPerson)及系统时间(SysTime)。。
我用了一个发送过程Transmit和一个接收过程ReadData,发送的是字符串,接收的也是一个整的字符串。。我构造的函数如下:
Function GetDoorInf(Address:integer):shortstring;//提取门禁机的信息
var
   i:integer;
   a,b,c,d:shortstring;
begin
    i:=4;
while i>0 do
begin
   bagsize:=chr($03);
   s0:=start;//同步字符
   s1:=start;
   s2:=chr($81);//命令字符
   s3:=chr(Address);
   s4:=bagsize;
   send:=s0+s1+s2+s3+s4;//发送字符串
   Transmit;//发送命令

   ReadData;//接收命令
   Result:=Receive;//接收字符串Receive
   Raddress:=r3;
   r0:=copy(Receive,1,1);
   r1:=copy(Receive,2,1);
   r2:=copy(Receive,3,1);
   r3:=copy(Receive,4,1);
   bagnumber:=copy(Receive,5,2);
   r4:=copy(Receive,7,9);
 if r2=chr($91) then//数据处理与分离
    BoardID:=StrToInt(copy(r4,1,1));
    a:=copy(r4,2,1);
    nperson:=ord(a[1]);
    b:=copy(r4,3,2);
    nOpenCount:=ord(b[1])*ord(b[2]);
    c:=copy(r4,5,2);
    MDelay:=inttostr(ord(c[1]))+inttostr(ord(c[2]));
    d:=copy(r4,7,3);
    SupOrder:=inttostr(ord(d[1]))+inttostr(ord(d[2]))+inttostr(ord(d[3]));
    if r2=chr($C1) then
          i:=i-1;
    end
end;
请问为什么我调用的时候就错了,这样构造对不?要不要把发送和接收分开,不在同一个函数里啊?接收另外判断吗??


~~~~~~~~~~~~~~~~~~~~~~~~  
 世界因为你我而年轻!
☆★○●◎◇◆□■△▲※

#3


gz

#4


接收和发送应该分开处理。
Function GetDoorInf(Address:integer):shortstring;//提取门禁机的信息
var
   i:integer;
   a,b,c,d:shortstring;
begin
...
   //Transmit;//发送命令
   comm1.writecommdate(pchar(send),length(send));
end;

在comm1的onreceivedate事件中处理;
   //Result:=Receive;//接收字符串Receive
   receive:=pchar(buffer);
   len:=integer(bufferlength);//接收字符串的长度
   
   Raddress:=r3;
   r0:=copy(Receive,1,1);
   r1:=copy(Receive,2,1);
...
end;



#5


我的Transmit和ReadData就是按照你这样做的啊 。。。我有一个函数成功了啊。。不过那个返回值是BOOL的。。判断少一些。。呵呵

~~~~~~~~~~~~~~~~~~~~~~~~  
 世界因为你我而年轻!
☆★○●◎◇◆□■△▲※

#6


关键是你不能把Transmit和readdata两个函数放在同一个过程里,因为writecommdata是主动发送,可以写在transmit中,返回值是true和false,表示发送成功或失败。readdata(也就是receivedata)是被动接收,只有当com口有数据到达的时候才执行,不能放在GetDoorInf函数中主动执行。

#7


那按照师兄的意思就是说我要分开写吧,一个单单用来发送,
然后所有的接收就一起判断,对不对啊

~~~~~~~~~~~~~~~~~~~~~~~~  
 世界因为你我而年轻!
☆★○●◎◇◆□■△▲※

#8


不管怎么说,谢谢师兄了

~~~~~~~~~~~~~~~~~~~~~~~~  
 世界因为你我而年轻!
☆★○●◎◇◆□■△▲※

#9


搂主,人家的问题你分析清楚了
你的问题呢出在那里
0-ff发送,任何一个都可以收到
不知道你为什么不行啊
你是如何显示,你收到的数据的,把那一段数据贴一下
呵呵
************
* 努力学习 *
*   全为   *
*¥人民币¥*
************

#10


yangyugw你好,我已经把源程序发送到你的信箱中了,你可以看看。

发送程序如下:
procedure TForm1.BitBtn5Click(Sender: TObject);
var tmp:string;
    pDataToWrite:Pchar;
    dwSizeofDataToWrite:Word;
begin
  tmp:=memo2.Text;
  dwSizeofDataToWrite:=length(tmp);
  pDataToWrite:=pchar(tmp);
  Comm1.WriteCommData(pDataToWrite,dwSizeofDataToWrite);
  sleep(1000);
end;

接收程序如下:
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
  BufferLength: Word);
var buff:string;
    count:integer;
begin
  ////////////////////////////////////
  //开始接收数据
  //////////////////////////////////////////////
  buff:=PChar(buffer);
  count:=integer(bufferlength);
  buff:=copy(buff,1,count);
  tbuff:=tbuff+buff;
  memo1.Text:=tbuff;
end;

在memo2中写入字符,发送后应该在memo1中显示相同的字符,在uedit中编辑一个字符串,其中包含十六进制的字符$11和$13,将整个字符串拷贝到memo2中,发送后将memo1中收到的字符串拷贝到uedit中,十六进制显示中没有$11和$13这两个字符,其他字符都有。

#11


老哥,你的程序怎么发11,13啊,我不明白
我给你段我的程序吧,你看看

var
r_b:ARRAY oF CHAR ;

begin

setlength(r_b,bufferlength);
   
move(buffer^,r_b,bufferlength);   

memo1.Text:=r_b

end;
我用你的程序无法发送$11,$13啊
************
* 努力学习 *
*   全为   *
*¥人民币¥*
************

#12


哦,用uedit是么,我明白了
#13,是回车,你要显示什么呢

************
* 努力学习 *
*   全为   *
*¥人民币¥*
************

#13


你把 memo1.txt:=r_b;改成
for i:=0 to bufferlength-1 do
memo1.text:=memo1.text+IntToHex(ord(r_b[i]))
************
* 努力学习 *
*   全为   *
*¥人民币¥*
************

#14


不是#13,是$13,在键盘上是PAUSE键。
我试过了,用SPCOMM控件不能发送$11和$13,在连续发送$01到$FF时,结果只显示0102030405060708090A0B0C0D0E0F10121415161718191A1B1C(十六进制),后面没有显示,而且可能是接收了一个PAUSE的命令,再次发送无响应,必须重新打开端口才能发送。
只要字符串中不包含$11和$13,所有字符串都能发送和接收,
只要包含$13,发送接收后必须重新打开端口才能再次发送。
包含$11,能多次发送,但是不能接收到$11。
有兴趣的人可以试一试,昨天回去查了一下,只要用一个9针的串口,将2和3短接,就可以实现同一端口的发送和接收。
改用MSCOMM控件没有问题,所有字符都可以发送和接收,这可能是SPCOMM的BUG吧。

#15


兄弟,我就是用一台计算机发送的啊
com1-com2啊,呵呵,一直这么用啊2,3交换,5直接连接
短接不太好。那样,你自己发的东西也回来了。

#16


厉害喔,现在小弟的问题用起来没有错了,就是没有真的传输过。。

哈哈哈,还是理论啊

~~~~~~~~~~~~~~~~~~~~~~~~  
 世界因为你我而年轻!
☆★○●◎◇◆□■△▲※

#17


我找到原因了 outx_xonxoffflow:=flase;
spcom的这个属性改成 flase就可以了
************
* 努力学习 *
*   全为   *
*¥人民币¥*
************

#18


一切都OK了,谢谢小杨兄的帮助。