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

Вниз

Асинхронный ввод/выод com-порта   Найти похожие ветки 

 
bobah ©   (2005-07-19 14:01) [0]

На сайте Королевство Делфи мне попался код. Вроде с ним разобрался, однако один блок не дает мне покоя (см. пояснение в тексте // начало непонятного блока; // конец непонятного блока)

//инициализируем TOverlapped структуру
 FillChar(Ovr,SizeOf(TOverlapped),0);
 Ovr.hEvent := CreateEvent(nil,TRUE,FALSE,#0);
//стартуем бесконечный цикл
 while not Parms.Terminated do with Parms do begin
   if Terminated then break;
   Mask := 0;
//запрашиваем ожилаемую маску ивэнтов
//-----------------------------------
// Начало непонятного блока
//------------------------------------
   if not WaitCommEvent(cId,Mask,@Ovr) then begin
     if GetLastError() = ERROR_IO_PENDING
      then GetOverlappedResult(cId,Ovr,Trans,False);
   end;
// -------------------------------
// Конец непонятного блока
// ------------------------------
    //очищаем ошибки
   ClearCommError(cId,Errs,@Stat);
   if Terminated then break;
   if Mask = 0  then continue;
   if (Mask and EV_RXCHAR) = EV_RXCHAR then begin
   //Если принят хотя бы один байт
    if Stat.cbInQue < 512
     then Kols := Stat.cbInQue
      else Kols := 512;
     if Terminated then break;
   //пытаемся считать принятые байты
     ReadFile(cId,Buff,Kols,Kols,@Ovr);
.........................................

А именно не понятно зачем здесь GetOverlappedResult? И вообще, если несложно, объясните зачем она нужна эта функция?


 
tesseract   (2005-07-19 14:13) [1]

Данный блок ждёт события Com-порта по маске. GetOverlappedResult  возвращает результат операции отложенного чтения. ERROR_IO_PENDING операция незавершена.

ЗЫ Код кстати не совсем грамотный.


 
bobah ©   (2005-07-19 14:32) [2]

Насчет код несовсем грамотный нельзя ли поподробнее?
Хотел спросить еще, насколько я знаяю при вызове WaitCommEvent, ReadFile, WriteFile в асинхронном режиме они запускаются, но прграмма не зависает, так вот как можно этот запущенный waitcommevent остановить, т.е. освободить hevent(случайно не с помощью ли GetOverlappedResult или WaitForSingleObject)?


 
tesseract   (2005-07-19 16:18) [3]

Код большой, выдран из первого попавшегося проекта может нуждаться в доработке


function trThread.InitPort:boolean;
var
   CommTimeOuts:TCOMMTIMEOUTS;
begin
// Не верим, что получится
 Result:=false;
// реагируем на символ
 fMask:=EV_RXCHAR and  not EV_RING; // в NT/2k/XP reqired!!!!!
 fPortname:=PChar("COM"+inttostr(fScaleSet.Port));
// создаём дескриптор
//crit.Acquire;
 try
  hCom:=CreateFile(fPortName,GENERIC_READ OR GENERIC_WRITE,0,NIL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED{FILE_ATTRIBUTE_NORMAL},0);
// Если неверен выходим
    if GetLastError=ERROR_ALREADY_EXISTS then
     begin
      CloseHandle(hCOM);
      status:=GetLastError;
      AddLog("Порт занят"+ fPortName)
     end;
     FillChar(ReadOl,SizeOF(ReadOL),0);

    ReadOl.hevent:=CreateEvent(nil,true,true,nil);
    Status:=GetLastError;

   if (hCom=0) or (hCom=INVALID_HANDLE_VALUE) then
    begin
     Status:=GetLastError;
     AddLog("Ошибка порта "+ fportName);
     // crit.Release;
     exit;
    end
    else
        AddLog("Открыт порт "+ fportName);
// Устанавливаем буфер
   if not(SetupComm(hCom,22,10)) then
    begin
     status:=GetLastError;
    AddLog("SetupComm Error "+ fPortName);
     exit;
    end;
// Чистим буфер
   if not(PurgeComm(hCom,PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR )) then exit;
// Устанавливаем задержки/время ожидания
     CommTimeOuts.ReadIntervalTimeout:= 50;
     CommTimeOuts.ReadTotalTimeoutMultiplier := 10;
     CommTimeOuts.ReadTotalTimeoutConstant := 00;
     CommTimeOuts.WriteTotalTimeoutMultiplier := 10;
     CommTimeOuts.WriteTotalTimeoutConstant := 00;
// DTR и RTS нам на фиг не нужен
    EscapeCommFunction(hCom,SETDTR);
    EscapeCommFunction(hCom,CLRRTS);
  //Если не получилось выходим
    SetCommTimeouts(hCom,CommTimeOuts);
 // Устанавливаем параметры порта через DCB
  if not(GetCommState(hCom,mDCB)) then
   begin
    status:=GetLastError;
    AddLog("GetCommState Error "+ fPortName);
    exit;
   end;

   MDCB.BaudRate:=fScalePar.hDCB.BaudRate;
   MDCB.ByteSize:=fScalePAr.hDCB.ByteSize;
   MDCB.Parity:=FscalePar.hDCB.Parity;
   MDCB.StopBits:=FScalePar.hDCB.StopBits;

//Заполняем нужные параметры
   // Устанавливаем параметры порта и перхвата
   if not(SetCommState(hCom,mDCB)) then
    begin
     Status:=GetLastError;
     Addlog("SetCommState Error "+ fPortName);
     exit;
    end;
// устанавливаем маску перехвата
    if not(SetCommMask(hCom,fMask)) then
     begin
       Status:=GetLastError;
       Addlog("SetComMask Error" +fportName);
       exit;
     end;
// Если дошли до сюда то всё ок
    Result:=true;
 finally
 end;
end;

// Чтение

function trThread.AsyncRead:boolean;
var tMask:DWord;
 begin
result:=false;
if terminated  then  exit;
// убираем событие - идёт запись

fWait.ReSetEvent;
{if State<>"Чтение" then
begin
  State:="Чтение";
  ChangeState;
 end;
 }
if hCom=0 then exit;
// Если надо синхронизироваться, то делаем это

// Ждём сообщения о чтении
WaitCommEvent(hCom,tMask,@READOL);

    // смотрим что у нас
    fSignaled:= WaitForSingleObject(ReadOl.hEvent,WaitInt);
    // Если событие произошло то
     if (fSignaled = WAIT_OBJECT_0) then
      begin
         // Читаем
        if GetOverlappedResult(hCom, REadOL, BytesTrans,false) then
         begin
           // Сравниваем произошедшее событие с прибытием символа
           if (tMask and EV_RXCHAR)<>0 then
            begin
             AvBytes:=GetAvBytes; // Сколько байтов пришло
             if AvBytes>=fScalePar.Size then
              begin
               //try
                // Если пришло нужное кол-во то
                 //buf:="";
                 if ReadFile(hCom,buf^,AvBytes,ReadBytes,@ReadOL) then
                 begin
                   // Чистим буфер
                   PurgeComm(hCom,PURGE_RXCLEAR);
                   result:=true;
                   // Если прочитали нужное кол-во
                   if (ReadBytes>=fScalePAr.Size) then
                   begin
                     if not terminated
                      then
                      begin
                      fWeight:=ScaleRead;
//                       ChangeWeight;
                      State:="Данные разобраны";
                     end;
                    end;
                 end// if REadFile
                 else
                  begin
                   // Ошибка
                   fWait.setEvent;
                   Status:=GetLastError;
                   Addlog("Чтение невозможно");
                  end; // if REadFile

               //  end;
                 end; // if AvBytes
            end; // if Fmask
         end;// if GetOVerlappedResult
      end; // if Signaled
  // end;
    end; // waitcommevent
CancelIO(hCom); // это отмена операций чтения
fWait.SetEvent;
end;

function trThread.ClosePort:boolean;
begin
// Закрываем отложенное чтение
if REadOL.hEvent<> 0 then
 CloseHandle(REadOL.hEvent);
// Сбро настроек порта
if hCom<>0 then
 begin
  try
  SetCommMask(hCom,0);
  CloseHandle(hCom);
  Status:=GetLastError;
  except
     AddLog(" Ошибка порта COM" + inttostr(fScaleSet.port));
  end;
 end;
  AddLog("Порт  COM" + inttostr(fScaleSet.port)+ " закрыт");
 result:=true;
end;

function tRthread.GetAvBytes:cardinal;
var hCurState:TCOMSTAT;
    ErrCode:cardinal;
begin
  ClearCommError(hCom, ErrCode, @hCurState);
  result:=hCurState.cbInQue;
end;


 
ZlDoc ©   (2005-07-19 17:28) [4]

WaitComEvent Возвращается сразу. Для ожидания завершения операции нужно  WaitForSingleObject. Освобождается event ,вроде, CloseHandle(надо проверить).


 
tesseract ©   (2005-07-20 10:02) [5]

to ZlDoc >> Ну а у нас что
  WaitCommEvent(hCom,tMask,@READOL);
  // смотрим что у нас
   fSignaled:= WaitForSingleObject(ReadOl.hEvent,WaitInt);


 
bobah ©   (2005-07-20 11:08) [6]

У меня появились следующие вопросы (уж простите если они вам покажутся глупыми):
1. Правильно ли вызывать функцию CreateEvent( то есть создовать собыие) в функции чтения, с учетом того что она не блокируется, т.е. вызывается n-ое количество раз в потоке, не накладно ли это для системы?
2. В каких случаях следует вызывать ResetEvent и SetEvent, например у меня функции чтения и записи в одном отдельном потоке, они не конкурируют... есть надобность в вызове этих функций для моего случая?
3. Какой смысл в вызове функции отмены операции чтения (CancelIO), когда ее следует использовать?
4. Как понять, что сработал таймаут, определенный в структуре COMMTIMEOUTS (можно на примере, предложенным tesseract, за который ему спасибо)?


 
Digitman ©   (2005-07-20 12:23) [7]

1. Ивент нужно создать до первого обращения к нему.

2. Справка на эту тему отвечает так :

..system sets the hEvent member of the OVERLAPPED structure to the not-signaled state before WaitCommEvent returns, and then it sets it to the signaled state when one of the specified events or an error occurs

т.е. если ты используешь WaitCommEvent, то о сбросе/установке ивента заботиться не нужно

3. CancelIO нужен для немедленной отмены ранее стартованной асинхронной операции ввода/вывода, когда та вернула ERROR_IO_PENDING

4. Ф-ции GetOverlappedResult, WaitCommEvent, Read/Write в этом случае вернут отказ с кодом ошибки ERROR_TIMEOUT = 1460



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

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

Наверх





Память: 0.5 MB
Время: 0.012 c
14-1123747026
Ilya___
2005-08-11 11:57
2005.09.04
Как думаете сколько мне можно попросить за мою програмку?


14-1123357998
Мао Ля
2005-08-06 23:53
2005.09.04
Вопрос питерцам


8-1114401843
Rusland
2005-04-25 08:04
2005.09.04
Вывод метафайла на канву формы.....


14-1123506366
oldman
2005-08-08 17:06
2005.09.04
У меня IE глючит?


1-1123492765
Ded Moroz
2005-08-08 13:19
2005.09.04
TTreeView Background





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский