mscomm控件中的oncomm事件为什么不触发呢?很奇怪,急死人了。

时间:2022-09-06 11:56:14
这是源代码,大家看一下哪里有错误?

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OleCtrls, MSCommLib_TLB, StdCtrls, Buttons;

type
  TForm1 = class(TForm)
    MSComm1: TMSComm;
    BitBtn1: TBitBtn;
    Edit3: TEdit;
    Edit4: TEdit;
    Memo2: TMemo;
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure MSComm1Comm(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
if MSComm1.PortOpen then MSComm1.PortOpen := false;//关闭端口
MSComm1.CommPort := 3;//设置端口3 
//MSComm1.InBufferSize := 256;//设置接收缓冲区为256个字节
//MSComm1.OutBufferSize := 256;//设置发送缓冲区为256个字节
MSComm1.Settings := '4800,n,8,1';//4800波特率,无校验,8位数据位,1位停止位
MSComm1.InputLen := 0;//读取缓冲区全部内容(32个字节) 
MSComm1.InBufferCount := 0;// 清除接收缓冲区
MSComm1.OutBufferCount:=0;// 清除发送缓冲区
MSComm1.RThreshold := 1;//设置接收32个字节产生OnComm 事件
 //MSComm1.InputMode := comInputModeText;//文本方式
MSComm1.InputMode := comInputModeBinary;//二进制方式
MSComm1.PortOpen := true;//打开端口
sleep(1000);
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if MSComm1.PortOpen then MSComm1.PortOpen := false;//关闭端口

end;

procedure TForm1.MSComm1Comm(Sender: TObject);
var 
buffer: Olevariant;//MSComm1.InputMode = comInputModeBinary 
str: string;//MSComm1.InputMode = comInputModeText 
i: integer; 
begin 
case MSComm1.CommEvent of 
comEvReceive: //串行接收事件处理
begin
if MSComm1.InputMode = comInputModeText then //字符方式读取 
str := MSComm1.Input//读出后会自动清除接收缓冲区,str[1]~str[32] 
else //二进制方式读取
buffer := MSComm1.Input;//读出后会自动清除接收缓冲区,buffer[0]~buffer[31]
Edit3.Text := '';
for i := 0 to MSComm1.RThreshold - 1 do //32字节Hex转换 
begin 
if MSComm1.InputMode = comInputModeText then //单行字符转换
Edit3.Text := Edit3.Text + inttohex(byte(str[i + 1]), 2) + ' '
else //单行二进制数据转换 
Edit3.Text := Edit3.Text + inttohex(buffer[i], 2) + ' ';
end;
Memo2.Lines.Add(Edit3.Text);//加入一行显示
end; 
end; 
end;


procedure TForm1.BitBtn1Click(Sender: TObject);
var 
i: integer;
s:string; 
begin 
Edit4.Text := '';
//for i := 0 to 31 do
begin 
//MSComm1.Output := char(i);//发送一个字符
//mscomm1.Output:='at#13#10';
mscomm1.Output:='at#13#10';

Edit4.Text := Edit4.Text + inttohex(i, 2);//以十六进制字符显示
end;
Memo1.Lines.Add(Edit4.Text);//加入一行显示

end;

end.

24 个解决方案

#1


是不是硬件有问题啊

#2


大家快看看吧,到底是哪里的原因呢?我COM3口上接得是一个无线上网卡,主要用来测一下信号。

#3


用超级终端测试,可以测出信号的。硬件应该没有问题。

#4


没人知道吗?高手们快来吧。上帝。

#5


upup

#6


看来没人知道了。

#7


不太清楚~ 没办法 mscomm控件中的oncomm事件为什么不触发呢?很奇怪,急死人了。

#8


配置信息正确不?波特率啥的

#9


Comm1.Settings := '4800,n,8,1';//4800波特率,无校验,8位数据位,1位停止位
这是波特率设置

#10


楼主,你的发送错误了,你设置InputMOde是二进制的,结果你发送的数据却是文本,试一试这个:

[code=Delphi(Pascal)]
unit Unit1; 

interface 

uses 
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, OleCtrls, MSCommLib_TLB, StdCtrls, Buttons; 

type 
  TForm1 = class(TForm) 
    MSComm1: TMSComm; 
    BitBtn1: TBitBtn; 
    Edit3: TEdit; 
    Edit4: TEdit; 
    Memo2: TMemo; 
    Memo1: TMemo; 
    procedure FormCreate(Sender: TObject); 
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
    procedure MSComm1Comm(Sender: TObject); 
    procedure BitBtn1Click(Sender: TObject); 
  private 
    { Private declarations } 
  public 
    { Public declarations } 
  end; 

var 
  Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
if MSComm1.PortOpen then MSComm1.PortOpen := false;//关闭端口 
MSComm1.CommPort := 3;//设置端口3 
MSComm1.InBufferSize := 1024;//设置接收缓冲区为1024个字节 
MSComm1.OutBufferSize := 1024;//设置发送缓冲区为1024个字节 
MSComm1.Settings := '4800,n,8,1';//4800波特率,无校验,8位数据位,1位停止位 
MSComm1.InputLen := 0;//一次性读取串口缓冲区的所有内容 
MSComm1.InBufferCount := 0;// 清除接收缓冲区 
MSComm1.OutBufferCount:=0;// 清除发送缓冲区 
MSComm1.RThreshold := 1;//设置接收1个字节产生OnComm 事件 
MSComm1.InputMode := comInputModeText;//文本方式 
//MSComm1.InputMode := comInputModeBinary;//二进制方式 
MSComm1.PortOpen := true;//打开端口 
//sleep(1000); 
end; 

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
begin 
if MSComm1.PortOpen then MSComm1.PortOpen := false;//关闭端口 

end; 

procedure TForm1.MSComm1Comm(Sender: TObject); 
var 
buffer: Olevariant;//MSComm1.InputMode = comInputModeBinary 
str: string;//MSComm1.InputMode = comInputModeText 
i: integer; 
begin 
case MSComm1.CommEvent of 
comEvReceive: //串行接收事件处理 
begin 
if MSComm1.InputMode = comInputModeText then //字符方式读取 
str := MSComm1.Input//读出后会自动清除接收缓冲区,str[1]~str[32] 
else //二进制方式读取 
buffer := MSComm1.Input;//读出后会自动清除接收缓冲区,buffer[0]~buffer[31] 
Edit3.Text := ''; 
for i := 0 to MSComm1.RThreshold - 1 do //32字节Hex转换 
begin 
if MSComm1.InputMode = comInputModeText then //单行字符转换 
Edit3.Text := Edit3.Text + inttohex(byte(str[i + 1]), 2) + ' ' 
else //单行二进制数据转换 
Edit3.Text := Edit3.Text + inttohex(buffer[i], 2) + ' '; 
end; 
Memo2.Lines.Add(Edit3.Text);//加入一行显示 
end; 
end; 
end; 


procedure TForm1.BitBtn1Click(Sender: TObject); 
var 
i: integer; 
s:string; 
begin 
Edit4.Text := ''; 
//for i := 0 to 31 do 
begin 
mscomm1.Output:='at#13#10'; 

Edit4.Text := Edit4.Text + inttohex(i, 2);//以十六进制字符显示 
end; 
Memo1.Lines.Add(Edit4.Text);//加入一行显示 

end; 

end. 

#11


10楼的朋友,还是不行。

#12


也是没有触发TForm1.MSComm1Comm事件

#13


你的MSComm控件的OnComm事件是连接到了你的程序的MSComm1Comm函数上吗?
你的MSComm是正常注册过的吗?
你的串口是不是正确的?
当发送的数据是String类型情况下,其模式是二进制还是ASCII都没影响(仅仅是不影响发送,但影响接收,但楼主使用的是二进制接收,所以在这一点上是没有问题的)

#14


楼主可以先抛开连接的硬件设备,仅仅进行MSComm控件和串口本身的测试,正常之后再连接硬件设备。
这样有利于分析问题产生的原因。

#15


是正常注册过的,并且comm事件也是连接到程序的MSCOMM1COMM函数上的。

#16


我对SPCOMM控件比较熟悉,觉得它一直是串口通讯的精品。而楼主所说的mscomm控件不熟悉,虽然也用过,觉得手感不好,就放弃了。

#17


16楼的朋友,都差不太多吧。能不能根据我的要求写一个程序呢?如果行的话,我马上给你100分

#18


MSComm1.CommPort := 3;//设置端口3 
MSComm1.Settings := '4800,n,8,1';//4800波特率,无校验,8位数据位,1位停止位 
如果上面2个你能肯定的话。
MSComm1.InputLen := 1024;这里修改试试看。

#19


帮你顶一下!

#20


MSComm1.RThreshold := 1;//设置接收32个字节产生OnComm 事件
这个跟说明是不是有出入啊

#21


LZ的COM3端口是USB转的吗?USB转的不是很可靠。
这是我自己写的一个发送过程:
var 

  i,tmpInt:Integer;
  tmpVar:array of Byte;
  tmpStr,Output:String;
begin
  try
    if not mscom.PortOpen  then
    begin
      Application.MessageBox('请确保串口已经打开!', '提示', 0 + 48);
      Exit;
    end;
    mscom.InBufferCount:=0; //清空接收缓冲区
    mscom.OutBufferCount:=0;//清空发送缓冲区
    if s <> '' then
    begin
      Output:=s;
      tmpStr:='FEFEFEFE'+ Output;
      tmpInt:=(Length(tmpStr) Div 2);
      tmpVar:=nil; //清空动态数组
      SetLength(tmpVar,tmpInt);//分配数组长度
      i:= 0;
      while i < tmpInt do
      begin
        tmpVar[i]:=StrtoInt('$' + Copy(tmpStr,(2*i+1),2));
        i:=i+1;
      end;
      mscom.Output:=tmpVar;
    end;
  finally
    ;
  end;

#22


17楼的朋友,有问题不防说出来大家一起讨论,如果单独让我帮你做程序,那不是给分就可以的。

#23


没有太看明白楼主的意思。你是要测试USB转串口卡是不是好的吧?你的串口的PIN2 和PIN3是短接起来的吗?短接起来的话应该会触发这个ONCOMM事件的。另外你程序里面有一段不知道是不是有问题。

for i := 0 to MSComm1.RThreshold - 1 do //32字节Hex转换 
begin 
if MSComm1.InputMode = comInputModeText then //单行字符转换 
Edit3.Text := Edit3.Text + inttohex(byte(str[i + 1]), 2) + ' ' 
else //单行二进制数据转换 
Edit3.Text := Edit3.Text + inttohex(buffer[i], 2) + ' '; 
end; 


MSCOMM1.RThreshold是触发串口事件的阀值,就是当接收缓冲区达到多少数值时就有这个ONCOMM事件,在读缓冲区数据时应该用缓冲区接收了多少字符的,也就是MSCOMM1.InBufferCount 。

我用过MSCOMM,用过SPCOMM,用过TURBOPOWER 的APDComport,觉得还是TurboPower做的串口控件好用一些。你可以尝试一下。

#24


使用串口调试器调试是否正常?

#1


是不是硬件有问题啊

#2


大家快看看吧,到底是哪里的原因呢?我COM3口上接得是一个无线上网卡,主要用来测一下信号。

#3


用超级终端测试,可以测出信号的。硬件应该没有问题。

#4


没人知道吗?高手们快来吧。上帝。

#5


upup

#6


看来没人知道了。

#7


不太清楚~ 没办法 mscomm控件中的oncomm事件为什么不触发呢?很奇怪,急死人了。

#8


配置信息正确不?波特率啥的

#9


Comm1.Settings := '4800,n,8,1';//4800波特率,无校验,8位数据位,1位停止位
这是波特率设置

#10


楼主,你的发送错误了,你设置InputMOde是二进制的,结果你发送的数据却是文本,试一试这个:

[code=Delphi(Pascal)]
unit Unit1; 

interface 

uses 
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, OleCtrls, MSCommLib_TLB, StdCtrls, Buttons; 

type 
  TForm1 = class(TForm) 
    MSComm1: TMSComm; 
    BitBtn1: TBitBtn; 
    Edit3: TEdit; 
    Edit4: TEdit; 
    Memo2: TMemo; 
    Memo1: TMemo; 
    procedure FormCreate(Sender: TObject); 
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
    procedure MSComm1Comm(Sender: TObject); 
    procedure BitBtn1Click(Sender: TObject); 
  private 
    { Private declarations } 
  public 
    { Public declarations } 
  end; 

var 
  Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
if MSComm1.PortOpen then MSComm1.PortOpen := false;//关闭端口 
MSComm1.CommPort := 3;//设置端口3 
MSComm1.InBufferSize := 1024;//设置接收缓冲区为1024个字节 
MSComm1.OutBufferSize := 1024;//设置发送缓冲区为1024个字节 
MSComm1.Settings := '4800,n,8,1';//4800波特率,无校验,8位数据位,1位停止位 
MSComm1.InputLen := 0;//一次性读取串口缓冲区的所有内容 
MSComm1.InBufferCount := 0;// 清除接收缓冲区 
MSComm1.OutBufferCount:=0;// 清除发送缓冲区 
MSComm1.RThreshold := 1;//设置接收1个字节产生OnComm 事件 
MSComm1.InputMode := comInputModeText;//文本方式 
//MSComm1.InputMode := comInputModeBinary;//二进制方式 
MSComm1.PortOpen := true;//打开端口 
//sleep(1000); 
end; 

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
begin 
if MSComm1.PortOpen then MSComm1.PortOpen := false;//关闭端口 

end; 

procedure TForm1.MSComm1Comm(Sender: TObject); 
var 
buffer: Olevariant;//MSComm1.InputMode = comInputModeBinary 
str: string;//MSComm1.InputMode = comInputModeText 
i: integer; 
begin 
case MSComm1.CommEvent of 
comEvReceive: //串行接收事件处理 
begin 
if MSComm1.InputMode = comInputModeText then //字符方式读取 
str := MSComm1.Input//读出后会自动清除接收缓冲区,str[1]~str[32] 
else //二进制方式读取 
buffer := MSComm1.Input;//读出后会自动清除接收缓冲区,buffer[0]~buffer[31] 
Edit3.Text := ''; 
for i := 0 to MSComm1.RThreshold - 1 do //32字节Hex转换 
begin 
if MSComm1.InputMode = comInputModeText then //单行字符转换 
Edit3.Text := Edit3.Text + inttohex(byte(str[i + 1]), 2) + ' ' 
else //单行二进制数据转换 
Edit3.Text := Edit3.Text + inttohex(buffer[i], 2) + ' '; 
end; 
Memo2.Lines.Add(Edit3.Text);//加入一行显示 
end; 
end; 
end; 


procedure TForm1.BitBtn1Click(Sender: TObject); 
var 
i: integer; 
s:string; 
begin 
Edit4.Text := ''; 
//for i := 0 to 31 do 
begin 
mscomm1.Output:='at#13#10'; 

Edit4.Text := Edit4.Text + inttohex(i, 2);//以十六进制字符显示 
end; 
Memo1.Lines.Add(Edit4.Text);//加入一行显示 

end; 

end. 

#11


10楼的朋友,还是不行。

#12


也是没有触发TForm1.MSComm1Comm事件

#13


你的MSComm控件的OnComm事件是连接到了你的程序的MSComm1Comm函数上吗?
你的MSComm是正常注册过的吗?
你的串口是不是正确的?
当发送的数据是String类型情况下,其模式是二进制还是ASCII都没影响(仅仅是不影响发送,但影响接收,但楼主使用的是二进制接收,所以在这一点上是没有问题的)

#14


楼主可以先抛开连接的硬件设备,仅仅进行MSComm控件和串口本身的测试,正常之后再连接硬件设备。
这样有利于分析问题产生的原因。

#15


是正常注册过的,并且comm事件也是连接到程序的MSCOMM1COMM函数上的。

#16


我对SPCOMM控件比较熟悉,觉得它一直是串口通讯的精品。而楼主所说的mscomm控件不熟悉,虽然也用过,觉得手感不好,就放弃了。

#17


16楼的朋友,都差不太多吧。能不能根据我的要求写一个程序呢?如果行的话,我马上给你100分

#18


MSComm1.CommPort := 3;//设置端口3 
MSComm1.Settings := '4800,n,8,1';//4800波特率,无校验,8位数据位,1位停止位 
如果上面2个你能肯定的话。
MSComm1.InputLen := 1024;这里修改试试看。

#19


帮你顶一下!

#20


MSComm1.RThreshold := 1;//设置接收32个字节产生OnComm 事件
这个跟说明是不是有出入啊

#21


LZ的COM3端口是USB转的吗?USB转的不是很可靠。
这是我自己写的一个发送过程:
var 

  i,tmpInt:Integer;
  tmpVar:array of Byte;
  tmpStr,Output:String;
begin
  try
    if not mscom.PortOpen  then
    begin
      Application.MessageBox('请确保串口已经打开!', '提示', 0 + 48);
      Exit;
    end;
    mscom.InBufferCount:=0; //清空接收缓冲区
    mscom.OutBufferCount:=0;//清空发送缓冲区
    if s <> '' then
    begin
      Output:=s;
      tmpStr:='FEFEFEFE'+ Output;
      tmpInt:=(Length(tmpStr) Div 2);
      tmpVar:=nil; //清空动态数组
      SetLength(tmpVar,tmpInt);//分配数组长度
      i:= 0;
      while i < tmpInt do
      begin
        tmpVar[i]:=StrtoInt('$' + Copy(tmpStr,(2*i+1),2));
        i:=i+1;
      end;
      mscom.Output:=tmpVar;
    end;
  finally
    ;
  end;

#22


17楼的朋友,有问题不防说出来大家一起讨论,如果单独让我帮你做程序,那不是给分就可以的。

#23


没有太看明白楼主的意思。你是要测试USB转串口卡是不是好的吧?你的串口的PIN2 和PIN3是短接起来的吗?短接起来的话应该会触发这个ONCOMM事件的。另外你程序里面有一段不知道是不是有问题。

for i := 0 to MSComm1.RThreshold - 1 do //32字节Hex转换 
begin 
if MSComm1.InputMode = comInputModeText then //单行字符转换 
Edit3.Text := Edit3.Text + inttohex(byte(str[i + 1]), 2) + ' ' 
else //单行二进制数据转换 
Edit3.Text := Edit3.Text + inttohex(buffer[i], 2) + ' '; 
end; 


MSCOMM1.RThreshold是触发串口事件的阀值,就是当接收缓冲区达到多少数值时就有这个ONCOMM事件,在读缓冲区数据时应该用缓冲区接收了多少字符的,也就是MSCOMM1.InBufferCount 。

我用过MSCOMM,用过SPCOMM,用过TURBOPOWER 的APDComport,觉得还是TurboPower做的串口控件好用一些。你可以尝试一下。

#24


使用串口调试器调试是否正常?