Работа с последовательными портами


Содержание

Работа с последовательным портом UART (serial) на Arduino

Последовательный интерфейс (serial) предназначен передачи данных через универсальный асинхронный порт UART. Порт UART очень часто используется для передачи данных с Ардуино на компьютер, и обратно, а также для связи нескольких плат ардуин между собой.

Для многопортовых DUE/MEGA см. здесь.

Основные функций для работы с последовательным портом (Serial)

Serial.begin(rate) — Открывает последовательный порт и задаёт скорость для последовательной передачи данных. Типичная скорость обмена для компьютерной коммуникации — 9600.

Очевидно, когда задействован последовательный порт, выводы 0 (RX) и 1 (TX) не могут использоваться для других целей.

Serial.println(data) — Передаёт данные в последовательный порт, сопровождая автоматическим возвратом каретки и переходом на новую строку.

Serial.print(data) — тоже самое без возврата каретки и перехода на новую строку.

Serial.begin(скорость_передачи); — Инициализация порта. Задает скорость передачи в битах в секунду. Нормированные скорости: 300, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, или 115200.

count = Serial.available(); — Принимаемые по последовательному порту байты попадают в буфер микроконтроллера, откуда Ваша программа может их считать. Функция возвращает количество накопленных в буфере байт. Последовательный буфер может хранить до 128 байт.

char = Serial.read(); — Считывает следующий байт из буфера последовательного порта. возвращает -1 если нет входящих данных

Serial.flush(); — Ожидает окончания передачи исходящих данных (до версии Arduino 1.0 функция очищала буфер последовательного соединения)..

Разные варианты функции print:

Serial.print(b, DEC); — выводит ASCII-строку — десятичное представление числа b.

Serial.print(b, BYTE) — выводит младший байт числа b.

(аналогично HEX, OCT, BIN).

Serial.print(str) // если str — строка или массив символов, побайтно передает str на COM-порт.

Serial.println(); — отличие заключается в том, что после данных дополнительно выводятся два символа – символ возврата каретки (ASCII 13, или ‘\r’) и символ новой линии (ASCII 10, или ‘\n’).

Функция write:

Serial.write(uint8_t c); — Записывает данные в последовательный порт. Данные посылаются как байт или последовательность байт.

Serial.write(val); // где val — переменная для передачи, как единственный байт

Serial.write(str); // где str — строка для передачи, как последовательность байт

Serial.write(buf, len); // где buf — массив для передачи, как последовательность байт; len — длина массива.

Пример 1. Передача данных по Serial-порту с Arduino на компьютер

Инициализация порта со скоростью 9600 бот и передача данных (от Arduino на внешние устройства, например на компьютер):

Пример 2. Передача данных по Serial-порту с компьютера на Arduino

serialEvent() — функция вызывается автоматически, когда поступают данные.

Serial.setTimeout() — задает максимальное время (в мс) для работы Serial.readBytesUntil();

Возможные проблемы

1) auto-reboot DTR : возможна автоперезагрузка МК при передаче на него данных по serial-пору. Чтобы отключить это, надо поставить конденсатор 10мкФ между RES и GND. Я ставил электролитический кондер (естественно, + на RES).

Как соединить две ардуины по UART (serial) порту

Схема соединения двух ардуин:

Длина провода и скорость: RS-232 (англ. Recommended Standard 232) — стандарт физического уровня для асинхронного интерфейса (UART).

Расстояние связи по RS232 максимум 15 метров.

Но всё зависит от скорости.

Работа Arduino MEGA/DUE с несколькими последовательными serial портами

Многопортовые ардуино.

Как вы уже заметили, на ардуиновских платах Mega и Due имеется по 4 последовательных порта, а именно:

Serial — выводы 0 (RX) and 1 (TX);

Serial1 — выводы 19 (RX) and 18 (TX);

Serial2 — выводы 17 (RX) and 16 (TX);

Serial3 — выводы 15 (RX) and 14 (TX).

Естественно, что на Due используется напряжение 3.3 В (на MEGA как обычно 5 В).

Как с ними работать?

Здесь синим цветом выделены собственно имена объектов ( Serial , Serial1 , Serial2 , Serial3 ), которые используются в коде программы для работы с их методами. Всё просто! Например,

Пример вывода на дисплей LCD1602 через последовательный порт UART Arduino из-под Linux средствами языка Python

Короче говоря, есть комп с линуксом, к которому подключена Arduino через USB, а к арудине подключен дисплей LCD1602, и мы хотим на него выводить инфу.

Сначала привожу полный код программы для Arduino UNO, к которой подключен дисплей LCD1602:

Я сделал здесь решетку ‘#’ в качестве символа завершения передачи пакета данных. Как только в потоке данных встречается символ #, данные выводятся на дисплей, и буфер обнуляется, при этом сам символ ‘#’ не выводится. Конечно, можно было бы использовать ‘\n’ или др.

Далее мы напишем скрипт на Python, который будет выводить инфу на дисплей. Я выбрал Python, потому что это прикладной язык и он лучше всего подходит для подобных задач. С такими языками как C++/C# и т.п. больше возни с библиотеками, а здесь всё просто, особенно если это дело происходит под линуксом.

Первым делом устанавливаем необходимые библиотеки (для 2-ой или 3-ей версии python)

$sudo apt-get install python-serial

$sudo apt-get install python3-serial

Далее в интерпретаторе python пишем:

Здесь ардуина у меня подключена к порту /dev/ttyUSB0 — это я узнавал из Arduino IDE. Обычно она всегда на этом порту сидит, если других устройств на последовательный порт не подключено.

Как вы уже догадались, и в первой, и во второй программы должна быть указано одинаковая скорость в бодах. В моем случае это 9600 — стандартная, хотя и маленькая скрость. Может быть и больше (читай выше).

Использование последовательного порта (стр. 1 из 7)

МИНИСТЕРСТВО НАУКИ И ОБРАЗОВАНИЯ РЕСПУБЛИКИ КАЗАХСТАН

ЮЖНО-КАЗАХСТАНСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ им. М. Ауезова

Кафедра: «Программное и аппаратное обеспечение компьютерных систем и сетей»

По дисциплине: «Системное программное обеспечение»

На тему: Использование последовательного порта: передача файлов и простейшие ЛВС.

по специальности 37.04 «Программное и аппаратное обеспечение систем и сетей»

Разработал (а): _____________________

Руководитель проекта: ____________________________________

Курсовой проект защищен с оценкой _____________________________

1.


2.

3.

4.

5.

Введение. 3
Асинхронная последовательная передача данных. 3
1.1 Стандарт RS-232. 4
1.2 Проблемы передачи данных. 5
1.3 Доступ к последовательному порту компьютера. 5
1.4 Передача и прием байтов. 7
Передача файлов и программ между компьютерами. 9
2.1 Перекачка файла. 10
2.2 Прием файла. 11
2.3 Перекачка программы. 12
Простейшая ЛВС. 17
3.1 Файловый сервер. 17
3.2 Загрузка удаленных файлов в узел сети. 24
3.3 Хранение файлов. 27
3.4 Использование ЛВС. 30
Заключение: Совершенствование ЛВС. 30
Список использованной литературы. 31

Использование последовательного порта: передача файлов и простейшие ЛВС.

Пожалуй нет такой дpугой общей беды для всех пpогpаммистов, как асинхpонный последовательный поpт. Непохожий на более пpостой паpаллельный поpт, последовательный поpт, как ни кто более подвеpжен целому семейству pазличных типов ошибок пеpедачи данных. Пpоблема усложняется тем, что сигнал «подтвеpждение связи», котоpый помогает коppектно выполнять соответствующую пеpедачу данных пpименительно к последовательному поpту часто пеpедается «мимо» шины кабеля, связывающего последовательный поpт и внешнее устpойство. Однако, несмотpя на эти пpоблемы последовательный поpт используется шиpе, так как именно он позволяет использовать самый дешевый путь для соединения двух устpойств, pазнесенных на pасстояние, пpевышающее паpу футов.

Цель этой работы — дать основы устpойства последовательного поpта и pаботы с ним, включая инициализацию, пеpедачу и пpием данных, а также обсудить наиболее общие ошибки, возникающие во вpемя pаботы с последовательным поpтом.

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

Пpимеpы, пpиведенные в этой работе, совместимы с компьютеpами IBM PC, XT, AT или PS/2 (а также на совместимых с этими моделями) под упpавлением DOS. Однако вы легко сможете осуществить их пеpенос в дpугие опеpационные системы, включая OS/2.

1 . Асинхронная последовательная передача данных

Пеpед тем, как пеpейти к изучению последовательного асинхpонного поpта вообще вам необходимо получить некотоpые сведения о пpинципах асинхpонной пеpедачи данных. ( В дальнейшем, для пpостоты изложения матеpиала будем называть асинхpонный последовательный поpт — «последовательным поpтом»). Данные пеpедаются чеpез последовательный поpт поpциями в один бит за единицу вpемени. В этом состоит отличие последовательного поpта от паpаллельного, котоpый осуществляет пеpедачу данных поpциями в один байт за единицу вpемени. Пеpедача данных называется асинхpонной потому, что длина интеpвала вpемени между пеpедачей очеpедного байта инфоpмации (по 1 биту за единицу вpемени) не имеет никакого значения. Поэтому основными являются синхpонизация и последовательность пеpедачи цепочки бит,котоpые в конечном итоге составляют байт или дpугую инфоpмационную единицу.

Каждый байт данных, пеpедаваемых чеpез последовательный поpт, состоит из следующей последовательности сигнальных битов:

1. Один стаpтовый бит

2. Восемь битов данных ( в некотоpых случаях — 7 )

3. Необязательный бит четности

4. Один или два конечных бита

Между пеpедачей каждого байта может пpоходить некотоpый пpомежуток вpемени.

Вpемя пpостоя канала пеpедачи для этого pежима довольно велико. Младший бит пеpедаваемой «поpции» данных имеет нулевое значение, стаpший бит, завеpшающий очеpедную «поpцию» данных, пpинимает значение pавное единице. Стаpший бит сигнализиpует о начале пеpедачи нового байта, котоpый считывается в канал за один цикл, начиная с младшего бита. Биты данных пеpедаются вслед за необязательным битом четности. В конце пеpесылаются один или два бита, сигнализиpующих о конце очеpедной «поpции» данных, считанных за один цикл. Завеpшающие (конечные) биты опpеделяют минимальное вpемя между пеpедачей двух байтов. Обычно число завеpшающих битов не имеет большого значения, поэтому вы можете использовать либо один, либо два завеpшающих бита в зависимости от того, какое их число используют пеpедающий и пpинимающий поpты.

Бит четности, если он пpисутствует в пеpедаваемом сообщении, используется для контpоля коppектности пеpедачи и поиска ошибок. Контpоль пеpедачи может пpоводиться как на четность (контpольный pазpяд pавен сумме по модулю 2 инфоpмационных pазpядов и общее число единичных pазpядов четно), так и на нечетность (контpольный pазpяд не pавен сумме по модулю 2 инфоpмационных pазpядов и общее число единичных pазpядов нечетно).

Скоpость пеpедачи битов по каналу измеpяется в бодах (бит в секунду). Наименьшей скоpостью пеpедачи инфоpмации считается 300 бод. Эта скоpость пеpедачи использовалась в стаpых модемах (сейчас большинство модемов позволяют достигать скоpости пеpедачи от 1200 до 56 000 бод). Семейство компьютеpов IBM PC поддеpживают скоpость пеpедачи данных в 56 000 бод. Некотоpые типы компьютеpов позволяют достигать скоpости пеpедачи данных в 1 000 000 бод!

Несмотpя на то, что изучение стандаpта RS-232 не имеет большого влияния на понимание pаботы асинхpонного последовательного поpта в целом, ознакомление со стандаpтом асинхpонного последовательного интеpфейса RS-232 (аналог в СССР — стык С-2) является целью настоящей работы. Изучение этого матеpиала поможет вам более детально понять, какие пpоблемы возникают пpи использовании последовательного поpта и как эти пpоблемы могут быть pазpешены.

Конфигуpация большинства последовательных поpтов является стандаpтной, однако наиболее шиpокое pаспpостpанение получила конфигуpация, соответствующая стандаpту RS-232. По этому стандаpту pазъем содеpжит 25 контактов. (В компьютеpе IBM PC AT используется 9-ти контактный pазъем). Следует отметить, что довольно большое число последовательных поpтов не поддеpживают весь набоp сигналов, специфициpованных в стандаpте RS-232. Некотоpые сигналы не поддеpживаются в связи с тем, что они не пpедназначены для использования в таком пpиложении и служат для дpугих целей; дpугие не поддеpживаются по пpичине того, что они выпускались в то вpемя, когда стандаpт RS-232 еще не существовал вообще или же целью их создания не являлась полная поддеpжка стандаpта RS-232 и они в этом случае включают лишь огpаниченный набоp сигналов RS-232 . Наиболее общими сигналами стандаpта RS-232 являются:

Сигнал Аббpевиатуpа Штыpь pазъема

Запpос на посылку данных RTS 4

Очистка для посылки CTS 5

Набоp данных готов DSR 6

Набоp данных завеpшен DTR 20

Пеpедача данных TxD 2

Пpием данных RxD 3

На самом деле сигналов намного больше и это обусловлено тем, что последовательный поpт пеpвоначально pазpабатывался как устpойство поддеpжки модема. В связи с этим, если поpт используется совместно с дpугими устpойствами, то многие из его сигналов пpосто в этом случае не нужны. Эти сигналы используются для установления пpотокола аппаpатного уpовня между модемом и компьютеpом, если этот компьютеp (1) еще не пеpедавал инфоpмацию, но уже готов к ее пеpедаче или (2) пеpедача данных от модема к компьютеpу еще не осуществлялась.

COM порт Windows. SerialPort. C#.Продолжение.

Для создания Windows приложения будем использовать Microsoft Visual Studio 2012. В более современных версиях Visual Studio всё должно работать аналогично. В версиях младше , следует проверить наличие компонента SerialPort.

Создаем новый проект Visual C # с графическим интерфейсом. Затем, открываем дизайнер форм и размещаем необходимые нам элементы. Я размещу ComboBox для отображения доступных COM портов системы, Button для подключения к порту , Label для отображения принятых данных и компонент SerialPort для работы с COM портом.

У меня получилось так :

Так же не забудьте настроить свойства COM -порта (скорость передачи, чисто бит данных, число стоп-бит и т.д.), при необходимости, что так же делается в дизайнере форм.

В панели событий можете так же настроить обработку события DataReceived , которое происходит при каждом получении данных COM портом. Теперь перейдем к коду. Принцип работы с компонентом SerialPort можете посмотреть в предыдущем уроке.

Вопросы по работе кода можете оставлять в комментариях.

Похожие статьи

COM порт Windows. SerialPort. C#.Продолжение. : 11 комментариев

В 2010 версии тоже есть. А вот в Дельфях нет, приходится инициализировать вручную длинным нудным кодом )))

Да, в плане скорости разработки C# прекрасен)
2010 студии под рукой не было)

Не работает. Создаю элементы, вставляю код. 17 ошибок. В чем может быть проблема?

Будьте добры, приведите код ошибок.

Я разобрался. Все работает! Спасибо!

Добрый день, только начал работать с C# при создании всех элементов формы их переименовывании и добавлении вашего кода вылетает основная ошибка в виде: «Имя SerialPort отсутствует в текущем контексте».
Using SYSTEM.IO.Ports подключен

Здравствуйте!
Это означает что нет переменной с данным названием. Вы добавили на форму соответствующий компонент?

Неужели при приеме данных у вас не возникает вот такая ошибка:
Недопустимая операция в нескольких потоках: попытка доступа к элементу управления ‘label1’ не из того потока, в котором он был создан.

Что бы обеспечить прием данных в C# вообще нужно вот такой сатанинский код писать

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
<
this.Invoke(new EventHandler(DoUpdate)); // Что это такое вообще не понятно…
>

private void DoUpdate(object s, EventArgs e)
<
label1.Text = serialPort1.ReadExisting(); // И вот только теперь нормально считывается в label1
>

И этот код самое вменяемое, что мне удалось найти. Есть еще более извращенные методы, которые совсем для новичков не понятны

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

не обрабатывается событие click У кнопки.
private void connectButton_Click(object sender, EventArgs e) <
connectButton.Text = «…»;
>

Спасибо за инструкции, со многим разобрался.
Даже написал свой COM — COM чат.

Arduino. Работа с COM-портом

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

Подготовка к работе

Большинство микроконтроллеров обладают множеством портов ввода-вывода. Для связи с ПК наиболее пригоден из них протокол UART. Это протокол последовательной асинхронной передачи данных. Для его преобразования в интерфейс USB на плате есть конвертор USB-RS232 – FT232RL.
Для выполнения примеров их этой статьи вам будет достаточно только Arduino-совместимая плата. Мы используем EduBoard. Убедитесь, что на вашей плате установлен светодиод, подключенный к 13му выводу и есть кнопка для перезагрузки.

Таблица ASCII

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

Переменная symbol хранит код символа. Таблица начинается со значения 33 и заканчивается на 126, поэтому изначально переменной symbol присваивается значение 33.
Для запуска работа порта UART служит функция Serial.begin(). Единственный ее параметр – это скорость. О скорости необходимо договариваться на передающей и приемной стороне заранее, так как протокол передачи асинхронный. В рассматриваемом примере скорость 9600бит/с.
Для записи значения в порт используются три функции:

  1. Serial.write() – записывает в порт данные в двоичном виде.
  2. Serial.print() может иметь много значений, но все они служат для вывода информации в удобной для человека форме. Например, если информация, указанная как параметр для передачи, выделена кавычками – терминальная программа выведет ее без изменения. Если вы хотите вывести какое-либо значение в определенной системе исчисления, то необходимо добавить служебное слово: BIN-двоичная, OCT – восьмеричная, DEC – десятичная, HEX – шестнадцатеричная. Например, Serial.print(25,HEX).
  3. Serial.println() делает то же, что и Serial.print(), но еще переводит строку после вывода информации.

Для проверки работы программы необходимо, чтобы на компьютере была терминальная программа, принимающая данные из COM-порта. В Arduino IDE уже встроена такая. Для ее вызова выберите в меню Сервис->Монитор порта. Окно этой утилиты очень просто:

Теперь нажмите кнопку перезагрузки. МК перезагрузится и выведет таблицу ASCII:

Обратите внимание на вот эту часть кода:

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

Отправка команд с ПК


Прежде чем этим заниматься, необходимо получить представление относительного того, как работает COM-порт.
В первую очередь весь обмен происходит через буфер памяти. То есть когда вы отправляете что-то с ПК устройству, данные помещаются в некоторый специальный раздел памяти. Как только устройство готово – оно вычитывает данные из буфера. Проверить состояние буфера позволяет функция Serial.avaliable(). Эта функция возвращает количество байт в буфере. Чтобы вычитать эти байты необходимо воспользоваться функцией Serial.read(). Рассмотрим работу этих функций на примере:

После того, как код будет загружен в память микроконтроллера, откройте монитор COM-порта. Введите один символ и нажмите Enter. В поле полученных данных вы увидите: “I received: X”, где вместо X будет введенный вами символ.
Программа бесконечно крутится в основном цикле. В тот момент, когда в порт записывается байт функция Serial.available() принимает значение 1, то есть выполняется условие Serial.available() > 0. Далее функция Serial.read() вычитывает этот байт, тем самым очищая буфер. После чего при помощи уже известных вам функций происходит вывод.
Использование встроенного в Arduino IDE монитора COM-порта имеет некоторые ограничения. При отправке данных из платы в COM-порт вывод можно организовать в произвольном формате. А при отправке из ПК к плате передача символов происходит в соответствии с таблицей ASCII. Это означает, что когда вы вводите, например символ “1”, через COM-порт отправляется в двоичном виде “00110001” (то есть “49” в десятичном виде).
Немного изменим код и проверим это утверждение:

После загрузки, в мониторе порта при отправке “1” вы увидите в ответ: “I received: 110001”. Можете изменить формат вывода и просмотреть, что принимает плата при других символах.

Управление устройством через COM-порт

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

При отправке в COM-порт символа “H” происходит зажигание светодиода на 13ом выводе, а при отправке “L” светодиод будет гаснуть.
Если по результатам приема данных из COM-порта вы хотите, чтобы программа в основном цикле выполняла разные действия, можно выполнять проверку условий в основном цикле. Например:

Если в мониторе порта отправить значение “1” светодиод будет мигать с частотой 5Гц. Если отправить “0” – частота изменится на 1Гц.

Работа с COM-портом в C++ (соединение с Arduino)

Доброго времени суток, уважаемые коллеги!
Мне для проекта требуется соединить Arduino и компьютер через СОМ-порт. Скачал библиотеку CSerialPort, написал программу — не работайт! Пожалуйста, помогите разобраться, желательно с примерами кода, поменьше WinAPI (Я не профи в этой области).
Заранее благодарю.

Добавлено через 1 минуту
P. S.: Я использую VisualStudio!

01.12.2020, 12:51

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

Работа с COM портом
Здравствуйте! В процессе написания программы работы с устройством, подключенным к ПК через.

Работа с COM-портом
Подскажите, какие компоненты нужны для работы с ком-портами? а именно (хотя бы для начала) отправка.

Работа с COM портом
по COM порту через Agilen подключается вольтметр с адресом 1. необходимо «прозвонить» все порты и.

Работа с Com портом
Привет всем! У меня собственно такая ситуация, есть bluetooth и телефон Nokia устанавливаю.

Работа с последовательными портами

Эта статья показывает, как записывать и читать данные от устройства, подключенного к последовательному порту (COM-порт) из приложения на языке C# в среде .NET. Мы будем читать и записывать данные через TextBox на форме, и будем работать с потоками.

В недалеком прошлом для работы с Serial Port в среде .Net 1.1, мы должны были использовать либо Windows API, либо использовать управление из сторонних библиотек. В среде .Net 2.0 (и в более поздних версиях .NET) компания Microsoft добавила поддержку последовательного порта включением класса SerialPort как части пространства имен System.IO.Ports. Реализация класса SerialPort сделана очень прямо и очевидно. Чтобы создать экземпляр класса SerialPort class, просто передайте опции SerialPort конструктору класса:

Для приема данных нам нужно создать обработчик события EventHandler для «SerialDataReceivedEventHandler»:

Вы можете также установить другие опции, такие как ReadTimeout и WriteTimeout (таймауты чтения и записи):

Как только Вы готовы использовать последовательный порт, Вам нужно открыть его:

Сейчас мы готовы принять данные. Однако чтобы записать эти данные в область ввода TextBox на форме, нам нужно создать так называемого делегата (delegate). Библиотеки .Net не позволяют межпотоковое взаимодействие (cross-thread action), так что нам нужно использовать делегат. Делегат используется для записи в поток пользовательского интерфейса (User Interface, UI) из другого потока (не UI).

Мы создадим теперь метод «sp_DataReceived», который будет выполнен при поступлении данных в последовательный порт:

Теперь создадим наш метод «si_DataReceived»:

Мы можем теперь принять данные из последовательного порта от устройства и отобразить их на форме. Некоторые устройства отправляют данные сами, без запроса. Однако некоторым устройствам нужно отправить определенные команды, чтобы они ответили на них какими-то своими данными. Для этих устройств Вы будете записывать данные в последовательный порт, и будете использовать предыдущий код, чтобы получить данные обратно. В этом примере будет происходить обмен со шкалой. Для отдельной шкалы отправка команды «SI\r\n» приведет к возврату веса, который имеется на шкале. Эта команда является специфической именно для этого устройства, в Вашем же случае нужно читать документацию по протоколу устройства, чтобы найти команды, принимаемые устройством. Для записи в последовательный порт создайте кнопку «Start» на форме, и добавьте код в событие клика на ней Click_Event:

Это все, что нужно Вам сделать. См. ссылку [1] для загрузки готового проекта Microsoft Visual C# 2010.

[Как передавать по одному символу, с задержкой]

В случае, когда нужно реализовать обмен с устройством, рассчитанным на взамодействие с пользователем (управляющая консоль). Так как пользователь вводит символы команды медленно, устройство успевает принять все символы и обработать. Если передавать символы быстро (методом SerialPort.Write), по несколько байт, то есть риск потери данных. Во врезке ниже приведен пример класса COMdevice, где реализован метод Write, который передает символы через задержку.

[Как перекодировать символы ANSI в UTF8]

Очень часть устройства на микроконтроллерах передают русские символы в кодировке ANSI (Windows-1251). Однако среда разработки Visual Studio C# хранит и обрабатывает русскоязычный текст в кодировке UTF8, и при попытке отобразить принятый текст (методом ReadExisting) выводятся кракозябры.

Решить проблему можно, если организовать байтовый буфер, и перекодировать массив байт с помощью класса Encoding (методом GetEncoding(1251).GetString). Пример кода в классе COMdevice приведен во врезке ниже.

[Ссылки]

Комментарии

[quote name=»Владимир»]Не очень шарю в С/С++/С#. При запуске этого приложения выдает ошибку в textbox «Порт ‘COM1’ не существует.» Всё подключено в порт COM4. В Вашем приложении не предлагается выбор портов в ComboBox1, список пуст. Подскажите в чем может быть проблема.

Работа с последовательными портами

Эта статья показывает, как записывать и читать данные от устройства, подключенного к последовательному порту (COM-порт) из приложения на языке C# в среде .NET. В этой статье мы создадим class RS485Server для работы с нашим газоанализатором по интерфейсу RS485. В недалеком прошлом для работы с Serial Port в среде .Net 1.1, мы должны были использовать либо Windows API, либо использовать управление из сторонних библиотек. В среде .Net 2.0 (и в более поздних версиях .NET) компания Microsoft добавила поддержку последовательного порта включением класса SerialPort как части пространства имен System.IO.Ports. Реализация класса RS485Server сделана очень прямо и очевидно. Для начала опишем используемые классом переменные:

На следующем этапе реализуем функцию Connect, отвечающую за открытие нашего com порта:

Как видите функция получилась достаточно простой. В качестве аргументов она принимает имя com порта и требуюмую скорость. Для определения существующих com портов удобно пользоваться следующей конструкцией:

Для приема данных нам нужно создать обработчик события EventHandler для «SerialDataReceivedEventHandler». В качестве этого приемника будет выступать метод Receiver:

Мы уже писали про использование формата JSON для общения наших устройств с серверным ПО. По этому в потоке происходит чтение данных с нашего com порта, и поиск данных заключенных в фигурные скобки < >. Далее для десериализации принятых данных используется компонент JsonConvert Class. Использовать его достаточно просто, для парсинга принятых данных, необходимо создать класс, соответствующий нашему запросу:

Для десеарилизации наших данных достаточно создать экземпляр класса Ans_Device с нашими десериализованными данными:

Для завершения создания нашего класса осталось реализовать два простых метода. Первый, это метод Send, отправляющий данные в com порт:

Второй, это метод Close, закрывающий наш порт, если он открыт:

Ниже можно наблюдать видео работы получившегося класса.

Работа с COM-портом в C++

В сети есть куча мануалов и примеров по работе с портом в C++, но у меня как-то неохотно они работают. Изначально юзал QSerialPort, все было прекрасно до тех пор, пока случайно не выяснил, что QT-шный waitForReadyRead() забагован и кладет мою программу когда ему вздумается.

Решил попробовать поработать с HANDLE , но лыжи пока не едут.

Если я напишу «COM6», что вполне логично, то порт открыть не получается. Зато спокойно открывает «COM:6» и COM-ы 7, 11, 15 и т.д., которых и в помине нет. Выгрузить и установить настойки скорости, например, тоже не получается — вываливается ошибка.

Что я делаю не так?

Edit: Прошу прощения, после 2-3 часового тупняка решил спросить здесь от безнадеги. Я понял, что открываются все порты, кроме тех, которые реально существуют, проверил if(..) , оказалось выдернул где-то неверный код. Должно быть так:

2 ответа 2

Для открытия порта лучше использовать вот такое имя port = «\\\\.\\COM2»;
1) с хэндлом сами нашли if(serialPort!=INVALID_HANDLE_VALUE)
1.1) Для работы с портом с помощью асинхронного ио необходим флаг FILE_FLAG_OVERLAPPED
2) Для установки очереди SetupComm(. )
3) Для установки таймаутов SetCommTimeouts(. )
4) Для установки скоростей/четности и т.п. SetCommState(. )
5) Для установки маски событий на порту SetCommMask(. )
6) Для выполнения доп. функций EscapeCommFunction(. )
7) Для очистки линии PurgeComm(. )
8) Для сброса ошибок ClearCommError(. )

Для асинхронного ио нужно создавать структуру примерно так:

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

Для чтения можно подписаться на ожидание сигналов на порту с помощью функции WaitCommEvent(. ) , который вернет вам управление при получении одного из сигналов, заданных в SetCommMask(. )

При получении сигнала EV_RXCHAR можно читать из порта.

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

Работа с последовательными портами

Вот мы и добрались до COM порта. Но с ним все не так просто как с LPT, и его полноценное использование потребует значительно больших усилий. Главной загвоздкой является и его главное преимущество — передача данных в последовательном виде. Если в LPT байт данных передается по 8-ми линиям по биту на каждую, и состояние каждой линии можно было легко посмотреть, то в COM порту байт данных передается бит за битом по одной линии (относительно земли, конечно) и посмотреть что там передается с помощью одних светодиодов не удастся. Для этого нужно специальное устройство — преобразователь потока последовательных данных в парраллельный, т.н. USART (Universal Synchronous/Asynchronous Receiver Transmitter). Например, он есть в составе материнской платы компьютера, снабженного COM портом, в любом более мение серьезном микроконтроллере.

Надеюсь, вы еще пали духом в освоении COM порта. Все не так уж и мрачно. Некоторые результаты можно получить и без USART. Сформулируем задачу, которую реализуем на начальном этапе работы с COM портом:

«Хочу что бы к компьютеру через COM порт подключался светодиод. Запускаю программу. Далаю какое-то действие в этой программе, светодиод загорается, делаю другое — светодиод тухнет.»

Задача довольно специфичная (с учетом того, что USART не используется) и является чистой «самопальщиной», но вполне реализуема и работоспособна. Давайте приступим к ее реализации.

Опять берем системный блок вашего ПК и смотрим в тыловую часть. Примечаем там 9-ти штырьковй разъем — это и есть COM порт. Реально их может быть неколько (до 4-х). На моем ПК установлено два COM порта (см. фото).

2. Удлинитель COM порта

Нам потребуется удлинитель COM порта, но не просто удлинитель, а т.н. нуль-модемный кабель. Как он выглядит? Так как на фото, причем на обох его концах установлен разьем типа «мама». Далее втыкайте его в любой COM порт Вашего ПК и выводите его на рабочее место.

3. Аппаратная часть


С аппаратной частью нам тоже придется «повозиться», в том смысле что она будет сложнее чем с первым устройством для LPT порта. Дело в том что протокол RS-232 по которому идет обмен данными в COM порту, имеет несколько отличное соотношение логическое состояние — напряжение. Если обычно это логический 0 0 В, логическая 1 +5 В, то в RS-232 это соотношение следующее: логический 0 +12 В, логическая 1 -12 В.

И например, получив -12 В не сразу понятно что с этим напряжением делать. Обычно проводят преобразование уровней RS-232 в ТТЛ (0, 5 В). Самый простой вариант — стабилитроны. Но я предлагаю сделать этот преобразователь на специальной микросхеме. Называется она MAX232.

Микросхема эта дешевая и широко распространенная. Особенных проблем в ее добывании возникнуть не должно. Что она умеет? Она одновременно может преобразовывать два сигнала из RS-232 в ТТЛ и еще два из ТТЛ в RS-232.

Теперь давайте посмотрим, а какие сигналы из COM порта мы можем посмотреть на светодиодах? В действительности, в COM порту есть аж 6 независимых линий, представляющих интерес для разработчика устройств сопряжения. Две из них пока для нас недоступны — линии по передаче последовательных данных. А вот оставшиеся 4 предназначены для управления и индикации процесса передачи данных и мы сможем «передалать» их под свои нужды. Две из них предназначены для управления со стороны внешнего устройства и мы их пока трогать не будем, а вот последние две оставшиеся линии мы сейчас и поиспользуем. Они называются:

  • RTS — Запрос на передачу. Линия взаимодействия, которая показывает, что компьютер готов к приему данных.
  • DTR — Компьютер готов. Линия взаимодействия, которая показывает, что компьютер включен и готов к связи.

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

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

А вот ее практичекая реализация. Я думаю вы меня простите, что я сделал ее в таком стремном макетном варианте, ибо делать плату для такой «высоко продуктивной» схемы не хочется.

4. Программная часть

Тут все попроще. Давайте создадим Windows приложение в Microsoft Visual C++ 6.0 на основе MFC для управления двумя линиями взаимодействия COM порта. Для этого создаем новый проект MFC и указываем ему имя, например, TestCOM. Далее выбираем вариант построения на основе диалога.

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

Далее, в файле TestCOMDlg.h в описание класса диалога добавьте строчку: HANDLE hFile;.

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

С помощью стандарной функции Win API CreateFile() открываем COM-порт COM2. Далее проверяем успешность открытия с выводом информационного сообщения. Вот тут надо сделать важное замечание: COM2 — это в моем компьютере, а на Вашем компьютере Вы могли подключить его к другому COM порту. Соответственно, его имя нужно изменить на то, кокай порт Вы используете. Посмотреть, какие номера портов присутствуют на Вашем компьютере, можно так: Пуск -> Настройка -> Панель управления -> Система -> Оборудование -> Диспетчер устройств -> Порты (COM и LPT).

В итоге, функция CTestCOMDlg::OnInitDialog(), расположенная в файле TestCOMDlg.cpp, класса нашего диалога должна принять вид:

Теперь добавим обработчики кнопок управления линиями. Я дал им соответствующие имена: функция, которая устанавливает еденицу на линии DTR — OnDTR1(), 0 — OnDTR0(). Для линии RTS соответственно аналогичным образом. Напомню, что обработчик создается при двойном щелчке на кнопке. В итоге, эти четыре функции должны принять вид:

Поясню немного как они работают. Как видно, внитри себя они содержат вызов одной и той же Win API функции EscapeCommFunction() с двумя параметрами. Первый из них — это хэндл (HANDLE) на открытый порт, второй — специальный код действия, соответствующий необходимому состоянию линии.

Все, комилируем, запускаем. Если все хорошо, должны увидеть сообщение об успешном открытии порта. Далее, нажатием соответствующих кнопок мигаем светодиодами, подключенными к COM порту.

Serial Programming Guide for POSIX Operating Systems

Данное руководство: «The Serial Programming Guide for POSIX Operating Systems» — покажет вам как правильно, эффективно и переносимо программировать последовательные порты на вашей рабочей станции UNIX® и/или PC. Каждая глава предусматривает примеры программ которые используют POSIX (Portable Standard for UNIX) функции управления терминалом, и которые, с минимальными изменениями, должны работать на IRIX®, HP-UX, SunOS®, Solaris®, Digital UNIX®, Linux®, и большинстве других UNIX-подобных операционных системах. Наибольшие различия, которые вы обнаружите, затрагивают имена файлов устройств последовательных портов и файлов блокировки.

Руководство содержит следующие главы и приложения:

Эта глава является введением в передачу данных по последовательным линиям, RS-232 и другие стандарты которые используются для большинства компьютеров, а также о том как получить доступ к последовательным портам из C программы.

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

При последовательной передаче, каждое пересылаемое слово (байт или символ) данных посылается побитно. Каждый бит имеет состояние on ( 1 ) или off ( 0 ). Другие возможные термины: mark для состояния on и space для состояния off .

Очень часто скорость последовательной передачи данных выражается в количестве битов переданных за секунду (bits-per-second / «bps») или в бодах («baud»). Это представляет только количество единиц и нулей которые могут быть переданы в течение одной секунды. На заре компьютерной техники, скорость передачи в 300 бод считалась достаточно быстрой, но в наше время компютеры могут обеспечить скорость передачи по RS-232 вплоть до 430,800 бод! Возможно, когда скорость передачи достигает 1,000, вы видите скорость показываемую в кило бодах, или kbps (т.е. 9.6k, 19.2k, и т.д.). Для скоростей выше 1,000,000 значения показываются в мега бодах, или Mbps (т.е. 1.5Mbps).

Когда говорят об устройствах последовательной передачи или о последовательных портах, их называют как Data Communications Equipment («DCE») или Data Terminal Equipment («DTE»). Различие между ними в том, что каждая сигнальная пара приема и передачи у них поменяна местами. При подключении двух DTE (или двух DCE) используется нуль-модемный кабель или адаптер, который меняет местами сигнальные пары приема и передачи.

RS-232 — это стандартный электрический интерфейс для последовательной передачи данных, объявленный Electronic Industries Association («EIA»). Реально, RS-232 встречается с тремя различными особенностями (A, B, и C) каждая из которых объявляет различный диапазон напряжений для уровней on и off . Наиболее часто встречаемая разновидность — RS-232C, которая объявляет уровень mark bit ( on ) как напряжение между -3V и -12V, и уровень space bit ( off ) как напряжение между +3V и +12V. Спецификация RS-232C говорит, что эти сигналы могут распространяться на расстояние до 25 футов (8 метров). Обычно вы можете передавать сигналы немного дальше, но при этом понижается скорость передачи.

Кроме сигналов принимаемых и передаваемых данных, существуют другие сигналы, предусматривающие синхронизацию, состояние и квитирование:

Таблица 1 — Назначение выводов RS-232
Pin Description Pin Description Pin Description Pin Description Pin Description
1 Earth Ground 6 DSR — Data Set Ready 11 Unassigned 16 Secondary RXD 21 Signal Quality Detect
2 TXD — Transmitted Data 7 GND — Logic Ground 12 Secondary DCD 17 Receiver Clock 22 Ring Detect
3 RXD — Received Data 8 DCD — Data Carrier Detect 13 Secondary CTS 18 Unassigned 23 Data Rate Select
4 RTS — Request To Send 9 Reserved 14 Secondary TXD 19 Secondary RTS 24 Transmit Clock
5 CTS — Clear To Send 10 Reserved 15 Transmit Clock 20 DTR — Data Terminal Ready 25 Unassigned

Также, вы можете встретить еще два стандарта на последовательный интерфейс: RS-422 и RS-574. RS-422 использует более низкое напряжение и дифференциальные сигналы, что позволяет увеличить длину кабеля до 1000 футов (300 метров). RS-574 описывает 9-контактный последовательный PC разъем и напряжения.

Стандарт RS-232 описывает 18 различных сигналов для обеспечения последовательного обмена. Однако, только шесть из них реально доступны в окружении UNIX.

GND — Logic Ground (логическая земля)

Технически, логическая земля сигналом не является, без нее ни один из других сигналов не будет работать.

TXD — Transmitted Data (передача данных)

Сигнал TXD содержит данные передаваемые с вашей рабочей станции на компьютер или устройство, подключенное к другому концу линии (например, модем). Напряжение уровня mark (on) интерпретируется как значение 1, а напряжение уровня space (off) интерпретируется как значение 0.

RXD — Received Data (прием данных)

Сигнал RXD содержит данные передаваемые с компьютера или устройства, подключенного к другому концу линии, на вашу рабочую станцию. Также как и в случае сигнала TXD уровни mark и space интерпретируются как значения 1 и 0, соответственно.

DCD — Data Carrier Detect (обнаружение несущей удаленного модема/устройства)

Сигнал DCD принимается от компьютера или устройства, подключенного к другому концу линии. Уровень space (off) индицирует, что компьютер или устройство в текущий момент подключено к линии. Сигнал DCD не всегда используется и не всегда присутствует в реализации.

DTR — Data Terminal Ready (готовность терминала к передаче данных)

Сигнал DTR генерируется вашей рабочей станцией и указывает компьютеру или устройству, подключенному к другому концу линии, что вы готовы (уровень space (off)) или не готовы (уровень mark (on)) к передаче данных. Обычно сигдал DTR автоматически устанавливается в состояние готовности когда вы открываете (open) последовательный интерфейс вашей рабочей станции.

CTS — Clear To Send (разрешение передачи данных терминалу)

Сигнал CTS принимается с другого конца последовательной линии. Уровень space (off) индицирует готовность к посылке последовательных данных с вашей рабочей станции.

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

RTS — Request To Send (запрос на передачу)

Сигнал RTS, установленный в состояние уровня space (off) вашей рабочей станции, указывает о готовности вашей рабочей станции к пересылке данных.

Сигнал RTS, также как и сигнал CTS, используется для управления потоком передачи данных между вашей рабочей станцией и компьютером или устройством, подключенным к другому концу последовательной линии. Большинство рабочих станций удерживают этот сигнал в состоянии уровня space (off) все время.

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

В асинхронном режиме, линия последовательной передачи данных остается в состоянии mark (1) пока нет передачи символа. start -бит предшествует передаче каждого символа и немедленно сопровождается битами передаваемого символа, одним опциональным битом четности, и одним или более stop -битами. start -бит всегда передается уровнем space (0), и указывает компьютеру, что доступны новые данные для последовательной передачи. Данные могут быть посланы или приняты в любой момент времени, поэтому передача называется асинхронной.

Рисунок 1 — Асинхронная передача данных

Опциональный бит четности — это простая сумма битов данных, которая индицирует что данные содержат или не содержат четное или нечетное число единичных битов. При при установке передачи четной четности ( even parity ), бит четности равен 0 если в переданом символе четное число единичных битов. При при установке передачи нечетной четности ( odd parity ), бит четности равен 0 если в переданных данных нечетное число единичных битов. Вы также можете встретить термины: space parity , mark parity , и no parity . Space parity подразумевает, что бит четности всегда равен 0. Mark parity подразумевает, что бит четности всегда равен 1. No parity подразумевает, что бит четности отсутствует и не передается.

Оставшиеся биты называются stop -битами. Может быть представлено 1, 1.5, или 2 стоп-бита между передаваемыми символами. Стоп-биты всегда имеют значение 1. Традиционно, стоп-биты использовались для того, чтобы дать компьютеру время для обработки предидущего переданного символа, но в настоящее время стоп-биты используются только для синхронизации передачи данных.

Формат передачи асинхронных данных обычно выражается как «8N1», «7E1», и т.д. Это указывает «8 битов данных, нет четности, 1 стоп-бит», и «7 битов данных, четная (even) четность, 1 стоп-бит» соответственно.

Full duplex (полный дуплекс) подразумевает, что компьютер может одновременно передавать и принимать данные — существует два раздельных канала данных (один для входящих данных, и один для исходящих).

Half duplex (полудуплекс) подразумевает, что компьютер не может одновременно передавать и/или принимать данные. Обычно это подразумевает, что существует только один канал передачи данных. Однако, это не подразумевает, что любой из сигналов RS-232 не используется. Скорее это подразумевает, что комуникационная линия использует какой-нибудь другой стандарт, отличный от RS-232, который не поддерживает полнодуплекснуюработу.

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

Первый метод, часто называемый как «программное» управление потоком передачи данных («software» flow control), использует специальные символы для начала (XON или DC1, восьмеричное значение 021) или остановки (XOFF или DC3, восьмеричное значение 023) передачи данных. Эти символы объявлены в American Standard Code for Information Interchange («ASCII»). Эти коды полезны при передаче текстовой информации, однако они не могут быть использованы припередаче других типов данных без дополнительного специального программирования.

Второй метод, называемый как «аппаратное» управление потоком передачи данных («hardware» flow control), вместо специальных символов использует сигналы CTS и RTS интерфейса RS-232. Приемник устанавливает CTS в уровень space (off) когда он готов к приему последующих данных и в уровень mark (on) когда он не готов. Также, передатчик устанавливает RTS в уровень space (off) когда он готов к передаче последующих данных. Поскольку аппаратный метод управления потоком использует различные сигналы он намного быстрее программного метода, которому требуется пересылка множества битов для выполнения той же задачи. Однако, CTS/RTS управление потоком не всегда поддерживается аппаратной частью или операционной системой.

Обычно, сигнал приема или посылки данных находится в состоянии уровня mark (on) до начала передачи нового символа. Если сигнал переходит в состояние уровня space (off) на длительный период времени, обычно от 1/4 до 1/2 секунды, то говорят о возникновении условия break.

Иногда break используется для переустановки (сброса) коммуникационной линии или изменения режима работы коммуникационного оборудования подобного модему. Глава 3, Управление модемом описывает это более подробно.

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

Даже при такой синхронизации компьютер должен каким-нибудь образом обозначать начало данных. Наиболее общий способ решения этой задачи — использование пакетного протокола передачи данных, подобного Serial Data Link Control («SDLC») или High-Speed Data Link Control («HDLC»).

Каждый протокол объявляет определенные битовые последовательности для представления начала и конца пакета данных. Каждый протокол также описывает битовые последовательности которые используются при отсутствии данных. Эти битовые последовательности позволяют компьютеру обнаружить начало пакета данных.

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

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

Подобно всем устройствам, UNIX предоставляет доступ к последовательным портам через файлы устройств ( device files ). Для доступа к последовательному порту вы просто открываете соответствующий файл устройства.

Каждый последовательный порт в системе UNIX имеет один или более файлов устройств (файлы в каталоге /dev ) ассоциированных с ним:

Таблица 2 — Файлы устройств последовательных портов
Система Порт 1 Порт 2
IRIX® /dev/ttyf1 /dev/ttyf2
HP-UX /dev/tty1p0 /dev/tty2p0
Solaris®/SunOS® /dev/ttya /dev/ttyb
Linux® /dev/ttyS0 /dev/ttyS1
Digital UNIX® /dev/tty01 /dev/tty02

Поскольку последовательный порт — это файл, то для доступа используется функция open(2) . Одна из проблем в UNIX заключается в том, что файлы устройств обычно не доступны для обычных пользователей. Решением подобной проблемы может служить изменение прав доступа к файлу при запуске вашей программы с привелегиями администратора (root), или маркировании вашей программы как set-userid таким образом, что она будет запущена с правами владельца файла устройства.


На данный момент мы будем предпологать, что файл устройства доступен всем пользователям. Код для открытия последовательного порта 1 на рабочей станции sgi ® под управлением IRIX выглядит следующим образом:

Листинг 1 — Открытие последовательного порта.

Другие системы могут потребовать соответствующее имя для файла устройства, но остальной ко останется таким же самым.

Опции открытия

Вы можете заметить, что когда мы открывали файл устройства, мы использовали два дополнительных флага вместе с режимом чтение+запись:

Флаг O_NOCTTY говорит UNIX, что эта программа не хочет быть управляющим терминалом для этого порта. Если вы не укажете этого, то любой ввод (подобный сигналу абортирования от клавиатуры или что-нибудь подобное) будет затрагивать ваш процесс. Программы подобные getty(1M/8) используют эту возможность при старте логин-процесса, но обычно пользовательская программа не нуждается в таком поведении.

Флаг O_NDELAY говорит UNIX, что эта программа не заботится о состоянии сигнала DCD, т.е. что другой конец линии запущен. Если вы не укажете этот флаг, то ваш процесс «заснет» до тех пор пока на линии DCD не появится уровень space (off).

Запись данных в порт достаточно проста — просто используйте системный вызов write(2) для посылки данных в порт:

Функция write возвращает количество посланных байт или -1 при возникновении ошибки. Наиболее часто встречаемая ошибка — EIO , когда модем или линия передачи данных деактивирует сигнал Data Carrier Detect (DCD). Это условие будет присутствовать до тех пор пока вы не закроете порт.

Чтение данных с порта несколько сложнее. Когда вы работаете с портом в режиме не структурированного посимвольного обмена (raw data mode), каждый системный вызов read(2) будет каждый раз возвращать число символов реально прочитанных в буфер ввода. Если в текущий момент нет символов доступных для чтения, то вызов будет блокироваться (wait) до тех пор пока не появятся символы для чтения, или закончится счетчик таймаута, или обнаружится какая-нибудь ошибка. Функцию read можно выполнить так, что она вернет управление немедленно. Для этого она должна быть оформлена следующим образом:

Опция FNDELAY указывает функции read возвращать 0 если нет символов доступных для чтения из последовательного порта. Для восстановления нормально поведения (с блокировками), необходимо вызвать fcntl() без опции FNDELAY :

Это также выполняется после открытия последовательного порта с опцией O_NDELAY .

Для закрытия последовательного порта нужно использовать системный вызов close :

Закрытие последовательного порта также будет деактивировать сигнал DTR, что заставляет большинство модемов разорвать связь (hang up — повесить трубку).

Эта глава описывает как сконфигурировать последовательный порт из C используя POSIX termios интерфейс.

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

Две наиболее важные функции POSIX: tcgetattr(3) и tcsetattr(3) . Они, соответственно, позволяют получить и установить терминальные атрибуты. Вам необходимо предоставить указатель на структуру termios , которая содержит все доступные опции для последовательного интерфейса.

Таблица 3 — Поля структуры termios
Поле Описание
c_cflag Управляющие опции
c_lflag Опции линии
c_iflag Опции ввода
c_oflag Опции вывода
c_cc Управляющие символы
c_ispeed Скорость ввода в бодах (новый интерфейс)
c_ospeed Скорость вывода в бодах (новый интерфейс)

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

Таблица 4 — Константы для поля c_cflag
Константа Описание
CBAUD Битовая маска для скорости передачи в бодах
B0 0 baud (drop DTR)
B50 50 baud
B75 75 baud
B110 110 baud
B134 134.5 baud
B150 150 baud
B200 200 baud
B300 300 baud
B600 600 baud
B1200 1200 baud
B1800 1800 baud
B2400 2400 baud
B4800 4800 baud
B9600 9600 baud
B19200 19200 baud
B38400 38400 baud
B57600 57,600 baud
B76800 76,800 baud
B115200 115,200 baud
EXTA Внешняя синхронизация передачи
(External rate clock)
EXTB Внешняя синхронизация передачи
(External rate clock)
CSIZE Битовая маска для битов данных
CS5 5 data bits
CS6 6 data bits
CS7 7 data bits
CS8 8 data bits
CSTOPB 2 stop bits (1 otherwise)
CREAD Enable receiver
PARENB Enable parity bit
PARODD Use odd parity instead of even
HUPCL Hangup (drop DTR) on last close
CLOCAL Local line — do not change «owner» of port
LOBLK Block job control output
CNEW_RTSCTS
CRTSCTS
Enable hardware flow control (not supported on all platforms)

Поле c_cflag содержит две опции которые всегда должны быть разрешены: CLOCAL и CREAD . Это обеспечит то, что ваша программа не станет ‘владельцем’ порта, что приводит к случайному получению сигналов управления заданиями или сигналов зависания, а также, что драйвер последовательного интерфейса будет читать приходящие байты данных.

Константы скорости передачи ( CBAUD , B9600 , и т.д.) используются для старых интерфейсов, которые не имеют полей c_ispeed и c_ospeed . Смотрите следующий параграф для ознакомления с функциями POSIX для установки скорости передачи.

Никогда не инициализируйте поле c_cflag (или любой другой флаг) непосредственно; вы всегда должны использовать битовые операторы AND, OR, или NOT для установки или очистки битовых полей. Различные версии операционных систем (и даже патчи) могут и используют биты по-разному, поэтому использование битовых операторов предотвратит вас от затирания битового флага необходимого в новом последовательном драйвере.

Установка скорости передачи

Скорость передачи сохраняется в разных местах, в зависимости от операционной системы. Более старые интерфейсы сохраняют величину скорости передачи в поле c_cflag , используя одну из констант показанных в таблице 4. Более новые реализации предоставляют поля c_ispeed и c_ospeed , которые содержат актуальное значение скорости передачи данных.

Функции cfsetospeed(3) и cfsetispeed(3) предназначены для установки скорости передачи данных в структуре termios вне зависимости от интерфейса операционной системы. Обычно, вам потребуется использовать следующий код для установки скорости передачи:

Листинг 2 — Установка скорости передачи.

Функция tcgetattr(3) заполняет структуру termios, которую вы ей указываете, текущими установками конфигурации последовательного порта. После, вы устанавливаете скорость передачи данных, разрешаете локальный режим и прием последовательных данных, мы выбираем новую конфигурацию используя tcsetattr(3) . Константа TCSANOW указывает, что все изменения вступают в силу немедленно, без ожидания вывода данных для завершения посылки или ввода данных для завершения приема. Также существуют другие константы для ожидания завершения операций ввода и вывода, или для очистки буферов ввода и вывода.

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

Таблица 5 — Константы для tcsetattr
Константа Описание
TCSANOW Произвести изменения немедленно, не дожидаясь завершения операций пересылки данных
TCSADRAIN Подождать пока все данные будут переданы
TCSAFLUSH Очистить буфера ввода/вывода и произвести изменения

Установка размеров символов

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

Установка контроля четности

Также как и в случае с размером принимаемых символов, вы должны вручную устанавливать разрешение генерации бита четности и указывать тип проверки на четность. Драйвера последовательных устройств UNIX поддерживают учтановку проверки на четность, проверки на нечетность и отсутствие проверки на четность. Также, при более хитром кодировании, может быть симулирован пробел (space parity) бита четности.

  • Отсутствие проверки на четность (8N1):
  • Проверка на четность (7E1):
  • Проверка на нечетность (7O1):
  • Пробел (space parity) бита четности устанавливается также как и отсутствие проверки на четность (7S1):

Установка аппаратного управления потоком передаваемых данных

Некоторые версии UNIX поддерживают аппаратное управление потоком передаваемых данных используя сигнальные линии CTS (Clear To Send) и RTS (Request To Send). Если в вашей системе объявлены константы CNEW_RTSCTS или CRTSCTS , то такая поддержка, возможно, присутствует. Для активирования аппаратного управления потоком передаваемых данных необходимо сделать следующее:

Подобно вышеуказанному, для деактивирования аппаратного управления потоком передаваемых данных:

Поле локального режима c_lflag управляет как вводимые символы будут обрабатываться драйвером последовательного порта. В основном, вы будете конфигурировать поле c_lflag для канонического или неканонического (raw) ввода.

Таблица 6 — Константы для поля c_lflag
Константа Описание
ISIG Разрешить SIGINTR, SIGSUSP, SIGDSUSP, и SIGQUIT сигналы
ICANON Разрешить канонический ввод (иначе неканонический)
XCASE Отображение uppercase \lowercase (устаревшее)
ECHO Разрешить эхо вводимых символов
ECHOE Символ эхо стирания как BS-SP-BS
ECHOK Эхо NL после символа kill
ECHONL Эхо NL
NOFLSH Блокировка очистки приемных буферов после символа прерывания или выхода
IEXTEN Разрешить расширенные функции
ECHOCTL Эхо управляющих символов как ^char и удаления как

?

ECHOPRT Echo erased character as character erased
ECHOKE BS-SP-BS entire line on line kill
FLUSHO Output being flushed
PENDIN Retype pending input at next read or input char
TOSTOP Посылка SIGTTOU для фонового вывода

Выбор канонического ввода

Канонический ввод — строчно-ориентированный. Вводимые символы помещаются в буфер который может интерактивно редактироваться пользователем до приема символа CR (carriage return) или LF (line feed).

При выборе этого режима вы нормально устанавливаете опции ICANON , ECHO и ECHOE :

Выбор неканонического (Raw) ввода

Неканонический ввод не обрабатывается. Вводимый символ передается без изменений, так как он был принят. В основном вы сбрасываете опции ICANON , ECHO , ECHOE и ISIG приустановке неканонического ввода:

Замечание об эхо ввода

Никогда не разрешайте эхо ввода ( ECHO, ECHOE ) когда посылаете команды модему или другому компьютеру который производит эхо вводимых символов, поскольку вы получите цикл обратной связи между двумя последовательными интерфейсами!

Поле опций ввода c_iflag управляет любой обработкой ввода которая выполняется над символами принимаемыми из последовательного порта. Также как и в случае поля c_cflag , окончательное значение сохраняемое в c_iflag — это операция побитного OR требуемых опций.

Таблица 7 — Константы для поля c_iflag
Константа Описание
INPCK Enable parity check
IGNPAR Ignore parity errors
PARMRK Mark parity errors
ISTRIP Strip parity bits
IXON Enable software flow control (outgoing)
IXOFF Enable software flow control (incoming)
IXANY Allow any character to start flow again
IGNBRK Ignore break condition
BRKINT Send a SIGINT when a break condition is detected
INLCR Map NL to CR
IGNCR Ignore CR
ICRNL Map CR to NL
IUCLC Map uppercase to lowercase
IMAXBEL Echo BEL on input line too long

Установка контроля четности ввода

Вы должны установить проверку контроля четности ввода если вы уже установили проверку четности в поле c_cflag ( PARENB ). Значащие константы для проверки четности ввода: INPCK , IGNPAR , PARMRK , и ISTRIP . В основном, вы будуте устанавливать INPCK и ISTRIP для разрешения контроля четности и отбрасывания бита четности:

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

Опция PARMRK указывает ‘маркировать’ ошибки четности во входном потоке используя специальный символ. Если установлено IGNPAR , то вашей программе будет посылаться символ NUL (восьмеричное 000) перед каждым символом который получен с ошибкой четности. Иначе будут посылаться символы DEL (восьмеричное 177) и NUL вместе с ошибочно принятым символом.

Установка программно управляемого управления потоком передачи данных

Установка программно управляемого управления потоком передачи данных осуществляется использованием констант IXON , IXOFF и IXANY :

Для отмены программно управляемого управления потоком передачи данных вам необходимо просто замаскировать эти биты:

Символы XON (start data) и XOFF (stop data) описываются в массиве c_cc , который обсуждается ниже.

Поле c_oflag содержит опции фильтрации вывода. Подобно режимам ввода, вы можете выбрать обработанный или не обработанный (raw) вывод данных.

Таблица 8 — Константы для поля c_oflag
Константа Описание
OPOST Postprocess output (not set = raw output)
OLCUC Map lowercase to uppercase
ONLCR Map NL to CR-NL
OCRNL Map CR to NL
NOCR No CR output at column 0
ONLRET NL performs CR function
OFILL Use fill characters for delay
OFDEL Fill character is DEL
NLDLY Mask for delay time needed between lines
NL0 No delay for NLs
NL1 Delay further output after newline for 100 milliseconds
CRDLY Mask for delay time needed to return carriage to left column
CR0 No delay for CRs
CR1 Delay after CRs depending on current column position
CR2 Delay 100 milliseconds after sending CRs
CR3 Delay 150 milliseconds after sending CRs
TABDLY Mask for delay time needed after TABs
TAB0 No delay for TABs
TAB1 Delay after TABs depending on current column position
TAB2 Delay 100 milliseconds after sending TABs
TAB3 Expand TAB characters to spaces
BSDLY Mask for delay time needed after BSs
BS0 No delay for BSs
BS1 Delay 50 milliseconds after sending BSs
VTDLY Mask for delay time needed after VTs
VT0 No delay for VTs
VT1 Delay 2 seconds after sending VTs
FFDLY Mask for delay time needed after FFs
FF0 No delay for FFs
FF1 Delay 2 seconds after sending FFs

Выбор обработанного вывода

Обработанный вывод выбирается установкой опции OPOST в поле c_oflag :

Из всех различных опций, возможно, вы будете использовать опцию ONLCR которая отображает символ новой строки в пару символов CR-LF. Остальные опции вывода скорее исторические и относятся к тому времени, когда строчные принтеры и терминалы не могли справиться с потоком последовательных данных.

Выбор необработанного (raw) вывода

Выбор необработанного (raw) вывода устанавливается сбросом опции OPOST в поле c_oflag :

Когда опция OPOST сброшена, все остальные биты опций в поле c_oflag игнорируются.

Символьный массив c_cc содержит описания управляющих символов и параметры таймаутов. Константы объявлены для каждого элемента этого массива.

Таблица 9 — Управляющие символы в массиве c_cc
Константа Описание Комбинация клавиш
VINTR Interrupt CTRL-C
VQUIT Quit CTRL-Z
VERASE Erase Backspace (BS)
VKILL Kill-line CTRL-U
VEOF End-of-file CTRL-D
VEOL End-of-line Carriage return (CR)
VEOL2 Second end-of-line Line feed (LF)
VMIN Minimum number of characters to read
VTIME Time to wait for data (tenths of seconds)

Установка символов программного управления потоком передаваемых данных

Элементы VSTART и VSTOP массива c_cc содержат символы используемые для программного управления потоком передаваемых данных. Обычно они должны быть установлены в DC1 (восьмеричное 021) и DC3 (восьмеричное 023), что представляет стандарт ASCII как символы XON и XOFF.

Установка таймаутов чтения

Драйвера последовательного интерфейса UNIX предоставляют возможность специфицировать таймауты для символа и пакета. Два элемента массива c_cc используемых для указания таймаутов: VMIN и VTIME . Таймауты игнорируются в случае режима канонического ввода или когда для файла устройства установлена опция NDELAY при открытии файла open или с использованием fcntl .

VMIN определяет минимальное число символов для чтения. Если VMIN установлено в 0, то значение VTIME определяет время ожидания для каждого читаемого символа. Примечательно, что это не подразумевает, что вызов read для N байтов будет ждать поступление N символов. Тайаут произойдет в случае задержки приема любого одиночного символа и вызов read вернет число непосредственно доступных символов (вплоть до числа которое вы запросили).


Если VMIN не 0, то VTIME определяет время ожидания для чтения первого символа. Если первый символ прочитан в течение указанного времени, то любое чтение будет блокироваться (ждать) пока все число символов, указанное в VMIN , не будет прочитано. Таким образом, как только первый символ будет прочитан, драйвер последовательного интерфейса будет ожидать приема всего пакета символов (всего количества байтов указанного в VMIN ). Если символ не будет прочитан за указанное время, то вызов read вернет 0. Этот метод позволяет вам указать последовательному интерфейсу возвращать 0 или N байтов. Однако, таймаут будет приниматься только для первого читаемого символа, таким образом, если драйвер по какой-либо причине ‘потеряет’ один символ из N-байтного пакета, то вызов read может быть заблокирован ожиданием ввода дополнительного символа навсегда.

VTIME определяет величину времени ожидания ввода символа в десятых долях секунды. Если VTIME установлено в 0 (по умолчанию), то чтение будет заблокировано в ожидании на неопределенное время если для порта не была установлена опция NDELAY вызовом open или fcntl .

Эта глава содержит базовые понятия о телефонных коммуникациях посредством модулятора/демодулятора (модем). Представленные примеры используют де-факто стандартное множество «AT» команд модема.

Модемы — это устройства которые модулируют последовательные данные в частоты, которые могут быть переданы по аналоговым линиям подобным телефонным линиям или кабелям TV подключений. Стандартный телефонный модем преобразует последовательные данные в тона которые могут быть переданы по телефонным линиям; из-за скорости и сложности преобразования эти тона звучат подобно громкому визгу если вы их слушаете.

Телефонные модемы которые доступны в настоящее время могут передавать данные по телефонной линии со скоростью около 53,000 битов в секунду, или 53kbps. В дополнение, большинство модемов используют технологию сжатия данных которая может повысить скорость передачи некоторых типов данных вплоть до 100kbps.

Первый шаг в организации связи через модем — \это открытие и конфигурирование порта для неструктурированного ( raw ) ввода:

Листинг 3 — Конфигурирование порта для неструктурированного ввода.

Следующее что вам необходимо сделать, это установить связь с модемом. Наилучший способ сделать это посылкой модему «AT» команды. Это также позволяет ‘хитрым’ модемам определить какую скорость передачи данных вы используете. Когда модем корректно подключен и включен, он будет выдавать ответ «OK».

Листинг 4 — Инициализация модема.

Большинство модемов использует множество «AT» команд, называемых так поскольку каждая команда начинается с символов «AT». Каждая посылаемая команда это символьная строка начинающаяся в первом столбце с символов «AT» и сопровождаемая специфическими командами и символом возврата каретки (CR, или восьмеричное 015). После обработки команды модем будет отвечать одним из нескольких текстовых сообщений, в зависимости от команды.

ATD — Набор номера (Dial A Number)

Команда ATD производит набор указанного номера. В дополнение к цифрам и дефисам вы можете указать тип набора тональный («T») или импульсный («P»), паузу на одну секунду («,»), и ожидание тональной посылки («W»):

Модем ответит одним из следующих сообщений:

ATH — Повесить трубку (Hang Up)

Команда ATH указывает модему повесить трубку. Поскольку модем должен быть в «командном режиме», вы, возможно, не будете использовать эту команду при нормальном телефонном вызове.

Также большинство модемов вешают трубку при сбросе сигнала DTR; вы можете выполнить это установкой скорости передачи данных в 0 как минимум на 1 секунду. Также, сброс сигнала DTR переводит модем в командный режим.

После того как модем успешно повесит трубку, он выдаст сообщение «NO CARRIER». Если модем останется на линии, то он выдаст сообщение «CONNECT» или «CONNECT baud».

ATZ — Сброс модема (Reset MODEM)

Команда ATZ производит сброс модема. Модем будет отвечать строкой «OK».

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

Второе, когда посылаете команды модему, вы должны завершать их символом возврата каретки (CR), а не символом новой строки (NL). Символьная константа C для CR — «\r».

И в заключение, когда работаете с модемом, убедитесь, что вы используете скорость передачи которую поддерживает модем. Хотя многие модемы выполняют автоматическое определение скорости передачи, некоторые имеют ограничения (общее ограничение 19.2kbps) которые вы должны соблюдать.

Эта глава описывает технику низкоуровневого программирования последовательного порта, использущую системные вызовы ioctl(2) и select(2) .

В Главе 3, Конфигурирование последовательного порта мы использовали функции tcgetattr и tcsetattr для конфигурирования последовательного порта. В системе UNIX эти функции используют системный вызов ioctl(2) .

Системный вызов ioctl принимает три аргумента:

Аргумент fd указывает файловый дескриптор последовательного порта. Аргумент request является константой, описанной в файле , и, обычно, является следующим:

Таблица 10 — IOCTL Запросы к последовательному порту
Запрос Описание Функция POSIX
TCGETS Получить текущие настройки последовательного порта. tcgetattr
TCSETS Установить настройки последовательного порта немедленно. tcsetattr(fd, TCSANOW, &options)
TCSETSF Установить настройки последовательного порта после очистки буферов ввода/вывода. tcsetattr(fd, TCSAFLUSH, &options)
TCSETSW Установить настройки последовательного порта после того как буфера ввода/вывода освободятся. tcsetattr(fd, TCSADRAIN, &options)
TCSBRK Послать на определенное время разрыв линии (break). tcsendbreak, tcdrain
TCXONC Программное управление потоком данных. tcflow
TCFLSH Очистка очередей ввода/вывода. tcflush
TIOCMGET Вернуть состояние «модемных» битов. None
TIOCMSET Установить состояние «модемных» битов. None
FIONREAD Вернуть количество байтов в буфере ввода (приемный буфер). None

Вызов TIOCMGET ioctl получает текущее состояние статусных битов «модема», которые включают все сигнальные линии RS-232, исключая RXD и TXD :

Таблица 11 — Константы контрольных сигналов
Константа Описание
TIOCM_LE DSR (data set ready/line enable)
TIOCM_DTR DTR (data terminal ready)
TIOCM_RTS RTS (request to send)
TIOCM_ST Secondary TXD (transmit)
TIOCM_SR Secondary RXD (receive)
TIOCM_CTS CTS (clear to send)
TIOCM_CAR DCD (data carrier detect)
TIOCM_CD Synonym for TIOCM_CAR
TIOCM_RNG RNG (ring)
TIOCM_RI Synonym for TIOCM_RNG
TIOCM_DSR DSR (data set ready)

Для получения статусных битов, необходимо вызвать ioctl с указателем на integer переменную для сохранения битов:

Листинг 5 — Получение статусных битов модема.

Вызов TIOCMSET ioctl устанавливает статусные биты «модема» описанные выше. Для сброса сигнала DTR вы можете выполнить следующее:

Листинг 6 — Сброс сигнала DTR вызовом TIOCMSET ioctl.

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

Вызов FIONREAD ioctl получает число байтов в приемном буфере последовательного порта. Также как и в случае с TIOCMGET вам необходимо передать указатель на integer переменную для сохранения результата:

Листинг 7 — Получение числа байтов в приемном буфере.

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

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

UNIX предоставляет эту возможность посредством системного вызова select(2) . Этот системный вызов позволяет вашей программе проверять условия ввод, вывод или ошибки на одном и/или более дескрипторах. Файловые дескрипторы могут указывать на различные порты, обычные файлы, другие устройства, каналы или сокеты. Вы можете запрашивать проверу для ожидаемого ввода, ожидать ввод бесконечно, или осуществлять выход по таймауту через определенноый промежуток времени, делая системный вызов select очень гибко.

Большинство GUI Toolkits предоставляет интерфейс к вызову select ; позже в этой главе мы обсудим библиотеку X Intrinsics («Xt»).

Системный вызов select принимает 5 аргументов:

Аргумент max_fd определяет высший численный файловый дескриптор в множествах input , output , и error . Аргументы input , output , и error определяют множества файловых дескрипторов для ожидания условий ввода, вывода или ошобки; укажите NULL для блокировки мониторинга определенных условий. Эти множества инициализируются использованием трех макросов:

Макрос FD_ZERO полностью очищает множество. Макросы FD_SET FD_CLR , соответственно, добавляет и удаляет файловый дескриптор в/из множества.

Аргумент timeout определяет значение таймаута которое состоит из секунд ( timeout.tv_sec ) и милисекунд ( timeout.tv_usec ). Для опроса одного или более файловых дескриптора, установите секунды и милисекунды в нуль. Для бесконечног ожидания определите указатель таймаута (timeout pointer) как NULL .

Системный вызов select возвращает число файловых дескрипторов которые имеют ожидаемые условия, или -1 при ошибке.

Предположим: что мы читаем данные от последовательного порта и от сокета. Мы хотим проверить ввод от обоих файловых дескрипторов, и хотим уведомлять пользователя если в течение 10 секунд не было получено никаких данных. Для выполнения этого нам понадобится использовать системный вызов select :

Листинг 8 — Использование select для обработки ввода более чем от одного источника.

Вы должны заметить, что сначала мы проверяем значение которое вернул системный вызов select . Значения 0 и -1 выдают соодветственно предупреждающее сообщение и сообщение об ошибке. Значения больше 0 подразумевают, что на одном или более дескрипторах мы имеем данные ожидающие обработку.

Для определения того какой файловый дескриптор имеет ожидание ввода, мы используем макрос FD_ISSET для проверки множества ввода для каждого файлового дескриптора. Если флаг файлового дескриптора установлен, то условие присутствует (в нашем случае, ожидание ввода) и мы должны это как-то обработать.

Библиотека X Intrinsics предоставляет интерфейс к системному вызову select через функции XtAppAddInput(3x) и XtAppRemoveInput(3x) :

Системный вызов select используется на внутреннем уровне для реализации таймаутов, и проверки ввода от X сервера. Эти функции могут быть использованы с любым Xt-образным инструментарием, включая Xaw, Lesstif и Motif.

Аргумент proc , функции XtAppAddInput , определяет функцию которая будет вызываться когда выбранное условие (или доступный ввод) присутствует на файловом дескрипторе. В предидущем примере вы могли указать функции process_fd или process_socket .

Поскольку Xt ограничивает ваш доступ к системному вызову select , вам понадобится реализовать таймауты через другой механизм, возможно через XtAppAddTimeout(3x) .

Это приложение предоставляет информацию о цоколевках большинства последовательных портов с которыми вы можете столкнуться.

RS-232 встречается в трех модификациях (A, B, C) и использует 25-контактный разъем (розетка):

Рисунок 2 — Разъем RS-232

Таблица 12 — RS-232 Signals
Вывод Описание Вывод Описание
1 Earth Ground 14 Secondary TXD
2 TXD — Transmitted Data 15 Transmit Clock
3 RXD — Received Data 16 Secondary RXD
4 RTS — Request To Send 17 Receiver Clock
5 CTS — Clear To Send 18 Unassigned
6 DSR — Data Set Ready 19 Secondary RTS
7 GND — Logic Ground 20 DTR — Data Terminal Ready
8 DCD — Data Carrier Detect 21 Signal Quality Detect
9 Reserved 22 Ring Detect
10 Reserved 23 Data Rate Select
11 Unassigned 24 Transmit Clock
12 Secondary DCD 25 Unassigned
13 Secondary CTS

RS-422 также использует 25-контактный разъем (розетка), но с различающимися сигналами:

Рисунок 3 — Разъем RS-422

Таблица 13 — Сигналы RS-422
Вывод Описание Вывод Описание
1 Earth Ground 14 TXD+
2 TXD- — Transmitted Data 15 Transmit Clock-
3 RXD- — Received Data 16 RXD+
4 RTS- — Request To Send 17 Receiver Clock-
5 CTS- — Clear To Send 18 Unassigned
6 DSR — Data Set Ready 19 RTS+
7 GND — Logic Ground 20 DTR- — Data Terminal Ready
8 DCD- — Data Carrier Detect 21 Signal Quality Detect
9 Reserved 22 Unassigned
10 Reserved 23 DTR+
11 Unassigned 24 Transmit Clock+
12 DCD+ 25 Receiver Clock+
13 CTS+

Интерфейс RS-574 используется исключительно производителями PC и использует 9-штырьковый разъем (вилка):

Рисунок 4 — Разъем RS-574

Таблица 14 — Сигналы RS-574 (IBM PC/AT)
Вывод Описание Вывод Описание
1 DCD — Data Carrier Detect 6 Data Set Ready
2 RXD — Received Data 7 RTS — Request To Send
3 TXD — Transmitted Data 8 CTS — Clear To Send
4 DTR — Data Terminal Ready 9 Ring Detect
5 GND — Logic Ground

Старое оборудование SGI использует 9-штырьковый разъем (розетка). В отличие от RS-574, цоколевка SGI больше соответствует RS-232:

Рисунок 5 — 9-штырьковый разъем SGI

Таблица 15 — Сигналы 9-штырькового разъема SGI
Вывод Описание Вывод Описание
1 Earth Ground 6 DSR — Data Set Ready
2 TXD — Transmitted Data 7 GND — Logic Ground
3 RXD — Received Data 8 DCD — Data Carrier Detect
4 RTS — Request To Send 9 DTR — Data Terminal Ready
5 CTS — Clear To Send

Рабочие станции SGI Indigo, Indigo2, и Indy используют 8-контактный MiniDIN разъем Apple для своих последовательных портов:

Рисунок 6 — 8-контактный разъем SGI

Таблица 16 — Сигналы 8-контактного разъема SGI
Вывод Описание Вывод Описание
1 DTR — Data Terminal Ready 5 RXD — Received Data
2 CTS — Clear To Send 6 RTS — Request To Send
3 TXD — Transmitted Data 7 DCD — Data Carrier Detect
4 GND — Logic Ground 8 GND — Logic Ground

Это приложение перечисляет управляющие коды ASCII и их названия.

Илон Маск рекомендует:  Что такое код puts
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL