📟 FAQ по доступу к Serial из Crystal
Перевёл FAQ чувака с SOF, на вопрос работы с Serial в Crystal.
Как мне получить доступ к Serial в Linux/BSD?
Открыть его как файл.
В Linux/BSD последовательное соединение устанавливается в тот момент,
когда устройство было подключено,
и затем отображается в разделе /dev/
(обычно как /dev/ttyUSB0
).
Чтобы получить доступ к этому соединению, просто откройте его как обычный файл.
Иногда этого достаточно, чтобы начать взаимодействовать с устройством,
поскольку современное оборудование работает со всеми скоростями и флагами по умолчанию.
Как мне настроить устройство Serial/tty в Linux/BSD?
Необходимо установить флаги termios для файла.
Если необходимо для соединения установить такие параметры,
как скорость передачи данных в бодах, IXON/IXOFF и т.д.,
это можно сделать еще до запуска вашей программы с помощью команды
stty, если она доступна.
Например чтобы установить скорость передачи данных в бодах,
необходимо выполнить следующую команду: stty -F /dev/ttyUSB0 9600
.
И после того, как соединение настроено,
можно просто открыть соединение как файл и начать использовать.
Вы можете запустить stty
из Crystal с помощью
Process.run
, если нужен простой способ настройки устройства из вашего приложения.
Я бы, вероятно, порекомендовал этот способо в качестве решения.
Как мне установить флаги termios из Crystal, не используя stty?
Используйте функции termios
напрямую.
Crystal предоставляет FileDescriptor с несколькими
распространенными настройками termios
, такими как
cooked,
что означает, наличие минимальных привязок
termios.
Мы можем начать с использования существующего кода:
require "termios"
# Открываем файл
serial_file = File.open("/dev/ttyACM0")
raise "Oh no, not a TTY" unless serial_file.tty?
# Извлекаем unix FD. Это всего лишь цифра.
fd = serial_file.fd
# Извлекаем существующие флаги TTY файла
raise "Can't access TTY?" unless LibC.tcgetattr(fd, out mode) == 0
# `mode` теперь содержит структуру termios. Давайте включим, ммм.. ISTRIP and IXON
mode.c_iflag |= (Termios::InputMode::ISTRIP | Termios::InputMode::IXON).value
# Давайте также отключим IXOFF.
mode.c_iflag &= ~Termios::InputMode::IXOFF.value
# Обнаружение неисправности: в Termios недоступна скорость cfset[ввода-вывода]
# Давайте добавим их, чтобы изменить скорость передачи данных в бодах было не так сложно.
lib LibC
fun cfsetispeed(termios_p : Termios*, speed : SpeedT) : Int
fun cfsetospeed(termios_p : Termios*, speed : SpeedT) : Int
end
# Используйте приведенные выше функции, чтобы установить скорость ввода
# и скорость вывода на заданную вами скорость передачи данных в бодах.
LibC.cfsetispeed(pointerof(mode), Termios::BaudRate::B9600)
LibC.cfsetospeed(pointerof(mode), Termios::BaudRate::B9600)
# Пишите свои изменения в FDA.
LibC.tcsetattr(fd, Termios::LineControl::TCSANOW, pointerof(mode))
# Сделано! Ваш дескриптор serial_file готов к использованию.
Чтобы установить другие флаги, обратитесь к руководству termios или к этому замечательному руководству по Serial, которое я только что нашел.
Есть ли библиотека, которая могла бы сделать все это за меня?
Нет :(. Но было бы здорово, если бы кто-нибудь написал. Вероятно, что написать библиотеку не составит большого труда, если у кого-нибудь будет личный интерес :)
Источник
- Crystal-lang Accessing Serial port — StackOverFlow.