![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Событие чтения из Com порта происходит когда в порте ничего нет
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. В 2ReadResult = 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] надо передавать - массив динамический.