假设我们有一个标题为'807F'的字节序列,它通过RS232输入到PC。例如“...... 80 7F 4B 97 80 7F 21 3A 80 7F ......”其中“21 3A”是我们的粗体包装数据,21是MSB,3A是LSB。我们如何从DELPHI中的序列中提取数据?
答案 0 :(得分:4)
您的数据存储方式有点不清楚,但假设它存储在TBytes
数组中,下面是一些解包数据的代码:
procedure ExtractWordFromRS232Data( a : TBytes);
var
i: integer;
myWord: word;
begin
// a is a TBytes buffer from reading the RS232 port
i := 0;
while (i < Length(a)-3) do
begin
if (a[i] = $80) and (a[i+1] = $7F) then
begin
myWord := (a[i+2] shl 8) + a[i+3];
// Do something with myWord
Inc(i,4);
end
else
Inc(i);
end;
end;
它将搜索标头$ 80 $ 7F的第一个输出并将以下两个字节解压缩到word
。用这个词做你想做的事。然后搜索继续,直到输入数据数组结束。
更新: 目前还不清楚你真正想要什么,但这里有一些代码,数据通过一个事件进入程序。
var
gData : array[1..4] of byte;
gIX : integer;
gIx := 1; // initialized at start
procedure InterpretIndataEvent( b : byte);
var
i : integer;
myWord : word;
begin
gData[gIx] := b;
if (gIx = 4) then
begin
if (gData[1] = $80) and (gData[2] = $7f) then
begin
myWord := (gData[3] shl 8) + gData[4];
// do something with myWord
gIx := 1;
end
else
begin
for i := 1 to 3 do gData[i] := gData[i+1];
end;
end
else
Inc(gIx);
end;
更新2:
从评论的角度来看,似乎数据就像ascii字符一样。
然后解码过程看起来像这样(包括一个小测试):
uses
System.SysUtils;
var
gData : string[8] = '12345678'; // Old fixed size ansistring type
gIX : integer = 1;
procedure InterpretIndataEvent( a : AnsiChar);
var
i : integer;
myWord : word;
begin
gData[gIx] := a;
if (gIx = 8) then
begin
if (Copy(gData,1,4) = '807F') then
begin
myWord := StrToInt('$'+Copy(gData,5,4));
// do something with myWord
WriteLn(IntToHex(myWord,4));
gIx := 1;
end
else
begin
for i := 1 to 7 do gData[i] := gData[i+1];
// During startup or if a character is missed we end up here.
// These events can be logged from here.
end;
end
else
Inc(gIx);
end;
const
testBuf : string[8] = '807F213A';
var
i : integer;
begin
for i := 1 to 8 do
InterpretIndataEvent(testBuf[i]);
ReadLn;
end.
答案 1 :(得分:0)
从你的评论中我假设......
program project;
{$mode objfpc}{$H+}
const
DATA_HEADER = Word(Swap($807F));
type
TData = Word;
TDataCallback = procedure(const aData: TData);
PDataStruct = ^TDataStruct;
TDataStruct = packed record
Header: Word;
Data: TData
end;
procedure DecodeData(const aData: Pointer; const aDataSize: Integer;
const aCallback: TDataCallback);
type
PDataBuffer = ^TDataBuffer;
TDataBuffer = packed array[0..High(Integer)-1] of Byte;
var
Ix: Integer;
Data: PDataStruct;
begin
if not Assigned(aCallback) then
Exit; // WARRNING: program flow disorder
Ix := 0;
while (Ix <= aDataSize - SizeOf(TDataStruct)) do
begin
Data:= @PDataBuffer(aData)^[Ix];
if Data^.Header = DATA_HEADER then
begin
aCallback(Swap(Data^.Data));
Inc(Ix, SizeOf(Data^));
end
else
Inc(Ix)
end
end;
var
W: TData = 0;
procedure ProcessData(const aData: TData);
begin
Inc(W, aData)
end;
var
InputIx: Integer = 0;
// youre serial input
function ReadByte(): Byte;
const
DATA: packed array[0..11] of Byte = (
$80, $7F, $4B, $97, $80, $7F, $21, $3A, $80, $7F, $AB, $CD);
begin
Result:= DATA[InputIx];
InputIx:= (InputIx + 1) mod SizeOf(DATA);
end;
var
Buffer: packed record
case Byte of
0: (
Data: TDataStruct);
1: (
Raw: array[0..Pred(SizeOf(TDataStruct))] of Byte)
end;
var
Ix: Integer;
begin
while true do
begin
for Ix := Low(Buffer.Raw) to High(Buffer.Raw) do
begin
Buffer.Raw[Ix]:= ReadByte()
end;
DecodeData(
@Buffer,
SizeOf(Buffer),
@ProcessData)
end
end.
但是阅读Byte输入的内容可能有点无效。