在CSDN上很久没人理,还是回到大富翁来。(还是串口通信问题)(150分)

  • 主题发起人 主题发起人 moodboy
  • 开始时间 开始时间
M

moodboy

Unregistered / Unconfirmed
GUEST, unregistred user!
1.MScomm输入缓冲区怎么设置好?(30分)
我发现设置大小不同,接收到的数据大小也不同。举例说:
我接收的数据最大有64K,但不知道到底是多少,当我设成1024时统计了一下,
约接收到2K多,设成128字节时,约1K多,设成最大时又比设成1024时多。
2.spcomm的使用(120分)
我的要求是把Memo1中的不定长字符串转换成十六进制发送给外设,
外设发回的十六进制数据再转换成字符串在Memo2中显示。
我用全文检索找了很久,发现以前看到的一些好贴子找不到了,只好请高手再花点时间。
谢谢!

 
好失望。
怎样给问题加分?
 
function TForm1.Send(Text: string): Boolean;
var
s: string;
begin
s := '';
for i := 1 to Length(Text) do
s := s + IntToHex(Byte( Text);
Result := SpComm.WriteCommData(PChar(s), Length(s));
end;

procedure TForm1.CommReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
sBuffer, s: string;
begin
sBuffer := '';
SetLength(sBuffer, BufferLength);
StrLCopy(PChar(sBuffer), Buffer, BufferLength);
s := '';
for i := 0 to BufferLength div 2 do
s := s + HexToInt('$' + Copy(sBuffer, i * 2 + 1, 2));
ShowMessage(s);
end;


------
http;//www.8421.org
 
问题一:
串行口控件的输入缓冲区是与你读它的频率有关的,传输1M的数据并不是需要1M的缓冲区,
如果通讯速率(波特率)是9600,那么每秒将会有960字节的数据,如果你对控件的读间隔
时间不大于一秒,那么1024字节的缓冲区就够了,不管你的报文是1M还是10M;
问题二:
把报文读进一个 String 变量,然后定义一个 PByteAry 型的指针
TByteAry = array [0..1] of Byte;
PByteAry = ^TByteAry;
让这个指针变量指向字符串的第一个字符
var P: PByteAry;
begin
P:= @S[1];
...
然后,就 for I:= 1 to length(S) do P^...
 
呵呵!moodboy不好意思,赚了你不少分,问题却没给你怎么解决.
第一个问题说明白点,好吗?
第二个问题
var //字符串转为16进制;
Send:array of Byte;
Chr1,Chr2:Char;
Byte1,Byte2:Byte;
I:Integer;
begin
Byte1:=0;
Byte2:=0;
SetLength(Send,(Length(String) div 2));
for I:=1 to Length(String) div 2 do
begin
Chr1:=Str[2*I-1];
Chr2:=Str[2*I];
if (Chr1 in['0'..'9']) then
Byte1:=Ord(Chr1)-48
else
if (Chr1 in['A'..'f']) then
Byte1:=Ord(Chr1)-55;
if (Chr2 in['0'..'9']) then
Byte2:=Ord(Chr2)-48
else
if (Chr2 in['A'..'F']) then
Byte2:=Ord(Chr2)-55;
Send:=Byte1*16+Byte2;
end;
end;
16进制转为字符串用IntToHex函数;
你有QQ吗?聊一聊?
 
你MEMO1,MEMO2中都是数字吗,只有数值才有16进制的,转换可以用FORMAT函数实现.只要是
字符串了,收发自然不在话下.
 
多谢大家的帮忙!
to 卸健飞天:
我没有QQ,只有信箱:mumuhai@sohu.com
第一个问题,我也不知道怎样表达了,我向单片机发出命令后就等着它自己接收,结果发现
不同的缓冲区大小,接收到的数据大小也不同。大概如supmermanTm所说。
还有,我只用了2、3、5线,这样对传输速率是否有影响?spcomm是否比较快?
希望大家继续关注。
 
spcomm比mscomm好
 
to qdyoung:
能否发一份Demo给我?我对spcomm太陌生,加上我水平低,调试不出。谢谢!
to all:
谁还有什么办法使MScomm接收速率快点?其实我很不想改控件了,改了后代码又不同,到
时候CRC还得重新做。
 
是不是你缓冲区每次没有取尽或计算机读数据的时间间隔过大,造成缓冲区溢出?
亦或是你说的无线通讯中,数据出错?
 
一个磁卡机的例子,还是要自己看懂程序,自己慢慢调试吧:
type
TWriteCardForm = class(TForm)
Comm: TComm;
procedure FormDestroy(Sender: TObject);
procedure CommReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
bWriteCard, bWriteCardResult: Boolean;
function OpenComm: Boolean;
function WriteCard(sText: string): Boolean;
public
{ Public declarations }
end;

implementation

{$R *.DFM}
uses
Utils;

{ 磁卡机状态:
1. 三个灯都亮:电源打开而串口没有打开
2. 绿灯亮:准备好读磁卡
3. 黄灯亮:准备好写磁卡,20秒后超时
4. 红灯亮:出现错误
5. 声音:读写成功或收到电脑信息响一声,失败三声
}

procedure TWriteCardForm.FormCreate(Sender: TObject);
begin
bWriteCard := False;
OpenComm;
end;

procedure TWriteCardForm.FormDestroy(Sender: TObject);
begin
Comm.StopComm;
end;

procedure TWriteCardForm.CommReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
p: array[0..256] of Char;
sText: string;
i: Integer;
begin
if BufferLength < 256 then
begin
Dec(BufferLength); //最后一个BCC字符不要
StrLCopy(p, Buffer, BufferLength);
p[BufferLength] := #0;
sText := '';
for i := 0 to BufferLength - 1 do
if not (p in [#2, #3, '%', ';', '+', '?']) then
sText := sText + p; //从接收到的字符中去掉控制符,得到实际内容
if p[1] = #21 then //错误标志:#2 15h #3 BCC
begin
if bWriteCard then
begin
bWriteCardResult := False;
ShowError('出现错误,写卡失败。请重试!');
end
else ShowError('读卡失败')
end
else
begin
if bWriteCard then
begin
bWriteCardResult := True;
ShowMessage('写卡成功,写的内容是:' + sText);
end
else
begin
if Assigned(ReadCardEdit) and ReadCardEdit.Focused then
begin
ReadCardEdit.Text := sText;
if Assigned(ReadCardEdit.OnEnterPress) then
ReadCardEdit.OnEnterPress(ReadCardEdit);
end
else ShowMessage('从磁卡读到:' + sText);
end;
end;
end
else
begin
if bWriteCard then bWriteCardResult := False;
ShowError('接收的信息超过系统估计的256个字符');
end;
bWriteCard := False;
end;

function TWriteCardForm.OpenComm: Boolean;
begin
Result := True;
if Comm.Handle = 0 then
try
Comm.StartComm;
except
on E: Exception do
begin
Result := False;
ShowError('写卡机故障:' + E.Message, True);
end;
end;
end;

function TWriteCardForm.WriteCard(sText: string): Boolean;
var
sBuffer: string;
BCC: Byte;
i: Integer;
dw: DWord;
begin
Result := OpenComm;
if not Result then Exit;
sBuffer := ';' + sText + '?'#3; //第一轨起始符"%"、第二轨起始符";"、第三轨起始符"+"、结束符都是"?",所有数据结束符#3
BCC := 0; //求异或和
for i := 1 to Length(sBuffer) do //
BCC := BCC xor Byte(sBuffer); //
sBuffer := #2 + sBuffer + Char(BCC); //所有数据以#2起始,BCC结束
Result := Comm.WriteCommData(PChar(sBuffer), Length(sBuffer));
if not Result then ShowMessage('系统错误,无法启动写卡过程')
else
begin
Result := False;
BeginWait('开始写卡,请把磁卡划过写卡机...');
bWriteCard := True; //进入写卡状态
bWriteCardResult := False; //写卡结果
dw := GetTickCount;
repeat
Sleep(1);
Application.ProcessMessages;
until not bWriteCard or (GetTickCount - dw > 20000); //超时或完成
EndWait;
if bWriteCard then
ShowError('超时,写卡失败。请重试!') //超时
else Result := bWriteCardResult;
bWriteCard := False; //退出写卡状态
end;
end;
 
to 卸健飞天:
怎样才算取尽?我现在还只是人工方式调试,发一次命令就接收一次数据。
数据应该不会有错,我是控制单片机,再由单片机控制无线通讯设备的。单片机发送的
数据为每62字节加一个校验码,前面加一个帧头,最大数据达到64K。我还没有把数据分开
来校验。但接收其它的小数据,校验后是对的。(有很多种数据)
 
to qdyoung:
你的发送函数里这句不能通过:s := s + IntToHex(Byte( Text));
下面的代码
procedure TForm1.CommReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
sBuffer, s: string;
begin
sBuffer := '';
SetLength(sBuffer, BufferLength);
StrLCopy(PChar(sBuffer), Buffer, BufferLength);
s := '';
for i := 0 to BufferLength div 2 do
s := s + HexToInt('$' + Copy(sBuffer, i * 2 + 1, 2));
ShowMessage(s);
end;
没有hexToint这个函数吧?
 
s := s + IntToHex(Byte( Text));
->
s := s + IntToHex(Byte( Text), 2);

HexToInt -> StrToInt
 
to qdyoung:
strtoint得到整型,s为字符串,怎么行?
 
请看看以下代码怎么没反应?是这样发送吗?

procedure TsendForm.Button2Click(Sender: TObject);
var
s: string;
j:integer;
text:string;
begin
text:=memo2.text;
s := '';
for j := 1 to Length(Text) do
s := s + IntTohex(Byte( Text[j]),2);
Comm1.WriteCommData(PChar(s), Length(s));
end;

procedure TsendForm.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
sBuffer, s: string;
i:integer;
begin
sBuffer := '';
SetLength(sBuffer, BufferLength);
StrLCopy(PChar(sBuffer), Buffer, BufferLength);
s := '';
for i := 0 to BufferLength div 2 do
s := s +('$'+Copy(sBuffer, i * 2 + 1, 2));
ShowMessage(s);
end;

 
Chr(StrToInt('$'+Copy(sBuffer, i * 2 + 1, 2)));
 
烦,服务器罢工老半天,上来后又说非法操作!
终于上来了!
 
本以为中午休息一下醒来后就没事了,看来还是我水平太低。
qdyoung,你调试过吗?
 
还有哪儿有错
 
后退
顶部