2-РПЗ (1061363), страница 3
Текст из файла (страница 3)
DWORD fRlsdHold:1;
DWORD fXoffHold:1;
DWORD fXoffSent:1;
DWORD fEof:1;
DWORD fTxim:1;
DWORD fReserved:25;
DWORD cbInQue;
DWORD cbOutQue;
} COMSTAT.
Кратко рассмотрим значения ее полей:
fCtsHold — Передача приостановлена из-за сброса сигнала CSR.
fDsrHold — Передача приостановлена из-за сброса сигнала DSR.
fRlsdHold — Передача приостановлена из-за ожидания сигнала RLSD (receive-line-signal-detect). Более известное название данного сигнала - DCD (обнаружение несущей).
fXoffHold — Передача приостановлена из-за приема символа XOFF.
fXoffSent — Передача приостановлена из-за передачи символа XOFF. Следующий передаваемый символ обязательно должен быть XON, поэтому передача собственно данных тоже приостанавливается.
fEof — Принят символ конца файла (EOF).
fTxim — В очередь, с помощью TransmitCommChar, поставлен символ для экстреной передачи.
fReserved — Зарезервировано и не используется.
cbInQue — Число символов в приемном буфере. Эти символы приняты из линии но еще не считаны функцией ReadFile.
cbOutQue — Число символов в передающем буфере. Эти символы ожидают передачи в линию. Для синхронных операций всегда 0.
2.3Структура OVERLAPPED.
Структура необходима при выполнении асинхронных операций ввода/вывода и ожидании событий от порта (п. 4.6).
Структура имеет следующее объявление:
typedef struct _OVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
HANDLE hEvent;
} OVERLAPPED.
Кратко рассмотрим значения ее полей:
Internal — Зарезервировано для использования операционной системой. Это поле, которое определяет системозависимый статус, используется, когда функция GetOverlappedResult завершается без установления ошибки в значение ERROR_IO_PENDING.
InternalHigh — Зарезервировано для использования операционной системой. Это поле, которое определяет количество переданных байт, используется, когда функция GetOverlappedResult возвращает TRUE.
Offset — Определяет позицию в файле, с которой начнется передача. Позиция в файле это смещение в байтах от начала файла. Вызывающий процесс устанавливает это поле перед вызовом функций ReadFile и WriteFile. Это поле игнорируется при чтении из или записи в именованный канал или коммуникационное устройство.
OffsetHigh — Определяет старшее слово позиции в файле, с которой начнется передача. Это поле игнорируется при чтении из или записи в именованный канал или коммуникационное устройство.
hEvent — Определяет событие для сигнализации состояния когда передача закончена. Вызывающий процесс устанавливает это поле перед вызовом функций ReadFile, WriteFile, ConnectNamedPipe или TransactNamedPipe.
3Функции для работы с COM-портом, которые предоставляет WIN32 API.
3.0Функции открытия/закрытия COM-порта.
В Win32 нет функций для непосредственной работы с последовательными и параллельными портами, поэтому с ними работают работают как с файлами. Для этого необходимо воспользоваться функцией открытия файла CreateFile. Ее прототип выглядит так:
HANDLE CreateFile(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDistribution,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
Приведем краткое описание параметров:
lpFileName — Указатель на строку с именем открываемого или создаваемого файла. Последовательные порты имеют имена "COM1", "COM2", "COM3", "COM4" и так далее. Точно так же они назывались в MS-DOS, так что ничего нового тут нет.
dwDesiredAccess — Задает тип доступа к файлу. Возможно использование следующих значений:
| 0 | Опрос атрибутов устройства без получения доступа к нему. |
| GENERIC_READ | Файл будет считываться. |
| GENERIC_WRITE | Файл будет записываться. |
| GENERIC_READ|GENERIC_WRITE | Файл будет и считываться и записываться. |
dwShareMode — Задает параметры совместного доступа к файлу. Коммуникационные порты нельзя делать разделяемыми, поэтому данный параметр должен быть равен 0.
lpSecurityAttributes — Задает атрибуты защиты файла. Поддерживается только в Windows NT. Однако при работе с портами должен в любом случае равняться NULL.
dwCreationDistribution — Управляет режимами автосоздания, автоусечения файла и им подобными. Для коммуникационных портов всегда должно задаваться OPEN_EXISTING.
dwFlagsAndAttributes — Задает атрибуты создаваемого файла. Так же управляет различными режимами обработки. Для наших целей этот параметр должен быть или равным 0, или FILE_FLAG_OVERLAPPED. Нулевое значение используется при синхронной работе с портом, а FILE_FLAG_OVERLAPPED при асинхронной, или другими словами, при фоновой обработке ввода/вывода.
hTemplateFile — Задает описатель файла-шаблона. При работе с портами всегда должен быть равен NULL.
При успешном открытии файла, в нашем случае порта, функция возвращает описатель (HANDLE) файла. При ошибке INVALID_HANDLE_VALUE. Код ошибки можно получить вызвав функцию GetLastError.
Открытый порт должен быть закрыт перед завершением работы программы. В Win32 закрытие объекта по его описателю выполняет функция CloseHandle:
BOOL CloseHandle(
HANDLE hObject
);
Функция имеет единственный параметр - описатель закрываемого объекта. При успешном завершении функция возвращает не нулевое значение, при ошибке нуль
3.1Функции записи/чтения COM-порта.
Прием и передача данных выполняется функциями ReadFile и WriteFile, то есть теми же самыми, которые используются для работы с дисковыми файлами. Прототипы этих функций выглядят так:
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumOfBytesToRead,
LPDWORD lpNumOfBytesRead,
LPOVERLAPPED lpOverlapped
);
BOOL WriteFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumOfBytesToWrite,
LPDWORD lpNumOfBytesWritten,
LPOVERLAPPED lpOverlapped
);
hFile — Описатель открытого файла коммуникационного порта.
lpBuffer — Адрес буфера. Для операции записи данные из этого буфера будут передаваться в порт. Для операции чтения в этот буфер будут помещаться принятые из линии данные.
nNumOfBytesToRead, nNumOfBytesToWrite — Число ожидаемых к приему или предназначеных к передаче байт.
nNumOfBytesRead, nNumOfBytesWritten — Число фактически принятых или переданых байт. Если принято или передано меньше данных, чем запрошено, то для дискового файла это свидетельствует об ошибке, а для коммуникационного порта совсем не обязательно. Причина в тайм-аутах.
lpOverlapped — Адрес структуры OVERLAPPED, используемой для асинхронных операций. Для синхронных операций данный параметр должен быть равным NULL.
3.2Функции управления приемом/передачей COM-порта.
Функция PurgeComm сбрасывает порт. Ее прототип выглядит так:
BOOL PurgeComm(
HANDLE hFile,
DWORD dwFlags
);
Вызов этой функции позволяет решить две задачи: очистить очереди приема/передачи в драйвере и завершить все находящиеся в ожидании запросы ввода/вывода. Какие именно действия выполнять, задается вторым параметром (значения можно комбинировать с помощью побитовой операции OR):
| PURGE_TXABORT | Немедленно прекращает все операции записи, даже если они не завершены |
| PURGE_RXABORT | Немедленно прекращает все операции чтения, даже если они не завершены |
| PURGE_TXCLEAR | Очищает очередь передачи в драйвере |
| PURGE_RXCLEAR | Очищает очередь приема в драйвере |
-
Реализация асинхронного обмена информацией.
Синхронный режим обмена довольно редко оказывается подходящим для серьезной работы с внешними устройствами через последовательные порты. Вместо полезной работы Ваша программа будет ждать завершения ввода/вывода, ведь порты работают значительно медленнее процессора. Да и гораздо лучше отдать время процессора другой программе, чем крутиться в цикле, ожидая какого-либо события. Следовательно, нужно работать в асинхронном режиме с портами.
Начать нужно с событий, связанных с последовательными портами. Нужно указать системе, осуществлять слежение за возникновением связанных с портом событий, устанавливая маску с помощью функции:
BOOL SetCommMask(
HANDLE hFile,
DWORD dwEvtMask
);
Маска отслеживаемых событий задается вторым параметром. Можно указывать любую комбинацию следующих значений:
| 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 равно нулю, то отслеживание событий запрещается. Всегда можно получить текущую маску отслеживаемых событий с помощью функции:
BOOL GetCommMask(
HANDLE hFile,
LPDWORD lpEvtMask
);
Вторым параметром задается адрес переменной, принимающей значение текущей установленной маски отслеживаемых событий. В дополнение к событиям, перечисленным в описании функции SetCommMask, данная функция может возвратить следующие:
| EV_EVENT1 | Устройство-зависимое событие |
| EV_EVENT2 | Устройство-зависимое событие |
| EV_PERR | Ошибка принтера |
| EV_RX80FULL | Приемный буфер заполнен на 80 процентов |
Эти дополнительные события используются внутри драйвера. Вы не должны переустанавливать состояние их отслеживания.
Когда маска отслеживаемых событий задана, можно приостановить выполнение своей программы до наступления события. При этом программа не будет занимать процессор. Это выполняется вызовом функции:
BOOL WaitCommEvent(
HANDLE hFile,
LPDWORD lpEvtMask,
LPOVERLAPPED lpOverlapped,
);
Замечу, что в переменной, адресуемой вторым параметром, не будут устанавливаться внутренние события драйвера (перечислены в описании функции GetCommMask). В единичное состояние установятся только те биты, которые соответствуют реально произошедшим событиям.
Адрес структуры OVERLAPPED требуется для асинхронного ожидания (возможно и такое). Замечу только, что при асинхронном ожидании данная функция может завершиться с ошибкой, если в процессе этого ожидания будет вызвана функция SetCommMask для переустановки маски событий. Кроме того, связанное со структурой OVERLAPPED событие (объект создаваемый функцией CreateEvent, а не событие порта) должно быть с ручным сбросом. Вообще, поведение функции с ненулевым указателем на структуру OVERLAPPED аналогично поведению функций чтения и записи.
Описание функции CreateEvent выглядит так:
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,















