Модераторы: Snowy, MetalFan, bems, Poseidon

Поиск:

Закрытая темаСоздание новой темы Создание опроса
> Принять данные от машины по k-line, т.е. принять их по COM порту и разобрать 
:(
    Опции темы
mr_smit
  Дата 12.10.2011, 08:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Здравствуйте. Давно я не программировал на Delphi. А тут задался целью сделать для своей машины (ВАЗ 11183) считыватель ошибок на микроконтроллере. Чтобы разобраться с протоколом, хочу для начала из своего приложения на ПК посмотреть/почитать данные. Диагностическая линия (k-line) представляет из себя "обычный ком порт" только с измененными логическими уровнями. 0 вольт - это логический 0, +12 вольт - это логическая единица. У ком порта 0 это минус 12 вольт. Собственно все переходники для машины и представляют собой просто согласователи этих самых уровней.
Скачал бесплатную программу Diagnostic Tools. Подключился к машине. Всё работает. Всё показывает. Взял снифер ком порта, посмотрел что шлет программа. Скачал описание протокола обмена. Чуда не произошло, всё строго по пунктам smile

Не буду сильно вдаваться в подробности протокола. Собственно что меня интересует:

1. Чтобы начать диагностику, нам надо отправить:

Запрос startCommunication:
  81 10  F1 81 03
Ответ:
  83 F1 10 C1 6B 8F 3F

В ответе C1  означяет что ЭБУ готов с нами работать.

Поставил компонент AsyncFree104 для работы с com портом:
Код

var
  startCommunication: array [0..4] of byte = ($81, $10, $f1, $81, $03);

...

procedure TForm1.Button1Click(Sender: TObject);
begin
  AfComPort1.Open;
  AfComPort1.WriteData(startCommunication, sizeof(startCommunication));
end;


Как мне прочитать ответ? И как оттуда вытащить C1 ?

2. Сдернул клемму. Прочитал ошибки свои. Для определения значений данного параметра используется десятичная (BCD) кодировка.

Запрос ошибок readDTCByStatus:
  84 10 F1 18 00 00 00 9D
Ответ:
  88 F1 10 58 02 04 43 E0 14 26 E0 24
  
P0443  -  всё верно, 2 ошибки появилось.
P1426

Первые 3 байта нас не интересуют. Нам интересно: 58 - положительный ответ, 02 - число ошибок, дальше ошибки разделенные E0. Последняя цифра во всех запросах/ответах - контрольная сумма (2 младших разряда).

Как вытащить ошибки из этого ответа?

У компонента есть:
Код

AfComPort1.ReadData (var Buf; Size: Integer);

Как принимать в этот Buf ? Если длинна его меняется. И как разобрать данные?


Это сообщение отредактировал(а) mr_smit - 12.10.2011, 08:33
PM MAIL   Вверх
bems
Дата 12.10.2011, 08:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 18
Всего: 88



1. В чем вопрос-то? Как вытащить четвертый байт из буффера?
2. Выделять с запасом


--------------------
Обижено школьников: 8
PM MAIL   Вверх
mr_smit
Дата 12.10.2011, 08:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Пока писал, сам сообразил. Вроде так:

Код

procedure TForm1.Button1Click(Sender: TObject);
begin
AfComPort1.Open;
AfComPort1.WriteData(startCommunication, sizeof(startCommunication));
AfComPort1.ReadData(ReadBuffer, Length(ReadBuffer));
if ReadBuffer[3] = $C1 then
  begin
  Label1.Caption:='ЭБУ на связи';
  end;
end;

Так?

Это сообщение отредактировал(а) mr_smit - 12.10.2011, 08:56
PM MAIL   Вверх
bems
Дата 12.10.2011, 09:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 18
Всего: 88



зависит от того что такое ReadBuffer, но похоже, да


--------------------
Обижено школьников: 8
PM MAIL   Вверх
mr_smit
Дата 12.10.2011, 09:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Цитата(bems @ 12.10.2011,  09:04)
зависит от того что такое ReadBuffer, но похоже, да

Да, забыл написать
Код

ReadBuffer: array of byte;


Если так, то тогда ещё вопрос:

BCD кодировка, как с ней работать? Как мне, например, в Memo отобразить ошибки?


Это сообщение отредактировал(а) mr_smit - 12.10.2011, 09:06
PM MAIL   Вверх
bems
Дата 12.10.2011, 09:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 18
Всего: 88



ну и там же наверное чтонить и возвращается из WriteData и ReadData


--------------------
Обижено школьников: 8
PM MAIL   Вверх
mr_smit
Дата 12.10.2011, 09:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Хочу прочитать ошибки из тестового массива. 
Код

TestArray: array[0..11] of byte = ($88,$f1,$10,$58,$02,$04,$43,$E0,$14,$26,$E0,$24);
...
procedure TForm1.Button2Click(Sender: TObject);
var i:integer;
      j:integer;
begin
j:=5;
for i:=0 to TestArray[4]-1 do     // 5-й байт - число ошибок
  begin
  Memo1.Lines.Add('P'+IntToStr(TestArray[j])+IntToStr(TestArray[j+1]));
  j:=j+3;
  end;
end;


В мемо получается:
P467
P2038

А должно:
P0443
P1426

Как перевести из BCD формата в String?

Это сообщение отредактировал(а) mr_smit - 12.10.2011, 09:48
PM MAIL   Вверх
AndreyIQ
Дата 12.10.2011, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 185
Регистрация: 5.2.2007

Репутация: 1
Всего: 8



Код

Memo1.Lines.Add('P'+IntToHex(TestArray[j],2)+IntToHex(TestArray[j+1],2));

PM MAIL   Вверх
mr_smit
Дата 12.10.2011, 10:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Цитата(AndreyIQ @ 12.10.2011,  09:49)
Код

Memo1.Lines.Add('P'+IntToHex(TestArray[j],2)+IntToHex(TestArray[j+1],2));

Оооооо....!!!! Спасибо! Работает.

Кстати. Вот запрос параметров:
  82 10 F1 21 01 A5
ЭБУ моей машины отвечает:
 80 F1 10 26 61 01 3B 90 41 04   
 00 00 00 00 47 80 00 00 00 52 52 80 18 00 8E 00   
 5C 00 00 00 00 00 00 00 00 00 FF FF DD A4 47 02

 CE

61 - Положительный ответ readDataByLocalIdentifier
01 - afterSalesServiceRecordLocalIdentifier (что то там....)
....
11-й байт - Температура охлаждающей жидкости
....


Формула для расчета: N=E-40 [°C]
  E - передаваемое значение
  N - физическая величина
У меня это значение 47. Берем windows калькулятор. Переводим 47 hex в dec. Получаем 71. Дальше 71-40=31°C. Соглашусь. На момент снятия данных машина часа полтора простояла на улице. До конца не остыла.

Как бы мне теперь на Delphi так конвертнуть?
PM MAIL   Вверх
AndreyIQ
Дата 12.10.2011, 10:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 185
Регистрация: 5.2.2007

Репутация: 1
Всего: 8



Цитата(mr_smit @ 12.10.2011,  10:15)
47 hex в dec

Код

StrToInt('$' + IntToStr(47))

PM MAIL   Вверх
mr_smit
Дата 12.10.2011, 11:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Чего то у меня в ошибку вываливается на строке:
Код

if ReadBuffer[3] = $C1 then


Может где то длинну массиву назначать?

Это сообщение отредактировал(а) mr_smit - 12.10.2011, 11:48
PM MAIL   Вверх
AndreyIQ
Дата 12.10.2011, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 185
Регистрация: 5.2.2007

Репутация: 1
Всего: 8



Цитата(mr_smit @ 12.10.2011,  11:48)
Может где то длинну массиву назначать?

SetLength.

Это сообщение отредактировал(а) AndreyIQ - 12.10.2011, 11:58
PM MAIL   Вверх
mr_smit
Дата 12.10.2011, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Кажется понял, ReadBuffer у меня сейчас пустой, а я пытаюсь 4-й элемент массива прочитать.

А где её задавать? Сразу после чтения?
Код

SetLength(ReadBuffer, Length(ReadBuffer));


Добавлено @ 12:07
Код

AfComPort1.ReadData(ReadBuffer, sizeof(ReadBuffer));
SetLength(ReadBuffer, Length(ReadBuffer));
try
if ReadBuffer[3] = $C1 then
  begin
  Label1.Caption:='ЭБУ на связи';
  end;
except
  Label1.Caption:='нет ответа от ЭБУ';
end;


Так?

И нужно ли буфер обнулять перед каждым вызовом? Или он автоматически каждый раз с нулевого значения записывается?

Это сообщение отредактировал(а) mr_smit - 12.10.2011, 13:51
PM MAIL   Вверх
northener
Дата 12.10.2011, 14:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(mr_smit @  12.10.2011,  11:58 Найти цитируемый пост)
AfComPort1.ReadData(ReadBuffer, sizeof(ReadBuffer));
SetLength(ReadBuffer, Length(ReadBuffer));

1. Размер массиву ReadBuffer задавать ДО передачи его в качестве параметра функции ReadData.
2. Размер массива это Length, а SizeOf это размер переменной, которая хранит адрес массива в памяти.
3. Первый параметр в функции ReadData должен быть передан как ReadBuffer[0].


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
mr_smit
Дата 12.10.2011, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Чего то у меня не работает код smile

Дело в том что, как я понимаю, поскольку по K-Line обмен идет по одному проводу, то в момент передачи, принимать ничего не надо! Закончили передавать - начинаем линию слушать. Вот как этот момент реализовать?

Добавлено @ 15:39
Я когда сниффером обмен смотрю:
Запрос startCommunication:
  81 10  F1 81 03
Ответ:
  81 10  F1 81 03 83 F1 10 C1 6B 8F 3F

Реальный ответ это только 83 F1 10 C1 6B 8F 3F. А в начале идет запрос, просто он автоматом попадает на вход. Провод то связи один.  Он и на передачу работает и на прием.


Это сообщение отредактировал(а) mr_smit - 12.10.2011, 15:46
PM MAIL   Вверх
northener
Дата 12.10.2011, 16:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(mr_smit @  12.10.2011,  15:34 Найти цитируемый пост)
поскольку по K-Line обмен идет по одному проводу, то в момент передачи, принимать ничего не надо! Закончили передавать - начинаем линию слушать. Вот как этот момент реализовать?

Слушать постоянно. Отделять ответ от своего же "эха" потом.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
northener
Дата 12.10.2011, 23:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(mr_smit @  12.10.2011,  15:34 Найти цитируемый пост)
Чего то у меня не работает код smile

Какой именно код не работает?

1. Вы смогли самостоятельно разработать или где-то купить преобразователь СОМ-"однопроводная линия"? Это не так сложно теоретически, но я сомневаюсь, что вы его хоть как-то получили. А без него вы ничего не сможете сделать.
2. Вы изучили полностью тот компонент, который вы решили использовать? Наверняка нет.
  Все эти компоненты созданы по одному лекалу. И у них, у всех есть событие типа OnRxChar. Вот в нём, в этом событии и надо вызывать функцию ReadData. Кстати, заметьте. Это наверняка именно функция, а не процедура!
3. Умение пользоваться "сниффером" и т.п. очень  полезное умение. Но оно мало помогает при недостаточном уровне знаний.

Это сообщение отредактировал(а) northener - 13.10.2011, 00:10


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
mr_smit
Дата 13.10.2011, 07:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Я сам спаял преобразователь USB <-> K-Line. Там ничего сложного. Он работает! Я несколько программ диагностики уже использовал. Все видят контроллер. Все параметры в режиме реального времени. С этим нет проблем.
user posted image
Цитата(northener @ 12.10.2011,  23:48)
у них, у всех есть событие типа OnRxChar

Да, я уже тоже про это подумал. Просто с наскока разобраться не получилось. Буду копать глубже теперь. Сниффер классная вещь когда под рукой описание протокола. Наглядно всё видишь.
Код

AfComPort1.WriteData(startCommunication, sizeof(startCommunication));
AfComPort1.ReadData(ReadBuffer, Length(ReadBuffer));
if ReadBuffer[3] = $C1 then
  begin

  end;

Теперь я понимаю что это точно работать не будет. Надо принимать только после окончания передачи.

P.S. ReadData - это процедура, а не функция. Справку на компонент прилагаю.


Присоединённый файл ( Кол-во скачиваний: 18 )
Присоединённый файл  AsyncFree.rtf 149,98 Kb
PM MAIL   Вверх
mr_smit
Дата 13.10.2011, 08:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Код

property OnOutBufFree: TNotifyEvent;
//Occurs when all the data in output buffer was sent.

Код

procedure PurgeRX;
//Clears device driver's input buffer

Код

property OnDataRecived: TAfCPTDataReceivedEvent;
TAfCPTDataReceivedEvent = procedure(Sender: TObject; Count: Integer) of object;
//Occurs when a data is received by communication port. Count is the actual number of bytes avaiable to read. 
//You should read the whole number of bytes given in Count parameter. 


Стало быть как только выходной буффер освободился, т.е. все данные переданы - очищаем входной буффер, и читаем из него данные по событию DataRecived:
Код

procedure TForm1.AfComPort1OutBufFree(Sender: TObject);
begin
AfComPort1.PurgeRX;
end;

procedure TForm1.AfComPort1DataRecived(Sender: TObject; Count: Integer);
begin
AfComPort1.ReadData(ReadBuffer[0], Count);
end;


Правильно?

Это сообщение отредактировал(а) mr_smit - 13.10.2011, 08:14
PM MAIL   Вверх
mr_smit
Дата 13.10.2011, 09:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Итак, нам надо отправить запрос startCommunication. При положительном ответе на него отправить startDiagnosticSession. При положительном ответе на него периодически отправлять testerPresent чтобы ЭБУ видел что тестер до сих пор подключен. Попробовал пока вот так это изобразить:
Код

...
Timer1: TTimer;
...
type Mode = (TesterOnline, ReadData, ReadError, Connect, Disconnect);

var
  Form1: TForm1;
  startCommunication:         array[0..4] of byte = ($81,$10,$f1,$81,$03);
  startDiagnosticSession:     array[0..6] of byte = ($83,$10,$f1,$10,$81,$0A,$1F);
  testerPresent:              array[0..5] of byte = ($82,$10,$f1,$3E,$01,$C2);
  ...
  ReadBuffer: array[0..99] of byte;
  TesterMode: Mode;
...

procedure TForm1.Button1Click(Sender: TObject);
begin
  AfComPort1.ComNumber:=AfPortComboBox1.ComPort.ComNumber;
  AfComPort1.Open;
  StatusBar1.Panels[0].Text:=AfComPort1.SettingsStr;
  TesterMode:= Connect;
  AfComPort1.PurgeTX; // очистили выходной буффер
  AfComPort1.WriteData(startCommunication, length(startCommunication));
  Timer1.Enabled:=true;
end;

procedure TForm1.AfComPort1DataRecived(Sender: TObject; Count: Integer);
begin
AfComPort1.ReadData(ReadBuffer[0], Count);
end;

procedure TForm1.AfComPort1OutBufFree(Sender: TObject);
begin
AfComPort1.PurgeRX; // как закончили передавать - очищаем входной буффер.
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if TesterMode = Connect then
  begin
    if ReadBuffer[3] = $C1 then   // положительный ответ на startCommunication
    begin
      AfComPort1.PurgeTX; // очистили выходной буффер
      AfComPort1.WriteData(startDiagnosticSession, length(startDiagnosticSession));
    end
    else if ReadBuffer[3] = $50 then   // положительный ответ на startDiagnosticSession
    begin
      TesterMode:= TesterOnline;
      StatusBar1.Panels[1].Text:='ЭБУ на связи';
    end;
  end

  else if TesterMode = TesterOnline then
  begin
    AfComPort1.PurgeTX; // очистили выходной буффер
    AfComPort1.WriteData(testerPresent, length(testerPresent));
    if ReadBuffer[3] = $7E then    // ответ ЭБУ на testerPresent
    begin
      StatusBar1.Panels[1].Text:='ЭБУ на связи';
    end
    else begin
      StatusBar1.Panels[1].Text:='Связь потеряна';
    end;
  end

  else if TesterMode = Disconnect then
  begin
    AfComPort1.WriteData(stopDiagnosticSession, length(stopDiagnosticSession));
    AfComPort1.WriteData(stopCommunication, length(stopCommunication));
    AfComPort1.Close;
  end
end;


Что скажете?

Это сообщение отредактировал(а) mr_smit - 13.10.2011, 09:13
PM MAIL   Вверх
northener
Дата 13.10.2011, 11:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(mr_smit @  13.10.2011,  08:09 Найти цитируемый пост)
Стало быть как только выходной буффер освободился, т.е. все данные переданы - очищаем входной буффер, и читаем из него данные по событию DataRecived:
...

Правильно?

Теоретически правильно. Но на практике почти всегда неправильно.
Ибо большинство таких компонент ххСОМPort игнорируют аппаратный FIFO СОМ-порта. А событие "Выходной буфер пуст" для них означает только то, что пуст выходной буфер драйвера СОМ-порта. Т.о. данное событие будет обработано гораздо раньше, чем СОМ-порт выдаст на линию всю предназначенную железяке посылку.

Советую вам очищать входной буфер непосредственно перед посылкой команды железяке. И постоянно читать в событии
Цитата(mr_smit @  13.10.2011,  08:09 Найти цитируемый пост)
property OnDataRecived: TAfCPTDataReceivedEvent;
TAfCPTDataReceivedEvent = procedure(Sender: TObject; Count: Integer) of object;

учитывая параметр Count.
Принятое "эхо" вы сможете легко вычленить из приемного буфера. Ведь вы знаете, что вы посылали железяке.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
mr_smit
Дата 13.10.2011, 11:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Цитата(northener @ 13.10.2011,  11:25)
И постоянно читать в событии OnDataRecived

А как???

Код

procedure TForm1.AfComPort1DataRecived(Sender: TObject; Count: Integer);
begin
AfComPort1.ReadData(ReadBuffer[0], Count);
end;

Если так, то постоянно перезаписываться будет [0] элемент. Как ReadBuffer получить заполненный моим запросом + ответ? Я чего то не пойму никак.
PM MAIL   Вверх
northener
Дата 13.10.2011, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(mr_smit @  13.10.2011,  11:47 Найти цитируемый пост)
Если так, то постоянно перезаписываться будет [0] элемент. 


Цитата(northener @  13.10.2011,  11:25 Найти цитируемый пост)
учитывая параметр Count.

Т.е. заведите переменную CurrentPos. Перед посылкой присваивайте ей 0. А затем
Код

  AfComPort1.ReadData(ReadBuffer[CurrentPos], Count);
  Inc(CurrentPos,Count);



--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
mr_smit
Дата 13.10.2011, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Код

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if TesterMode = Connect then
  begin
  showmessage(inttostr(ReadBuffer[3] ));
    if ReadBuffer[3] = $C1 then   // положительный ответ на startCommunication
    begin
      AfComPort1.PurgeTX; // очистили выходной буффер
      AfComPort1.WriteData(startDiagnosticSession, length(startDiagnosticSession));
    end
...


showmessage мне возвращает ноль  smile 

Обмен смотрю сниффером. ЭБУ отвечает. Но ответ распознать не могу  smile 

P.S. northener, сейчас попробую как вы говорите

Это сообщение отредактировал(а) mr_smit - 13.10.2011, 15:49
PM MAIL   Вверх
northener
Дата 14.10.2011, 00:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(mr_smit @  13.10.2011,  15:47 Найти цитируемый пост)
P.S. northener, сейчас попробую как вы говорите

Можете обращаться ко мне в личку.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
mr_smit
Дата 14.10.2011, 09:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Цитата(northener @ 13.10.2011,  12:56)
Код

  AfComPort1.ReadData(ReadBuffer[CurrentPos], Count);
  Inc(CurrentPos,Count);

Из справки:
Код

procedure ReadData(var Buf; Size: Integer);
//Reads the specified number of bytes from input buffer. If there aren't enough data to read, an exception is raised

Перевод: Читает  указанное число байт из  входного буфера. Если не достаточно данных для чтения, вызывается исключение

Код

function InBufUsed: Integer;
//Returns the number of bytes in device driver's input buffer

Количество байт во входном буфере

Получается вот так что ли?
Код

  AfComPort1.ReadData(ReadBuffer[CurrentPos], AfComPort1.InBufUsed);
  Inc(CurrentPos, AfComPort1.InBufUsed);


Это сообщение отредактировал(а) mr_smit - 14.10.2011, 09:20
PM MAIL   Вверх
northener
Дата 14.10.2011, 11:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(mr_smit @  14.10.2011,  09:01 Найти цитируемый пост)
Получается вот так что ли?

Может быть так. Может быть нет. Надо пробовать и смотреть что получается. 
Поймите меня правильно. Я не знаком с именно этим компонентом xxCOMport.
Как правило "ReadData" в подобных компонентах - функция возвращающая количество байт реально вычитанных из приемного буфера.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
mr_smit
Дата 14.10.2011, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Я взял этот компонент потому что у него можно задать произвольную скорость обмена. Мне нужна 10400. Может подскажите знакомый вам компонент. Может что попроще.
PM MAIL   Вверх
northener
Дата 14.10.2011, 21:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(mr_smit @  14.10.2011,  13:43 Найти цитируемый пост)
Я взял этот компонент потому что у него можно задать произвольную скорость обмена. Мне нужна 10400. 

Вообще-то произвольную скорость должен уметь ставить любой компонент. Особенно если он с исходниками.
Посоветовать ничего не могу, потому что никаким никогда не пользовался. Только смотрел. Кроме библиотеки AsyncPro, но это слишком тяжелая вещь.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
northener
Дата 15.10.2011, 00:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Ещё раз.

Цитата(northener @  14.10.2011,  11:37 Найти цитируемый пост)
Может быть так. Может быть нет. Надо пробовать и смотреть что получается.

Т.е. 
1. Создаём таймер. Его период выбираем исходя из скорости СОМ-порта, на которой работает железяка и из максимального количества байт посылки/команды и ответа. (Один байт - это как минимум 10 бит, как максимум 12 бит. Зависит от наличия/отсутствия бита чётности и от длины стоп-бита(1,1.5,2). Плюс запас 50-500 ms из-за того, что Винда не есть система реального времени.
2. Перед посылкой запроса/команды к железяке очищаем приемный/передающий буфер СОМ-порта методами компонента.
3. Сбрасываем в ноль переменную CurrentPos.
4. Посылаем запрос/команду железяке. Запускаем таймер. Читаем в событии OnDataRecived всё в буфер ReadBuffer по адресу ReadBuffer[CurrentPos].
5. По срабатыванию таймера смотрим, чему равен CurrentPos и что мы уже получили.  После анализа принятого возвращаться к пункту 2.
5-бис Смотреть "чему равен CurrentPos и что мы уже получили" можно уже в событии OnDataRecived после выполнения процедуры ReadData. И если всё уже принято, то сбрасывать/дизейблить таймер. И после анализа принятого переходить к пункту 2.


Это сообщение отредактировал(а) northener - 15.10.2011, 00:22


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
mr_smit
Дата 18.10.2011, 17:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Вобщем вот так всё заработало:
Код

...

else if TesterMode = ReadData then
  begin
    {
      НЕТ ПРОВЕРКИ КОНТРОЛЬНОЙ СУММЫ!!!
    }
    Timer1.Interval:=330;
    AfComPort1.PurgeTX; // очистили выходной буффер
    AfComPort1.PurgeRX;
    CurrentPos:=0;
    AfComPort1.WriteData(readDataByLocalIdentifier, length(readDataByLocalIdentifier));

    Label6.Caption:=IntToStr(40*(StrToInt(IntToStr(ReadBuffer[23]))))+' об/мин';
    Label7.Caption:=IntToStr(StrToInt(IntToStr(ReadBuffer[25])))+' шаг.';
    Label8.Caption:=IntToStr(StrToInt(IntToStr(ReadBuffer[20]))-40)+' град.';
    Label9.Caption:=floatToStrF(5.2+(StrToInt(IntToStr(ReadBuffer[30]))*0.05),ffGeneral,4,2)+' B';
    Label11.Caption:=IntToStr(StrToInt(IntToStr(ReadBuffer[22])))+' %';
    Button1.Enabled:=false;
    Button2.Enabled:=true;
    Button5.Enabled:=true;
  end

...

procedure TForm1.AfComPort1DataRecived(Sender: TObject; Count: Integer);
begin
  AfComPort1.ReadData(ReadBuffer[CurrentPos], Count);
  Inc(CurrentPos, Count);
end;


user posted image

northener, спасибо
PM MAIL   Вверх
northener
Дата 18.10.2011, 23:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(mr_smit @  18.10.2011,  17:03 Найти цитируемый пост)
northener, спасибо 

Не за что.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
mr_smit
Дата 19.10.2011, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Единственное я не пойму почему запрос ошибок у меня не работает.

Код

...
procedure TForm1.Button5Click(Sender: TObject);
begin
  TesterMode:= ReadError;
end;

...

  else if TesterMode = ReadError then
  begin
    AfComPort1.PurgeTX; // очистили выходной буффер
    AfComPort1.PurgeRX;
    CurrentPos:=0;
    AfComPort1.WriteData(readDTCByStatus, Length(readDTCByStatus));
    Memo1.Clear;

    for i:=0 to ReadBuffer[12]-1 do  // количество ошибок
    begin
      Memo1.Lines.Add('P'+IntToHex(ReadBuffer[j],2)+IntToHex(ReadBuffer[j+1],2));
      j:=j+3;
    end;
    j:=13;
    TesterMode:=ReadData;
  end;
...

Сделал вывод массива на форму. Почему то запрос/ответ на чтение ошибок не проходит. Т.е. после нажатия на кнопку "ошибки" массив не обновляется. И в нем хранятся данные ещё с предыдущего запроса параметров. Странно. Вроде делаю CurrentPos:=0;

user posted image
PM MAIL   Вверх
northener
Дата 19.10.2011, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(mr_smit @  19.10.2011,  09:49 Найти цитируемый пост)
Почему то запрос/ответ на чтение ошибок не проходит. Т.е. после нажатия на кнопку "ошибки" массив не обновляется. И в нем хранятся данные ещё с предыдущего запроса параметров. Странно. Вроде делаю CurrentPos:=0;

В приведенном куске кода есть обнуление CurrentPos. Есть посылка команды WriteData. А где чтение ответа?


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
mr_smit
Дата 19.10.2011, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Код

procedure TForm1.AfComPort1DataRecived(Sender: TObject; Count: Integer);
begin
  AfComPort1.ReadData(ReadBuffer[CurrentPos], Count);
  Inc(CurrentPos, Count);
end;

PM MAIL   Вверх
northener
Дата 19.10.2011, 23:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(northener @  19.10.2011,  10:45 Найти цитируемый пост)
В приведенном куске кода есть обнуление CurrentPos. Есть посылка команды WriteData. А где чтение ответа? 


Цитата(mr_smit @  19.10.2011,  20:36 Найти цитируемый пост)
procedure TForm1.AfComPort1DataRecived(Sender: TObject; Count: Integer);
begin
  AfComPort1.ReadData(ReadBuffer[CurrentPos], Count);
  Inc(CurrentPos, Count);
end;


Так. Я тогда не понимаю, чему вы радовались в 
Цитата(mr_smit @  18.10.2011,  17:03 Найти цитируемый пост)
Вобщем вот так всё заработало:
?
И за что вы мне плюсик дали?

Смотрим ваш кусок кода:
Код

else if TesterMode = ReadError then
  begin
    AfComPort1.PurgeTX; // очистили выходной буффер
    AfComPort1.PurgeRX;
    CurrentPos:=0;
    AfComPort1.WriteData(readDTCByStatus, Length(readDTCByStatus)); [I][color=blue]<---Вот тут вы посылаете запрос железяке.[/color][/I]
    Memo1.Clear;
    for i:=0 to ReadBuffer[12]-1 do  // количество ошибок  [I][color=blue]<---А тут, в цикле, уже выводите данные из вашего приемного буфера в Мемо! И что вы надеятесь увидеть в данный момент в вашем приёмном буфере?  Да. После вызова метода компонента WriteData, компонент запустил свой механизм по передаче драйверу СОМ-порта данных для выдачи на линию. Плюс запустил в отдельном потоке функцию WaitCommEvent для получения события о том, что драйвер СОМ-порта что-то прочитал. И возможно даже драйвер уже успел что-то прочитать и сообщить об этом компоненту. Но ваша программа не сможет НИЧЕГО об этом узнать до выхода из той процедуры, кусок которой вы привели! Ибо пока вы не вышли из этой процедуры вашей программы, ваша программа не сможет обработать событие компонента ReadData[/color][/I]
    begin
      Memo1.Lines.Add('P'+IntToHex(ReadBuffer[j],2)+IntToHex(ReadBuffer[j+1],2));
      j:=j+3;
    end;
    j:=13;
    TesterMode:=ReadData;
  end;


Добавлено через 13 минут и 27 секунд
То ли лыжи не едут, то ли я ...
Привожу полностью тот мой комментарий к коду, который начинался словами "А тут, в цикле, вы выводите из вашего приемного..."
А тут, в цикле, уже выводите данные из вашего приемного буфера в Мемо! И что вы надеетесь увидеть в данный момент в вашем приёмном
 буфере?  Да. После вызова метода компонента WriteData, компонент запустил свой механизм по передаче драйверу СОМ-порта данных для
 выдачи на линию. Плюс запустил в отдельном потоке функцию WaitCommEvent для получения события о том, что драйвер СОМ-порта что-то
 прочитал. И возможно даже драйвер уже успел что-то прочитать и сообщить об этом компоненту. Но ваша программа не сможет
 НИЧЕГО об этом узнать до выхода из той процедуры, кусок которой вы привели! Ибо пока вы не вышли из этой процедуры вашей
 программы, ваша программа не сможет обработать событие компонента ReadData.



--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
mr_smit
Дата 20.10.2011, 01:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Плюс поставил за кусок кода:
Код

procedure TForm1.AfComPort1DataRecived(Sender: TObject; Count: Integer);
begin
  AfComPort1.ReadData(ReadBuffer[CurrentPos], Count);
  Inc(CurrentPos, Count);
end;


В принципе я думал  что просто не успевает массив заполнится данными. Но в режиме реального времени параметры у меня отображаются. Таймер настроен на 330 мс. Т.е. 3 раза в секунду считываю параметры.

А как тогда тут поступить со считыванием ошибок по нажатию кнопки? Добавить как то задержку? Или 2 раза запрашивать?

Почему когда я считываю данные - массив успевает обновляться, а когда ошибки считываю таким же образом, то массив не обновляется.

Это сообщение отредактировал(а) mr_smit - 20.10.2011, 01:27
PM MAIL   Вверх
northener
Дата 20.10.2011, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(mr_smit @  20.10.2011,  01:02 Найти цитируемый пост)
Но в режиме реального времени параметры у меня отображаются.


Цитата(mr_smit @  20.10.2011,  01:02 Найти цитируемый пост)
А как тогда тут поступить со считыванием ошибок по нажатию кнопки?


Приведите код вашей процедуры OnTimer. Я подскажу как её изменить.

Тогда хоть я смогу (если смогу), хоть как-то отработать тот плюсик, который вы мне добавили. :(

Это сообщение отредактировал(а) northener - 21.10.2011, 01:04


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
mr_smit
Дата 21.10.2011, 08:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 254
Регистрация: 27.2.2008
Где: Самара

Репутация: нет
Всего: 4



Вот:

Присоединённый файл ( Кол-во скачиваний: 44 )
Присоединённый файл  Unit1.pas 6,04 Kb
PM MAIL   Вверх
Korod
Дата 24.10.2011, 11:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 24.10.2011

Репутация: нет
Всего: нет



На СОМ-портах персоналки -12в - это лог.1, а +12в - это лог.0.
PM MAIL   Вверх
northener
Дата 24.10.2011, 23:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(mr_smit @  21.10.2011,  08:05 Найти цитируемый пост)
Вот: 

Чтобы не захламлять форум, ответил в личку.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
Darkblue
Дата 20.1.2012, 18:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 10
Регистрация: 20.1.2012

Репутация: нет
Всего: нет



Уважаемые подскажите пожалуйста procedure TForm1.AfComPort1DataRecived ставится на рабочее поле,или просто прописывается в процедурах. Никак не могу научиться байт ловить ,помогите пожалуйста
PM MAIL   Вверх
bems
Дата 20.1.2012, 20:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 18
Всего: 88




M
bems
Один топик — один вопрос!

Пожалуйста, ознакомьтесь с правилами форума.




Тема закрыта. Создайте по одной теме для каждого интересующего вас вопроса.



--------------------
Обижено школьников: 8
PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Закрытая темаСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1853 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.