使用Spcomm的Comm1.WriteCommByte,接受时怎么样才能转换为byte?程序(有关图象传送)贴出,帮忙解决问题的再加50分!!! (50分)

C

cjh_xf

Unregistered / Unconfirmed
GUEST, unregistred user!
在传送是使用的是Comm1.WriteCommByte(B),接受是使用Move(Buffer,S,BufferLength);
B:Byte;
S:String;
怎样使接受的东西转换为byte?

另:我编的是利用串口传送图片的程序,但数据传送中,接受方的程序回自动关闭,郁闷!
 
传的过程中有错误吗》?
 
在传送是使用的是Comm1.WriteCommByte(B),接受是使用Move(Buffer,S,BufferLength);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
错误!
正确应该是
SetLength(S,BufferLength);
Move(Buffer^,PChar(S)^,BufferLength);

>>怎样使接受的东西转换为byte?
var pb: PBtye;
pb := PByte(Buffer);
就转化成Byte指针,用pb[0],pb....就可以取每个字节的值了

 
我把我的程序的主要部分帖出,高手帮我看看,再加50分!!我接受是不能成功将数据转换为图象
显示与Image中!

//数据发送部分
procedure TForm1.Button1Click(Sender: TObject);
var
Stream1:TFileStream;
J:Integer;
B:Byte;
begin
//将图形数据放于stream中,然后再按字节读出,发送
Stream1:=TFileStream.Create('C:/My Documents/My Pictures/3.bmp', fmOpenRead);
try
for J:=0 to Stream1.Size do
begin
Stream1.Read(B,1);
if not Comm1.WriteCommByte(B) then
Sleep(1);
end;
//以#为结束标志
Comm1.WriteCommData('#',1);
finally
Stream1.Free;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
try
Comm1.StartComm;
StatusBar1.SimpleText:='正常工作';
except
StatusBar1.SimpleText:='串口被占用或不存在!';
end;
Stream2:=TMemoryStream.Create;
//创建bitmap
Bitmap1:=TBitmap.Create;
//
Edit1.Text:=IntToStr(Comm1.BaudRate);
ComboBox1.Text:=Comm1.CommName;
end;

//接受部分
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
S:String;
I:Integer;
begin
SetLength(S,BufferLength);
Move(Buffer^,Pchar(S)^,BufferLength);
I:=SizeOf(S);
if I<0 then
exit;
/////////////////////////////////////////////////
//判断是否结束
if S='#' then
begin
//将接受到的图片存放文件中,并显示在image中
Stream2.Position:=0;
Bitmap1.LoadFromStream(Stream2);
Image1.Picture:=TPicture(Bitmap1);
end
else
begin
//将数据读入到流中
Stream2.Write(S,1);
end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Comm1.StopComm;
Bitmap1.FreeImage;
Stream2.Free;
end;

哪位大侠出手,感激不尽!
 
接收部分
Move(Buffer^,Pchar(@S)^,BufferLength);
 
啊!?!
 
>Move(Buffer^,Pchar(@S)^,BufferLength);
~~ 错误
语重心长的对cjh_xf说:你的低级错误有好多,高级错误更多
哎,怎么办,要改正你的错误,还不如我重新给你编,可是才
50分,再加50也才100,哎,分太少,怎么办,等我吃完饭再
说吧。
不过有些高人不要分也会给你解决,就看你的运气了(你的错
误很简单,很明显,很好改正的)。
 

//判断是否结束
if S='#' then
~~~~~~~~~~~~~永远也不会成立(1万亿分之一的可能)
begin
//将接受到的图片存放文件中,并显示在image中
Stream2.Position:=0;
Bitmap1.LoadFromStream(Stream2);
Image1.Picture:=TPicture(Bitmap1);
end
else
begin
//将数据读入到流中
Stream2.Write(S,1);
~~~~~~~~~~~~~~~~~~~~~~怎么才写一个字节,也没有看到循环呀?
end;

 
我并不是一个高手,但是我还是提出我的意见,供参考

接收时缓冲区中不会一次只接收一个字符的,所以
if S='#' then....
这种写法一定不对;

我以前也写过此类程序,接收缓冲区用的是一个Byte数组,长度2048
因为接收缓冲区最大也就这么大了
var
RecvBuffer: Array[0..2047] of Byte;

接收时我将Buffer的内容转移到数组中,
Move(Buffer^,Pchar(@RecvBuffer)^,BufferLength);
然后再对数组处理。
楼上的说我的写法错误,但是我觉得是对的,除非这种写法对于string类型是错误的,
还请指教
 
var
RecvBuffer: Array[0..2047] of Byte;

接收时我将Buffer的内容转移到数组中,
Move(Buffer^,Pchar(@RecvBuffer)^,BufferLength);
这是正确的
但是
Move(Buffer^,Pchar(@S)^,BufferLength);
这是错误的,因为
var S: string;
S的定义是string,而不是Array[0..2047] of Byte;
你就写一个Move(Buffer^,Pchar(@S)^,BufferLength);
当然认为S的定义和上面一样,当然就是错误的了!
所以 当 S: string时你错误,S: Array[0..2047] of Byte;你是正确的
不过,你就写一句Move(Buffer^,Pchar(@S)^,BufferLength);
你认为是正确还是错误?



 
我的理解是string是一个字符序列(D6的help如此描述),
在使用move对其进行数据传递时当然要指明其地址,
因为string并不是一个指针,
还请指教

 
小弟是刚刚接受Delphi,而且自感在编程方面没有天赋!不过犯了这么多低级错误还是很汗颜!~~~~
谢谢ss2000的解答!我袋子里的银子不多,但大侠如若想助(帮我把接受部分的程序搞掂),愿意倾禳报答!(100+141分)
 
大侠,既然您说不难就伸手帮帮俺吧,就人一命,胜七级浮屠呀!~~~打拱装!
 
lmcui:
看来你还是很谦虚,那我们再讨论讨论。
string确实是一个字符序列,而Move函数需要的是指向缓冲区的变量,注意,不是
指针,所以如果是指针,一定要加^.
而PChar(@S)^仔细分析,其实等同于S,也就是说
Move(Buffer^,Pchar(@S)^,BufferLength);
等同于
Move(Buffer^,S,BufferLength);
那么Move(Buffer^,S,BufferLength);是否正确呢?
相信大家可以比较清楚的明白这是错误的。这里大家需要仔细理解一下
为什么PChar(@S)^等同于S!
那为什么PChar(S)^又可以呢?是因为Delphi专门对PChar(S)作了处理,
使PChar(S)相当于一个函数,功能为取字符串S中,指向实际存储字符串
的内存地址,所以PChar(@S)是一种想当然的用法,因为S的地址不等于
保存字符串的内存地址!不知lmcui兄是否明白了?

cjh_xf:
以下是你的程序:

//数据发送部分
procedure TForm1.Button1Click(Sender: TObject);
var
Stream1:TFileStream;
J:Integer;
B:Byte;
begin
//将图形数据放于stream中,然后再按字节读出,发送
Stream1:=TFileStream.Create('C:/My Documents/My Pictures/3.bmp', fmOpenRead);
try
for J:=0 to Stream1.Size do
begin
Stream1.Read(B,1);
if not Comm1.WriteCommByte(B) then
Sleep(1);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~这有什么用?失败了还是照发不误,仅仅Sleep(1),作用何在?
end;
//以#为结束标志
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
首先,你在设计传输协议上是错误的,或者说你根本没有作过
这方面的东西,所以想出了个用'#'作结束符的主意。难道图形数据中
你能保证没有'#'这个数据?那么接收端收到'#'后,怎么判断是结束还
是图形中的数据?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Comm1.WriteCommData('#',1);
finally
Stream1.Free;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
try
Comm1.StartComm;
StatusBar1.SimpleText:='正常工作';
except
StatusBar1.SimpleText:='串口被占用或不存在!';
end;
Stream2:=TMemoryStream.Create;
//创建bitmap
Bitmap1:=TBitmap.Create;
//
Edit1.Text:=IntToStr(Comm1.BaudRate);
ComboBox1.Text:=Comm1.CommName;
end;

//接受部分
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
S:String;
I:Integer;
begin
SetLength(S,BufferLength);
Move(Buffer^,Pchar(S)^,BufferLength);
I:=SizeOf(S);
if I<0 then
exit;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I的值是多少?什么意思?I=SizeOf(S)永远是4,想想为什么?
如果你要取S的长度,应该用I=Length(S),但是,显然S的长度
是BufferLength,所以,这几句话混乱不堪,概念和逻辑错误百出
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/////////////////////////////////////////////////
//判断是否结束
if S='#' then
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
由于S是整个字符串,所以这里又是概念和逻辑错误百出
当然,以下的代码就毫无用处了
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
begin
//将接受到的图片存放文件中,并显示在image中
Stream2.Position:=0;
Bitmap1.LoadFromStream(Stream2);
Image1.Picture:=TPicture(Bitmap1);
end
else
begin
//将数据读入到流中
Stream2.Write(S,1);
end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Comm1.StopComm;
Bitmap1.FreeImage;
Stream2.Free;
end;

所以,第一,需要重新设计传输协议,规定如何才算到达结束,如果
要在你的基础上改动的话,需要加入转义字符,比如,定义ESC(0x1B)
为转义字符,'#'是结束字符,那么,遇到数据'#',我们用ESC+'#'两个
字符表示,遇到ESC,用ESC+ESC来表示,如果碰到'#'而前面没有ESC,
则表示结束。
相应的,需要在接收端判断转义字符,来确定是否是ESC,数据'#'还是
结束'#'!
我想不用我给你编程吧,那样的话就没有意思了,对吧,不过你可以把你
的改动给我看看,一起帮你做,这样还是可以的,加油干吧,小伙子!

 
to:SS2000
谢了!今天又上一课!
 
热烈欢迎ss2000给我们指导!~~:)
 
ss2000,先给大家说说清楚加^和不加^的出现情况吧!怎么才能用好她。也就是说怎么才能用好指针,
至少简单说一下吧,我帮大家先谢谢你了:D
sizeof是算byte流的大小的,length是算数组大小的,这个肯定是cjh_xf错!呵呵
我想问的是ss2000说的意思是:
pchar是这个s的指向,而这个指向也是有个地址的,那么指针指向这个指向的地址的,我这么理解对吗?

这些感念上的东西还请ss2000快快着重的解释下吧!~谢谢谢谢!~~
 
rockjie,我被你说晕了
pchar是这个s的指向,而这个指向也是有个地址的,那么指针指向这个指向的地址的,我这么理解对吗?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
我没有能很好的理解你的意思,所以不知道你理解是否正确,不过,我在解释一下
S: string;
S是个变量,没错,既然是变量,在内存中就有地址,而S又是一个字符串,字符串
肯定是放在某个地址上,那么,问题就在S变量的地址是否就是存放字符串的地址呢?
答案是它们不是同一个地址,如果我们这么理解
string = record
length: integer; 存放字符串的长度
pc: PChar; 存放字符串的指针
end;
那么,你说S的的地址是否是保存字符串的地址呢?
事实上,Delphi差不多就是这么干的,你可以找本这方面的书研究一下

加^和不加^的出现情况就是非法使用指针的问题
Move会把变量自动取地址,这样指针加^后,Move再取地址,就是指针指向的
地址,OK,没有问题。如果是指针不加^,Move取到的是指向指针变量的地址,
你说会发生什么情况?程序崩溃!

 
“S是个变量,没错,既然是变量,在内存中就有地址,而S又是一个字符串,字符串
肯定是放在某个地址上”,你这么一说我就更明白了,呵呵~~~
那么我想再确认一下,此结构
string = record
length: integer; 存放字符串的长度
pc: PChar; 存放字符串的指针
end;
其中的PChar就是存放着字符串的地址的指针喽?而这个结构就是对这个变量的阐述是吗?
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
828
SUNSTONE的Delphi笔记
S
顶部