2015-03-10 2 views
1

Я новичок в программировании Delphi, и мне нужна помощь. У меня проблема с разделением моих серийных данных. Это мой код:Разделить серийные данные в delphi

procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer); 
var 
    DataByte : string; 
    x, i: integer; 
    save_data : TStringList; 
begin 
    save_data := TStringList.create; 

    for x := 0 to Count-1 do begin 
    ComPort1.ReadStr(DataByte,1); 
    if DataByte = 'n' then 
    begin 
     memo1.Text := ''; 
    end 
    else 
    begin 
     memo1.Text := memo1.Text + DataByte; 
     Split(' ', DataByte, save_data); 
    end; 
    end; 
    save_gyroX := save_data[0]; 
    save_gyroY := save_data[1]; 
    save_gyroZ := save_data[2]; 
    save_accelX := save_data[3]; 
    save_accelY := save_data[4]; 
    save_accelZ := save_data[5]; 
    SerialProcess(); 
    save_data.Free; 
end; 

Мой Split(' ', DataByte, save_data); не работает. Я не понимаю, потому что я просто разделил данные String, которые взяты из последовательного порта. Это моя Split() процедура:

procedure TForm1.Split(const Delimiter: Char; Input: string; const Strings: TStrings) ; 
begin 
    Assert(Assigned(Strings)); 
    Strings.Clear; 
    Strings.Delimiter := Delimiter; 
    Strings.DelimitedText := Input; 
end; 

Я не знаю, почему моя программа дает мне ошибку EStringListError.

+1

Можете ли вы привести пример данных вы –

+1

Получать Не 'databyte' не только один символ, который вы не можете разделить? Почему бы вам не разбить полную строку из 'memo1.text'? – gammatester

ответ

2

Вы вызываете ReadStr() для чтения отдельных байтов, и вызов Split() на каждый байт (за 'n' исключением). Таким образом, TStringList будет удерживать только одну строку за раз. Как MBO сказал, что вам нужно исправить цикл, чтобы избежать этого, например:

procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer); 
var 
    DataByte : string; 
    x: integer; 
    save_data : TStringList; 
begin 
    ComPort1.ReadStr(DataByte, Count); 

    for x := 1 to Length(DataByte) do 
    begin 
    if DataByte[x] = 'n' then 
    begin 
     Memo1.Text := ''; 
    end 
    else 
    begin 
     Memo1.Text := Memo1.Text + DataByte[x]; 
    end; 
    end; 

    save_data := TStringList.create; 
    try 
    Split(' ', DataByte, save_data); 

    save_gyroX := save_data[0]; 
    save_gyroY := save_data[1]; 
    save_gyroZ := save_data[2]; 
    save_accelX := save_data[3]; 
    save_accelY := save_data[4]; 
    save_accelZ := save_data[5]; 
    SerialProcess(); 
    finally 
    save_data.Free; 
    end; 
end; 

Это, как говорится, вы не принимая во внимание, что число байтов, вы получите для любого заданного OnRxChar вызова события является произвольным , Это то, что необработанных байтов были прочитаны в тот момент. Вы принимаете полную строку с как минимум 6 подстроками, и это просто не гарантируется. Вам нужно буферизовать необработанные данные по мере их получения, а затем анализировать и удалять только завершенные строки из буфера по мере необходимости.

Попробуйте что-то больше, как это:

var 
    DataBuffer: string; 

// consider using the OnRxBuf event instead... 
procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer); 
var 
    DataByte : string; 
    x: integer; 
    save_data : TStringList; 
begin 
    ComPort1.ReadStr(DataByte, Count); 
    DataBuffer := DataBuffer + DataByte; 

    x := Pos('n', DataBuffer); 
    if x = 0 then Exit; 

    save_data := TStringList.Create; 
    try 
    repeat 
     DataByte := Copy(DataBuffer, 1, x-1); 
     Delete(DataBuffer, 1, x); 

     Memo1.Text := DataByte; 

     Split(' ', DataByte, save_data); 
     if save_data.Count >= 6 then 
     begin 
     save_gyroX := save_data[0]; 
     save_gyroY := save_data[1]; 
     save_gyroZ := save_data[2]; 
     save_accelX := save_data[3]; 
     save_accelY := save_data[4]; 
     save_accelZ := save_data[5]; 
     SerialProcess(); 
     end; 

     x := Pos('n', DataBuffer); 
    until x = 0; 
    finally 
    save_data.Free; 
    end; 
end; 
1

если Comport является Деяна Crnila CPort класс, то эта линия

ComPort1.ReadStr(DataByte,1); 

заменяет Databyte содержимое каждый раз, и эта строка всегда является длина 1 байт.

Просто читать все байты из буфера с одним вызовом

ComPort1.ReadStr(DataByte, Count); 

и работают со строкой