Работа с COM и LPT в Win32.
Шрифт:
fXoffHold
Передача приостановлена из-за приема символа XOFF.
fXoffSent
Передача приостановлена из-за передачи символа XOFF. Следующий передаваемый символ обязательно должен быть XON, поэтому передача собственно данных тоже приостанавливается
fEof
Принят символ конца файла (EOF).
fTxim
В очередь, с помощью TransmitCommChar, поставлен символ для экстреной передачи.
fReserved
Зарезервировано и не используется.
cbInQue
Число символов в приемном буфере. Эти символы приняты из линии но еще не считаны функцией ReadFile.
cbOutQue
Число
Теперь Вы знаете почти все о работе с последовательными и параллельными портами в синхронном режиме. Особенности непосредственной работы с модемами я не буду рассматривать, так как существует большой набор высокоуровневых функций и протоколов, таких как TAPI, специально предназначеных для работы с модемами. Если Вас все же интересует эта тема, то почитайте описания функции GetCommModemStatus, и структур MODEMDEVCAPS и MODEMSETTINGS. В остальном работа с модемом ничем не отличается от работы с обычным портом.
Синхронный режим обмена довольно редко оказывается подходящим для серьезной работы с внешними устройствами через последовательные порты. Вместо полезной работы Ваша программа будет ждать завершения ввода/вывода, ведь порты работают значительно медленнее процессора. Да и гораздо лучше отдать время процессора другой программе, чем крутиться в цикле ожидая какого-либо события. Другими словами, пришло время знакомиться с асинхронной работой с портами.
Начнем с событий связаных с последовательными портами. Вы указываете системе осуществлять слежение за возникновением связанных с портом событий устанавливая маску с помощью функции
Маска отслеживаемых событий задается вторым параметром. Можно указывать любую комбинацию следующих значений:
EV_BREAK | Состояние разрыва приемной линии |
EV_CTS | Изменение состояния линии CTS |
EV_DSR | Изменение состояния линии DSR |
EV_ERR | Ошибка обрамления, перебега или четности |
EV_RING | Входящий звонок на модем (сигнал на линии RI порта) |
EV_RLSD | Изменение состояния линии RLSD (DCD) |
EV_RXCHAR | Символ принят и помещен в приемный буфер |
EV_RXFLAG | Принят символ заданый полем EvtChar структуры DCB использованой для настройки режимов работы порта |
EV_TXEMPTY | Из буфера передачи передан последний символ |
Если dwEvtMask равно нулю, то отслеживание событий запрещается. Разумеется всегда можно получить текущую маску отслеживаемых событий с помощью функции
Вторым параметром задается адрес переменной принимающей значение текущей установленой маски отслеживаемых событий. В дополнение к событиям, перечисленым в описании функции SetCommMask, данная функция может возвратить следующие:
EV_EVENT1 | Устройство-зависимое событие |
EV_EVENT2 | Устройство-зависимое
|
EV_PERR | Ошибка принтера |
EV_RX80FULL | Приемный буфер заполнен на 80 процентов |
Эти дополнительные события используются внутри драйвера. Вы не должны переустанавливать состояние их отслеживания.
Когда маска отслеживаемых событий задана, Вы можете приостановить выполнение своей программы до наступления события. При этом программа не будет занимать процессор. Это выполняется вызовом функции
Замечу, что в переменной, адресуемой вторым параметром, не будут устанавливаться внутренние события драйвера (перечислены в описании функции GetCommMask). В единичное состояние установятся только те биты, которые соответствуют реально произошедшим событиям.
Адрес структуры OVERLAPPED требуется для асинхронного ожидания (возможно и такое). Однако пока будем полагать, что порт открыт для синхронных операций, следовательно этот параметр должен быть NULL. Замечу только, что при асинхронном ожидании данная функция может завершиться с ошибкой, если в процессе этого ожидания будет вызвана функция SetCommMask для переустановки маски событий. Кроме того, связанное со структурой OVERLAPPED событие (объект создаваемый функцией CreateEvent, а не событие порта) должно быть с ручным сбросом. Вообще, поведение функции с ненулевым указателем на структуру OVERLAPPED аналогично поведению функций чтения и записи. Теперь коротенький пример:
В данном примере ожидается начало сообщения (первый полученый символ), после чего вызывается функция чтения.
Освобождать процессор на время ожидания хорошо, но хотелось бы параллельно с вводом/выводом делать какую-либо полезную работу. Что бы это стало возможным, необходимо в качестве параметра dwFlagsAndAttributes вместо 0 указать FILE_FLAG_OVERLAPPED. Кроме того, для функций ReadFile, WriteFile и WaitCommEvent необходимо в качестве параметра lpOverlapped указывать адрес правильно инициализированной структуры OVERLAPPED. Вот как выглядит эта структура: