96 lines
5.6 KiB
Markdown
96 lines
5.6 KiB
Markdown
---
|
||
title: "📟 FAQ по доступу к Serial из Crystal"
|
||
date: 2023-05-16T01:29:30+03:00
|
||
draft: false
|
||
tags: [crystal, serial, tips]
|
||
---
|
||
|
||
Перевёл FAQ чувака с SOF, на вопрос работы с Serial в Crystal.
|
||
|
||
## Как мне получить доступ к Serial в Linux/BSD?
|
||
|
||
Открыть его как файл.
|
||
В Linux/BSD последовательное соединение устанавливается в тот момент,
|
||
когда устройство было подключено,
|
||
и затем отображается в разделе `/dev/` (обычно как `/dev/ttyUSB0`).
|
||
Чтобы получить доступ к этому соединению, просто откройте его как обычный файл.
|
||
Иногда этого достаточно, чтобы начать взаимодействовать с устройством,
|
||
поскольку современное оборудование работает со всеми скоростями и флагами по умолчанию.
|
||
|
||
## Как мне настроить устройство Serial/tty в Linux/BSD?
|
||
|
||
Необходимо установить флаги [termios](https://linux.die.net/man/3/termios) для файла.
|
||
Если необходимо для соединения установить такие параметры,
|
||
как скорость передачи данных в бодах, IXON/IXOFF и т.д.,
|
||
это можно сделать еще до запуска вашей программы с помощью команды
|
||
[stty](https://linux.die.net/man/1/stty), если она доступна.
|
||
Например чтобы установить скорость передачи данных в бодах,
|
||
необходимо выполнить следующую команду: `stty -F /dev/ttyUSB0 9600`.
|
||
И после того, как соединение настроено,
|
||
можно просто открыть соединение как файл и начать использовать.
|
||
|
||
Вы можете запустить `stty` из Crystal с помощью
|
||
`Process.run`, если нужен простой способ настройки устройства из вашего приложения.
|
||
Я бы, вероятно, порекомендовал этот способо в качестве решения.
|
||
|
||
## Как мне установить флаги termios из Crystal, не используя stty?
|
||
|
||
Используйте функции `termios` напрямую.
|
||
Crystal предоставляет FileDescriptor с несколькими
|
||
распространенными настройками `termios`, такими как
|
||
[cooked](https://crystal-lang.org/api/1.8.2/IO/FileDescriptor.html#cooked%28%26%3Aself-%3E_%29-instance-method),
|
||
что означает, наличие минимальных привязок
|
||
[termios](https://github.com/crystal-lang/crystal/blob/master/src/termios.cr).
|
||
|
||
Мы можем начать с использования существующего кода:
|
||
|
||
```crystal
|
||
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 готов к использованию.
|
||
```
|
||
|
||
Чтобы установить другие флаги, обратитесь
|
||
к [руководству](https://linux.die.net/man/3/termios) termios
|
||
или к этому замечательному
|
||
[руководству](https://en.wikibooks.org/wiki/Serial_Programming/termios) по Serial,
|
||
которое я только что нашел.
|
||
|
||
## Есть ли библиотека, которая могла бы сделать все это за меня?
|
||
|
||
Нет :(. Но было бы здорово, если бы кто-нибудь написал.
|
||
Вероятно, что написать библиотеку не составит большого труда,
|
||
если у кого-нибудь будет личный интерес :)
|
||
|
||
## Источник
|
||
- [Crystal-lang Accessing Serial port](https://stackoverflow.com/questions/51069578/crystal-lang-accessing-serial-port) — StackOverFlow.
|