программирование интерфейса rs-232

advertisement
ПРОГРАММИРОВАНИЕ ИНТЕРФЕЙСА RS-232
ИНТЕРФЕЙС RS-232
Информация по линиям интерфейса RS-232 передается асинхронно
последовательным кодом. Это означает, что передатчик посылает байт
данных бит за битом. Для такой последовательной передачи требуется только
две линии (два провода). Стандарт RS-232 использует несимметричные
передатчики и приемники – сигнал передается относительного общего
провода. Интерфейс не обеспечивает гальванической развязки устройств, т.е.
при подключении устройств одно или оба порта должны быть обесточены, в
противном случае возможно повреждение портов вследствие разницы
потенциалов. Логической единице соответствует напряжение на входе
приемника в диапазоне –12...-3В. Логическому нулю соответствует диапазон
+3...+12В. Диапазон –3...+3В – зона нечувствительности, обусловливающая
гистерезис приемника: состояние линии считается измененным только после
пересечения порога (см. рис. 1).
Рис. 1. Уровни сигналов интерфейса RS-232
В стандарте при передаче слов (посылок) информации реализуется так
называемый старт-стопный метод, т.е. каждое передаваемое слово
начинается специальным старт-битом, позволяющим приемнику определить
начало передачи слова. Затем передается информационный байт младшими
битами вперед бит за битом, т.е. первым передается младший значащий бит
(МЗБ), а последним старший (СЗБ). После битов данных может следовать
бит контроля (бит проверки четности/нечетности). Иногда бит проверки
может отсутствовать. Бит контроля предназначен для повышения уровня
достоверности при приеме данных и показывает четно или не четно в байте
информации кол-во нулей и единиц. Завершение передачи слова отмечается
специальными стоп-битами (см. рис. 2).
Старт
бит
МЗБ
Биты
данных
Бит
контроля
Стоп
биты
CЗБ
Рис.2. Формат слова в RS-232
Таким образом, формат слова определяет следующие особенности
переноса информации через интерфейс:
1.
число битов, используемых для кодирования самого
переносимого символа;
2.
наличие или отсутствие контроля по четности;
3.
способ формирования контрольного бита;
4.
число стоп-битов.
Как рассматривалось ранее, старт бит является для приемной стороны
сигналом начала слова. По этому сигналу на приемной стороне запускается в
работу специальный аппаратный узел — сдвиговый регистр, который
«собирает» в параллельный код принятое бит за битом слово информации.
Биты передаются с известной приемнику и передатчику частотой,
измеряемой в бодах в секунду. Боды - это количество передаваемых
изменений сигнала (бит) в секунду. При этом учитываются и старт/стопные
биты, а также бит четности. Иногда используется другой термин - биты в
секунду (bps). Здесь имеется в виду эффективная скорость передачи данных,
без учета служебных битов. Передатчик и приемник используют разные
источники синхронизации, которые работают с близкой, но все-таки
различающейся частотой. Сильное расхождение частот приемника и
передатчика вызывает возникновение специфической для асинхронной связи
ошибки, называемой ошибкой кадрирования. Так же ошибка кадрирования
может возникать тогда, когда формат слова приемника и передатчика не
согласованы. Рассчитаем на примере допустимый сдвиг интервала одного
бита в посылке: пусть скорость приемника и передатчика 9600 бод/с, формат
слова 1 старт бит, 1 стоп бит, 8 бит информации, контрольного бита нет,
тогда время 1 бода t = 1 / 9600 ~ 0,1042 мс. Учитывая, что съем данных
происходит в середине бода, получаем что максимальный сдвиг за 10 бод не
должен превышать времени половины бода, т.е. 0,0521 мс, таким образом,
сдвиг времени на бод должен быть не более 0,0521 / 10 = 0,00521 мс. На
практике время сдвига должно быть значительно меньше, вследствие
влияния емкостной и индуктивных составляющих линии передачи.
ПОРТЫ АСИНХРОННОГО АДАПТЕРА ПК
Современный персональный компьютер зачастую не оснащается
последовательными портами, тем не менее, для оснащения современных
компьютеров последовательными портами используют:

PCI платы расширения, содержащие от 1 до 8 портов
последовательной передачи данных. Зачастую такие платы так же
оснащаются параллельным интерфейсом LPT.

USB-to-COM переходники, имеющие с одной стороны полноценный
последовательны порт стандарта RS-232, с другой стороны USB
вилку для подключения к персональному компьютеру.
В основе последовательного порта передачи данных лежит микросхема
Intel 16550. Это универсальный асинхронный приемо-передатчик (UART Universal Asynchronous Receiver Transmitter). Микросхема содержит
несколько интерфейсов RS-232 и соответствующее количество внутренних
регистров, предназначенных для управления работой портами ввода/вывода.
Микросхема 16550 содержит регистры передатчика и приемника
данных. При передаче байта он записывается в буферный регистр
передатчика, откуда затем переписывается в сдвиговый регистр передатчика.
Байт «выдвигается» из сдвигового регистра по битам. Аналогично имеются
сдвиговый и буферный регистры приемника.
Программный доступ можно осуществлять только к буферным
регистрам, копирование информации в сдвиговые регистры, и процесс сдвига
выполняется микросхемой 16550 автоматически.
Внешние устройства подключаются к порту ввода/вывода через разъем
DB25P (имеющий 25 выводов, рис. 3) или DB9P (имеющий 9 выводов, рис.
4). В табл. 2 приведена разводка разъема последовательной передачи данных
DB25P и DB9P.
Рис.3. Разъем DB25P
Рис.4. Разъем DB9P
Обозначен
ие цепи
RS-232
Номер
контакта
DB9P
DP25P
-
1
5
7
3
2
2
3
7
4
8
5
6
6
4
20
1
8
9
22
PG
SG
TD
RD
RTS
CTS
DSR
DTR
DCD
RI
Таблица №2. Описание сигналов интерфейса RS-232
Направлен
ие
Назначение сигнала
передачи
Вход/выхо
д
Protected Ground. Защитное заземление,
соединяется с корпусом устройства и экраном
кабеля
Signal Ground. Сигнальная земля - уровень
напряжения относительно которого действуют
уровни сигналов.
Transmit Data. Последовательные данные –
выход
выход передатчика
Receive Data. Последовательные данные - вход
вход
приемника.
Request To Send. Выход запроса передачи
данных. Состояние «включено» уведомляет о
выход
наличии у терминала данных для передачи.
Clear To Send – разрешение терминалу
вход
передавать данные. Состояние «выключено»
запрещает передачу.
Data Set Read. Готовность устройства на другой
вход
стороне канала к обмену данными
Data Terminal Ready. Готовность к обмену
выход
данными.
Data
Carrier
Detected.
Вход
сигнала
обнаружения
несувход
щей удаленного модема
Ring Indicator. Вход индикатора вызова
(звонка).
вход
В коммутируемом канале этим сигналом модем
сигнализирует о принятии вызова.
Рассмотрим пример обмена сигналами между сторонами интерфейса RS232 модемом и ПК:
1.
Компьютер после включения питания выставляет сигнал
готовности DTR, который постоянно удерживается активным.
Если модем включен и исправен, он отвечает компьютеру
сигналом DSR. Этот сигнал служит подтверждением того, что
DTR принят, и информирует компьютер о готовности модема к
приему информации;
2.
Если компьютер получил сигнал DSR и хочет передать данные он
выставляет сигнал RTS;
3.
Если модем готов принять данные, он отвечает сигналом CTS. C
этого момента адаптер компьютера может бит за битом
передавать информацию по линии TD;
4.
Получив порцию данных, модем может сбросить свой сигнал
CTS, информируя компьютер о необходимости «притормозить»
передачу следующего байта, например из-за переполнения
внутреннего буфера;
5.
Программа компьютера, обнаружив сброс CTS, прекращает
передачу данных, ожидая повторного появления CTS.
Когда модему необходимо передать данные в компьютер он выставляет
сигнал DCD. Программа компьютера, принимающая данные, обнаружив этот
сигнал, читает приемный регистр, в который сдвиговый регистр «собрал»
биты, принятые по линии приема данных RD. Когда для связи используются
только линии TD, RTS и DTR (от компьютера к модему), то компьютер не
может попросить модем «повременить» с передачей следующего байта. Как
следствие, существует опасность переопределения помещенного ранее в
приемном регистре байта данных вновь «собранным» байтом. Поэтому при
приеме информации компьютер должен очень быстро освобождать
приемный регистр адаптера. В полном наборе сигналов RS-232 есть линии,
которые могут аппаратно «приостановить» модем.
ПРОГРАММИРОВАНИЕ ПОСЛЕДОВАТЕЛЬНЫХ ПОРТОВ В ОС
СЕМЕЙСТВА WINDOWS NT (WIN32 API)
Работа с последовательными СОМ-портами в ОС семейства Windows NT
значительно отличается от работы с портами в DOS. Основными отличиями
являются:

запрещен прямой доступ к регистрам контроллера портов
(возможен только в режиме ядра);

запрещена работа с одним и тем же портом более чем двум
программам (неродственным процессам);
Но, несмотря на перечисленные запреты, инициализация и работа с
портом значительно проще. Для того чтобы инициализировать порт,
достаточно вызвать функцию CreateFile с соответствующими аргументами.
После этого можно записывать и считывать данные посредством стандартных
функций WriteFile и ReadFile. Кроме того, для настройки портов и
последующего управления ими предназначен целый ряд дополнительных
функций. Рассмотрим основные моменты программирования портов
подробнее.
Перед началом работы необходимо открыть порт и настроить его на
требуемый режим работы (для СОМ-порта). В листинге №1 показан пример
инициализации COM1 порта.
Листинг №1. Инициализация COM1 порта
#include <windows.h>
// объявляем структуру для конфигурации последовательного порта
DCB dcb;
ZeroMemory ( &dcb, sizeof ( DCB));
// дескриптор порта
HANDLE hCom 1 = NULL;
// пишем функцию инициализации порта СOМ1
bool Init_COMl ()
{
// открываем порт СOM1 (для COM2 "COM2", для LPT1 "LPT1")
hCom_l = CreateFile ( "COM1", GENERIC_READ | GENERIC_WRITE, 0,
NULL,OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if ( hCom_l == INVALID_HANDLE_VALUE)
// если порт не удалось открыть
return false; // выходим из функции
// если порт успешно открыт, получаем его состояние
if ( !GetCommState ( hCom_l, &dcb))
{
// если не удалось получить статус порта, выходим из функции
CloseHandle ( hCom_l);
return false; // выходим из функции
}
// настраиваем параметры порта
dcb.BaudRate = CBR_19200; // скорость передачи 19 200 бод
dcb.ByteSize =8; // размер байта данных
dcb.StopBits = ONESTOPBIT; // один стоповый бит
dcb.Parity = NOPATITY; // контроля четности нет
// сохраняем новые параметры конфигурации для порта
if ( !SetCommState ( hCom_l, &dcb))
{ // если не удалось настроить порт, выходим из функции
CloseHandle ( hCom_l);
return false; // выходим из функции
}
return true;
}
Теперь, когда COM1 порт открыт и сконфигурирован для работы, нужно
настроить обработку сигналов DSR и CTS. Пример кода для активизации
уведомлений для последовательного порта показан в листинге №2.
Листинг №2. Настройка уведомляющих событий сигналов DSR и CTS
// объявляем структуру для асинхронного ввода-вывода данных
//и помещаем ее в глобальную область видимости
OVERLAPPED over;
ZeroMemory (&over, sizeof(OVERLAPPED));
// пишем функцию настройки событий
bool SetEventCOM ()
// настраиваем мониторинг за определенными событиями порта
if ( !SetCommMask ( hCom_l, EV_DSR | EV_CTS))
{ // если не удалось настроить порт, выходим из функции
CloseHandle( hCom_l);
return false; // выходим из функции
} // создаем объект события
over.hEvent = CreateEvent ( NULL, FALSE, FALSE, NULL);
if ( !over.hEvent)
{ // если не удалось создать событие, выходим из функции
CloseHandle ( hCom_l);
return false; // выходим из функции
}
return true;
}
На данный момент вся начальная подготовка для работы с портом
закончена. Далее нужно написать функции чтения и записи данных и функцию
управления последовательного порта. Примеры функций чтения и записи
показаны в листинге №3.
Листинг №3. Функции чтения и записи для работы с COM портов
// функция чтения одного байта данных
BYTE ReadByteCOM ()
{
BYTE read = 0;
DWORD dwByteRead = 0;
do
{ // читаем байт из порта
if ( !ReadFile ( hCom_l, &read, sizeof ( BYTE),
&dwByteRead,NULL))
return 0;
} while ( !dwByteRead);
return read; // возвращаем прочитанный байт
}
// функция чтения массива данных
DWORD ReadData_COM ( void* Data, unsigned int uNumBytes)
{
DWORD dwBytesRead - 0;
if ( !ReadFile ( hCom_l, Data, uNumBytes, &dwBytesRead, NULL))
return dwBytesRead; // сколько удалось прочитать
return dwBytesRead;
// возвращаем полное число прочитанных байтов
}
// функция для записи одного байта
bool WriteByteCOM ( BYTE bByte) {
BYTE write = 0;
DWORD dwByteWrite = 0;
if ( !WriteFile ( hCom_l, &write, sizeof ( BYTE),
SdwByteWrite,NULL))
return false;
return true;
}
// функция для записи массива данных
DWORD WriteDataCOM ( void* Data, unsigned int uNumBytes)
{
DWORD dwBytesWrite = 0;
if ( !WriteFile ( hCom_l, Data, uNumBytes, SdwByteWrite,
NULL))
return dwBytesWrite; // сколько удалось записать
return dwBytesWrite;
// возвращаем полное число записанных байтов
}
Пример общей функции работы с портом представлен в листинге №4.
Листинг №4. Пример общей функции работы с COM портом
// добавляем в глобальную область данных значение для сигнала
DWORD dwSignal;
void GeneralCOM ()
{
// проверяем сигнал в линии
if ( WaitCommEvent ( hCom_l, &dwSignal, &over))
{
if ( dwSignal & EV_DSR) // данные готовы для чтения
{
// читаем байт из порта
BYTE data = ReadByteCOM ();
// сохраняем полученный байт куда-либо
}
if ( dwSignal & EV_CTS) { // можно писать данные в порт
// передаем извне байт и пишем его в порт
WriteByteCOM ( myByte);
}
}
}
// после завершения работы следует вызвать
// функцию очистки ресурсов
void CloseCOM ()
{
if ( over.hEvent)
{
CloseHandle ( over.hEvent); // закрываем объект события
over.hEvent = NULL;
}
if ( hCom_l)
{
CloseHandle ( hCom_l); // закрываем порт СOМ1
hCom = NULL;
}
}
ЛИТЕРАТУРА
1.
2.
3.
4.
5.
Агуров П. Последовательные интерфейсы ПК. Практика
программирования. – СПб.: БХВ – Петербург, 2004. – 496 с.
Ан П. Сопряжение ПК с внешними устройствами / Пей Ан; Пер.
с англ. Мерещука П.В. – 2-е изд. стер. – М.: ДМК Пресс; СПб.:
Питер, 2004. – 320 с.: ил.
Гук М. Аппаратные интерфейсы ПК. Энциклопедия. – СПб.:
Питер, 2002. – 528 с.: ил.
Несвижский В.А. Программирование аппаратных средств в
Windows. – СПб.: БХВ – Петербург, 2004. – 880 с.: ил.
Смит Дж. Сопряжение компьютеров с внешними устройствами.
Уроки реализации / Смит Дж.; Пер. с англ. – М.: Мир, 2000. – 266
с.
Download