在线等待 spcomm 232 通讯失败(50分)

  • 主题发起人 david_xl
  • 开始时间
D

david_xl

Unregistered / Unconfirmed
GUEST, unregistred user!
在发送框内给下位机(仪表)命令AA(仪表接受16进制命令)时仪表没有响应。同样串口配置下用现成的C编的通讯测试模块则发送后有响应。那位大侠帮忙看一下那里错了(字符串和数据?)
原代码如下:
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;
cmbStopbits.ItemIndex := 0;
cmbParity.ItemIndex := 0;
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.
 
如果你的帧头是16进制的AA,那么你的发送数据框的数据要做一个转换才可以发送
//HEX字串转ASC字串
function HexToStr(SourceString : string) : string;
var i:integer;
begin
result:='';
i:=1;
while i<=length(SourceString)do
if SourceString<>' '
then
if SourceString[i+1]=' '
then
begin
result:=result+char(StrToInt('$'+SourceString));
i:=i+2;
end
else
begin
result:=result+char(StrToInt('$'+SourceString+SourceString[i+1]));
i:=i+2;
end
else
i:=i+1;
end;
 
能否帮忙看一下如何将以上转换加到我的程序中
 
有没有简单的办法直接修改我原来的程序?
 
comm.CommName := edtCommName.Text;
comm.BaudRate := strToInt(edtBaudRate.Text);
comm.ByteSize := TByteSize(cmbByteSize.ItemIndex);
comm.StopBits := TStopBits(cmbStopBits.ItemIndex);
comm.Parity := TParity(cmbParity.ItemIndex);
这里出问题了, 你用showmessage检查一下看.真正赋的值是什幺?
 
comm.ByteSize := TByteSize(cmbByteSize.ItemIndex);
comm.StopBits := TStopBits(cmbStopBits.ItemIndex);
老老实实写原型
//字元長度
case StrToInt(cmbByteSize.Text) of
5: DM.Comm1.ByteSize := _5;
6: DM.Comm1.ByteSize := _6;
7: DM.Comm1.ByteSize := _7;
8: DM.Comm1.ByteSize := _8;
end;
 
请教我该如何改呢?
 
我太菜了,没看懂怎么改,能否更具体点?
 
此程序在PC之间收发正常,但发送给仪表没反应,我感觉是字符/16进制问题,但不知如何
修改
 
找个串口监控软件看你发下去的数据是否正确吧。
有可能是你下位机的串口设置和PC不一样,比如检验位之类的
 
已试过,下位机正常,设置也一样
 
procedure TfrmComm.btnSendClick(Sender: TObject);
var
str: Pchar;
S:STRING;
Count: integer;
begin
S:=HEXTOSTR(edtSendText.Text);
str := Pchar(S);
Count := Length(S);
if Comm.WriteCommData(str, Count) then
mmoComm.Lines.Add('已发送' + intTostr(Count) + '个字符')
else
raise exception.Create('发送错误');
end;
 
你确认下位机收到的数据是正常的了吗?如何确认的,现在肯定是发到下位机的数据有问题
由于很久没有做串口了,估计错误可能是
1) 串口参数不匹配
2)发送用这个 Comm.WriteCommData(str, Count) 可能有问题,尝试一下
Comm.WriteCommData(str[1], Count),如果不行,你试试逐个数据发下去,
大概是
SendData:array of Byte;
然后填你的协议 发Comm.WriteCommData(@SendData[0],Count),
 
HEXTOSTR如何声明
 
不用声明,直接调用即可
 
RJU:用串口检测软件发AA下位机正确地执行了“置零”
 
maxim88, 执行时出错:[Error] MainfrmAM2008receiver.pas(102): Undeclared identifier: 'HEXTOSTR'
 
AA是'AA'还是 $AA?我想是$AA吧
SendData:Byte;
SendData:=$AA;
Comm.WriteCommData(@SendData,1)?
 
把这个函数放在调用它的过程之前试试
还不行就留个邮箱,给你个例子
 
还是不行, 我的邮箱marc.ma@163.com 谢谢
 
顶部