Tuborg
Команда клуба
Offline
|
|
« : 21-02-2008 09:23 » |
|
создаю хэндл порта: CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); читаю порт (пока один раз на запуске) void CSerialPort::ReadEx(void* lpBuf, DWORD dwCount) { ASSERT(IsOpen());
OVERLAPPED* pOverlapped = new OVERLAPPED; ZeroMemory(pOverlapped, sizeof(OVERLAPPED)); pOverlapped->hEvent = (HANDLE) this; if (!ReadFileEx(m_hComm, lpBuf, dwCount, pOverlapped, _OnCompletion)) { delete pOverlapped; TRACE(_T("Failed in call to ReadFileEx\n")); AfxThrowSerialException(); } } Хочу чтобы как только приходил какой-нибудь байтик в порт, тут же запускалась CALL-BACK функция _OnCompletion: void CSerialPort::_OnCompletion(DWORD dwErrorCode, DWORD dwCount, LPOVERLAPPED lpOverlapped) { //Validate our parameters ASSERT(lpOverlapped);
//Convert back to the C++ world CSerialPort* pSerialPort = (CSerialPort*) lpOverlapped->hEvent; ASSERT(pSerialPort->IsKindOf(RUNTIME_CLASS(CSerialPort)));
//Call the C++ function pSerialPort->OnCompletion(dwErrorCode, dwCount, lpOverlapped); } ставлю внутрь _OnCompletion breakpoint но управление к этой функции так и не передается, что я не пытаюсь запихнуть в порт. В Синхронном режиме всё работает нормально. Где я не прав?
|
|
|
Записан
|
|
|
|
v2
Помогающий
Offline
|
|
« Ответ #1 : 21-02-2008 14:04 » |
|
//?? Тут вроде должен быть Event pOverlapped->hEvent = (HANDLE) this; Из MSDN VOID [b]CALLBACK[/b] FileIOCompletionRoutine( DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped );
PS. IOCompletionRoutine не лучший вариант.
|
|
|
Записан
|
|
|
|
|
v2
Помогающий
Offline
|
|
« Ответ #3 : 21-02-2008 14:47 » |
|
Например WaitForMultipleObjects в отдельном потоке, куда и указатель передать можно.
/**/ startTh pVoid
readEv,commEv,sendEv,endEv
WaitCommEvent ReadFile
while 1 WaitForMultipleObjects sendEv -> OnSendEn; readEv -> OnReadEn, ReadFile; commEv -> OnCommEv, WaitCommEvent; endEv -> break;
CloseHandles endTh /**/
|
|
|
Записан
|
|
|
|
|
v2
Помогающий
Offline
|
|
« Ответ #5 : 21-02-2008 14:55 » |
|
Да, с этим проблем нет.
|
|
|
Записан
|
|
|
|
Tuborg
Команда клуба
Offline
|
|
« Ответ #6 : 27-02-2008 16:20 » |
|
приватные переменные класса: DWORD dwEvtMask; OVERLAPPED m_overlapped; HANDLE m_hComm;
при открытии порта делаю следующее: bool Open(...){
m_hComm = CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED);
m_overlapped.hEvent = CreateEvent( NULL, // default security attributes FALSE, // auto reset event FALSE, // not signaled NULL // no name );
// Intialize the rest of the OVERLAPPED structure to zero. m_overlapped.Internal = 0; m_overlapped.InternalHigh = 0; m_overlapped.Offset = 0; m_overlapped.OffsetHigh = 0; .... }
в параллельном потоке на каждый из ком-портов (4 их у меня) делаю следующее: if (WaitCommEvent(m_hComm, &dwEvtMask, &m_overlapped)) { printf("I/O ...\n"); if (dwEvtMask & EV_RXCHAR) { // To do. }
if (dwEvtMask & EV_TXEMPTY) { // To do. } } else { DWORD dwRet = GetLastError(); if( ERROR_IO_PENDING == dwRet) { printf("I/O is pending...\n");
// To do. } else printf("Wait failed with error %d.\n", GetLastError()); }
при посылки байтиков в ком-порт строка printf("I/O ...\n"); не работает, ставил туда даже breakpoint. Всё время переходит по else. Почему не работает? О чём я забыл?
|
|
|
Записан
|
|
|
|
Scorp__)
Молодой специалист
Offline
Пол:
|
|
« Ответ #7 : 27-02-2008 17:31 » |
|
По-моему, SetCommMask неплохо бы еще сделать При инициализации.
|
|
« Последнее редактирование: 27-02-2008 17:34 от Scorp__) »
|
Записан
|
- А Вы сами-то верите в привидения? - Конечно, нет, - ответил лектор и медленно растаял в воздухе.
|
|
|
|
v2
Помогающий
Offline
|
|
« Ответ #9 : 27-02-2008 20:44 » |
|
А в M$ только ошибки ждут ... else { DWORD dwRet = GetLastError(); if( ERROR_IO_PENDING == dwRet) { printf("I/O is pending...\n");
// To do. } ...
Если у тебя много портов, смотри в сторону CreateIoCompletionPort и задай timeouts чтобы не дергаться за каждым байтом.
|
|
|
Записан
|
|
|
|
v2
Помогающий
Offline
|
|
« Ответ #10 : 27-02-2008 21:11 » |
|
ERROR_IO_PENDING эта "ошибка" почти всегда после OVERLAPPED Read/Write/..
|
|
|
Записан
|
|
|
|
|
lag
Участник
Offline
|
|
« Ответ #12 : 02-03-2008 12:52 » |
|
я не применяю здесь объекты ядра, а делаю так:
COMMTIMEOUTS cto; cto.ReadIntervalTimeout = 1; cto.ReadTotalTimeoutConstant = g_dwCommTimeout; cto.ReadTotalTimeoutMultiplier = 0; cto.WriteTotalTimeoutConstant = 30; cto.WriteTotalTimeoutMultiplier = 0; SetCommTimeouts(g_hComm, &cto);
g_dwCommTimeout - задает константу, в миллисекундах, используемую для вычисления общего тайм-аута операции чтения.
ReadIntervalTimeout - максимальное время, в миллисекундах, допустимое между двумя последовательными символами считываемыми с коммуникационной линии.
Определив таким образом, делаю просто - WriteFile и сразу ReadFile. Конечно в моем случае я знаю, что данные (ответ) должны быть получены не более чем через g_dwCommTimeout миллисекунд.
Если же я просто слушаю порт, то в отдельном потоке:
while (!ReadFile(...)) Sleep(1); // чтобы не нагружать процессор
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #13 : 02-03-2008 13:23 » |
|
lag, while (!ReadFile(...)) - потеряешь первый (как минимум) байт. Тогда уж надо его запомнить - и добавить в начало буфера, куда будешь читать остальное
|
|
|
Записан
|
|
|
|
lag
Участник
Offline
|
|
« Ответ #14 : 03-03-2008 07:28 » |
|
Ну так я и не стал дописывать, что я делаю после приема данных. У каждого ведь свои задачи после чтения. Реально я собираю данные и разбираю по пакетам. Затем анализирую каждый пакет и выделяю нужное в соответствии с протоколом. Я описываю, что не всегда надо задействовать WaitFor...Object - компорт нам сам дает возможность принять все данные за g_dwCommTimeout миллисекунд. Надо только грамотно установить таймауты. По крайней мере меня устраивает, как это работает в моей задаче и с моим протоколом.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #15 : 03-03-2008 07:38 » |
|
а я тоже так делаю, кстати ) Без событий - просто суюсь в порт и смотрю, идёт что нибудь или нет. События пока даже не приходилось использовать
|
|
|
Записан
|
|
|
|
|
|