Crystal-lang访问串行端口

时间:2018-06-27 18:47:22

标签: python serial-port pyserial crystal-lang

我想使用Crystal lang访问串行端口。

我在python中有以下代码。我想为宠物项目编写等效的Crystal-lang代码。

import serial

def readSerData():

    s = ser.readline()
    if s:
        print(s)
        result = something(s) #do other stuff
        return result

if __name__ == '__main__':

    ser = serial.Serial("/dev/ttyUSB0", 9600)
    while True:
        data = readSerData()
        #do something with data

我找不到用于访问串行端口的任何库。

在crystal-lang中访问串行端口的正确方法是什么?

谢谢。

1 个答案:

答案 0 :(得分:7)

要真正覆盖所有内容,更容易分多个部分回答这个问题:

问:如何访问linux / bsd上的串行端口?

A:将其作为文件打开。在linux / bsd上,插入设备后即建立了串行连接,然后在/dev/下列出了这些位置(最近,通常为/ dev / ttyUSB0)。为了访问此连接,您只需像打开常规文件一样打开它即可。有时,实际上这足以开始与设备进行通信,因为现代硬件通常可以在所有波特率和默认标志下使用。

问:如何在linux / bsd上配置串行/ tty设备?

A:在文件上设置termios标志。如果确实需要配置连接以设置波特率,IXON / IXOFF等设置,则可以在使用stty(如果可用)运行程序之前进行此操作。例如。设置波特率,您可以运行:stty -F /dev/ttyUSB0 9600。设置完成后,您可以将其作为文件打开并开始使用。

如果您想从应用程序配置设备的简单方法,则可以使用Process.run从Crystal生成stty。我可能会在下一个解决方案中推荐这种方法。

问:如何在不使用stty的情况下从crystal设置termios标志?

A:直接使用termios posix函数。 Crystal实际上为FileDescriptor句柄提供了一些常见的termios设置,例如cooked,这意味着它已经具有最少的termios bindings。我们可以从使用现有代码开始获取灵感:

require "termios" # See above link for contents

#Open the file
serial_file = File.open("/dev/ttyACM0")
raise "Oh no, not a TTY" unless serial_file.tty?

# Fetch the unix FD. It's just a number.
fd = serial_file.fd

# Fetch the file's existing TTY flags
raise "Can't access TTY?" unless LibC.tcgetattr(fd, out mode) == 0

# `mode` now contains a termios struct. Let's enable, umm.. ISTRIP and IXON
mode.c_iflag |= (Termios::InputMode::ISTRIP | Termios::InputMode::IXON).value
# Let's turn off IXOFF too.
mode.c_iflag &= ~Termios::InputMode::IXOFF.value

# Unfun discovery: Termios doesn't have cfset[io]speed available
# Let's add them so changing baud isn't so difficult.
lib LibC
  fun cfsetispeed(termios_p : Termios*, speed : SpeedT) : Int
  fun cfsetospeed(termios_p : Termios*, speed : SpeedT) : Int
end

# Use the above funcs to set the ispeed and ospeed to your nominated baud rate.
LibC.cfsetispeed(pointerof(mode), Termios::BaudRate::B9600)
LibC.cfsetospeed(pointerof(mode), Termios::BaudRate::B9600)
# Write your changes to the FD.
LibC.tcsetattr(fd, Termios::LineControl::TCSANOW, pointerof(mode))

# Done! Your serial_file handle is ready to use.

要设置其他任何标志,请参考termios manual或我刚刚找到的这个不错的serial guide

问:有图书馆为我做这些吗?

A:否:(。我看不到,但是如果有人做到了,那就太好了。如果有人有既得利益,那么要创建一个人可能就没多少工作了:)