Извлечение данных из последовательности байтов - PullRequest
0 голосов
/ 12 марта 2012

Предположим, у нас есть последовательность байтов с заголовком '807F', которая вводится в ПК через RS232.например, "... 80 7F 4B 97 80 7F 21 3A 80 7F ...", где "21 3A" - это наши данные в жирном шрифте, 21 - MSB, а 3A - LSB.Как мы можем извлечь данные из последовательности в DELPHI?

Ответы [ 2 ]

4 голосов
/ 12 марта 2012

Как хранятся ваши данные, немного неясно, но при условии, что они хранятся в массиве 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.
0 голосов
/ 13 марта 2012

Исходя из ваших комментариев, я предполагаю ...

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.

Но чтение вашего байта может быть немного неэффективным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...