下面这段协议怎么用spcomm接收数据 ( 积分: 50 )

  • 主题发起人 主题发起人 pyalhm
  • 开始时间 开始时间
P

pyalhm

Unregistered / Unconfirmed
GUEST, unregistred user!
接口电平RS-232C串行传输,19200BPS,偶校验。
开机10秒后,以采样频率50Hz送出接果
AD每转换一次即送出结果。24位AD值分4次8 BIT送出。高位在前。
格式 00XXXXXXXX
01XXXXXXXX
10XXXXXXXX
11XXXXXXXX
去掉最高2 BIT 顺序号,24个X 可组成24位AD值。
 
怎么没有人理我,难道很做吗?
 
50H就是一秒种接收20次,spcomm可能不行吧
 
type
TForm1 = class(TForm)
Comm1: TComm;
procedure Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
procedure FormCreate(Sender: TObject);
private
bTempAdData:array [0..3] of byte; //储存未收完的数据
iAdIndex:integer; //接收到的数据计数。
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}
//网络字节序与主机字节序转换函数。
function BSwap(x:integer):integer;
asm
BSWAP eax
end;

// Spcomm串口控件的ReceiveData事件。。。。
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
pByte:^Byte;
i:Word;
iAd:integer;
begin
pByte:= Buffer;
for i:= 0 to BufferLength-1 do
begin

//遇到第一位则放弃以前的数据。
if (pByte^ and $C0) = 0 then iAdIndex:= 0;

//如果顺序是正确的就录入
if iAdIndex = (pByte^ and $C0) shr 6 then
begin

bTempAdData[iAdIndex] := pByte^;
inc(iAdIndex);

//正确收到32位的数据后进行处理。
if iAdIndex = 4 then
begin

iAd:=integer(bTempAdData);

//将每个字节的顺序号置为0 ,同时将网络字节序转换为主机字节序。
iAd:=BSwap(iAd and $3F3F3F3F);

//j是已经转换好的,在这里写处理代码。
showmessage(inttostr(iAd));

end;
end;
inc(pByte);
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
self.iAdIndex := 0;
end;
 
怎么理解:AD每转换一次即送出结果。24位AD值分4次BIT送出?
spcomm怎么保证接到的是完整00XXXXXXXX01XXXXXXXX10XXXXXXXX11XXXXXXXX数据格式?
readintervaltimeout应设为多少?
 
1、24位AD值分成4字节发过来。上面处理代码写错了应该是:

//将每个字节的顺序号置为0 ,同时将网络字节序转换为主机字节序。
iAd:= ((bTempAdData[0] and $3f) shl 18)
or ((bTempAdData[1]and $3f) shl 12)
or ((bTempAdData[2] and $3f) shl 6 )
or (bTempAdData[3] and $3f);

2、spcomm是不能保证是正确的,它只负责接收,发送数据,数据到达的先后顺序它是管不了的,只有自己写代码处理,我的代码已有做处理了。

3、spcomm我是第一次有,不知到。

PS:你这个问题我之所以回答,是因为spcomm我没有用过,而我做的程序正好有串口的操作,所以做来玩玩。

最终代码:

// Spcomm串口控件的ReceiveData事件。。。。
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var
pByte:^Byte;
i:Word;
iAd:integer;
begin
pByte:= Buffer;
for i:= 0 to BufferLength-1 do
begin

//遇到第一位则放弃以前的数据。
if (pByte^ and $C0) = 0 then iAdIndex:= 0;

//如果顺序是正确的就录入
if iAdIndex = pByte^ shr 6 then
begin

bTempAdData[iAdIndex] := pByte^;
inc(iAdIndex);

//正确收到32位的数据后进行处理。
if iAdIndex = 4 then
begin

iAd:=integer(bTempAdData);

//将每个字节的顺序号置为0 ,同时将网络字节序转换为主机字节序。
iAd:= ((bTempAdData[0] and $3f) shl 18)
or ((bTempAdData[1]and $3f) shl 12)
or ((bTempAdData[2] and $3f) shl 6 )
or (bTempAdData[3] and $3f);

//iAd是已经转换好的AD值,在这里写处理代码。
showmessage(inttostr(iAd));

end;
end else
begin
{这里写错误顺序的字节的处理代码,
当有处理的字节(pByte^)不能接上bTempAdData[iAdIndex -1]字节,
如果这里不作处理当前字节将被放弃。}
{其实处理也没有什么好处理的,做些提示,或者保存这几个字节就是了。}
end;
inc(pByte);
end;
end;
 
首先,设立一个全局变量,记录当前局部结果
var
ComADTmp: Integer;

假定处理接收数据的过程是
procedure HandleADData(X: Integer);
begin
...
end;

接收数据事件过程
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer; BufferLength: Word);
var
I, X: Integer;
begin
for I:= 0 to BufferLength - 1 do begin
X:= PByteArray(Buffer)^;
if (X shr 6) <> (ComADTmp shr 24) then
ComADTmp:= 0
else begin
X:= X and $3F;
case (ComADTmp shr 24) of
0: ComADTmp:= (X shl 18) + (1 shl 24);
1: ComADTmp:= ComADTmp + (X shl 12) + (1 shl 24);
2: ComADTmp:= ComADTmp + (X shl 6) + (1 shl 24);
3: begin
ComADTmp:= (ComADTmp + X) and $FFFFFF;
HandleADData(ComADTmp);
ComADTmp:= 0;
end;
else ComADTmp:= 0;
end;
end;
end;
end;

单元初始化
initialization
ComADTmp:= 0;
end.
 
qqjm和SupermanTm的方法都能正确。多谢了!
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
后退
顶部