Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Событие чтения из Com порта происходит когда в порте ничего нет


Страницы:   1 2

Kolan ©   (2006-05-30 18:37:00) 

Здравствуйте,
 Для чтения из порта использую вот такую ф-цию:

function TAnisochronousComm.Read(var Buffer: array of Byte;
 NumberOfBytesToRead: Cardinal; TimeOut: Cardinal;
 var IsTimeOutExpire: Boolean): Cardinal;
begin
 Result := 0;
 IsTimeOutExpire := False;
 if FPortHandle <> INVALID_HANDLE_VALUE then
 begin
   if TimeOut <> INFINITE then
     TimeOut := TimeOut * NumberOfBytesToRead;

   ReadFile(FPortHandle, Buffer, NumberOfBytesToRead, Cardinal(Result),
     @FOverlappedRead);
   if WaitForSingleObject(FOverlappedRead.hEvent, TimeOut) = WAIT_OBJECT_0 then
     GetOverlappedResult(FPortHandle, FOverlappedRead, Cardinal(Result), False)
   else
     IsTimeOutExpire := True;
 end;
end;


Вызываю вот так:
FBytesRead := FCommPort.Read(FBuffer, 1, INFINITE, IsTimeOut);

Вот тут я попросил прочесть 1 байт. Соответственно WaitForSingleObjectдолжна ждать пока не придет 1 байт, так? Но событие случается даже если в порт ничего не приходит. И GetOverlappedResult(FPortHandle, FOverlappedRead, Cardinal(Result), False)Result равен 0.

Эффекет проявляется при маленьких количествах считываемых байт, при больших 10, 20 такого нет.

Почему так получается?


Kolan   (2006-06-02 13:06:00) [1]

Дааа, короче проблема в руках(моих) :)
Вот оказывается что было вконструкторе:

 F ReadIntervalTimeout:= 1000;
 FReadTotalTimeoutMultiplier := 1000;
 FReadTotalTimeoutConstant := 1000;
 FWriteTotalTimeoutMultiplier := 1000;
 FWriteTotalTimeoutConstant := 1000;


Поэтому, то событие и наступало.

Всех благодарю за ответы..

PS
 Вот тебе и повторное использование кода... :)


tesseract   (2006-06-01 15:19:00) [2]

меньше загрузка процессора, этак раз в 10 меньше тактов уходит.


atruhin   (2006-06-01 15:09:00) [3]


> но там прямой доступ к дровам

А зачем если не секрет? Что это дает?


Evgeny V   (2006-06-01 14:03:00) [4]


> Елси там ничего нет - 0, зачем читать, почему возникает
> событие?.

Это возможно.
Событие может возникнуть при возникновении тайм-аута порта,  смотрите COMMTIMEOUTS.  Для настройки таймаутов см SetCommTimeouts


Kolan   (2006-05-31 16:55:00) [5]

Угу. Благодарю за обсуждение :) Пошел разбираться.


tesseract   (2006-05-31 16:53:00) [6]

Подсекай.


Kolan   (2006-05-31 16:49:00) [7]

НУ давай, буду благодарен... Хотя прямой доступ к дровамэту уж слишком...


tesseract   (2006-05-31 16:46:00) [8]


> Ладно. Буду разбираться. Конечно пример с пояснениями мне
> бы очень помог... :)Благодарю.

Могу выслать, но там прямой доступ к дровам и мало комментов, рискуашь ниасилить :-)


Kolan   (2006-05-31 16:45:00) [9]

Ладно. Буду разбираться. Конечно пример с пояснениями мне бы очень помог... :)
Благодарю.


tesseract   (2006-05-31 16:41:00) [10]


> Я хотел бы, чтобы моя функция Read не читала 0 байт. Елси
> там ничего нет - 0, зачем читать, почему возникает событие?
> . Оноже должно вознинуть когда хотябы 1 байт прийдет...


Так бы сразу и скакзал, а я мучаюсь. :-)

WaitCommMask используй на EV_RXCHAR.


Kolan   (2006-05-31 16:30:00) [11]


> Тогда не понял - ну нуль там, что же ты хочешь от ReadFile?
>
>

Я хотел бы, чтобы моя функция Readне читала 0 байт. Елси там ничего нет - 0, зачем читать, почему возникает событие?. Оноже должно вознинуть когда хотябы 1 байт прийдет...

Всеравно, что меня попросилибы: "Позвони когда пидет Вася", а я бы каждые 5 минтут звонил и говорил - "Вася не пришел". Спрашивается чё ты звонишь? Тебе же сказали только когда прийдёт позвонить.....


tesseract   (2006-05-31 16:24:00) [12]

Тогда не понял - ну нуль там, что же ты хочешь от ReadFile?


Kolan   (2006-05-31 16:19:00) [13]


> Да и попробуй узнать есть-ли реально в буфере что-то с помощью
> ClearComError.

Узнаю

var
 Errors: Cardinal;
begin
 Result := 0;
 if FPortHandle <> INVALID_HANDLE_VALUE then
 begin
   ClearCommError(FPortHandle, Errors, @FCommStat);
   Result := FCommStat.cbInQue;
 end;
end;

Нуль там...

А у тебя случаем реакция на начальный символ не стоит?
Незнаю... как и где проверить...


tesseract   (2006-05-31 15:56:00) [14]


> GetOverlappedResult будет ждать вечно, так как нет способа
> указать максимальное время ожидания. Ждать завершения ввода/вывода
> лучше с помощью функций


Бред.
Мы УЖЕ получили WaitForSingleObject. Теперь просто забираем буфер.

А у тебя случаем реакция на начальный символ не стоит?

Да и попробуй узнать есть-ли реально в буфере что-то с помощью ClearComError.


Kolan   (2006-05-31 15:35:00) [15]

Проблему я как-бы решил добавив проверку:
FCriticalSection.Acquire;
     try
       FBytesRead := FCommPort.Read(FBuffer, 1, INFINITE, IsTimeOut);
     finally
       FCriticalSection.Release;
     end;
      if FBytesRead > 0 then

Очень хочу именно понять вчём дело. Что не так я сделал...


Kolan   (2006-05-31 15:34:00) [16]

Не очень понял:
GetOverlappedResult(FPortHandle, FOverlappedRead, Cardinal(Result), True);
LastError := GetLastError;- ERROR_IO_PENDING
True - ничего не дало. И ошибка после GetOverlappedResult - ERROR_IO_PENDING.
А еще у меня есть кусочек статьи:


Замечу, что ожидать завершения ввода/вывода с помощью функции GetOverlappedResult не самое правильное решение. При работе с дисковым файлом операция завершится гарантированно, а при работе с последовательным или параллельным портом совсем не обязательно. Представьте, что Вы не настроили тайм-ауты последовательного порта, а подключенное устройство неисправно. GetOverlappedResult будет ждать вечно, так как нет способа указать максимальное время ожидания. Ждать завершения ввода/вывода лучше с помощью функций:
WaitForSingleObject
WaitForMultipleObjects


tesseract   (2006-05-31 15:22:00) [17]


GetOverlappedResult(hCom, ReadOL, result, true);


<winApi reference>
bWait
Specifies whether the function should wait for the pending overlapped operation to be completed. If TRUE, the function does not return until the operation has been completed. If FALSE and the operation is still pending, the function returns FALSE and the GetLastError function returns ERROR_IO_INCOMPLETE.
</winApi reference>

Соответственно получаешь ERROR_IO_INCOMPLETE. Делай проверкe возвращаемого значения.


Kolan   (2006-05-31 15:10:00) [18]

(1)ReadResult := ReadFile(FPortHandle, Buffer, NumberOfBytesToRead, Cardinal(Result),
     @FOverlappedRead);
    (2)if not ReadResult then
   begin
      (3)LastError := GetLastError;
      (4)if LastError = ERROR_IO_PENDING then
        (5)if WaitForSingleObject(FOverlappedRead.hEvent, TimeOut) = WAIT_OBJECT_0 then
          (6)GetOverlappedResult(FPortHandle, FOverlappedRead, Cardinal(Result), False)
       else
         IsTimeOutExpire := True;
   end;


Вот вроде сделал как в tesseract ©   (30.05.06 22:00) [3].
Тоже самое.
Попадаем в 1. В 2 ReadResult = False.
LastError = ERROR_IO_PENDING- истина
WaitForSingleObject- дожидается

Cardinal(Result),- Результат = 0..

Что за фигня..

Причем читает каждые 5 секунд(приблизительно).....


han_malign   (2006-05-31 14:22:00) [19]


> Ещё одна - buffer[0] надо передавать - массив динамический.

- не трынди, массив - открытый, а не динамический -   varпередается прямой ссылкой, а не косвенной...


tesseract   (2006-05-31 13:00:00) [20]


>   ReadFile(FPortHandle, Buffer, NumberOfBytesToRead, Cardinal(Result),
>       @FOverlappedRead);

Ещё одна - buffer[0] надо передавать - массив динамический.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо