title |
---|
Лабораторная работа RS-232 |
Целью лабораторной работы является знакомство с последовательным интерфейсом UART
и его реализацией на ПК (COM-порт), а также получение навыков разработки и использования ПО для обмена данными с периферийным устройством.
- изучение принципов работы старт-стопной синхронизации;
- изучение принципов работы интерфейса RS-232;
- изучение принципов проектирования коммуникационного ПО для обмена данными с удаленным устройство.
- Ознакомиться с основными элементами адаптера асинхронной связи и коммуникационного ПО.
- Изучить особенности программирования адаптера асинхронной связи для работы в различных режимах.
- Отладить и протестировать программы, реализующие алгоритмы, заданные преподавателем (см. пункт “Ход работы”).
В области промышленной автоматизации актуальным является использование последовательных асинхронных интерфейсов UART
, задокументированных стандартами RS-232
и RS-485
. Ключевыми преимуществами данных интерфейсов являются простота монтажа и использования, а также широкий спектр совместимо-го оборудования.
Данный стандарт был введен в действие организацией EIA (США) в 1969 г. под названием RS-232-C (Recommended Standard).
Стандарты RS-XXX являются условно стандартными, поскольку аббревиатура RS содержит “мягкое” слово “Recommended Standard” – “рекомендованный стандарт”. Эти рекомендации исходят от американской организации EIA, RS-232-подобный стандарт описан в ГОСТ 18145-81.
Первоначально протокол, описанный в стандарте, предназначался для подключения к аппаратуре, предназначенной для передачи данных (Data Terminal Equipment – DTE) устройств, отвечающих за непосредственное соединение с линией передачи (Data Communication Equipment – DCE). Полное название “Интерфейс между терминальным оборудованием и связным оборудованием с обменом по последовательному двоичному коду”. Каждое слово в названии значимое, оно определяет интерфейс между терминалом (DTE) и модемом (DCE) по передаче последовательных данных.
В качестве первого устройства, как правило, выступал компьютер, а в качестве второго – модем, соединенный с линией связи. В дальнейшем область применения протокола расширялась. Он использовался для подключения к компьютеру периферийных устройств прикладного назначения (принтер, сканер, мышь и др.), а также для связи компьютеров между собой.
В настоящее время основная область его применения – связь со специализированными устройствами автоматизации (счетчики электроэнергии, расхода ресурсов и т. п.).
Интерфейс RS-232C предусматривает передачу и приём информации по несимметричной линии, то есть сигнал передаётся относительно общего провода. Логической единице соответствует уровень -12 …-3 В, логическому нулю +3…+12 В.
Далее будем называть такое оборудование наиболее распространенными терминами – “интерфейс RS-232C”, или “последовательный асинхронный интерфейс”.
Последовательный интерфейс RS-232 – это промышленный стандарт для последовательной двунаправленной асинхронной передачи данных между двумя устройствами на расстоянии до 15 метров.
Информация передается по проводам с уровнями сигналов, отличающимися от стандартных 5 В, для обеспечения большей устойчивости к помехам. Асинхронная передача данных осуществляется с установленной скоростью при синхронизации уровнем сигнала стартового импульса.
Стандартные физические порты, используемые промышленными сетями:
- RS-232,
- RS-422,
- RS-485.
Подавляющее большинство сетей использует наиболее мощный по числу узлов в сети и наиболее скоростной по передаче данных порт RS-485.
RS-232 широко используется в промышленных средствах автоматизации. Он обеспечивает соединение «точка к точке» между последовательным портом контроллера и приборами. Часто, за счет усовершенствования передатчика и кабеля, достигаются большие длина линии и скорость, чем зафиксировано в стандарте.
Популярность интерфейса RS-232C объясняется его универсальностью по диапазону скоростей передачи информации (от 50 до 115000 бит в секунду), “прозрачностью”, т.е. отсутствием запрещенных к передаче кодовых комбинаций, наличием специализированных БИС и ИС, на которых достаточно эффективно реализуется данный интерфейс, простотой конструкции соединительных кабелей.
Микросхемы, на основе которых строится интерфейс RS-232C, обычно называют универсальными асинхронными приемниками – передатчиками (universal asynchronous receiver transmitter или UART).
Обычно, ПК имели в своем составе два интерфейса RS-232C, которые обозначались COM1 и COM2. Была возможна установка дополнительного оборудования, которое обеспечивало функционирование в составе ПК четырех, восьми и шестнадцати интерфейсов RS-232C.
В современных ПК разъемы для последовательного интерфейса на корпусе системного блока отсутствуют. Как правило, они заменены на набор выводов прямо на материнской плате.
Работа коммуникационных портов реализована на универсальных асинхронных приемопередатчиках UART. Для СОМ порта компьютера используется 9-ти штырьковый разъем DE9p. В этом разъеме используется шесть сервисных сигналов и два канала обмена последовательными данными.
Интерфейс между терминалом (DTE) и модемом (DCE) по передаче последовательных данных
Устройства для связи по последовательному каналу соединяются кабелями с девятью или двадцатью пятью контактными разъемами типа DE-9, DB-25, CANNON 9, CANNON 25 и т.д:
- D-образный 9-ти или 25-пиновый разъем типа male для DTE устройства
- D-образный 9-ти или 25-пиновый разъем типа female для DCE-устройства.
Назначение линий в соответствии со стандартом RS-232 приведено в таблице:
Обозначение | Расшифровка | Описание |
---|---|---|
PG | Protective Ground | защитное заземление (экран) |
TxD | Transmitted Data | данные, передаваемые DTE |
RxD | Received Data | данные, принимаемые DTE |
RTS | Request To Send | сигнал запроса передачи к DCE |
CTS | Clear To Send | сигнал готовности DCE к приему данных от DTE |
DTR | Data Terminal Ready | готовность DTE к приему данных от DCE |
DSR | Data Set Ready | Сигнал готовности DCE к приему и передаче данных |
DCD | Data Carrier Detect | DCE принимает данные от удаленного DCE (обнаружена несущая) |
RI | Ring | DCE принимает сигнал вызова из линии |
SG | Signal Ground | сигнальное заземление, нулевой провод |
Нумерация контактов в разъемах:
Контакт | Обозначение | Направление | Описание |
---|---|---|---|
1 | SHIELD | … | Shield Ground – защитная земля, соединяется с корпусом устройства и экраном кабеля |
2 | TXD | -> | Transmit Data – выход передатчика |
3 | RXD | <- | Receive Data – вход приемника |
4 | RTS | -> | Request to Send – выход запроса передачи данных |
5 | CTS | <- | Clear to Send – вход разрешения терминалу передавать данные |
б | DSR | <- | Data Set Ready – вход сигнала готовности от аппаратуры передачи данных |
7 | GND | … | System Ground – сигнальная (схемная) земля |
8 | CD | <- | Carrier Detect – вход сигнала обнаружения несущей удаленного модема |
9-19 | N/C | - | - |
20 | DTR | -> | Data Terminal Ready – выход сигнала готовности терминала к обмену данными |
21 | N/C | - | - |
22 | RI | <– | Ring Indicator - вход индикатора вызова (звонка) |
23-25 | N/C | - | - |
Контакт | Обозначение | Направление | Описание |
---|---|---|---|
1 | CD | <- | Carrier Detect |
2 | RXD | <- | Receive Data |
3 | TXD | -> | Transmit Data |
4 | DTR | Data Terminal Ready | |
5 | GND | – | System Ground |
6 | DSR | <- | Data Set Ready |
7 | RTS | Request to Send | |
8 | CTS | <- | Clear to Send |
9 | RI | <- | Ring Indicator |
Интерфейс UART (Uuniversal Asynchronous Rreceiver/Ttransmitter) так же можно отнести к разновидности интерфейса RS-232, с той разницей, что он является наиболее “полной” его разновидностью.
Скорость передачи данных по интерфейсу UART может достирать до 2764800 бит/с.
Принципиальными отличиями в структуре интерфейса UART является то, что если в интерфейс RS-232 значение “Стоп-бит” могло принимать значения 1; 1,5 и 2, то интерфейс UART имеет значения “Стоп-бит” только 1 и 2.
Дополнительно в интерфейсе UART добавлено понятие “Направление бит” и “Уровень холостого хода”. Направление бит означает какие биты информации передаются первыми – старшие (MSB) или младшие (LSB). Уровень холостого хода, в отличие от интерфейса RS-232, в котором при отсутствии передачи информации, уровень на шине принимает низкое значение или уровень логического нуля, в интерфейсе UART при отсутствии передачи информации, уровень на шине может принимать как низкое значение (уровень логического нуля), так и высокое значение (уровень логической единицы).
Уровни сигналов UART
UART использует уровни сигналов -12 В…+12 В. Зоной нечувствительности – отсутствие сигналов – считается напряжение -3 В…+3 В. При этом принимаемые/передаваемые данные инвертированы.
Рис. Уровни сигналов UART по стандарту RS-232c
Исходные состояния порта
- порт не инициализирован – на всех линиях напряжения находятся в диапазоне -3 В…+3 В
- режим ожидания – на всех линиях напряжение находится в диапазоне -3 В…-12 В
При передаче данных символы передаются из буфера передатчика последовательно (первым пришел – первым вышел).
На рис. показан вид сигнала на информационной линии интерфейса RS-232C. Логической единице соответствует напряжение -12 В, а логическому нулю – +12 В.
Передача символов “0” “0” без паритета, с одним стоповым битом
За последним битом данных символа может следовать бит паритета, служащий для обнаружения ошибки передачи битов данных. Последним передается стоповый бит, который необходим для временного разделения переданных символов.
Стоповый бит разделяет два переданных символа. При необходимости можно увеличить этот интервал до 2 стоповых битов, если конечное устройство не успевает разделять символы.
Передача символов “0” “0” с проверкой на четность (EVEN), с одним стоповым битом
Рассмотрим пример передачи через интерфейс передается числа 0101010b
, соответствующее кодировке символа «U». Следует обращать внимание, что последовательность старших и младших бит при дальнейших преобразованиях должна быть соблюдена: «Бит 7»-«Бит 6»-«Бит 5»-«Бит 4»-«Бит 3»-«Бит 2»-«Бит 1»-«Бит 0».
Сигнал на информационной линии интерфейса RS‑232C | |
Отображаемый информационный сигнал |
Количество стоповых бит может быть увеличено пользователем ПК до 2. Стартовый бит единственен.
На основании полученной эпюры напряжения можно определить логическую последовательность передаваемых информационных разрядов:
[0(01001110)1][0(10100110)1][0(00110110)1][0(10000110)1][0(10011110)1],
где [стартовый(младший…старший)стоповый]
биты.
В дальнейшем принятую последовательность необходимо преобразовать в кодировку ASCII. Результатом проделанных действий является выделенное слово “relay”.
Следует учитывать, что передача начинается с младших бит, а заканчивается старшим битом!
При использовании контроля четности посылаются сообщения, подсчитывающие число единиц в группе бит данных. В зависимости от результата устанавливается бит четности. Приемное устройство также подсчитывает число единиц и затем сверяет бит четности.
Для обеспечения контроля четности компьютер и устройство должны одинаково производить подсчет бита четности. То есть, определиться устанавливать бит при четном (even) или нечетном (odd) числе единиц. При контроле на четность биты данных и бит четности всегда должны содержать четное число единиц. В противоположном случае бит соответствует контролю на нечетность.
Часто в драйверах доступны еще две опции на четность: Mark и Space. Эти опции не влияют на возможность контроля ошибок. Mark означает, что устройство всегда устанавливает бит четности в 1, а Space – всегда в 0.
Обнаружение ошибок
Проверка на четность – это простейший способ обнаружения ошибок. Он может определить возникновение ошибок в одном бите, но при наличии ошибок в двух битах уже не заметит ошибок. Также такой контроль не отвечает на вопрос какой бит ошибочный. Другой механизм проверки включает в себя Старт и Стоп биты, циклические проверки на избыточность, которые часто применяются в соединениях Modbus.
Пример
В примере показана структура передаваемых данных со синхронизирующим тактовым сигналом. В этом примере используется 8 бит данных, бит четности и стоп бит. Такая структура также обозначается 8Е1.
Примечание: Тактовый сигнал – для асинхронной передачи это внутренний сигнал
Старт-бит
Сигнальная линия может находится в двух состояниях: включена и выключена. Линия в состоянии ожидания всегда включена. Когда устройство или компьютер хотят передать данные, они переводят линию в состояние выключено – это установка Старт-бита. Биты сразу после Старт-бита являются битами данных.
Стоп-бит
Стоп-бит позволяет устройству или компьютеру произвести синхронизацию при возникновении сбоев. Например, помеха на линии скрыла Старт-бит. Период между старт и стоп битами постоянен, согласно значению скорости обмена, числу бит данных и бита четности. Стоп-бит всегда включен. Если приемник определяет выключенное состояние, когда должен присутствовать стоп бит, фиксируется появление ошибки.
Установка Стоп-бита
Стоп бит не просто один бит минимального интервала времени в конце каждой передачи данных. На компьютерах обычно он эквивалентен 1 или 2 битам, и это должно учитываться программе драйвера. Хотя, 1 стоп бит наиболее общий, выбор 2 бит в худшем случае немного замедлит передачу сообщения.
(Есть возможность установки значения стоп бита равным 1.5. Это используется при передаче менее 7 битов данных. В этом случае не могут быть переданы символы ASCII, и поэтому значение 1.5 используется редко).
Электрические сигналы после прохождения по кабелю ослабляются и искажаются. Ослабление растет с увеличением длины кабеля. Этот эффект сильно связан с электрической емкостью кабеля. По стандарту максимальная нагрузочная емкость составляет 2500 пФ. Типичная погонная емкость кабеля составляет 130 пФ, поэтому максимальная длина кабеля ограничена примерно 17 м.
Перед соединением двух компьютеров через RS-232, каждый из которых питается от различных источников, рекомендуется выровнять напряжения между их сигнальными землями перед подключением.
Два типа устройств RS-232, 1488 и 1489, используются и сейчас. Это ранние представители стандарта. Устройства того времени запитывались мощными источниками питания, поскольку согласно стандарту RS-232 передатчики должны были обеспечивать минимальный +5 В сигнал низкого уровня и минимальный -5 В сигнал высокого уровня. Эти уровни сигналов обеспечивали устойчивость к помехам после передачи по проводам к приемнику. Но это требовало наличие двухполярного источника питания, и поэтому многие материнские платы включали в себя источник отрицательного напряжения исключительно для питания устройств типа 1488 или 1489.
Семейство микросхем MAX220-MAX249 линейных приемо-передатчиков предназначены для интерфейсов EIA/TIA-232E и V.28/V.24, особенно в устройствах, где отсутствуют напряжения ±12 В.
Альтернативная микросхема ICL232. Это сдвоенный приемо-передатчик соответствующая спецификациям RS-232C и V.28. Для питания ИС требуется только напряжение +5 В. Напряжения +10 В и -10 В преобразуются из 5 В при помощи двух емкостных преобразователях напряжения.
На приведенном рисунке для сравнения отображены сигналы TTL serial и RS-232, снятые при передаче значения одного байта.
MAX232 — интегральная схема, преобразующая сигналы последовательного порта RS-232 в сигналы, пригодные для использования в цифровых схемах на базе ТТЛ или КМОП технологий. MAX232 работает приемопередатчиком и преобразует сигналы RX, TX, CTS и RTS
Микросхема MAX232 быстро стала индустриальным стандартом. Многие разработчики используют ее, несмотря на то, что параметры микросхем с однополярным питанием значительно улучшились.
Конфигурация выводов MAX232 представлена на рис.
Полезно понимать, что происходит с уровнями напряжения. Когда схема MAX232 получает на вход логический «0» от ТТЛ, она преобразует его в напряжение от +3 до +15 В, а когда получает логическую «1» — преобразует её в напряжение от −3 до −15 В, и по тому же принципу выполняет обратные преобразования от RS-232 к ТТЛ.
Тип линии и логический уровень RS-232 | Напряжение RS-232 | Напряжение от ТТЛ к MAX232 или обратно |
---|---|---|
Линия данных, логический «0» | от +3 В до +15 В | 0 В |
Линия данных, логическая «1» | от −3 В до −15 В | 5 В |
Все DTE-DCE кабели прямого соединения, контакты соединяются один к одному.
Кабели DTE-DTE и DCE-DCE – кросс-кабели.
- DTE - DCE называется “прямой кабель”
- DTE - DTE называется “нуль-модемный кабель”
- DCE - DCE называется “Tail Circuit Cable”
Схема подключения DTE-устройства к DCE-устройству показана на рис. Однако, изменив порядок соединения линий, можно добиться соединения двух DTE-устройств, что позволяет образовать между ними канал передачи данных.
Так как большая часть линий стандарта требуется для синхронизации работы DTE и DCE, то при соединении двух устройств DTE (двух компьютеров) эти линии остаются незадействованными. Для корректной работы микросхемы порта необходимо их замыкание на соответствующие парные выводы на ближнем конце. Таким образом, данное соединение требует кабеля, состоящего как минимум из 7 линий.
В настоящее время наиболее широко используется упрощенный способ соединения, в которой используется трехпроводная линия связи (линия приема, передачи и сигнальной земли).
Схемы подключения устройств по стандарту RS-232: a) DTE-DCE, б) DTE-DTE (полный нуль-модемный кабель), в) DTE-DTE (упрощенный вариант)
При таком соединении терминалы соединяются между собой непосредственно через СОМ-порты. Так как компьютеры обладают большой скоростью обработки данных, то синхронизировать их работу не нужно. Предполагается, что режим синхронизации обмена (Handshaking): 0-None, то есть сервисные сигналы не влияют на процедуры обмена данными. Для этого используется нуль-модемный кабель.
Нуль-модемный кабель для Handshaking = 0 (None)
Так как режим синхронизации обмена на СОМ портах может быть включен, то часто сервисные сигналы СОМ портов замыкают самих на себя, тем самым исключая их влияния на процедуру обмена.
Нуль-модемный кабель для любых режимов Handshaking
Можно использовать полный кабель, но при этом СОМ-порты должны быть настроены на аппаратную синхронизацию обмена. Данный режим используется, когда устройство не успевает перерабатывать информацию, полученную по СОМ-порту. Этот режим позволяет останавливать обмен данных на время обработки полученной информации.
Нуль-модемный кабель для аппаратного режима синхронизации Handshaking=2
системный блок ПК и два 9-ти штырьковых разъема
Нуль-модемный кабель. На обоих его концах установлен разъем типа “female”.
При проведении инициализации порта коммуникации (“открытии”) устанавливаются все характеризующие его режим параметры:
- длину слова,
- число стоп-битов,
- установку четности
- скорость обмена.
Длина слова – это число битов, которое образует основную единицу данных. Помимо варианта, когда обмен ведется привычными порциями по 8 битов, возможно использование 7 битов, что достаточно для стандартных файлов ASCII (в которых все символы имеют коды, не превышающие ASCII 128), в то время как для передачи численных данных достаточно порций по 4 бита.
Важно учитывать следующие основные принципы обмена информацией по интерфейсу RS-232C:
- обмен данными обеспечивается по двум цепям, каждая из которых является для одной из сторон передающей, а для другой приемной;
- в исходном состоянии по каждой из этих цепей передается двоичная единица, т.е. стоповая посылка. Передача стоповой посылки может выполняться сколько угодно;
- передаче каждого знака данных предшествует передача стартовой посылки, т.е. передача двоичного нуля в течение времени, равного времени передачи одного бита данных;
- после передачи стартовой посылки обеспечивается последовательная передача всех разрядов знака данных, начиная с младшего разряда. Количество разрядов знака может быть 5, 6, 7 или 8;
- после передачи последнего разряда знака данных возможна передача контрольного разряда, который дополняет сумму по модулю 2 переданных разрядов до четности или нечетности. В некоторых системах передача контрольного разряда не выполняется;
- после передачи контрольного разряда или последнего разряда знака, если формирование контрольного разряда не предусмотрено, обеспечивается передача стоповой посылки. Минимальная длительность посылки может быть равной длительности передачи одного, полутора или двух бит данных.
Обмен данными по описанным выше принципам требует предварительного согласования приемника и передатчика по количеству используемых разрядов в символе, правилам формирования контрольного разряда и длительности передачи бита данных.
Последнее согласование обеспечивается путем стандартизации ряда скоростей: 50, 75, 100, 110, 200, 300, 600, 1200, 2400, 4800, 9600, 19 200, 38 400, 57 000 или 115 000 бит в секунду. Установленная скорость должна отличаться от номинальной не более чем на 2 %, что гарантированно обеспечивается применением генераторов с кварцевыми резонаторами.
ОС Windows зарезервировала имена от СОМ1 до СОМ9 для работы с физическими СОМ-портами.
Правильнее обращаться с последовательными портами через встроенные в Windows функции WinAPI (API Application Programming Interface, интерфейс программирования приложений). Их полное описание можно найти в справочной системе MS SDK Help files, поставляемой со многими системами разработки приложений. Функции для работы с коммуникационным оборудованием описаны в разделе Communications
файла Win32 Programmer’s Reference.
Любые коммуникационные ресурсы, физические и логические устройства ввода/вывода с точки зрения Windows – одиночные двунаправленные асинхронные потоки данных. Их открывают, инициализируют и конфигурируют функцией CreateFile
, закрывают функцией CloseHandle
.
Для хранения параметров коммуникационных ресурсов определен тип tDCB
(Device Control Block блок управления устройством) – структура, в полях которой задают скорость обмена, число бит в посылке, число стоп-бит, режим проверки на четность.
Предусмотрены функции GetCommState
и SetCommState
, которыми читают и устанавливают эти параметры. Размер буферов ввода и вывода задают функцией SetupComm
.
Для чтения и записи в порт вызывают функции ReadFile
, ReadFileEx
, WriteFile
, WriteFileEx
.
Структура типа tCOMSTAT
имеет поля cblnQueue
и cbOutQueue
, содержащие сведения о числе принятых байтов в буфере приема и числе еще не переданных в буфере передачи. Функция ClearCommError
обновляет эту информацию и сообщает о возникших в процессе работы порта ошибках.
Ядро Windows самостоятельно обрабатывает все события, возникающие при работе последовательных портов, настраивает прерывания и программирует контроллеры портов ввода/вывода, принимает и передает байты данных. Прикладной программе остается читать принятые данные из буфера приемника, а предназначенные для передачи – записывать в буфер передатчика. Эти операции обычно выполняют блоками с периодичностью, зависящей от скорости приема/передачи и объема буферов.
Последовательность операций работы с COM-портом
Работа с портом средствами функций WinAPI аналогична работе с файлом. Для работы создается идентификатор открытого порта (хэндл).
HANDLE hPort;
Функция для открытия порта:
LPCTSTR Name=L"COM1"; // UNICOD L""
hPort = CreateFile( Name,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
//здесь выполняем действия, требуемые в случае неуспешного открытия порта
if (hPort == INVALID_HANDLE_VALUE)
{
DWORD dw = GetLastError();
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
message = Convert::ToString(lpMsgBuf);
MessageBox::Show(this, message, "Ошибка", MessageBoxButtons::OK);
return;
}
//здесь выполняем действия, требуемые в случае успешного открытия порта
...
Инициализация параметров порта выполняется заданием значений полей структуры DCB
. Работа с данной структурой:
DCB dcbSerialParams = { 0 };
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (!GetCommState(hPort, &dcbSerialParams))
{
MessageBox::Show(this, "Получение свойств порта", "Ошибка", MessageBoxBut-tons::OK);
return;
}
dcbSerialParams.StopBits = ONESTOPBIT; // количество стоп-битов
// ONESTOPBIT - 1 стоп-бит
// ONE5TOPBITS - 1.5 стоп-бита
// TWOSTOPBITS - 2 стоп-бита
dcbSerialParams.BaudRate = CBR_1200; // скорость подключения (бод/с)
dcbSerialParams.ByteSize = 5; // количество информационных бит
dcbSerialParams.Parity = NOPARITY; // режим проверки на четность
// NOPARITY – нет проверки,
// EVENPARITY – проверка на четность
// ODDPARITY – проверка на нечетность
if (!SetCommState(hPort, &dcbSerialParams))
{
MessageBox::Show(this, "Запись свойств порта", "Ошибка", MessageBoxButtons::OK);
}
Для того чтобы функции чтения и записи в порт выполнялись в асинхронном режиме (не было зависания программы по причине ожидания символа из порта) необходимо установить таймауты приема и передачи для порта.
COMMTIMEOUTS CommTimeOuts = { 0xFFFFFFFF,0,0,0,1500 };
if (!SetCommTimeouts(hPort, &CommTimeOuts))
{
MessageBox::Show(this, "Запись таймаутов порта", "Ошибка", MessageBoxBut-tons::OK);
}
В случае успешного подключения к порту можно принимать и передавать данные с помощью функций ReadFile
и WriteFile
.
Перед вызовом метода WriteFile
необходимо сформировать массив байтов для передачи. Например, если требуется передать слово “Hello”, вызов метода будет иметь вид:
char str[10]; // строка для передачи
DWORD dwSize = 5; // размер строки
DWORD dwBytesWritten; // количество переданных байт
strcpy(str,”Hello”);
BOOL iRet = WriteFile(hPort, str, dwSize, &dwBytesWritten, NULL);
if (dwBytesWritten!= dwSize)
{
MessageBox::Show(this, "Ошибка при записи в порт", "Ошибка", MessageBoxBut-tons::OK);
}
Функция для получения данных считывает данные побайтно:
DWORD iSize;
char sReceivedChar[2];
char recBuf[100];
string Symb;
sReceivedChar[1] = 0;
do
{
ReadFile(hPort, &sReceivedChar, 1, &iSize, 0); // получаем 1 байт
// если что-то принято, выводим
if (iSize > 0)
{
strcat(recBuf, sReceivedChar);
}
} while (iSize > 0);
считывает все данные, принятые из последовательного интерфейса и сохраненные в буфере приема recBuf
.
При завершении работы с портом необходимо закрыть подключение вы-зовом метода CloseHandle
.
CloseHandle(hPort);
Обработка событий COM-порта
дописать про асинхронную обработку и многопоточный режим
по материалам PCPORTS
Агуров, П. Последовательные интерфейсы ПК. Практика программирования / П. Агуров. – СПб.: БХВ-Петербург, 2004. – 496 с.
и по std::thread c++
Для того чтобы узнать о том, что произошло изменение сигнала на линии CTS
или DSR
, можно применить два подхода:
- с помощью таймера (периодический опрос состояния линий). Недостаток – минимальный интервал опроса составляет всего 10-20 мс
- использование специализированных функций-обработчиков событий для COM-порта
Функция SetCommMask
указывает стандартному драйверу порта отслеживать определенные события. Становится возможным узнать о каждом случае возникновения события порта.
Пример листинга
HANDLE hCom; OVERLAPPED o; BOOL fSuccess; DWORD dwEvtMask;
hCom = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, /* exclusive access / NULL, / no security attrs */ OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
if (hCom == INVALID_HANDLE_VALUE) {
// Обработка ошибок }// Установка масок событий Com порта. fSuccess = SetCommMask(hCom, EV_CTS | EV_DSR); if (!fSuccess) {
// Обработка ошибок }// Создать объект события для использования в функции WaitCommEvent o.hEvent = CreateEvent(NULL, /* no security attributes / FALSE, / auto reset event / FALSE, / not signaled / NULL / no name */); assert(o.hEvent);
if (WaitCommEvent(hCom, &dwEvtMask, &o)) {
if (dwEvtMask & EV_DSR) { /* */ }<span class="token keyword">if</span> <span class="token punctuation">(</span>dwEvtMask <span class="token operator">&</span> EV_CTS<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">/* */</span> <span class="token punctuation">}</span>
}
Следующий пример открывает handle
для COM1
и заполняет DCB
структуру информацией о текущей конфигурации.
Сама DCB
структура затем модифицируется и используется для реконфигурации устройства
DCB dcb; HANDLE hCom; DWORD dwError; BOOL fSuccess;
hCom = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, /* comm devices must be opened w/exclusive-access / NULL, / no security attrs / OPEN_EXISTING, / comm devices must use OPEN_EXISTING / 0, / not overlapped I/O / NULL / hTemplate must be NULL for comm devices */ );
if (hCom == INVALID_HANDLE_VALUE) { dwError = GetLastError(); // Обработка_ ошибки _handle }
// Опускаем вызов SetupComm, используя размеры очередей по умолчанию. Получаем текущую конфигурацию fSuccess = GetCommState(hCom, &dcb); if (!fSuccess) {
// Обрабатываем ошибку }// Fill in the DCB: baud=9600, 8 data bits, no parity, 1 stop bit. dcb.BaudRate = 9600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT;
fSuccess = SetCommState(hCom, &dcb); if (!fSuccess) {
// Обрабатываем ошибку }
Алгоритм программирования СОМ-порта с помощью API-функций:
- Для работы с СОМ-портом необходимо открыть порт с помощью API функции
CreateFile
: - После открытия СОМ порта можно передавать и принимать данные через этот СОМ-порт. Для передачи данных используется API функция
WriteFile
. Для приёма данных используется API функцияReadFile
. - После окончания работы с портом его нужно закрыть. Закрытие порта осуществляется API функцией
CloseHandle
. - Настройка режима работы СОМ-порта осуществляется с помощью структур данных, которые представляют из себя набор переменных разного типа. Структуру загружаются и читаются с помощью API функций.
Структура DCB
определяет основные настройки СОМ порта.
COMMPROP
структура сообщает информацию о свойствах коммуникационного устройства.
Для того чтобы параллельно с чтением данных из порта сохранялась возможность работы программы пользователя (обработка действий пользователя, если они предусмотрены) функции чтения данных необходимо запускать не непрерывно, а по таймеру.
Альтернативным вариантом является вынесение чтения из порта в отдельный поток выполнения программы.
Описание функций класса SerialGate:
SerialGate – библиотека для работы с COM портами на языке С++. Упрощает программирование последовательных портов за счет использования классов.
Имеет возможность определять все установленные в системе COM порты.
Корректно работает как с реальными так и виртуальными COM портами.
В основе библиотеки лежит класс SerialGate. Используя его методы можно выполнять наиболее часто востребованные действия на COM портом: прием-передача данных, управление линиями взаимодействия, определение доступных портов в сиcтеме и т.д.
Функция открывает доступ к к COM-порту с номером port
на скорости baud
байт/c. Если указанный порт существует и не занят другим приложением в данный момент, функция вернет true
, иначе false
. Если, к примеру, параметр port
был указан как 3, то функция попытается открыть доступ к COM-порту с именем COM3. Функция корректно работает и с виртуальными портами.
bool Open(int port, int baud);
Пример использования:
SerialGate sg;
bool b = sg.Open(1, 19200); if(b == true) { // port is open sucsesfully } else { // port open error }
Функция записывает в ранее открытый порт szBuff
байт данных из буфера buff
. Возвращает число успешно записанных байт данных в порт.
int Send(char* buff, int szBuff);
Пример использования:
char buff[256];
for(int i=0; i < sizeof(buff); i++)
{
buff[i] = i;
}
int SendCounter = sg.Send(buff, sizeof(buff));
if(SendCounter != sizeof(buff))
{
//не все данные были записаны в порт
}
Читает из ранее открытого порта szBuff
байт данных и помещает их в буфер buff
. Возвращает число реально прочитанных байт данных.
int Recv(char* buff, int szBuff);
Пример использования:
char buff[256]; int RcvCounter = sg.Recv(buff, sizeof(buff));
if(RcvCounter != sizeof(buff)) { // прочли меньше, чем заказывали }
Функция устанавливает в логическую единицу или ноль одну из выходных сигнальных линий, а именно DTR
или RTS
. Имя линии задается через перечислитель OUT_LINES_NAME
. Вторым параметром передается состояние (true
– 1, false
– 0) в которое необходимо перевести линию.
void SetLine(OUT_LINES_NAME ln, bool state);
Пример использования:
sg.SetLine(sg.RTS, true); // установит на линии RTS лог. 1
Функция возвращает состояние одной из входных сигнальных линий (CTS
, DSR
, RING
или RLSD
). Имя линии задается через перечислитель IN_LINES_NAME
.
bool GetLine(IN_LINES_NAME ln);
Пример использования:
bool b = sg.GetLine(sg.DSR); // читаем состояние линии DSR
Функция заполняет переданную ей структуру PortInfo
информацией о установленных в системе COM портах.
void GetPortsInfo(PortInfo* pi);
Очищает входной и выходной буфер данных COM-порта.
void Clean();
Пример использования:
sg.Clean();
Закрывает ранее установленное соединение с COM-портом.
void Close();
Пример использования:
sg.Close();
В данном курсе используется достаточно современный стандарт языка программирования C++
(C++ 2014
).
В качестве компилятора рекомендуется использовать gcc
версии 5 и старше, clang
версии >= 7.3. Для работы в среде Windows
потребуется развернуть MSYS2
.
Проект MSYS2
предоставляет для Windows
пакетный менеджер Pacman, портированный из Arch Linux
. С помощью пакетного менеджера можно устанавливать необходимые инструменты разработки, библиотеки, например, GTK+
или Qt5
.
Установщик MSYS2
скачивается с сайта http://www.msys2.org/. MSYS2
не может быть установлен на диск с разметкой FAT**
и на ОС Windows XP
.
- Скачиваем и запускаем установщик: для 64-битной системы
x86_64
, для 32-битной –i686
. - Указываем директорию установки. Путь должен быть коротким, содержать только латиницу с цифрами (
ASCII
). В пути не должно быть знаков ударений, пробелов и символических ссылок. Лучше оставить путь по-умолчанию или устанавливать в корень логического диска. - Для работы через
proxy
в сети университета, необходимо отредактировать файл/home/st/.bash_profile
(st
– название домашней директории пользователя) в любом текстовом редакторе, добавив туда:
export http_proxy=http://proxy.ugatu.ac.ru:8008
export https_proxy=$http_proxy
export ftp_proxy=$http_proxy
export rsync_proxy=$http_proxy
export no_proxy="localhost, 127.0.0.1, localadress, .localdomain.com"
- После установки необходимо обновить основные системные пакеты
MSYS2
и базу данных с информацией об доступных пакетах.
pacman -Syu
И соглашаемся на обновление, вводом y
:
Для завершения установки возможно потребуется вручную закрыть окно с терминалом MSYS2
. И заново его запустить через ярлык в меню «Пуск»:
После перезапуска терминала MSYS2
, выполняем команду для обновления остальных пакетов:
pacman -Su
У пакетного менеджера pacman имеется группа mingw-w64-x86_64-toolchain
, в которой собраны компиляторы GCC
, стандартные библиотеки и инструменты разработки:
Для многопоточного программирования на C/C++
достаточно пакета mingw-w64-x86_64-gcc
и mingw-w64-x86_64-winpthreads-git
, с которыми по зависимостям установятся еще несколько необходимых пакетов:
pacman -S mingw-w64-x86_64-gcc
pacman -S mingw-w64-x86_64-winpthreads-git
Для работы с библиотекой libmodbus
понадобиться установить пакет mingw-w64-x86_64-libmodbus-git
, для этого можно выполнить команду:
pacman -S mingw-w64-x86_64-libmodbus-git
Если MSYS2
не обновляется и выдает ошибку “неизвестный ключ”
Если вы не обновляли MSYS2 на своём ПК с начала июня 2020 года, при попытке обновления вы получите такую ошибку:
ошибка: mingw64: неизвестный ключ "4A6129F4E4B84AE46ED7F635628F528CF3053E04"
В чем же дело? MSYS2
- https://www.msys2.org/news/#2020-06-29-new-packagers
Оказалось, что Alexey Pavlov (Alexpux) <alexpux@gmail.com>; больше не занимается подписанием пакетов, соответственно его ключ был отозван, так что нам нужно обновить PGP ключи MSYS2
.
Для этого введем следующие команды
$ curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz
$ curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig
$ pacman -U --config <(echo) msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz
И, на всякий случай, очистим хранилище PGP ключей и обновим его содержимое:
$ rm -r /etc/pacman.d/gnupg/
$ pacman-key --init
$ pacman-key --populate msys2
После этого запускаем обновление:
pacman -Syu
Обязательно, перезагрузите ПК, иначе консоль не запуститься после обновления pacman.
После установки необходимо проверить текущее местоположение в файловой система – домашний каталог активного пользователя. С помощью команды pwd
:
Для компиляции исходных кодов на языке с++ воспользуемся оболочкой g++
toolchain (набора утилит) gcc
. Инструкция по работе:
g++ -Wall -pedantic server.cpp SerialGate.cpp -o ./build/server.exe
Ключи | Значение |
---|---|
-Wall -pedantic |
выводить информацию о всех предупреждения компилятора |
server.cpp SerialGate.cpp |
Файлы, которые необходимо скомпилировать |
-o ./build/server.exe |
Имя и название файла, куда необходимо собрать исполняемый файл |
- С помощью программы Virtual Serial Ports Emulator необходимо создать пару виртуальных портов с именами
COM5
иCOM6
Главное окно приложения
Режим с выводом дополнительной информации
Диалог создания пары связанных виртуальных портов
- Протестировать приложение обмена текстовыми данными
server
иclient
- Запустить приложение
Lab_1\comPortsConnect\build\server.exe
. Для этого рекомендуется открыть два окна терминала (последовательность действий1-2-3
для открытия одного окна)
Если увидели, что приложение запустилось, но ничего не выводит на экран терминала, то действуем, добавляя код в телоmain
(в заготовках уже добавил), и перекомпилируя:
setvbuf(stdout, NULL, _IONBF, 0);
- Запустить приложение
Lab_1\comPortsConnect\build\client.exe
- Осуществить обмен информацией между двумя приложениями через связанную пару виртуальных портов. Передать ФИО и группу, например:
Hi, Ivanov from IVT-431
. Скриншот с такими данными является строго обязательным для отчета. - Проанализировать исходный код каждого приложения и вынести в отчет исходный код, отвечающий за процедуру подключения к портам и обмена информацией.
- Необходимо ознакомиться с основными программно - доступными элементами адаптера.
- Необходимо с использованием примеров написать клиентскую и серверную программы на языке С/С++ для реализации обмена через последовательный порт по полудуплексному вводу и выводу (с использованием WIN API). Код программ приведен в файлах директорий
client
иserver
: - Компиляция осуществляется средствами
mingw
. Необходимо запустить терминал и перейти в директорию с исходным кодом проекта. Далее запустить из консоли командный файлcompile.cmd
.
- Модернизировать клиент и сервер так, чтобы можно было обмениваться сообщениями в двухстороннем режиме (“полудуплексный консольный чат”).
- Отладить и протестировать программы.
- Проброс COM портов через TCP/IP с помощью Virtual Serial Ports Emulator (Windows) и взаимодействие с удаленным сервером
- Выполнить проброс COM-порта
Создаем коннектор к виртуальному COM-порту, с которым будет работать клиентское приложение
Указываем IP-адрес удаленного сервера (обязательно тот, который указан на скриншоте) и номер порта (аналогично). Выбираем COM-порт, который будет проброшен
Connector и TcpClient сконфигурированы
- установить параметры подключения к удаленному COM-порту сервера
int portRate = 9600; // Скорость обмена
- передать строку со своей фамилией и группой в качестве посылки на сервер. Например:
petrov_IVT_574
- сохранить ответ сервера в отчет и использовать его как ключ при отправке лабораторной работы на проверку
Отчет оформляется на листах формата А4 а соответствии с требованиями стандартов ЕСКД. Отчёт о лабораторной работе должен содержать:
- название, цель и задачи работы;
- скриншоты процедуры создания пары виртуальных портов, краткая характеристика программы создания;
- скриншоты тестирования обмена данными через пару виртуальных портов с помощью программ
client
иserver
, ключевые участки исходного кода приложений, описание используемых библиотек; - исходный код приложений, осуществляющих обмен данными по COM-порту, используя API Windows NT;
- исходный код и скриншоты приложения для взаимодействия с удаленным сервером с проброшенным COM-портом;
- выводы о проделанной работе в целом.
- В чем заключается старт-стопный способ синхронизации?
- Какое напряжение соответствует логической единице в интерфейсе RS232?
- В чем заключаются особенности использования последовательного интерфейса RS-232С?
- Опишите организацию сопряжения двух устройств через RS-232С.
- Охарактеризуйте внутреннее аппаратное устройство, разъем и кабель порта RS-232С?
- Объясните порядок обмена по интерфейсу RS-232С.
- Приведите типы последовательных интерфейсов и опишите их особенности.
- Опишите особенности программирования интерфейса RS-232С.