Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2005.02.13;
Скачать: [xml.tar.bz2];

Вниз

Вопрос по работе с COM портом   Найти похожие ветки 

 
Роман   (2004-12-16 09:56) [0]

Вопрос следующий:
При работе с СОМ портом для приёма данных пользуюсь примерно такой процедурой в отдельном потоке:

Stat : TComStat;
...    
   TransMask:=0;
   WaitCommEvent(CommHandle,TransMask,@Ovr);
   if (TransMask and EV_RXCHAR)=EV_RXCHAR Then  
   begin
         ClearCommError(CommHandle,Errs,@Stat);
         If stat.cbInQue=1 Then ...
...
При первом приёме данных (после запуска программы) почему-то в stat.cbInQue оказывается ровно восемь байт, а остальные куда-то пропадают. При повторной посылке данных принимаются все байты. В чём может быть проблема ?


 
Digitman ©   (2004-12-16 10:13) [1]

1. Неправильный алгоритм работы в overlapped-режиме - возврат из ф-ции WaitCommEvent() вовсе не означает, что приняты "все байты" .. следует анализировать рез-т выполнения этой ф-ции в соответствии с ее описанием

кр.того результат завершения overlapped-операции можно и, как правило, нужно проверять с пом. ф-ции GetOverlappedResult()

2. По поводу использования ф-ции ClearCommError() в справке сказано :
The function is called when a communications error occurs

Непонятно, почему ты вызываешь эту ф-цию безусловно .. на основании чего ты уверен, что возникла ошибка ?


 
tesseract   (2004-12-17 17:15) [2]

2. По поводу использования ф-ции ClearCommError()  - не правда! чере неё байты и смотрятся.

WaitCommEvent(CommHandle,TransMask,@Ovr);
-> а WaitForSingleObject  и GetOverlappedResult???

Для избавления от лишних байт при старте программы - PurgeCom

Для получения ВСЕХ байт - Если ClearComError не вернул нужное ко-во ну подожди ещё 100 мс :-) Или опять же ReadFile - сколько нужно байт и подождать до их прибытия в буфер.


 
ECM ©   (2004-12-17 18:11) [3]

2 tesseract
ClearCommError возвращает
cbInQue
Number of bytes received by the serial provider but not yet read by a ReadFile operation.
Это состояние внутренних буферов драйвера но не ReadFile
Поэтому смотреть через нее -не верно. Только через GetOverlappedResult.
Можешь поверить - http://kolibdb.100free.com/wTerm.zip 80kB - иммено так и построен.. Работает без проблем :)


 
ECM ©   (2004-12-17 18:17) [4]

Совет: в MSDN есть великолепный пример асинхронной работы с COM-портом - в поиске-MSDN - "mttty"


 
Роман   (2004-12-20 10:17) [5]

2 ECM
А как с помощью GetOverlappedResult посмотреть кол-во принятой инф-ии, в хелпе написано:

pNumberOfBytesTransferred
... For a ConnectNamedPipe or WaitCommEvent operation, this value is undefined.
И возвращается совсем не то...


 
tesseract   (2004-12-20 10:29) [6]

to ECM именно то что надо эта функция и возвращает. количество оставшихся байт  в буфере! Если их меньше, чем надо ,то ждём пока  они придут!


 
ECM ©   (2004-12-20 10:53) [7]

function  ReaderAndStatusThread(Param: Pointer): DWORD;
var
 lpoEv: TOverlapped;
 lpoRd: TOverlapped;
 bStop: Boolean;
 //bTmp:  Boolean;
 cbRead,dwMask: DWORD;
 dwRet,dwOvRes: DWORD;
 evArr: Array[0..2] of THandle;
 bWaitingOnStat: Boolean;
 bWaitingOnRead: Boolean;
 pCom: PComPort absolute Param;
begin
 Assert(Assigned(pCom));
 with pCom^ do begin
   FillChar(lpoEv,SizeOf(lpoEv),0);
   lpoEv.hEvent := CreateEvent(nil,TRUE,FALSE,nil);
   Assert(lpoEv.hEvent<>0, SysErrorMessage(GetLastError()));

   FillChar(lpoRd,SizeOf(lpoRd),0);
   lpoRd.hEvent := CreateEvent(nil,TRUE,FALSE,nil);
   Assert(lpoRd.hEvent<>0, SysErrorMessage(GetLastError()));

   bStop := SetCommMask(hComPort,dwCommMask);
   Assert(bStop,SysErrorMessage(GetLastError()));
   bStop          := FALSE;
   bWaitingOnStat := FALSE;
   bWaitingOnRead := FALSE;

   evArr[0] := evGlThreadExit;
   evArr[1] := lpoRd.hEvent;
   evArr[2] := lpoEv.hEvent;
   FillChar(OldComStat,SizeOf(OldComStat),0);
   repeat
     if WaitForSingleObject(evGlThreadExit,0) = WAIT_OBJECT_0 then break;

     if not bWaitingOnRead  then begin
       if not ReadFile(hComPort,RBuffer^,16384,cbRead,@lpoRd) then begin
         dwRet := GetLastError();
         if dwRet <> ERROR_IO_PENDING then begin
           Assert(FALSE,SysErrorMessage(dwRet));
           PostMessage(WinHandle,WM_CLOSE_ON_COM_ERR,dwRet,0);
 //          bStop := TRUE;
           break;
         end else bWaitingOnRead := TRUE;
         //Assert(FALSE,"Read TO!");
       end else begin
         dwRet := GetLastError();
         if dwRet = ERROR_IO_PENDING then begin
           bWaitingOnRead := TRUE;
         end else
           Assert(FALSE,SysErrorMessage(dwRet));
       end;
     end;

     if bNoEvents then bWaitingOnStat := TRUE;
     if not bWaitingOnStat then begin
       if (bNoEvents) or (dwCommMask = 0) then bWaitingOnStat := TRUE
       else if not WaitCommEvent(hComPort,dwMask,@lpoEv) then begin
         dwRet := GetLastError();
         if dwRet <> ERROR_IO_PENDING then begin
           Assert(FALSE,SysErrorMessage(dwRet));
           PostMessage(WinHandle,WM_CLOSE_ON_COM_ERR,dwRet,0);
 //          bStop := TRUE;
           break;
         end else bWaitingOnStat := TRUE;
       end;
     end;

     if bWaitingOnRead and bWaitingOnStat then begin
       dwRet := WaitForMultipleObjects(3,@evArr,FALSE,INFINITE);
       Case dwRet of

         WAIT_OBJECT_0,WAIT_ABANDONED_0..WAIT_ABANDONED_0+2: begin
           bStop := TRUE;
         end;

         WAIT_OBJECT_0+1: begin
           if GetOverlappedResult(hComPort,lpoRd,cbRead,TRUE) then begin
             if cbRead > 0 then begin
               Assert(pCom^.WinHandle <> 0, "Не установлен ComPort.WinHandle!");
              // if bMirror then ComWriter.WriteBuffer(@RBuffer[0],cbRead);
               SendMessage(WinHandle,WM_READ_BUFFER,Integer(RBuffer),cbRead);
               ReadTotal := ReadTotal + cbRead;
               SendMessage(WinHandle,WM_RD_TOTAL_UPDATE,0,0);

             end else begin
 //              CheckComStat();
               SendMessage(WinHandle,WM_READSTAT_TO,0,0);
             end;

           end else begin
             dwRet := GetLastError();
//              bStop := TRUE;
             if (dwRet <> ERROR_OPERATION_ABORTED) and (WaitForSingleObject(evGlThreadExit,0) <> WAIT_OBJECT_0) then begin
               Assert(FALSE,SysErrorMessage(dwRet));
               PostMessage(WinHandle,WM_CLOSE_ON_COM_ERR,dwRet,0);
             end;
 //            bStop := TRUE;
             break;
           end;
           if WaitForSingleObject(evGlThreadExit,0) = WAIT_OBJECT_0 then
             bStop := TRUE;
           bWaitingOnRead := FALSE;
         end;

         WAIT_OBJECT_0+2: begin
           if GetOverlappedResult(hComPort,lpoEv,dwOvRes,FALSE) then
             HandleComEvent(pCom,dwMask)
           else begin
             dwRet := GetLastError();
             if (dwRet <> ERROR_OPERATION_ABORTED) and (WaitForSingleObject(evGlThreadExit,0) = WAIT_OBJECT_0) then
//                bStop := TRUE
             else begin
               Assert(FALSE,SysErrorMessage(dwRet));
               PostMessage(WinHandle,WM_CLOSE_ON_COM_ERR,dwRet,0);
             end;
 //            bStop := TRUE;
             break;
           end;
           bWaitingOnStat := FALSE;
         end;
{
         WAIT_TIMEOUT: begin
 //          PostMessage(WinHandle,WM_READSTAT_TO,0,0);
         end;
}
       end;
     end;

   until bStop;

   CloseHandle(lpoRd.hEvent);
   CloseHandle(lpoEv.hEvent);
 end;
 Result := 0;
end;


 
Роман   (2004-12-20 10:56) [8]

PurgeComm(CommHandle,PURGE_RXCLEAR);
TransMask:=0;
WaitCommEvent(CommHandle,TransMask,@Ovr);
if (TransMask and EV_RXCHAR)=EV_RXCHAR Then  
begin
         WaitForSingleObject(CommHandle,100);
         ClearCommError(CommHandle,Errs,@Stat);
         GetOverlappedResult(CommHandle,Ovr,Num,True);
...
И в Num всегда ноль... Поясните пожалуйста поподробней как в данном случае из GetOverlappedResult получить кол-во байт в буфере.


 
ECM ©   (2004-12-20 11:11) [9]

См. выше


 
Роман_   (2004-12-22 09:50) [10]

Спасибо всем кто ответил. Пробема решилась путём ожидания перед ClearComError. Видимо, действительно не успевали все байты дойти. Теперь нормально



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2005.02.13;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.038 c
1-1106768480
Angela
2005-01-26 22:41
2005.02.13
Координаты и Panel...


6-1100847332
Дмитрий76
2004-11-19 09:55
2005.02.13
Проблемы с функцией NetShareAdd (netapi32.dll)


3-1106033256
Бизон
2005-01-18 10:27
2005.02.13
Событие выбора из PickList в DBGride


14-1106224865
Anonimus
2005-01-20 15:41
2005.02.13
Выделенка на Вынь2к


4-1103887922
cfytr
2004-12-24 14:32
2005.02.13
имитация клика





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский