Работа с модемом через Win API
От: Dakkar  
Дата: 20.04.03 11:07
Оценка:
Я нашёл несколько тем со схожими вопросами, однако в определённых моментах так и не разобрался.
Хочется работать с модемам не через TAPI, а передавая и принимая данные в COM-порт и из порта. Собственно, для начала была написана простая программа без обработки ошибок и с асинхронной моделью доступа, текст привожу ниже:

DCB ComDCB;
COMMTIMEOUTS CT;
HANDLE hComPort;
char* InputBuf;
char* OutputBuf = "ATZ\r";
OVERLAPPED OVRL;
DWORD mask;
DWORD bc;

//Заполнение структуры DCB
ComDCB.DCBlength = sizeof(DCB);
BuildCommDCB("baud=9600 parity=N data=8 stop=1", &ComDCB);

//Установка time-out'ов — используется только ограничение на время между началом приёма двух символов
CT.ReadIntervalTimeout = 100;
CT.ReadTotalTimeoutMultiplier = CT.ReadTotalTimeoutConstant = 0;
CT.WriteTotalTimeoutMultiplier = CT.WriteTotalTimeoutConstant = 0;

//Открываем порт, используется асинхронный режим обмена
hComPort=CreateFile("COM3", GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

//Сбрасываем события
ZeroMemory(&OVRL, sizeof(OVRL));
OVRL.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

//Установка параметров порта
SetCommState(hComPort, &ComDCB);
SetCommTimeouts(hComPort, &CT);
//Очистка порта
PurgeComm(hComPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR
| PURGE_RXCLEAR);
//Установление максимальной рекомендуемой длины сообщений
SetupComm(hComPort, 256, 256);

//Выделение памяти под принимаемую от модема строку — на 10 символов больше отправляемой
InputBuf = (char*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
strlen(OutputBuf) + 11);

//Запись строки в порт
WriteFile(hComPort, OutputBuf, strlen(OutputBuf), &bc, &OVRL);

//Ожидание окончания операции
if(WaitForSingleObject(OVRL.hEvent, 1000) == WAIT_OBJECT_0)
{
GetOverlappedResult(hComPort, &OVRL, &bc, FALSE);
}
else
{
//Выход по time-out'у
ShowMessage("Unable to write to port!");
CloseHandle(hComPort);
CloseHandle(OVRL.hEvent);
return;
}

//Сброс события
ZeroMemory(&OVRL, sizeof(OVRL));
OVRL.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

//Чтение строки из порта — читаем на 10 символов больше, чем записали
ReadFile(hComPort, InputBuf, strlen(OutputBuf) + 10, &bc, &OVRL);

//Ожидание окончания операции
if(WaitForSingleObject(OVRL.hEvent, 1000) == WAIT_OBJECT_0)
{
GetOverlappedResult(hComPort, &OVRL, &bc, FALSE);
}
else
{
//Выход по time-out'у
ShowMessage("Unable to read from port!");
CloseHandle(hComPort);
CloseHandle(OVRL.hEvent);
return;
}

//Вывод принятой строки
ShowMessage(InputBuf);

//Освобождение занятой памяти и закрытие порта
HeapFree(GetProcessHeap(), 0, InputBuf);
CloseHandle(hComPort);
CloseHandle(OVRL.hEvent);

Проблема заключается в том, что при первом вызове функции выходим по time-out'у с сообщением "Unable to read from port!". Такая ситуация сохраняется, если вызвать функцию ещё раз пять, затем получаем правильный результат — отправленную строку + ОК от модема. Собственно, не совсем понятно, почему первые попытки заканчиваются неудачей. Также время от времени выход по time-out'у происходит, если продолжать вызывать функцию и по получении корректного сообщения от модема.

Спасибо за ответ!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.