Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.02.13;
Скачать: CL | DM;

Вниз

Вопрос по работе с 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 вся ветка

Текущий архив: 2005.02.13;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.049 c
6-1102169874
MicrObiolOg
2004-12-04 17:17
2005.02.13
Непойму механизма TTcpServer =(


14-1106595496
Fin
2005-01-24 22:38
2005.02.13
Резюме


14-1106290671
sapsi
2005-01-21 09:57
2005.02.13
О программистах


14-1106288763
вразлет
2005-01-21 09:26
2005.02.13
Ваши предки...


14-1106253119
Nic87
2005-01-20 23:31
2005.02.13
Рост Шварценэггера