roboforum.ru

Технический форум по робототехнике.


Delphi и COM порт

В разделе рассматриваются вопросы информационного обмена в робототехнике.
Аппаратный уровень, протоколы.

Delphi и COM порт

Сообщение andy-k » 20 окт 2010, 17:55

Добрый вечер всем! Подскажите пожалуйста,я новенький, совсем новенький :)

Никак не могу на форуме найти ответа на свой вопрос.

В общем, есть у меня ардуина мега, она отправляет данные в COM порт, ну в смысле виртуальный COM порт, на компе. Я написал программу на Delphi, ибо больше ни на чем не умею, которая случает порт. Чтение идет в асинхронном режиме с использованием эвентов. Я до этого ничего подобного не делал и не совсем ещё разбираюсь в этом. Нашел в сети кучу описаний работы и реализовал наконец. Уже 2 дня мучаюсь.

Сначала пытался в синхронном режиме, без эвентов, чтение было, но команды принимались то целиком, то "кусками". Прочитал, что лучше делать с использованием эвентов, но все-равно не получается. В плату залит скетч, который раз в 5 секунд выдает сообщение на COM порт. Стоит точка остановки в дебаггере, эвент работает четко, в момент отправки сообщения платой код активируется. Все бы ничего, но проблема вот в чем. Отправляется строчка текста: ABCD1234, кучу раз она так и принимается, а бывает что проскакивают разы типа CD1234 или 1234 и т.п. Кто может помочь, буду очень благодарен.

Вот код инициализации порта:

begin
PortString := 'COM' + ComboBox5.Text;
CommHandle := CreateFile(PChar(PortString), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
unit2.CommHandle := CommHandle;

if (CommHandle = INVALID_HANDLE_VALUE) then
begin
MessageDlg('Can not open the specified port', mtError, [mbOK], 0);
end
else
begin
GetCommState(CommHandle, DCB);
DCB.BaudRate := CBR_115200;
DCB.Parity := NOPARITY;
DCB.ByteSize := 8;
DCB.StopBits := OneStopBit;

SetCommState(CommHandle, DCB);

end;


код метода execute потока, в котором крутится постоянное ожидание событий и их обработка:

Код: Выделить всёРазвернуть
var
    CurrentState : TComStat;
    AvaibleBytes,
    ErrCode,
    RealRead     : Cardinal;
    ReadOL       : TOverLapped;
    Signaled,
    Mask         : DWORD;
    BytesTrans   : DWORD;
    bReadable    : Boolean;
    MyBuff: array[0..1023] of Char;
begin
FillChar(ReadOL, SizeOf(ReadOL), 0);
ReadOL.hEvent:= CreateEvent(nil, True, True, nil);

SetCommMask(CommHandle, EV_RXCHAR);


WaitCommEvent(CommHandle, Mask, @ReadOL);

Signaled:= WaitForSingleObject(ReadOL.hEvent, INFINITE);
if (Signaled  = WAIT_OBJECT_0) then
  begin
  if GetOverlappedResult(CommHandle, ReadOL, BytesTrans, False) then
    begin

    if (Mask and EV_RXCHAR) <> 0 then
      begin

      ClearCommError(CommHandle, ErrCode, @CurrentState);

      AvaibleBytes:= CurrentState.cbInQue;

      bReadable:= AvaibleBytes > 0;

      if bReadable then
        begin
        ReadFile(CommHandle, MyBuff, SizeOf(MyBuff), RealRead, @ReadOL);// then begin
        mm := string(MyBuff);
       
        Synchronize(addData);
       
        end;
      end;
    end;
  end;
end;
andy-k
 
Сообщения: 32
Зарегистрирован: 20 окт 2010, 17:38
Откуда: Москва
прог. языки: Delphi,Morph
ФИО: Андрей

Re: Delphi и COM порт

Сообщение galex1981 » 20 окт 2010, 22:12

Понизь скорость приема/передачи по порту, 56000 например - мне помогло. Прблема походу у тебя в том что евент не успевает обработаться а ему уже нужно принимать следующий поток данных из порта. Путей здесь два: 1) уже называл выше - понизить скорость приема/передачи 2) оптимизировать код евента
if(!Operate) Read(pDatasheet);
Аватара пользователя
galex1981
 
Сообщения: 4363
Зарегистрирован: 04 дек 2008, 22:44
Откуда: Камышин
Skype: galk-aleksandr1
прог. языки: Kotlin, Java, C, C++, Assm, BasCom, VB, php
ФИО: Галкин Александр Владимирович

Re: Delphi и COM порт

Сообщение andy-k » 20 окт 2010, 22:23

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

но попробую ещё поэксперементировать. пробовал на 115200, на 57600 и на 14400
andy-k
 
Сообщения: 32
Зарегистрирован: 20 окт 2010, 17:38
Откуда: Москва
прог. языки: Delphi,Morph
ФИО: Андрей

Re: Delphi и COM порт

Сообщение galex1981 » 20 окт 2010, 22:26

А шнур какой у тебя COM портовый (имеется ввиду длина, экранирование)?
if(!Operate) Read(pDatasheet);
Аватара пользователя
galex1981
 
Сообщения: 4363
Зарегистрирован: 04 дек 2008, 22:44
Откуда: Камышин
Skype: galk-aleksandr1
прог. языки: Kotlin, Java, C, C++, Assm, BasCom, VB, php
ФИО: Галкин Александр Владимирович

Re: Delphi и COM порт

Сообщение andy-k » 20 окт 2010, 22:31

По поводу экранирования не знаю, длина пол-метра примерно, шнурок mini USB

скорость 4800 и все-равно проскакивают ошибки :( не знаю что с этим делать
andy-k
 
Сообщения: 32
Зарегистрирован: 20 окт 2010, 17:38
Откуда: Москва
прог. языки: Delphi,Morph
ФИО: Андрей

Re: Delphi и COM порт

Сообщение galex1981 » 20 окт 2010, 22:56

Попробуйте оптимизировать код
if(!Operate) Read(pDatasheet);
Аватара пользователя
galex1981
 
Сообщения: 4363
Зарегистрирован: 04 дек 2008, 22:44
Откуда: Камышин
Skype: galk-aleksandr1
прог. языки: Kotlin, Java, C, C++, Assm, BasCom, VB, php
ФИО: Галкин Александр Владимирович

Re: Delphi и COM порт

Сообщение andy-k » 20 окт 2010, 23:24

в том то и дело, что я не знаю что тут можно оптимизировать, я крутил и так и так уже, все перепробовал :(
andy-k
 
Сообщения: 32
Зарегистрирован: 20 окт 2010, 17:38
Откуда: Москва
прог. языки: Delphi,Morph
ФИО: Андрей

Re: Delphi и COM порт

Сообщение galex1981 » 20 окт 2010, 23:30

По сути в евенте сделать получение и сохранение данных, а обработку в основной программе делай
if(!Operate) Read(pDatasheet);
Аватара пользователя
galex1981
 
Сообщения: 4363
Зарегистрирован: 04 дек 2008, 22:44
Откуда: Камышин
Skype: galk-aleksandr1
прог. языки: Kotlin, Java, C, C++, Assm, BasCom, VB, php
ФИО: Галкин Александр Владимирович

Re: Delphi и COM порт

Сообщение andy-k » 20 окт 2010, 23:34

в эвенте имеется ввиду в потоке да?

думаешь поможет?
andy-k
 
Сообщения: 32
Зарегистрирован: 20 окт 2010, 17:38
Откуда: Москва
прог. языки: Delphi,Morph
ФИО: Андрей

Re: Delphi и COM порт

Сообщение galex1981 » 20 окт 2010, 23:45

1)Да в потоке
2)Я так оптимизировал
if(!Operate) Read(pDatasheet);
Аватара пользователя
galex1981
 
Сообщения: 4363
Зарегистрирован: 04 дек 2008, 22:44
Откуда: Камышин
Skype: galk-aleksandr1
прог. языки: Kotlin, Java, C, C++, Assm, BasCom, VB, php
ФИО: Галкин Александр Владимирович

Re: Delphi и COM порт

Сообщение Rockman » 21 окт 2010, 13:58

Вам можно попробовать модернизировать посылку и организовать приём данных до символа 13 и/или 10, что соответсвует "\r\n", т.е. до перевода каретки и/или новой строки. Таким образом, принимая пришедшие данные до этого символа, будет суммироваться приём посылки. У меня нечто похожее было, но не да делфи, а на C# под VS2008. Принцип один и тот же...
Последний раз редактировалось Rockman 21 окт 2010, 14:04, всего редактировалось 1 раз.
Rockman
 
Сообщения: 198
Зарегистрирован: 06 июл 2010, 16:36
Откуда: Черногорск
прог. языки: Objective-C, C#, C, C++

Re: Delphi и COM порт

Сообщение andy-k » 21 окт 2010, 14:02

кстати, отправка из контроллера итак идет впаре с этим символом(в конце), да и идеи были сделать что-то похожее, но на крайний случай если не разберусь :)

спасибо за ответ
andy-k
 
Сообщения: 32
Зарегистрирован: 20 окт 2010, 17:38
Откуда: Москва
прог. языки: Delphi,Morph
ФИО: Андрей

Re: Delphi и COM порт

Сообщение Rockman » 21 окт 2010, 14:06

Видимо событие приёма данных принимает вытолкнутые асинхронно в буфер данные. Далеко не всегда принимается весь пакет, поэтому частями и получается. Я с arduino так и принимаю данные до \r\n - все работает без проблем, пожалуйста :)
Rockman
 
Сообщения: 198
Зарегистрирован: 06 июл 2010, 16:36
Откуда: Черногорск
прог. языки: Objective-C, C#, C, C++

Re: Delphi и COM порт

Сообщение andy-k » 22 окт 2010, 10:04

Увеличил таймауты до 100, все заработало, правда несколько передач сливаются в одну. На стороне устройства добавил добавку символов #13 и #10, считанный буфер передаю функции, которая "расцепляет" сообщения ориентируясь на эти "разделители". Вроде все работает, пока тестирую.

Нужна на сто процентов стабильная передача, потеря одного из сообщений - весь проект под угрозой, несмотря на то, что аппаратная часть, над которой и бился большую часть времени работает идеально.
andy-k
 
Сообщения: 32
Зарегистрирован: 20 окт 2010, 17:38
Откуда: Москва
прог. языки: Delphi,Morph
ФИО: Андрей

Re: Delphi и COM порт

Сообщение boez » 22 окт 2010, 11:19

Если нужна на 100% стабильная - скорее всего нужен сверху протокол, устойчивый к потерям. Чтобы на каждый пакет в ответ слал подтверждение, пакеты защищены контрольными суммами и передающее устройство, не получив подтверждения, отправляло пакет повторно.
boez
 
Сообщения: 1981
Зарегистрирован: 27 авг 2008, 10:45
Откуда: Харьков
прог. языки: С/С++

След.

Вернуться в Коммуникации

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 9