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

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

Олег Титов - Работа с COM и LPT в Win32. краткое содержание

Прочтите описание перед тем, как прочитать онлайн книгу «Олег Титов - Работа с COM и LPT в Win32.» бесплатно полную версию:

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

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

baud=1200 parity=N data=8 stop=1

lpDCB

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

В случае успешного завершения функция BuildCommDCB возвращает ненулевое значение. В случае ошибки возвращается 0.

Обычно функция BuldCommDCB изменяет только явно перечисленые в строке lpDef поля. Однако существуют два исключения из этого правила:

• При задании скорости обмена 110 бит в секунду автоматически устанавливается формат обмена с двумя стоповыми битами. Это сделано для совместимости с командой mode из MS-DOS или Windows NT.

• По умолчанию запрещается программное (XON/XOFF) и аппаратное управление потоком. Вы должны вручную заполнить требуемые поля DCB если требуется управление потоком.

Функция BuilCommDCB поддерживает как новый, так и старый форматы командной строки mode. Однако, Вы не можете смешивать эти форматы в одной строке.

Новый формат строки позволяет явно задавать значения для полей DCB отвечающих за управление потоком. При использовании старого формата существуют следующие соглашения:

• Для строк вида 9600,n,8,1 (не заканчивающихся символами x или p):

 ○ fInX, fOutX,fOutXDsrFlow, fOutXCtsFlow устанавливаются в FALSE

 ○ fDtrControl устанавливается в DTR_CONTROL_ENABLE

 ○ fRtsControl устанавливается в RTS_CONTROL_ENABLE

• Для строк вида 9600,n,8,1,x (заканчивающихся символом х):

 ○ fInX, fOutX устанавливаются в TRUE

 ○ fOutXDsrFlow,fOutXCtsFlow устанавливаются в FALSE

 ○ fDtrControl устанавливается в DTR_CONTROL_ENABLE

 ○ fRtsControl устанавливается в RTS_CONTROL_ENABLE

• Для строк вида 9600,n,8,1,p (заканчивающихся символом p):

 ○ fInX, fOutX устанавливаются в FALSE

 ○ fOutXDsrFlow,fOutXCtsFlow устанавливаются TRUE

 ○ fDtrControl устанавливается в DTR_CONTROL_HANDSHAKE

 ○ fRtsControl устанавливается в RTS_CONTROL_HANDSHAKE

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

Заполнить DCB можно еще одним способом. Вызовом функции GetCommState. Эта функция заполняет DCB информацией о текущем состоянии устройства, точнее о его настройках. Вот как она выглядит:

BOOL GetCommState(HANDLE hFile, LPDCB lpDCB);

Функция очень проста и имеет всего два параметра:

hFile

Описатель открытого файла коммуникационного порта. Этот описатель возвращается функцией CreateFile. Следовательно, прежде чем получить параметры порта, Вы должны его открыть. Для функции BuildCommDCB это не требовалось.

lpDCB

Указатель на DCB. Для DCB должен быть выделен блок памяти.

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

Заполнив DCB можно приступать к собственно конфигурированию порта. Это делается с помощью функции SetCommState:

BOOL SetCommState(HANDLE hFile, LPDCB lpDCB);

Эта функция имеет точно такие же параметры, как GetCommState. Различается только направление передачи информации. GetCommState считывает информацию из внутренних управляющих структур и регистров порта, а SetCommState наоборот заносит ее. Следует быть осторожным при вызове функции SetCommState, поскольку она изменит параметры даже в том случае, если очереди приема/передачи не пусты, что может вызвать искажение потока передаваемых или принимаемых данных.

Еще одна тонкость этой функции заключется в том, что она завершится с ошибкой, если поля XonChar и XoffChar в DCB содержат одинаковые значения.

Как всегда, в случае успешного завершения возвращается отличное от нуля значение, а в случае ошибки – нуль.

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

typedef struct _COMMTIMEOUTS {

 DWORD ReadIntervalTimeout;

 DWORD ReadTotalTimeoutMultiplier;

 DWORD ReadTotalTimeoutConstant;

 DWORD WriteTotalTimeoutMultiplier;

 DWORD WriteTotalTimeoutConstant;

} COMMTIMEOUTS,*LPCOMMTIMEOUTS;

Поля структуры COMMTIMEOUTS имеют следующие значения:

ReadIntervalTimeout

Максимальное время, в миллисекундах, допустимое между двумя последовательными символами считываемыми с коммуникационной линии. Во время операции чтения временной период начинает отсчитываться с момента приема первого символа. Если интервал между двумя последовательными символами превысит заданое значение, операция чтения завершается и все данные, накопленые в буфере, передаются в программу. Нулевое значение данного поля означает, что данный тайм-аут не используется. Значение MAXDWORD, вместе с нулевыми значениями полей ReadTotalTimeoutConstant и ReadTotalTimeoutMultiplier, означает немедленный возврат из операции чтения с передачей уже принятого символа, даже если ни одного символа не было получено из линии.

ReadTotalTimeoutMultiplier

Задает множитель, в миллисекундах, используемый для вычисления общего тайм-аута операции чтения. Для каждой операции чтения данное значение умножается на количество запрошеных для чтения символов.

ReadTotalTimeoutConstant

Задает константу, в миллисекундах, используемую для вычисления общего тайм-аута операции чтения. Для каждой операции чтения данное значение прибавляется к результату умножения ReadTotalTimeoutMultiplier на количество запрошеных для чтения символов. Нулевое значение полей ReadTotalTimeoutMultiplier и ReadTotalTimeoutConstant означает, что общий тайм-аут для операции чтения не используется.

WriteTotalTimeoutMultiplier

Задает множитель, в миллисекундах, используемый для вычисления общего тайм-аута операции записи. Для каждой операции записи данное значение умножается на количество записываемых символов.

WriteTotalTimeoutConstant

Задает константу, в миллисекундах, используемую для вычисления общего тайм-аута операции записи. Для каждой операции записи данное значение прибавляется к результату умножения WriteTotalTimeoutMultiplier на количество записываемых символов. Нулевое значение полей WriteTotalTimeoutMultiplier и WriteTotalTimeoutConstant означает, что общий тайм-аут для операции записи не используется.

По тайм-аутам обычно возникает много вопросов. Поэтому попробую объяснить подробнее. Пусть мы считываем 50 символов из порта со скоростью 9600. При этом используется 8 бит на символ, дополнение до четности и один стоповый бит. Таким образом на один символ в физической линии приходится 11 бит (включая стартовый бит). 50 символов на скорости 9600 будут приниматься 50 * 11 / 9600 = 0.0572916 секунд, или примерно 57.3 миллисекунды, при условии нулевого интервала между приемом последовательных символов. Если интервал между символами составляет примерно половину времени передачи одного символа, т.е. 0.5 миллисекунд, то время приема будет 50 * 11 / 9600 + 49 * 0.0005 = 0.0817916 секунд, или примерно 82 миллисекунды. Если в процессе чтения прошло более 82 миллисекунд, то мы вправе предположить, что произошла ошибка в работе внешнего устройства и прекратить считывание избежав тем самым зависания программы. Это и есть общий тайм-аут операции чтения. Аналогично существует и общий там-аут операции записи.

Если тайм-аут при чтении понятен, то тайм-аут при записи вызывает недоумение. В самом деле, что нам мешает передавать? Управление потоком! Внешнее устройство может использовать, например, аппаратное управление потоком. При этом пропадание питания во внешнем устройстве заставит компьютер приостановить передачу данных. Если не контролировать тайм-аут возможно точно такое же зависание компьютера, как и при операции чтения.

Общий тайм-аут зависит от количества участвующих в операции чтения/записи символов и среднего времени передачи одного символа с учетом межсимвольного интервала. Если символов много, например 1000, то на общем времени выполнения операции начинают сказываться колебания времени затрачиваемого на один символ или времени межсимвольного интервала. Поэтому тайм-ауты в структуре COMMTIMEOUTS задаются двумя величинами. Таким образом формула для вычисления общего тайм-аута операции, например чтения, выглядит так NumOfChar * ReadTotalTimeoutMultiplier + ReadTotalTimeoutConstant , где NumOfChar это число символов запрошеных для операции чтения.

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

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