Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Помощь. COM port. WinAPI. Асинхронное чтение, Помощь. COM port. WinAPI. Асинхронное чт 
V
    Опции темы
EEEEEE
Дата 28.4.2008, 23:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 15.5.2006

Репутация: нет
Всего: нет



Может кто-либо подскажет. Шерстил Net, всё не то. Нужно организовать ассинхронное чтение/запись бинарных данных через COM порт. Код в коплекте. Инициирует порт нормально, но ничего не читает. Где ошибки? 


Код

//$$---- Form CPP ----
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit_ComPOrt.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
 hComm_1 = NULL;
 ZeroMemory( &dcb, sizeof(DCB));
 ZeroMemory( &over, sizeof(OVERLAPPED));
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 hComm_1 = CreateFile("COM5", GENERIC_READ | GENERIC_WRITE, 0,
                       NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

 if (hComm_1 == INVALID_HANDLE_VALUE)
  {
   Memo1->Lines->Add("Не удалось открыть порт COM5");
   return;
  }


  Memo1->Lines->Add("Порт COM5 открыт !");
   // чтение в dcb параметров порта
 if(! GetCommState(hComm_1, &dcb))
   {
    CloseHandle( hComm_1);
    Memo1->Lines->Add("Не удалось получить статус порта COM5");
    return;
   }

 Memo1->Lines->Add("Статус порта COM5 получен !");

}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
 #if 1
  dcb.BaudRate = CBR_4800;
  dcb.ByteSize = 8;
  dcb.StopBits = ONESTOPBIT;
  dcb.Parity   = NOPARITY;
 if(!SetCommState(hComm_1, &dcb))
   {
    CloseHandle( hComm_1);
    Memo1->Lines->Add("Не удалось настроить порт COM5!");
    return;
   }
 Memo1->Lines->Add("Порт COM5 готов к работе!");
#endif
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
//
   if(over.hEvent)
     {
      CloseHandle( over.hEvent);
      over.hEvent = NULL;
     }
   if(hComm_1)
     {
      CloseHandle( hComm_1);
      hComm_1 = NULL;
     }
}
//---------------------------------------------------------------------------
bool TForm1::SetEventCOM()
{
#if 0



 COMMTIMEOUTS timeouts;
GetCommTimeouts(comm_handle, &timeouts);
timeouts.ReadIntervalTimeout = 0xFFFFFFFF;
timeouts.ReadTotalTimeoutMultiplier = 0xFFFFFFFF;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(comm_handle, &timeouts);


#endif


  if(!SetCommMask( hComm_1,EV_RXCHAR | EV_TXEMPTY))
    {
     Memo1->Lines->Add("Мониторинг за событиями порта не настроен!");
     CloseHandle( hComm_1);
     return false;
    }
     Memo1->Lines->Add("Мониторинг за событиями порта настроен!");

  over.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  if(!over.hEvent)
     {
      Memo1->Lines->Add("Событие не настроено!");
      CloseHandle( hComm_1);
      return false;
     }
  Memo1->Lines->Add("Событие настроено!");

  return true;
}
//---------------------------------------------------------------------------
BYTE TForm1::ReadByteCOM()
{
 BYTE read =0;
 DWORD dwByteRead =0;
  do
   {
    if(! ReadFile( hComm_1, &read, sizeof(BYTE), &dwByteRead, NULL)) return 0;
   }while(!dwByteRead);
 return  read;
}
//---------------------------------------------------------------------------
DWORD TForm1::ReadData_COM( void* Data, unsigned int uNumBytes)
{
 DWORD dwBytesRead =0;
 if(!ReadFile( hComm_1, Data, uNumBytes, &dwBytesRead, NULL))
   {
     return dwBytesRead;
   }
 return dwBytesRead;
}
//---------------------------------------------------------------------------
bool TForm1::WriteBytesCOM(BYTE bByte)
{
 BYTE write =0;
 DWORD dwByteWrite = 0;
 if(!WriteFile( hComm_1, &write, sizeof(BYTE), &dwByteWrite, NULL)) return false;
 return true;
}
//---------------------------------------------------------------------------
DWORD TForm1::WriteDataCOM( void* Data, unsigned int uNumBytes)
{
 DWORD dwBytesWrite =0;
 if(!WriteFile( hComm_1, Data, uNumBytes, &dwBytesWrite, NULL)) return dwBytesWrite;
 return dwBytesWrite;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button3Click(TObject *Sender)
{

 DWORD Error;





  if(SetEventCOM()!=false)
    {
     //


if(ClearCommError(hComm_1, &Error, &comstat)!=0)
   {
    Memo1->Lines->Add("CtsHold "  + IntToStr(comstat.fCtsHold));
    Memo1->Lines->Add("DsrHold "  + IntToStr(comstat.fDsrHold));
    Memo1->Lines->Add("fRlsdHold "  + IntToStr(comstat.fRlsdHold));
    Memo1->Lines->Add("XoffHold "  + IntToStr(comstat.fXoffHold));
    Memo1->Lines->Add("XoffSent "  + IntToStr(comstat.fXoffSent));
    Memo1->Lines->Add("Eof "  + IntToStr(comstat.fEof));
    Memo1->Lines->Add("Txim "  + IntToStr(comstat.fTxim));
    Memo1->Lines->Add("Reserved "  + IntToStr(comstat.fReserved));
    Memo1->Lines->Add("bInQue "  + IntToStr(comstat.cbInQue));
    Memo1->Lines->Add("OutQue "  + IntToStr(comstat.cbOutQue));
   }


     if(!WaitCommEvent( hComm_1,&dwSingnal, &over))
       {
        Memo1->Lines->Add("Событие настроено!>>>>>");
//        if(dwSingnal & EV_DSR)
//          {
           Memo1->Lines->Add("<<<<dwSingnal & EV_DSR>>>>>");
//           BYTE data = ReadByteCOM();
           char rt[128];
           DWORD dfg = ReadData_COM( &rt, sizeof(rt));
           Memo1->Lines->Add("Прочитано "  +
                             IntToStr(dfg) +
                             "\n>" +
                             AnsiString(rt)+
                             "<");

           //Memo1->Lines->Add("Событие произошло!");
#if 0
           DWORD iSize;  char temp, *text; text=&temp;

           while(true)
                {
                 ReadFile(hComm_1,&text,1,&iSize,0);
                 Memo1->Lines->Add(AnsiString(temp));
                }
#endif
//          }
       }// if(WaitCommEvent....)
   }
   else Memo1->Lines->Add("Событие не настроено!");
}
//--------------------------------------------------------------------------- 

PM MAIL   Вверх
xvr
Дата 29.4.2008, 11:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 48
Всего: 223



У тебя порт настроен на Overlapped режим, поэтому WaitCommEvent отваливает сразу с ошибкой ERROR_IO_PENDING, нужно ждать на over.hEvent пока не наступит событие. Читай MSDN на тему Overlapped ввода/вывода
И вообще асинхронный обмен так не делают - для него нужен отдельный thread (используй класс TThread), так как даже при асинхронном обмене придется ждать события (на Event'е), а любое ожидание в главном thread'е программы полностью заблокирует GUI на это время.

PM MAIL   Вверх
EEEEEE
Дата 30.4.2008, 10:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 15.5.2006

Репутация: нет
Всего: нет



xvr , спасибо за совет.
А кода нет посмотреть, извини за нескромность.
PM MAIL   Вверх
xvr
Дата 30.4.2008, 11:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 48
Всего: 223



Цитата(EEEEEE @ 30.4.2008,  10:30)
xvr , спасибо за совет.
А кода нет посмотреть, извини за нескромность.

Кода под Builder с собой нет, есть код под VC (thread для приема организуется через _beginthread, метод ConfMgr::rs232_recver вызывается в нем)
shutdown_event - Event который взводится для прерывания цикла приема

Код

void ConfMgr::rs232_recver()
{
 int tso=tstamp_options;
 int tso1=tstamp_options_rs;
 int sh=(tso>>18)&1023;
 HANDLE h[2]={shutdown_event,CreateEvent(NULL,TRUE,FALSE,NULL)};
 OVERLAPPED ovr={0,0,0,0,h[1]};

 char nm[5]="COM1";
 nm[4]+=(tso>>28)&3;

 HANDLE comp=CreateFile(nm,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
 if (comp==INVALID_HANDLE_VALUE)
  {
   error(1,"RS232 TS Recv: Can't open COM port %s",nm); return;
  }
 DCB dcb={
  sizeof(DCB),//DWORD DCBlength;           // sizeof(DCB)
  tso1&0xFFFFF,  //DWORD BaudRate;            // current baud rate
  TRUE,       //DWORD fBinary: 1;          // binary mode, no EOF check
  FALSE,      //DWORD fParity: 1;          // enable parity checking
  FALSE,      //DWORD fOutxCtsFlow:1;      // CTS output flow control
  FALSE,      //DWORD fOutxDsrFlow:1;      // DSR output flow control
  DTR_CONTROL_DISABLE,//  DWORD fDtrControl:2;       // DTR flow control type
  FALSE,      //DWORD fDsrSensitivity:1;   // DSR sensitivity
  TRUE,       //DWORD fTXContinueOnXoff:1; // XOFF continues Tx
  FALSE,      //DWORD fOutX: 1;            // XON/XOFF out flow control
  FALSE,      //DWORD fInX: 1;             // XON/XOFF in flow control
  FALSE,      //DWORD fErrorChar: 1;       // enable error replacement
  FALSE,      //DWORD fNull: 1;            // enable null stripping
  RTS_CONTROL_DISABLE,//  DWORD fRtsControl:2;       // RTS flow control
  FALSE,      //DWORD fAbortOnError:1;     // abort reads/writes on error 
  0,          //DWORD fDummy2:17;          // reserved
  0,          //WORD wReserved;            // not currently used
  0,          //WORD XonLim;               // transmit XON threshold
  0,          //WORD XoffLim;              // transmit XOFF threshold
  8,          //BYTE ByteSize;             // number of bits/byte, 4-8 
  (tso1>>20)&3,//BYTE Parity;               // 0-4=no,odd,even,mark,space 
  TWOSTOPBITS,//BYTE StopBits;             // 0,1,2 = 1, 1.5, 2 
  0,          //char XonChar;              // Tx and Rx XON character 
  0,          //char XoffChar;             // Tx and Rx XOFF character
  0,          //char ErrorChar;            // error replacement character
  0,          //char EofChar;              // end of input character 
  0,          //char EvtChar;              // received event character 
  0           //WORD wReserved1;           // reserved; do not use
 };
 if (!SetCommState(comp,&dcb)) 
  {
   CloseHandle(comp);
   error(1,"RS232 TS Recv: Can't set COM port parameters");
   return;
  }

 COMMTIMEOUTS ctout = {0,0,0,0,0};
 if (!SetCommTimeouts(comp,&ctout))
  error(1,"RS232 TS Recv: Can't set COM port timeouts");
 SetupComm(comp,1,1);
 
 int last_recv=-1;
 unsigned lr_ts=0;
 bool is_error=false;
 unsigned error_count=0;

 for(;;)
  {
   char buf; unsigned ts; DWORD rd;

   if (!is_error) error_count>>=1; else
    {
     is_error=false; error_count++;
     if (error_count>1000)
      {
       error(1,"RS232 TS Recv: Error rate too high, giving up!");
       break;
      }
    }
    

   ResetEvent(h[1]);
   if (ReadFile(comp,&buf,1,&rd,&ovr)) ts=get_tmark(NULL,0); else
   if (GetLastError()==ERROR_IO_PENDING)
    {
     DWORD res=WaitForMultipleObjects(2,h,FALSE,INFINITE);
     ts=get_tmark(NULL,0);
     if (res!=WAIT_OBJECT_0+1) {CancelIo(comp); break;}
     if (!GetOverlappedResult(comp,&ovr,&rd,FALSE))
      {
       error(1,"RS232 TS Recv: Error reading COM port");
       is_error=true; continue;
      }
    }
   else
    {
     error(1,"RS232 TS Recv: Error reading COM port");
     is_error=true; continue;
    }
   if (!rd) continue;
   ts-=sh;
   DWORD cerr=0;
   ClearCommError(comp,&cerr,0);
   if (cerr)
    {
     is_error=true;
     if (cerr!=CE_RXPARITY) {error(1,"RS232 TS Recv: Error (%x) on RS232 port detected",cerr); continue;}
     error(1,"RS232 TS Recv: Parity error detected");
     if (last_recv!=-1)
      {
       send_mic_ts(last_recv,lr_ts);
       last_recv=-1;
      }
     continue;
    } 
   if (!(buf&0x80)) {last_recv=buf; lr_ts=ts; continue;}
   buf&=0x7F;
   if (last_recv==-1) {send_mic_ts(buf,ts); continue;}
   if (buf!=last_recv)
    {
     error(1,"RS232 TS Recv: MIC indexes missmatch %d/%d",last_recv,buf);
     last_recv=-1; is_error=true; continue;
    }
   send_mic_ts(buf,eval_tmark(lr_ts,ts));
   last_recv=-1;    
  }
 CloseHandle(comp); 
}

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0821 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.