有关用SPComm编写串口通信程序的问题! (100分)

  • 主题发起人 主题发起人 qikefei
  • 开始时间 开始时间
Q

qikefei

Unregistered / Unconfirmed
GUEST, unregistred user!
本人用一台计算机通过RS232/RS485转接口连接一台智能电表(MODBUS协议),结果向电表发送一个读寄存器的字符串却没有反映。但是我用一个串口测试软件Bitboy向串口发送相同的字符串就有返回值。想来想去也不知道个所以然,请各位大侠指教。谢谢!程序源代码如下:
unit Mainfrm;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, SPComm, ExtCtrls, ComCtrls;

type
TfrmComm = class(TForm)
Comm: TComm;
StatusBar1: TStatusBar;
Panel1: TPanel;
Panel2: TPanel;
mmoComm: TMemo;
btnOpen: TBitBtn;
btnClose: TBitBtn;
btnSend: TBitBtn;
Panel3: TPanel;
edtSendText: TEdit;
Label6: TLabel;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
cmbByteSize: TComboBox;
cmbStopBits: TComboBox;
cmbParity: TComboBox;
edtCommName: TEdit;
edtBaudRate: TEdit;
procedure btnOpenClick(Sender: TObject);
procedure btnCloseClick(Sender: TObject);
procedure btnSendClick(Sender: TObject);
procedure CommReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
procedure edtBaudRateExit(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure cmbByteSizeChange(Sender: TObject);
procedure cmbStopBitsChange(Sender: TObject);
procedure cmbParityChange(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmComm: TfrmComm;
implementation

{$R *.dfm}

//当窗体创建时,初始化参数
procedure TfrmComm.FormCreate(Sender: TObject);
begin
edtCommName.Text := 'COM1';
edtBaudRate.Text := '9600';
cmbByteSize.ItemIndex := 3; //8位
cmbStopbits.ItemIndex := 0; //1位
cmbParity.ItemIndex := 1; //奇校验
end;

//打开端口
procedure TfrmComm.btnOpenClick(Sender: TObject);
begin
//设置串口参数
comm.CommName := edtCommName.Text;
comm.BaudRate := strToInt(edtBaudRate.Text);
comm.ByteSize := TByteSize(cmbByteSize.ItemIndex);
comm.StopBits := TStopBits(cmbStopBits.ItemIndex);
comm.Parity := TParity(cmbParity.ItemIndex);
//打开串口
try
Comm.StartComm;
except
raise Exception.Create('打开串口错误');
end;
statusbar1.Panels[0].Text := Comm.CommName + '已打开';
statusbar1.Refresh;
btnOpen.Enabled := False;
btnSend.Enabled := True;
btnClose.Enabled := True;
end;

//关闭端口
procedure TfrmComm.btnCloseClick(Sender: TObject);
begin
Comm.StopComm;
statusbar1.Panels[0].Text := Comm.CommName + '已关闭';
statusbar1.Refresh;
end;


//向端口发送数据
procedure TfrmComm.btnSendClick(Sender: TObject);
var
str: Pchar;
Count: integer;
begin
str := Pchar(edtSendText.Text);
Count := Length(str);
if Comm.WriteCommData(str, Count) then
mmoComm.Lines.Add('已发送' + intTostr(Count) + '个字符')
else
raise exception.Create('发送错误');
end;

//从端口接收数据
procedure TfrmComm.CommReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
strRecv : string;
begin
setLength(strRecv,BufferLength);
Move(Buffer^,pchar(strRecv)^,BufferLength);
mmoComm.Lines.Add('已收到:'+intTostr(BufferLength)+'字节的数据');
mmoComm.Lines.Add(strRecv);
mmoComm.Invalidate ;
end;

//对波特率进行有效性检验
procedure TfrmComm.edtBaudRateExit(Sender: TObject);
var
i: integer;
begin
try
i := strToInt(edtBaudRate.Text)
except
edtBaudRate.setfocus;
raise Exception.Create('波特率设置错误');
end;
//改变串口的波特率
comm.BaudRate := StrToInt(edtBaudRate.Text);
end;

procedure TfrmComm.cmbByteSizeChange(Sender: TObject);
begin
//改变串口的数据位
comm.ByteSize := TByteSize(cmbByteSize.ItemIndex);
end;

procedure TfrmComm.cmbStopBitsChange(Sender: TObject);
begin
//改变串口的停止位
comm.StopBits := TStopBits(cmbStopBits.ItemIndex);
end;

procedure TfrmComm.cmbParityChange(Sender: TObject);
begin
//设置串口的奇偶校验位
comm.Parity := TParity(cmbParity.ItemIndex);
end;

end.
 
哦!会不会是字符串的进制的问题呢?该如何解决请各位大侠赐教!
字符串:0103011000018433
01(电表地址) 03(查询功能码) 0110(查询寄存器地址) 0001(寄存器个数) 8433(CRC校验码)
 
spcomm好像是有点问题
先用mscomm(或串口专家)收发一次数据,然后在用spcomm收发试试
 
先用示波表测测发送数据时COM口有没有反应吧
发送成功了 接收就没什么问题了
 
十六进制发送
$01+$03+$01+$10+$00+$01+$84+$33
 
串口速率是否匹配?
 
Spcomm 简单易用,一般没什么问题?
串口速率不匹配
也应该能收到数据(不过是错的)
16个bit作为2个Byte
再组合一下试试
 
用一个串口测试软件Bitboy向串口发送相同的字符串就有返回值,肯定不是硬件问题。
而且速率是匹配的。
是不是这个字符串在发送前要进行处理呢?起始位和结束位不用自己加吧?如果要转换成十六进制再发出,具体该怎样做?
谢谢!
 
起始位和结束位不用自己加
只要设com 232就行了。
发的时候不用转16进置  
 
智能电表一般来说都要转换成十六进制后发送

你的智能电表是什么牌子,型号?ELPANEL?MH?DUCATI?。。。

 
真是头痛啊!
各位大侠救命啊!
 
电表是YADA的,没名气,是个广东的厂家生产的。

那该如何转换成十六进制呢?
 
>>那该如何转换成十六进制呢?
上面不是说了吗!!!
 
好象我看到你没有做延迟处理哦...发完消息后要延迟哦.....
 
spcomm没有问题呀,你吧延时加进去看看
 
有些破仪表的开发商是弱智,我碰到广东佛分的一种灯光仪,发几个字节取数,
但每发一个字节,要等3ms以上再发下一个字节才行,开发仪表的人该去死了。
看看你的是不是这这问提,
命令分成字节一个一个发,每发一字节,等几ms
 
To Avenir:
大侠有没有相关的源代码?
 
谢谢大家,终于搞定了!!!
 
后退
顶部