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

Поиск:

Закрытая темаСоздание новой темы Создание опроса
> Принять данные от машины по k-line, т.е. принять их по COM порту и разобрать 
:(
    Опции темы
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   Вверх
Страницы: (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.1012 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


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

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