2015-03-19 3 views
0

Я сделал интерфейсное программное обеспечение, используя Delphi 7 для извлечения данных из arduino. У Arduino есть 3 датчика. Arduino отправит 16 символов для значения датчика. Пример:String Operation so Slow

m 0 0 . 0 1 0 0 . 0 2 0 0 . 0 3 
[1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16] 

[1] Flag for Start value 
[2],[7],[12] are sensors status (0=disconnected, 1=connected) 
[3][4][5][6] first sensor value 
[8][9][10][11] second sensor value 
[13][14][15][16] third sensor value 

Я назначаю строковое значение из arduino в editText с названием Edit1. После этого я использую строку «Копировать», чтобы получить значение датчика по одному. Затем значение датчика будет отображаться по одному на этикетке. Но ярлык требует много времени, чтобы изменить значение. В первый раз, я думаю, это вызвало ярлык, который замедляется при обновлении. Затем я меняю ярлык с помощью editText, но работаю одинаково (для обновления значения требуется много времени). Так есть способ сделать это быстрее? или что-то не так со строкой?

Это мой код:

procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer); 
var 
    Str,Buffer,Rstatus,Sstatus,Tstatus: String; 
    arus : real; 
    i : integer; 
begin 
    DecimalSeparator:='.'; 
    ComPort1.ReadStr(Str, 1); 
    begin 
    Buffer:=Buffer + Str; 
    Edit1.Text:=Edit1.Text+Str; 
    if Str='m' then 
    edit1.Text:=''; 
     if Length(Edit1.Text) >=15 then 
     begin 
     Rstatus:=copy(Edit1.Text,1,1); 
     Sstatus:=copy(Edit1.Text,6,1); 
     Tstatus:=copy(Edit1.Text,11,1); 
     if Rstatus='0' then 
      begin 
      Label1.Caption:='0 A'; 
      Label1.Update 
      end 
     else 
      begin 
      Label1.Caption:=copy(Edit1.Text,2,4)+' A'; 
      Label1.Update 
      end; 
     if Sstatus='0' then 
      begin 
      Label2.Caption:='0 A'; 
      Label2.Update 
      end 
     else 
      begin 
      Label2.Caption:=copy(Edit1.Text,7,4)+' A'; 
      Label2.Update; 
      end; 
     if Tstatus='0' then 
      begin 
      Label3.Caption:='0 A'; 
      Label3.Update 
      end 
     else 
      begin 
      Label3.Caption:=copy(Edit1.Text,12,4)+' A'; 
      Label3.Update; 
      end; 
     end; 
    end; 
end; 
+0

Код в вопросе, который работает со строками, может быть несколько улучшен, я уверен. Тем не менее, несмотря на это, он все равно будет выполняться в минимальные промежутки времени, конечно, быстрее, чем вы сможете обнаружить. Поэтому я предполагаю, что фактическая задержка находится в сообщениях. Если вы не согласны, пожалуйста, покажите свои тайминги, которые доказывают, что манипуляция строкой является узким местом. –

+0

Очевидными способами улучшения кода являются использование символа 'char', а не строки для значений одного символа. И использовать индексный оператор '[]', а не 'Copy' при извлечении одиночных значений. Кроме того, вы не инициализируете «Буфер». –

+0

Я так быстро наблюдал за изменением Edit1. Но не с надписью «Надписи». – izzuddin

ответ

5

Заголовок процедуры имеет важный параметр, Count:

procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer); 

Это говорит вам, сколько символов получены и готовы для чтения. В основном, с низкой скоростью передачи будет только один, но иногда может быть два или более. Если вы только читать 1 символ, как в

ComPort1.ReadStr(Str, 1); 

остальные символы будут потеряны, или они не будут считаны до следующего OnRxChar происходит. Для последних символов в сообщении это не произойдет до того, как следующее сообщение вызывает событие. Это может объяснить, почему вы считаете процесс настолько медленным. Исключением является чтение Count символов вместо одного.

Но, похоже, есть ошибка, и вы не смогли получить полные измерения. Давайте посмотрим на код:

Edit1.text := Edit1.text + Str; 
if Str = 'm' then 
    Edit1.text := ''; 
if Length(Edit1.text) >= 15 then 

Ваше намерение состоит в том, чтобы ждать m флага, и ясно Edit1.Text, когда вы его получите. Хорошо. Затем вы получаете и собираете остальную часть сообщения, пока у вас не будет 15 символов в Edit1.Text, что тоже нормально. Но тогда вы перезаписываете полученное сообщение '2'?

begin 
    Edit1.text := '2'; 

Конечно, остальная часть синтаксического анализа сообщения будет терпеть неудачу.

Если вы исправите две ошибки, я считаю, что ваш код действительно может работать.

Редактировать после комментария

Заменить эти строки

Edit1.text := Edit1.text + Str; 
if Str = 'm' then 
    Edit1.text := ''; 

с

for i := 1 to Length(Str) do 
if Str[i] = 'm' then 
    Edit1.text := '' 
else 
    Edit1.Text := Edit1.Text + Str[i]; 

И тогда вы можете также удалить Buffer, как вы его не используете, а также излишнее begin .. end; пара.

+0

Я думаю, что последовательная связь прекрасна, потому что я так быстро изменил Edit1. Проблема в изменении заголовка Label, которая так поздно. Даже отключив последовательный порт, надпись Label все еще меняет значение, потому что так поздно. жаль о Edit2.text: = '2'; это просто мой эксперимент. И я забыл удалить это. Я редактировал список. – izzuddin

+0

После того, как я снова посмотрел, я думаю, что ты прав. Edit1 так медленно при получении данных. Поэтому я заменяю 1 в readStr на Count. Но сейчас. как читать m как флаг запуска? – izzuddin

+0

Спасибо @Tom Brunberg, это прекрасно работает! – izzuddin

3

Вы читаете только один байт из коммуникационного порта и делать много ненужной работы с визуальными компонентами. Краткий очерк:

ComPort1.ReadStr(Str); // read out all data 
Buffer:=Buffer + Str; 

//ensure that buffer starts with right value 
pm := Pos('m', Buffer); 
if pm > 1 then 
    Delete(Buffer, 1, pm - 1); 
if pm < 0 then 
    Buffer := ''; 

if Length(Buffer) >= 16 then begin 
    if Buffer[2] = '0' then begin 
     //do something for zero rstatus 
    end else begin 
     //do something for nonzero rstatus 
    end; 

    //and so on 

    Delete(Buffer, 1, 16);//erase treated data 
end;