Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Микроконтроллеры (MCU) и микропроцессоры (MPU) > Arduino UART


Автор: alcogol 20.10.2010, 21:10
Добрый день друзья, помогите пожалуйста новичку. Пытаюсь сконнектиться со своей ардуиной. Она шлёт данные мне в виртуальный COM порт, причем порой очень быстро, несколько отправок безо всяких пауз. Ардуиновскмй монитор(из проги, который вызывается) нормально реагирует, все передачи приходят отдельными строчками, все цело, хорошо и красиво.

Я в делфях написал прогу и уже 2 дня не могу победить прием данных. Он идет, но не так как надо. Так как я новичек и ещё не работал с СОМ портами, я поискал в инете примеры, скажем так, ничего на сто процентов рабочего не нашел, перечитал кучу статей и то же самое. С инициализацией порта проблем нет, чтение идет в отдельном потоке, так вот, сначала в exexcete потока у меня был такой код:

Код

ReadFile(CommHandle, BinBuf, sizeof(BinBuf),
              dwRead, Nil);
b := BinBuf;
if (length(b)>3) then// 
  begin
  Synchronize(addData);
  end;
end;



Он работает, но как-то не так. Устройство посылает одну команду в порт, а в программе ReadFile не останавливаясь читает его. То есть не один раз, а как бы зацикливается, пока не прийдет следующая команда и с ней то же самое. То есть чтение не останавливается.


Попробовал асинхронное чтение по событиям, все работает, события тоже, но при чтении строки(устройство каждые 5 секунд отправляет 1234ABCD). Процентов 90 принимается нормально, остальные 10 что-то вроде того 12ABCD или ABCD или 34ABCD. Не понимаю, почему так :( Ребят, не забывайте что я ещё не такой опытный, подскажите что не так. Может у кого-либо есть рабочий пример.

вот код второй моей попытки:

Код

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);
        mm := string(MyBuff);

        Synchronize(addData);

        end;
      end;
    end;
  end;
end;


Автор: xvr 21.10.2010, 09:39
  •  Настройте размеры буферов и таймауты COM порта (это то, что делается после CreateFile, но до ReadFile)
  •  Принимаемые байты НЕ БУДУТ формировать строку - у них нет завершающего 0 в конце. Т.ч. конструкция b := BinBuf; и mm := string(MyBuff); неправильны, строку надо формировать dwRead/RealRead байтов длинной
  •  ReadFile читает байты по мере поступления, при этом количество этих байтов определяется не тем, как их отправляло устройство, а тем, сколько их накопилось в приемном буфере (и таймаутами). RS232 очень медленное устройство (даже виртуальный через USB) по компьютерным меркам. Так что ваш 1234ABCD вообще может придти побайтово. (Или настройте таймаут секунды на 3)

Автор: alcogol 21.10.2010, 10:57
xvr, спасибо за ответ.

Цитата

Настройте размеры буферов и таймауты COM порта (это то, что делается после CreateFile, но до ReadFile)


С таймаутами порта попробую поиграть, а вот про буффер немного не понял

Цитата

конструкция b := BinBuf; и mm := string(MyBuff); неправильны, строку надо формировать dwRead/RealRead байтов длинной


это вроде тоже понятно

Цитата

ReadFile читает байты по мере поступления, при этом количество этих байтов определяется не тем, как их отправляло устройство, а тем, сколько их накопилось в приемном буфере (и таймаутами). RS232 очень медленное устройство (даже виртуальный через USB) по компьютерным меркам. Так что ваш 1234ABCD вообще может придти побайтово. (Или настройте таймаут секунды на 3)


3 секунды для моих задач это очень много :(


Странно, а ардуиновский монитор работает превосходно и ничего не теряет

Автор: UniBomb 21.10.2010, 13:44
Цитата(alcogol @  21.10.2010,  11:57 Найти цитируемый пост)
буффер немного не понял

Размеры входного и выходного буффера задаются функцией http://msdn.microsoft.com/en-us/library/aa363439(VS.85).aspx. Так же было бы неплохо очищать буферы (входной после чтения и выходной перед записью) функцией http://msdn.microsoft.com/en-us/library/aa363428(VS.85).aspx.

Автор: xvr 21.10.2010, 13:56
Цитата(UniBomb @  21.10.2010,  13:44 Найти цитируемый пост)
Так же было бы неплохо очищать буферы (входной после чтения и выходной перед записью) функцией PurgeComm. 
А вот этого лучше не делать - данные в буферах просто так не появляются, они приходят от устройства. При очистке они будут потерянны.
Очищать буфера нужно только при полной инициализации/переинициализации устройства, когда нужно именно выкинуть все данные, пришедшие до сих пор


Автор: alcogol 21.10.2010, 16:43
UniBomb, 


xvr, 

спасибо

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

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

Автор: UniBomb 21.10.2010, 22:47
xvr, вот тут я не соглашусь. Если не очищать буфферы, то есть возможность принять или передать какой-либо мусор. 

Автор: xvr 21.10.2010, 23:53
Цитата(UniBomb @ 21.10.2010,  22:47)
xvr, вот тут я не соглашусь. Если не очищать буфферы, то есть возможность принять или передать какой-либо мусор.

А если не очищать, то есть не только возможность, но и неизбежность потерять данные  smile 
А вообще вопрос чистить или не чистить всецело зависит от протокола обмена. Если железка по своей инициативе в РС ничего не посылает, и если РС использует чистый протокол запрос-ответ (без возможности наложения запросов на предыдущие ответы), то лучше чистить. Если же что то из перечисленного используется - то чистить нельзя ни в коем случае

Автор: UniBomb 22.10.2010, 09:38
Цитата(xvr @  22.10.2010,  00:53 Найти цитируемый пост)
А вообще вопрос чистить или не чистить всецело зависит от протокола обмена.

Это да. Я сначала не заметил фразы ТС о том, что железяка сама шлёт данные. Но и всё равно перед отправкой данных почистить буффер не будет лишним  smile 


Как бы то нибыло, а тема больше подходит для http://forum.vingrad.ru/forum/delphi-winapi.html раздела (там уже даже кто-то зеркало сделал этой темы), т.к. вопроса по тематике этого раздела нет. Чистое делфи и винапи. Может стоит перенести?

Автор: xvr 22.10.2010, 10:44
Цитата(UniBomb @  22.10.2010,  09:38 Найти цитируемый пост)
Чистое делфи и винапи.
Пока дело не касается протокола обмена (а оно уже коснулось) - то да.

Цитата(UniBomb @  22.10.2010,  09:38 Найти цитируемый пост)
Может стоит перенести? 
Уже нет  smile 


Автор: alcogol 22.10.2010, 20:17
я просто сам сомневался куда засунуть темку smile

думал здесь правильнее

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)