Олег Титов - Работа с COM и LPT в Win32. Страница 4

Тут можно читать бесплатно Олег Титов - Работа с COM и LPT в Win32.. Жанр: Компьютеры и Интернет / Программирование, год неизвестен. Так же Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте Knigogid (Книгогид) или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.

Олег Титов - Работа с COM и LPT в Win32. читать онлайн бесплатно

Олег Титов - Работа с COM и LPT в Win32. - читать книгу онлайн бесплатно, автор Олег Титов

Теперь небольшой пример. ReadTotalTimeoutMultiplier = 2, ReadTotalTimeoutConstant = 1, ReadIntervalTimeout = 1, считывается 250 символов. Если операция чтения завершится за 250 * 2 + 1 = 501 миллисекунду, то будет считано все сообщение. Если операция чтения не завершится за 501 миллисекунду, то она все равно будет завершена. При этом будут возвращены символы, прием которых завершился до истечения тайм-аута операции. Остальные символы могут быть получены следеющей операцией чтения. Если между началами двух последовательных символов пройдет более 1 миллисекунды, то операция чтения так же будет завершена.

Надеюсь, что теперь тайм-ауты не будут вызывать у Вас затруднений. Для завершения темы тайм-аутов рассмотрим один частный случай. Если поля ReadIntervalTimeout и ReadTotalTimeoutMultiplier установлены в MAXDWORD, а ReadTotalTimeoutConstant больше нуля и меньше MAXDWORD, то выполнение оперции чтения подчиняется следующим правилам:

• Если в буфере есть символы, то чтение немедленно завершается и возвращается символ из буфера;

• Если в буфере нет символов, то операция чтения будет ожидать появления любого символа, после чего она немедленно завершится;

• Если в течении времени, заданого полем ReadTotalTimeoutConstant, не будет принято ни одного символа, оперция чтения завершится по тайм-ауту.

Помните функцию BuildCommDCB? Существует еще функция BuildCommDCBAndTimeouts, которая позволяет заполнить не только структуру DCB, но и структуру COMMTIMEOUTS. Вот как выглядит ее прототип:

BOOL BuildCommDCBAndTimeouts(LPCTSTR lpDef, LPDCB lpDCB, LPCOMMTIMEOUTS lpCommTimeouts);

Как видно, у этой функции, по сравнению с BuildCommDCB, появился третий параметр. Это указатель на структуру COMMTIMEOUTS. Конфигурационная строка при вызове этой функции должна задаваться в новом формате. Если эта строка содержит подстроку "TO=ON", то устанавливаются общие тайм-ауты для операций чтения и записи. Это значения устанавливаются на основе информации о скорости передачи и формате посылки. Если конфигурационная строка содержит подстроку "TO=OFF", то устанавливается режим работы без тайм-аутов. Если конфигурационная строка не содержит подстроки "TO=xxx" или эта подстрока имеет неверное значение, то указатель на структуру COMMTIMEOUTS просто игнорируется. При этом функция BuilCommDCBAndTimeouts оказывается идентичной функции BuildCommDCB.

Параметр lpCommTimeouts должен указывать на распределенную область памяти, причем корректность этой области не проверяется. Передача нулевого указателя приводит к ошибке.

Как и для заполнения структуры DCB, для COMMTIMEOUTS существует функция считывания установленых в системе значений. Это функция GetCommTimeouts:

BOOL GetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);

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

Заполнив структуру COMMTIMEOUTS можно вызывать функцию установки тайм-аутов порта. Это функция называется SetCommTimeouts:

BOOL SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);

Параметры этой функции тоже достаточно очевидны. Установку тайм-аутов можно производить как до установки параметров порта, так и после. Последовательность вызова функций SetCommState и SetCommTimeouts не имеет никакого значения. Главное, что бы все настройки были завершены до начала ввода/вывода информации.

Теперь приведу пример настройки порта:

#include <windows.h>

. . .

DCB *dcb;

COMMTIMEOUTS ct;

HANDLE port;

. . .

dcb=(DCB*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DCB));

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_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

SetCommState(port, dcb);

SetCommTimeouts(port, &ct);

HeapFree(GetProcessHeap(), 0, dcb);

. . .

CloseHandle(port);

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

Первым делом, с помощью функции HeapAlloc, выделяется и заполняется нулями область памяти для DCB. Затем в поле DCBlength заносится размер структуры DCB в байтах. Зачем это нужно обсуждалось выше, при описании данного поля. Для общего (и наглядного) заполнения DCB использована функция BuildCommDCB. Будем считать, что нас устраивает информация занесеная в DCB, но требуется игнорировать нулевые байты при приеме. Так как BuildCommDCB не выполняет требуемых действий мы вручную изменяем соответсвующее поле. Далее мы заполняем информацию о тайм-аутах. Общие тайм-ауты операций чтения и записи не используются, конец сообщения определяется по тайм-ауту между двумя последовательными символами большему 10 миллисекунд. Теперь можно открыть порт, что делается функцией CreateFile, и выполнить его настройку вызвав функции SetCommState и SetCommTimeots. После установки параметров порта структура DCB становится не нужной, поэтому можно освободить занимаемую ей память. Структура COMMTIMEOUTS в примере размещена статически, поэтому выделять под нее память и освобждать ее не требуется. Наконец, мы закрываем порт перед завершением.

Функции HeapAlloc и HeapFree занимаются выделением и освобождением памяти из куч, которых в программе может быть несколько. Вместо этих функций можно использовать malloc (calloc) и free. Однако использование функций предоставляемых Win32 API позволяет сократить размер программы, что может быть не маловажно, если работа с портами ведется из DLL (например Вы пишете своеобразный псевдодрайвер для своего устройства). Есть и другие аргументы в пользу этой точки зрения, которую я Вам, впрочем, не навязываю.

Рассмотренные структуры и функции позволяют программировать порт на достаточно низком уровне. Их, в большинстве случаев, более чем достаточно даже для тонкой настройки порта. Однако бывают и исключения. Например, под именем COM1 может скрываться вовсе не привычный порт RS-232, а какая-нибудь экзотика. Или порт может не позволять задавать скорость более 9600.

Исчерпывающая информация о возможностях коммуникационного устройства и драйвера содержится в структуре COMMPROP:

typedef struct _COMMPROP {

 WORD  wPacketLength;       // packet size, in bytes

 WORD  wPacketVersion;      // packet version

 DWORD dwServiceMask;       // services implemented

 DWORD dwReserved1;         // reserved

 DWORD dwMaxTxQueue;        // max Tx bufsize, in bytes

 DWORD dwMaxRxQueue;        // max Rx bufsize, in bytes

 DWORD dwMaxBaud;           // max baud rate, in bps

 DWORD dwProvSubType;       // specific provider type

 DWORD dwProvCapabilities;  // capabilities supported

 DWORD dwSettableParams;    // changable parameters

 DWORD dwSettableBaud;      // allowable baud rates

 WORD  wSettableData;       // allowable byte sizes

 WORD  wSettableStopParity; // stop bits/parity allowed

 DWORD dwCurrentTxQueue;    // Tx buffer size, in bytes

 DWORD dwCurrentRxQueue;    // Rx buffer size, in bytes

 DWORD dwProvSpec1;         // provider-specific data

 DWORD dwProvSpec2;         // provider-specific data

 WCHAR wcProvChar[1];       // provider-specific data

} COMMPROP;

Поля этой структуры описывают все возможности драйвера. Вы не можете выйти за пределы этих возможностей. Вот какое значение имеют поля:

wPacketLength

Задает размер, в байтах, структуры COMMPROP.

wPacketVersion

Номер версии структуры.

dwServiceMask

Битовая маска. Для коммуникационных устройств всегда SP_SERIALCOMM, включая модемы.

dwReserved1

Зарезервировано и не используется.

dwMaxTxQueue

Максимальный размер, в байтах, внутреннего буфера передачи драйвера. Нулевое значение свидетельствует об отсутствии ограничения.

dwMaxRxQueue

Максимальный размер, в байтах, внутреннего буфера приема драйвера. Нулевое значение свидетельствует об отсутствии ограничения.

dwMaxBaud

Максимально допустимая скорость обмена, в битах в секунду (бпс). Возможны следующие значения данного поля:

BAUD_075 75 бпс. BAUD_110 110 бпс. BAUD_134_5 134.5 бпс. BAUD_150 150 бпс. BAUD_300 300 бпс. BAUD_600 600 бпс. BAUD_1200 1200 бпс. BAUD_1800 1800 бпс. BAUD_2400 2400 бпс. BAUD_4800 4800 бпс BAUD_7200 7200 бпс. BAUD_9600 9600 бпс. BAUD_14400 14400 бпс. BAUD_19200 19200 бпс. BAUD_38400 38400 бпс. BAUD_56K 56K бпс. BAUD_57600 57600 бпс. BAUD_115200 115200 бпс. BAUD_128K 128K бпс. BAUD_USER Допускается программирование скорости обмена

dwProvSubType

Перейти на страницу:
Вы автор?
Жалоба
Все книги на сайте размещаются его пользователями. Приносим свои глубочайшие извинения, если Ваша книга была опубликована без Вашего на то согласия.
Напишите нам, и мы в срочном порядке примем меры.
Комментарии / Отзывы
    Ничего не найдено.