Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[5]

Познакомимся с параметрами функции CommConfigDialog:

lpszName

Указатель на строку с именем порта, для которого отображается диалоговое окно. К реальному имени порта эта строка не имеет никакого отношения, она просто выводится в заголовке окна.

Описатель окна, которое владеет данным диалоговым окном. Должен быть передан корректный описатель окна-владельца или NULL, если у диалогового окна нет владельца.

Указатель на структуру COMMCONFIG. Эта структура содержит начальные установки, используемые для отображения в диалоговом окне, и установленные пользователем изменения, при завершении диалога.

Как и большинство других функций Win32 API, функция CommConfigDialog возвращает отличное от нуля значение, в случае успешного завершения, и нуль, если возникла ошибочная ситуация.

Функция CommConfigDialog не выполняет настройки порта. Она все лишь позволяет пользователю изменить некоторые поля в блоке DCB, содержащемся в структуре COMMCONFIG. Разумеется, Вы можете изменить установленные пользователем некорректные значения или выполнить дополнительные настройки после вызова функции GetCommConfig.

Функция SetCommConfig

Фактическая настройка порта выполняется функцией SetCommConfig:

BOOL SetCommConfig(

HANDLEhCommDev,

LPCOMMCONFIG lpCC, DWORDdwSize

Параметры имеют то же самое значение, как и в функции GetCommConfig. Следует заметить, что описанные три функции позволяют настраивать и некоторые параметры модема, если он подключен к порту и опознан системой. Впрочем, эта возможность может отсутствовать, если она не предусмотрена производителем оборудования.

Функции GetDefaultCommConfig и SetDegaultCommConfig

Обратите внимание на кнопку "Restore Defaults". Вы в состоянии управлять ее поведением, правда опосредовано, с помощью функций GetDefaultCommConfig и SetDegaultCommConfig. Вот их прототипы:

BOOL GetDefaultCommConfig( LPCSTRlpszName,

LPCOMMCONFIG lpCC, LPDWORDlpdwSize

BOOL SetDefaultCommConfig( LPCSTRlpszName,

LPCOMMCONFIG lpCC, DWORDdwSize

Эти функции очень похожи на GetCommConfig и SetCommConfig, но предназначены совсем для другой цели. Предположим, что Ваше устройство, по умолчанию, работает на скорости 175 бит в секунду и обменивается пятибитными символами. Системные же умолчания - 9600 бит в секунду и 8 бит в символе. Что бы пользователь, при нажатии на кнопку "Restore Defaults", получал не системные, а Ваши умолчания, воспользуйтесь функциями GetDefaultCommConfig и SetDefaultCommConfig. SetDefaultCommConfig не настраивает порт, это выполняется функцией SetCommConfig, а изменяет параметры во внутренней области коммуникационного драйвера.

Функция SetupComm

Теперь познакомимся с функцией SetupComm, которая, на самом деле, совсем не то, что следует из названия.

BOOL SetupComm(

HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue

Эту функцию скорее следовало назвать SetCommQueueSize, поскольку все, что она делает, это устанавливает размеры (в байтах) очередей приема и передачи. Причем размеры рекомендуемые. В общем случае, система сама в состоянии определить требуемый размер очередей, однако Вы можете вмешаться в этот процесс. Внутренние оче-


реди драйвера позволяют избежать потери данных, если Ваша программа не успевает их считывать, и пауз в работе программы, если она передает данные слишком быстро. Размер очереди выбирается немного большим максимальной длины сообщения. Например, для протокола YMODEM, пакет данных которого имеет длину 1024 байт, разумным размером очереди будет 1200 байт.

Указанный Вами размер очереди будет принят драйвером к сведению. Но он оставляет за собой право внести коррективы или вообще отвергнуть устанавливаемое значение. В последнем случае функция завершится с ошибкой.

Внешние устройства управления объектами, чаще всего подключаемые к портам, обычно обмениваются с компьютером короткими сообщениями. Соответственно и вызов функции SetupComm не требуется. Однако, если Ваше устройство передает или принимает блоки данных длиной в несколько тысяч байт, рекомендуется установить размеры очередей драйвера.

Давайте сделаем паузу в изучении функций настройки и получения состояния коммуникационных портов. Пора от слов переходить к делу, а именно к приему и передаче данных. Начнем с синхронного чтения/записи, это проще.

Функцити ReadFile и WriteFile

Прием и передача данных выполняется функциями ReadFile и WriteFile, то есть теми же самыми, которые используются для работы с дисковыми файлами. Вот как выглядят прототипы этих функций:

BOOL ReadFile(

HANDLEhFile,

LPVOIDlpBuffer,

DWORDnNumOfBytesToRead,

LPDWORDlpNumOfBytesRead,

LPOVERLAPPEDlpOverlapped

BOOL WriteFile(

HANDLEhFile,

LPVOIDlpBuffer,

DWORDnNumOfBytesToWrite,

LPDWORDlpNumOfBytesWritten,

LPOVERLAPPEDlpOverlapped

Вы наверняка работали с этими функциями и знаете значение их параметров. Но я все-таки кратко остановлюсь на их описании:

Описатель открытого файла коммуникационного порта.

IpBuffer

Адрес буфера. Для операции записи данные из этого буфера будут передаваться в порт. Для операции чтения в этот буфер будут помещаться принятые из линии данные.

nNumOfBytesToRead, nN umOfBytesToWrite

Число ожидаемых к приему или предназначенных к передаче байт.

nNumOfBytesRead, nNumOfBytesWritten

Число фактически принятых или переданных байт. Если принято или передано меньше данных, чем запрошено, то для дискового файла это свидетельствует об ошибке, а для коммуникационного порта совсем не обязательно. Причина в тайм-аутах.

IpOverIapped

Адрес структуры OVERLAPPED, используемой для асинхронных операций. Подробнее как с структурой, так и с асинхронными операциями мы познакомимся позже. Для синхронных операций данный параметр должен быть равным NULL.

Еще раз коснусь темы тайм-аутов. Если Вы не используете ни общий, ни межбайтный тайм-ауты для операции чтения и внешнее устройство прекратило передачу, то Ваша программа будет вечно ждать завершения синхронной операции. Другими словами она зависнет. Аналогичный результат может быть при использовании программного или аппаратного управления потоком. Если же тайм-ауты используются, то операция чтения нормально завершится. Только количество считанных байт будет меньше количества запрошенных для чтения. Это не обязательно свидетельствует об ошибке. Например, программа может по тайм-ауту определять конец очередного блока данных. Аналогично и для операции записи, с той лишь разницей, что неполная передача данных из буфера, скорее всего, будет свидетельствовать о проблеме во внешнем устройстве. То есть будет считаться ошибкой.


Функция PurgeComm

Коммуникационный порт не совсем обычный файл. Например, для него нельзя выполнить операцию позиционирования файлового указателя. С другой стороны, порт позволяет управлять потоком, что нельзя делать с обычным файлом. Настало время познакомиться с функциями управления приемом/передачей данных через коммуникационные порты. Поскольку первой операцией, после открытия порта, является его сброс, то и начнем с функции выполняющей требуемые действия.

BOOL PurgeComm(

HANDLE hFile, DWORD dwFlags

Вызов этой функции позволяет решить две задачи: очистить очереди приема/передачи в драйвере и завершить все находящиеся в ожидании запросы ввода/вывода. Какие именно действия выполнять, задается вторым параметром (значения можно комбинировать с помощью побитовой операции OR):

•PURGE TXABORT Немедленно прекращает все операции записи, даже если они не завершены

•PURGE RXABORT Немедленно прекращает все операции чтения, даже если они не завершены

•PURGE TXCLEAR Очищает очередь передачи в драйвере

•PURGE RXCLEAR Очищает очередь приема в драйвере

Вызов этой функции нужен для отбрасывания мусора, который может находиться в приемном буфере на момент запуска программы, или как результат ошибки в работе устройства. Очистка буфера передачи и завершение операций ввода/вывода так же потребуются при ошибке, как процедура восстановления, и при завершении программы, для красивого выхода.

Функция FlushFileBuffers

Следует помнить, что очистка буфера передачи, как и экстренное завершение операции записи, не выполняют передачу данных находящихся в этом буфере. Данные просто отбрасываются. Если же передача остатка данных необходима, то перед вызовом PurgeComm следует вызвать функцию:

BOOL FlushFileBuffers( HANDLE hFile

Приведу пример выполнения настройки порта и выполнения чтения/записи данных.

#include <windows.h> #include <string.h>

DCBdcb;

COMMTIMEOUTS ct; HANDLEport;

DWORDbc;

char*buf out="Test string";

char*buf in;

dcb.DCBlength=sizeof(DCB);

BuildCommDCB("baud=9600 parity=N data=8 stop=1",&dcb);

dcb.fNull=TRUE;

ct.ReadIntervalTimeout=10;

ct.ReadTotalTimeoutMultiplier=ct.ReadTotalTimeoutConstant=0; ct.WriteTotalTimeoutMultiplier=ct.WriteTotalTimeoutConstant=0;

port=CreateFile("COM2",GENERIC READGENERIC WRITE,0,NULL,OPEN EXISTING,0,NULL

SetCommState(port,dcb); SetCommTimeouts(port,&ct);

PurgeComm(port,PURGE TXCLEARPURGE RXCLEAR);

SetupComm(port,256,256);

buf in=(char*)HeapAlloc(GetProcessHeap(),HEAP ZERO MEMORY,strlen(buf out)+1);

WriteFile(port,buf out,strlen(buf out),&bc,NULL); ReadFile(port,buf in,strlen(buf out),&bc,NULL); HeapFree(GetProcessHeap(),0,buf in); CloseHandle(port);



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7]