- Определение номера подключенного COM порта
- Windows
- Linux
- Работа с COM-портом (RS-232) в Linux
- Проверка ком порта линукс
- Работа с СОМ-портом на Си в linux
- Основы ввода-вывода в linux: всё есть файл
- Файл-устройство COM-порта
- Работа с файл-устройством терминала
- Создадим настоящее устройство передачи данных
- Простейший пример блокирующего чтения из СОМ-порта
- Как сделать неблокирующее чтение?
- Как подрыгать ножкой DTR и RTS, а также пара слов о RS-485
- Выводы
Определение номера подключенного COM порта
Для правильного подключения оборудования, необходимо определить номер COM порта.
Проверка проводится при условии, что сервер полностью развернут, и работает заведомо правильно.
Windows
Для определения номера COM порта на ОС Windows необходимо:
- Убедиться в том, что многожильный кабель подключен к COM-порту
- Перейти в «Диспетчер устройств», расположенный в: Панель управления\Оборудование и звук\Диспетчер устройств (необходимы права администратора)
- Раскрыть дерево «Порты (COM и LPT)»
- Отсоединить многожильный кабель
- Запомнить изменения в дереве устройств «Порты (COM и LPT)»
- Присоединить многожильный кабель обратно к COM-порту
- Найти новый порт в дереве устройств «Порты (COM и LPT)»
8. После того, как номер COM-порта определен его необходимо указать в схеме SCADA, для устройства, подключенного многожильным кабелем.
Linux
Для определения номера COM порта на ОС Linux необходимо:
- Обладать правами Root либо пользователь должен входить в группу dialout
- Убедиться в том, что многожильный кабель подключен к COM-порту
- Проверить наличие COM портов в системе, введя в командную строку следующую команду:
4. После выполнения команды отобразится список всех доступных COM-портов
dev/ttyS0 — первый COM порт
/dev/ttyS1 — второй COM порт
/dev/ttyUSB0 — специальный кабель-переходник из USB в COM (Gembird UAS111)
5. Установить программу minicom. Для этого вводим следующую команду:
6. Найти многожильный кабель в оплётке длиной 4-6 см.
7. Соединить 2 и 3 выводы COM порта перемычкой из кусочка многожильного провода. Оплётка будет удерживать провод на контактах, а металлические жилы внутри будут проводниками.
8. Настроить программу minicom. Для этого вводим следующую команду:
9. Выбрать «Настройка последовательного порта»
10. Нажимая А поочередно выбираем порты (если используется кабель-переходник из USB в COM то выбрать /dev/ttyUSB0)
11. Отключить аппаратное управление потоком, нажав «F»
12. Выйти из настроек нажав «Enter»
13. Сохранить настройки по умолчанию «Сохранить настройки как dfl»
14. Выйти из minicom
15. Запустить minicom выполнив команду:
16. Нажать на любую клавишу на клавиатуре
В случае, если символы не вводятся с клавиатуры, необходимо вернуться к пункту 10, и выбрать другой COM-порт
Если вводимые символы отображаются — значит COM-порт определен верно
17. После того, как номер COM-порта определен его необходимо указать в схеме SCADA, для устройства, подключенного многожильным кабелем.
Источник
Работа с COM-портом (RS-232) в Linux
Урок посвящен интерфейсу RS-232, который в простонародье называют COM-порт. Мы разберемся как он представлен в Linux, какой у него интерфейс, научимся его конфигурировать, а также узнаем, что написание программы для коммуникации через COM-порт в Linux не представляет сложности.
Разговор o коммуникации через COM-порт в Linux следует начать с того, что заметить, что каждому COM-порту в операционной системе соответствует файл устройства телетайп или tty. Он находится в каталоге dev и имеет имя /dev/ttyS и номер. Если посмотреть на мой каталог, то мы увидим следующее, что у меня таких файлов очень много [0:55]. Но по факту, в моем компьютере есть один физический COM-порт. Давайте попробуем его найти. Сделать это можно с помощью команды dmesg, которая выводит сообщения с момента инициализации системы. Если набрать
$dmeg | grep «ttyS»
то мы увидим, что, в действительности , у меня только один файл ttyS4 связанный с конкретным COM-портом, у которого есть некоторый диапазон ввода/вывода, номер прерывания, и который сейчас настроен на скорость обмена 150200 бит в секунду (или бод).
Для того, чтобы сконфигурировать мой COM-порт по умолчанию в Linux можно воспользоваться программой mincom, запускать её нужно от суперпользователя, либо добавить текущего пользователя в группу dialout. Запустим
$sudo minicom -s
Ключ -s – обозначает конфигурацию (setup),
Здесь мы видим следующее [2:24]. Есть параметры последовательного порта, важно прописать правильно файл, то есть указать тот файл, который у вас в системе связан с физическим COM-портом, Второй важный момент – это настройка параметров обмена (ключ Е). Дело в том, что корректный обмен данными по последовательному соединению возможен только тогда, когда обе стороны имеют один и тот же набор параметров. В этом окне можно набор этих параметров менять [3:08]. Мы видим, что у нас задана скорость 8 бит, нет контроля четности, и один стоповый бит. Именно здесь можно это все увидеть и настроить так, как требуется или, как требует ваше устройство.
Сохраняем конфигурацию по умолчанию. Дальше будем взаимодействовать — сначала с помощью команды терминала, чтобы проверить, как вручную это работает; а потом напишем небольшую программу, которая будет слать данные в COM-порт. Выйти из Mincom можно набрав ctrl-A-X.
Для того чтобы проверить, как работает COM-порт можно воспользоваться программой miniterm [4:03]. Я создал виртуальную машину с обычным linux, у неё указал, что в наличии имеется один COM-порт (это COM1), по умолчанию назначились линии обработки запросов прерывания. Я ассоциировал этот COM-порт с файлом на моей host-машине. С этого файла мы будем читать данные записанные в порт.
Итак, мы видим, что в левой части экрана у нас есть логин на виртуальную машину [4:46]. Давайте проверим с помощью minicom -s, как настроены коммуникации. Проверим, что /dev/ttyS0 – это действительно правильный физический порт – да, это именно так. Теперь мы можем вызвать команду
$sudo miniterm
она говорит, что есть следующие доступные порты, и просит ввести, через какой порт работать. Далее я попадаю терминал, связанный с COM-портом, где могу набирать текст. Набирая команды, я вижу «эхо» в моем файле справа. Обратите внимание, что я пишу в левом окне, а на экране надпись мы видим в правом. В левом окошке – виртуальная машина, на которой настроен порт. В правом – тот лог, который мы видим в файле ассоциированном с этим COM-портом на host-машине.
Создадим какой-нибудь каталог, в котором будем разрабатывать приложение. Как это ни странно, приложение будет выглядеть очень просто, потому что все действия, которые мы делаем с COM-портом в linux, это действия с файлами с использованием тех же самых файловых операций. Нам потребуется stdio.h, unistd.h, чтобы получить доступ – функциям open/read/write, fcntl.h, чтобы иметь возможность использовать файловые флажки. Открываем файловый дескриптор, COM-порт, имя, и флаги из COM-порта. Проверим, что файловый дескриптор у нас открылся, то есть если порт меньше или равен 0, то есть какая-то ошибка, оповестим об этом пользователя и вернем управление. В противном случае, можно писать в этот файловый дескриптор. write принимает файловый дескриптор, указатель на буфер, размер. Дальше мы закрываем файловый дескриптор и возвращаем управление. Приложение готово.
Теперь давайте попробуем запустить то, что у нас вышло, вернее, скомпилировать и запустить [10:40]. При запуске приложения произошла ошибка, но она вызвана понятными причинами, потому что пользователь должен был быть включен группу dialout [11:03], или нам надо запускать приложение от суперпользователя. Сделаем это. И сразу видим, что в нашем окошке появилась запись «hello world». Можно повторить и увидеть, что все работает корректно.
Точно таким же образом можно осуществлять чтение из COM-порта, то есть использовать не функцию write, а функцию read.
Источник
Проверка ком порта линукс
Как получить список доступных системе COM портов в Linux? Раньше искал в /dev файлы типа ttyS*, но что-то тут не так. На моем компе имеется один физический компорт. В /dev есть 4 порта (ttyS0, ttyS1, ttyS2, ttyS3). Но, например когда пытаюсь добавить в систему принтер, визард просит выбрать порт и показывает только ОДИН доступный компорт. Всё правильно, порт всего один. Хотя в девах их 4, в визарде только 1. На другом компе физически есть 1 компорт, а в /dev их аш 5. Как из кода в Linux-e можно получить список доступных компортов? или как проверить все ttyS0, ttyS1, ttyS2, ttyS3 и найти среди них рабочий(е)(реальный(е))?
Оглавление |
|
Сообщения по теме | [Сортировка по времени | RSS] |
1. «Как получить список доступных системе COM портов? « | + / – | |
Сообщение от ACCA | ||
Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору |
2. «Как получить список доступных системе COM портов? « | + / – | |
Сообщение от juvf | ||
Спасибо. Таким образом смог выделить из всех ttyS* только рабочие. А можно подобным образом получить инфу о портах типа ttyUSB*? Или достаточно по наличию в /dev/ttyUSB0 определить, что такой порт доступен системе? | ||
Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору |
3. «Как получить список доступных системе COM портов? « | + / – | |
Сообщение от ACCA | ||
Смотря откуда этот /dev/ttyUSB* взялся. Если его udev или ещё какой hal сделал — почти достаточно. Посмотри, что такое /dev. Если udev filesystem, то скорее всего можно — /dev/ttyUSB* создаются и убираются динамически, если udev скрипт не глюканул. Сделай `lshal’, почитаешь много интересного про ttyUSB. dmesg | grep ttyUSB тоже поможет. Источник Работа с СОМ-портом на Си в linuxКаждый, кто постоянно занимается электроникой и программирует встраиваемые устройства, неизбежно сталкивается с необходимостью работы с СОМ-портом под линуксом. Чаще всего появляется задача сопрячь какой-то датчик, либо удалённое устройство с одноплатником. Да, что греха таить, сейчас в 2020 году UART, наверное, самый распространённый интерфейс для обмена данными, несмотря на всю его архаичность.
Исторически сложилось, что СОМ-порт в UNIX использовался как терминал. То есть, как устройство для отображения и получения информации работы с ЭВМ. Отсюда идёт всё базовое наследие работы UART. Основы ввода-вывода в linux: всё есть файлПринцип операционных систем типа Unix (и GNU Linux вместе с ними): всё есть файл. Файл может быть регулярным на диске, к которому мы все привыкли, файлом может быть именованный или не именованный, канал для передачи данных, передача данных по сети, тоже по сути, работа с файл-сокетом (только не именованным). Таким образом разобравшись с функциями работы с файлами мы частично разберёмся с работой СОМ-порта. Принимает на вход имя файла, флаги опции открытия, и если расширенная функция, то и права доступа. Но нас это тоже пока не волнует. Возвращает дескриптор (описатель) открытого файла, число больше нуля. В любом другом случае – это ошибка открытия файла. Закрывает файл, на вход принимает дескриптор файла. Возвращает нуль в случае успеха. read() пытается записать count байтов файлового описателя fd в буфер, адрес которого начинается с buf. Обратите внимание! Что количество запрашиваемых байт на чтение, может не соответствовать реальному количеству считаных байт! Оно будет меньше, либо равно запрошенному. write записывает до count байтов из буфера buf в файл, на который ссылается файловый дескриптор fd. Обратите также внимание, что запись байт не гарантирует, что все байты будут записаны. Следует также контролировать количество байт, которое было записано, и в цикле дописывать их до окончания. С точки зрения ядра, функции read и write осуществляют копирование данных из ядра в пространство пользователя (для чтения), и копирование из пространства пользователя в ядро (в случае записи). Таким образом, важно понимать, что функция записи не гарантирует реальную запись в устройство, а только копирование во внутренние буфера ядра. И в случае чтение из файл-устройства порта, вы читаете не физически из устройства, а просто копируете накопленные данные, которое драйвер ядра уже получил из порта ввода-вывода и сложил во внутренний буфер. Файл-устройство COM-портаКак уже было сказано, в ОС Linux всё есть файл. Файл-устройство COM-портов обычно располагается в каталоге с именем /dev/tty*, где вместо звёздочки может стоять любая последовательность символов или её не быть вовсе. Эти устройства обладают сходным интерфейсом, который был выведен десятилетия назад для последовательных терминалов TeleType (см. фотографию в начале поста) и получил название tty. Реализация конечного имени устройства зависит от текущей реализации операционной системы. Например, классический COM1 в Ubuntu выглядеть, как /dev/ttyS0. А если подключить USB-COM переходник, то файл-устройство будет иметь имя /dev/ttyUSB0, конечно если он единственный в системе, либо другой порядковый номер на конце, если воткнуто несколько шнурков. Часто, составные устройства (например, lte-модемы), определяются как /dev/ttyACM0. то увидите множество файл-устройств. К одному из них подключен ваш виртуальный терминал это файл-устройство “/dev/tty”. Проще говоря, стандартный поток ввода, вывода и стандартный поток ошибок идёт в это файл-устройство. В данном случае командная оболочка (в моём случае bash) использует его для ввода-вывода. Можем в этом убедиться введя: Здесь мы командой echo вывели сообщение и перенаправили его в файл /dev/tty, в результате получили его на экране нашего терминала. Если вспомнить, как было всё организовано раньше, то терминал «подключен» к СОМ-порту и представляет собой пассивную железку, что к нему приходит, то он и выводит. Точно также отправляет сырые данные, введённые с клавиатуры. Таким образом, когда мы записали данные с помощью команды “echo” в файл-устройство (системный вызов write), то эти данные были отправлены на виртуальный порт и мы их увидели на экране нашего терминала.
Как несложно догадаться, если в сыром режиме передачи данных эти символы будут переданы, то драйвер последовательного порта пошлёт нашей программе такие сигналы, и не известно, к чему это может привести. И на выходе мы получим следующий результат: Обратите внимание, несмотря на то что данное файл-устройство виртуальное и не имеет реального воплощения в железе, у него всё равно есть скорость и управляющие флаги. Это флаги структуры termios. Как работать с этими флагами, что они значат и для чего нужны, мы разберёмся в следующей главе. Работа с файл-устройством терминалаВсе манипуляции tty осуществляются с помощью одной структуры, struct termios, а также нескольких функций, определенных в заголовочном файле . Из этих функций широко применяются только шесть. Когда не нужно устанавливать скорость передачи данных по линии, используются только две наиболее важных функции — tcgetattr() и tcsetattr(). Почти в каждом случае программы должны использовать tcgetattr() для получения текущих установок устройства, модифицировать эти установки, а затем применять tcsetattr() для активизации модифицированных установок. Для того, чтобы понять, как конфигурировать файл-устройства терминала (телетайпа, СОМ-порта, как будет угодно), разберём синтетический пример. Давайте разберём, что же делает данная программа: она переводит терминал ввода-вывода в неканонический режим, отключая эхо показа клавиш на экране, блокируя все специальные символы, вызывающие сигнал, и ожидает в цикле ввода всего одного символа «q» для выхода. Завершить работу программы комбинациями клавиш ctrl-c, ctrl-d и другими невозможно, так как драйвер терминала не обрабатывает соответствующие сигналы. На экране введённая информация не отображается. После завершения работы терминал восстанавливает своё первоначальное состояние. Здесь мы создаём два экземпляра структуры termios. Для того чтобы сохранить текущее состояние нашего терминала и потом иметь возможность его восстановить и новое. С помощью функции fileno(stdin) мы получаем дескриптор файла стандартного потока вывода, а функция tcgetattr получает текущие установки устройства в структуру oldsettings. Здесь мы снимаем флаги локального эха, снимаем флаг канонического режима терминала и отключаем получение сигналов. Подробнее о флагах структуры termios можно посмотреть тут. Здесь указывается минимальное количество символов, которое будет передано за раз — для неканонического ввода (то количество символов, которое будет отдано функции read до истечения таймаута VTIME). А также таймаут, в децисекундах, после которого будет отдано накопившееся количество символов функции read. Если символов нет, то read вернёт нуль (см. главу «Основы ввода-вывода в linux: всё есть файл»). Записываем новые настройки в наш терминал. Здесь идёт открытие файл-устройства «/dev/tty» c помощью функции open только для чтения. Можно было также разыменовать дескриптор стандартного ввода через fileno, но сделал так для наглядности. После этого, в цикле мы производим блокирующее чтение из этого файл-устройства по одному символу, пока не получим считанный символ, равный ‘q’. Восстанавливаем настройки терминала. Создадим настоящее устройство передачи данныхПредыдущий пример, хоть и был синтетическим, тем не менее часто используется, особенно при вводе паролей, либо при работе с псевдографикой в терминалах. Но наша задача, всё же, получить работу с живым реальным устройством. Для этого на Arduino сделаем такое вот синтетический пример. Мы просто шлём строку «01234567890123456789\n\r» на скорости 9600 каждые две секунды. Умышленно сделал ASCII-символы, чтобы было проще отлаживать. Таким образом мы можем в реальном времени мониторить сообщения ядра. Подключаем Arduino-плату к нашему компьютеру и видим следующие сообщения:
Для нас самая главная информация, что нас СОМ-порт определился, как ttyUSB0 и обитает он соответственно в /dev/ttyUSB0. Для того чтобы с этим файл-устройством можно было работать не из-под root, надо добавить вашего пользователя в группу dialout. Для этого введём команду И перезагрузим систему. После успешной перезагрузки, можно проконтролировать корректность работы этого порта. Зададим скорость порта и попробуем прочитать из него содержимое. Сообщения появляются раз в две секунды, значит всё корректно работает. Простейший пример блокирующего чтения из СОМ-портаРазберём пример блокирующего чтения из COM-порта был взят отсюда и немного модифицирован. Все исходники будут доступны в отдельном репозитории к этой статье. Блокирующее чтение, как следует из названия, блокирует программу в системном вызове read до тех пор, пока не появятся данные, которые может получить read. Если данных нет, то этот вызов будет ждать вечно и ничего работать не будет. Этот режим работы наиболее прост для понимания работы с СОМ-портом, и с него лучше всего начинать работать. Примеры работы с портом, разобранные выше, тот же cat и hexdump используют именно блокирующее чтение. Однако, на практике в реальных задачах, такое чтение применяется достаточно редко. Разберём основные части кода SerialPort_read.c: Обратите внимание на флаги открытия: O_RDWR – открываем для чтения и записи, O_NOCTTY – терминал не может управлять данным процессом (тот терминал, с которого мы запускаем это приложение, может управлять процессом, например послать сигнал при комбинации ctrl-c). Инициализируем структуру termios и получаем текущие значения структуры. Задаём скорость на чтение и на запись. Обратите внимание, что скорости на чтение и на запись могут быть разными. Так же скорость задаётся макросами, начинающиеся с символа “B” (они описаны в termios.h). Могут принимать следующие значения: Нулевая скорость, B0, используется для завершения связи. Далее идут стандартные настройки порта: Отключаем бит чётности (если флаг очищен). Если флаг установлен, то стоп-бит равен двум, если очищен (в этом случае), то равен одному. Очищаем маску размера данных. Устанавливаем размер передаваемых данных, равный восьми битам. Отключаем аппаратное управление потоком данных (RTS/CTS). Включаем приёмник, игнорируем контрольные линии модема. Отключаем управление потоком данных при вводе и выводе, отключаем возможность символов запускать ввод. Переводим терминал в неканонический режим (мы это уже разбирали). Отключаем режим ввода, определяемый реализацией по умолчанию. Теперь самое интересное (с этими параметрами мы ещё поиграемся). Хоть мы их разбирали уже, посмотрим какое будет поведение у них в нашем случае. Считываем за раз только 40 символов. Считываем каждую секунду. То есть, если значение отличное от нуля, функция read будет разблокирована по этому значению в децисекундах. Записываем значение структуры termios. Вы осознаёте теперь всю сложно работы с COM-портом? При этом мы не разобрали даже половины его возможностей, а уже это оказывается дико сложным. В любом случае придётся внимательно разобраться со всеми флагами структуры termios, чтобы понять, как корректно работать с портом. Скомпилируем и посмотрим, что же она будет у нас считывать. Таким образом, при данных настройках корректно вычитывает наше сообщение. Аналогично запись (системный вызов write) может быть блокирующей и не блокирующей, но в данном случае это не очень критично, так как после копирования данных в буфер ядра запись разблокируется. Как сделать неблокирующее чтение?Неблокирующее чтение отличается от блокирующего чтения тем, что если в буфере ядра linux нет данных, то функция read не будет ожидать их получения и сразу вернёт управление программе. С одной стороны это очень удобно, но с другой, если вы ожидаете посылку, то вам придётся в цикле читать, пока не получите данные. Для этих целей существует такие вещи как — select, poll и epoll. В рамках этой статьи нет возможности разобрать работу с ними, поэтому буду краток. Не буду разбирать подробно всю программу, пробегусь по основным моментам. Остальное в ней всё достаточно очевидно, и многое мы уже разобрали. Всё будет в файле uart.c. Таким образом, теперь, мы будем выходить сразу, после функции read, вне зависимости есть у нас данные или нет. На вход функция принимает файловый дескриптор открытого порта, длину запрашиваемых данных, таймаут в миллисекундах, после которого возвращается управление системе и указатель на буфер, куда будут считаны данные. В неё мы записываем файловый дескриптор, который хотим мониторить. Указываем, то что мы хотим мониторить событие получение данных: И соответственно взводим наш «сторожевой таймер». Из этой функции мы выйдем, либо по таймауту, либо по получению данных. Дальше мы проверяем событие, которое произошло. И если событие соответствует POLLIN, то производим чтение данных. Здесь poll настроен на передачу. Единственное, на что стоит обратить внимание, это на вызов функции tcdrain(fd); Эта функция будет ожидать, пока все данные вывода, записанные на объект, на который ссылается fd, не будут переданы. Функцию int set_rts(int fd, int on) мы разберём в следующей главе. Как подрыгать ножкой DTR и RTS, а также пара слов о RS-485Кроме системных вызовов read и write, есть системный вызов ioctl, который позволяет осуществлять тонкую настройку. Будем честны, вот эта работа со структурой termios, внизу имеет системный вызов ioctl, который записывает все настройки в ядро. Но это от нас скрыто библиотечными функциями. Системный вызов ioctl не стандартизован и очень опасен, но позволяет производить тонкую настройку порта. Приведу пример функции установки или снятия сигнала rts. Изначально мы получаем состояние флагов порта в переменную &flags. После чего, либо снимаем флаг состояния TIOCM_RTS, либо устанавливаем его. Аналогично выглядит функция работы с сигналом DTR. С RS-485 в линуксе всё обстоит не важно. Этот интерфейс совершенно не стандартизирован, и каждый производитель может делать всё что захочет. Где-то его нужно инициализировать в ядре, и драйвер ядра будет автоматически переключать приёмо-передатчик, где-то это всё реализовано аппаратно. Тут всё как бог на душу положит. Поэтому, с RS-485 приходится разбираться на месте. Но моя практика показывает, что всё что написано в документации – не актуально. Единственный эффективный путь – это лезть в код ядра и смотреть, что же там происходит на самом деле. ВыводыОчень сложно в рамках маленькой статьи рассказать о таком сложном явлении в linux, как работа с терминалами. Получается так, что надо сначала понять почему COM-порт не порт, а на самом деле терминал, и как его превратить обратно в порт. Этот терминал имеет множество режимов работы и функционала. И, в силу исторических причин, несёт это огромное наследие дальше. Работа с другими интерфейсами в linux (тем же i2c сильно проще). Di_halt просил меня рассказать о примерах работы с прерываниями и прочим, но это всё лишняя информация. Реальная работа с железом, именно с портами идёт в драйверах внутри ядра linux. Здесь мы взаимодействуем с интерфейсом, который предоставляет нам драйвер. Примеры к данным видео можно найти вот тут. Все программы, которые продемонстрированные были в данной статье можно найти у меня в гитхабе. Источник |