![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
Всем доброго времени суток.
Опишу все вкратце Задача такова: на порт приходят приерно раз в секунду несколько байтов данных использую с++ builder 6 (пробовал этот же проект в 2010 , ситуация та же), пользуюсь функциями из SDK(правильно ли оперирую терминами , поправьте если что) код собран из примеров http://msdn.microsoft.com/en-us/library/ms810467.aspx может важно а может нет - на компьютере нет com порта!! , для эмуляции всего процесса используется программа VSPD которая создает два порта и программа PROTEUS которая эмулирует устройство на эти вещи не грешу - изначально делал в NONOVERLAPPED режиме и данные читались без проблем НО как оказалось, это дубовый способ, ибо я жду прерывания (раз в секунду же) , а если ничего не приходит (сломалось устройство оторвался провод...) то функция WaitCommEvent будет ждать ждать ждать... причем если делать чтение в отделном потоке а потом его пытатся завершить то виснет и основной поток поэтому решил делать в OVERLAPPED режиме(ну и тоже в отделном потоке) , но тут возникает непонятная проблема - вроде все как показано на ссылке выше, НО функция чтения ReadFile возвращает false а функция GetLastError возвращает 998 ошибку (error_noaccess) порядок действий в коде ниже таков: создаем хендл для чтения (типа открываем файл с именем "COM7" скажем) устнавливаем настройки (может тут где проблема) bcb структура , временные интервалы для чтения, тип прерывания,OVERLAPPED структура далее в цикле WaitCommEvent возвращает ERROR_IO_PENDING и начинаем ждать функцией WaitForSingleObject когда они прибудут данные прибыли , функция возвратила WAIT_OBJECT_0 и мы ждем функцией GetOverlappedResult когда будут прочитан байт вот тут самое интересное - функция возвращает true и numbytes_ok содержит "4" ,хотя во-первых я посылаю 6 байт(5 и символ перевода строки) а во-вторых GetOverlappedResult выполняется после каждого принятого байта причем читается всего 5 байтов!! вызываем функцию ReadFile , она возвращает FALSE а GetLastError возвращает ошибку 998(error_noaccess) numbytes_ok после этого равна 0 и причем numbytes_ok = 4 устанавливается после первого же принятого байта (точнее после первого захода в WAIT_OBJECT_0 из пяти между секундными интервалами) какие либо перестановки в коде ничего толком не дали, если все элементы не принадлежащие потоку засунуть в метод и вызывать через Synchronize то ситуация все та же в общем наверно где-то допустил тупую ошибку и прошу беглым взглядом проверить сведущих людей данный код заранее спасибо! Код:
DCB dcb;
_COMSTAT ComState;
DWORD numbytes_ok;
DWORD dwEvtMask;
HANDLE hCom = CreateFile( portName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0
);
READ = GetCommState(hCom, &dcb);
dcb.BaudRate = 9600;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
READ = SetCommState( hCom, &dcb );
COMMTIMEOUTS CT;
GetCommTimeouts( hCom, &CT) ;
CT.ReadIntervalTimeout = 1;
CT.ReadTotalTimeoutMultiplier = MAXDWORD;
CT.ReadTotalTimeoutConstant = MAXDWORD;
SetCommTimeouts( hCom, &CT );
if (!SetCommMask(hCom,EV_RXCHAR))
Form1->Memo1->Lines->Add("error setting communications mask; abort");
int STATUS_CHECK_TIMEOUT =1300 ; // Milliseconds
DWORD dwCommEvent;
BOOL fWaitingOnStat = FALSE;
OVERLAPPED osStatus ;
osStatus.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osStatus.hEvent == NULL)
Form1->Memo1->Lines->Add("error creating event; abort");
if(READ)Form1->Memo1->Lines->Append("ОК");
char *buf_in;
while (!Thr->Terminated && READ)
{
if (!fWaitingOnStat && !Thr->Terminated)
{
if (!WaitCommEvent(hCom, &dwCommEvent, &osStatus))
{
if (GetLastError() == ERROR_IO_PENDING)
{
Form1->Memo1->Lines->Add("ERROR_IO_PENDING");
fWaitingOnStat = TRUE;
// Form1->Memo1->Lines->Add(AnsiString(numbytes_ok)+" "+ "0");
}
else
{
Form1->Memo1->Lines->Add(" error in WaitCommEvent; abort");
break;
}
}
else
{
Form1->Memo1->Lines->Add("WaitCommEvent returned immediately");
}
}
// Check on overlapped operation.
if (fWaitingOnStat && READ)
{
switch(WaitForSingleObject(osStatus.hEvent, STATUS_CHECK_TIMEOUT))
{
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hCom, &osStatus, &numbytes_ok, TRUE))
{
Form1->Memo1->Lines->Add("An error occurred in the overlapped operation");
}
else
{
/////////////////////////////////////////////////////////////////////////////////READING
if(ReadFile(hCom, buf_in, 1, &numbytes_ok, &osStatus))
{
Form1->Memo1->Lines->Add(buf_in);
}
else
{
Form1->Memo1->Lines->Add(GetLastError());
}
Form1->Memo1->Lines->Add(numbytes_ok);
}
fWaitingOnStat = FALSE;
break;
case WAIT_TIMEOUT:
Form1->Memo1->Lines->Add("WAIT_TIMEOUT");
break;
default:
Form1->Memo1->Lines->Add("CloseHandle");
CloseHandle(osStatus.hEvent);
}
}
} |