![串行通信中只有按下 Enter 键后才能接收字符](https://linux22.com/image/1432435/%E4%B8%B2%E8%A1%8C%E9%80%9A%E4%BF%A1%E4%B8%AD%E5%8F%AA%E6%9C%89%E6%8C%89%E4%B8%8B%20Enter%20%E9%94%AE%E5%90%8E%E6%89%8D%E8%83%BD%E6%8E%A5%E6%94%B6%E5%AD%97%E7%AC%A6.png)
我有一个简单的 PC 到主板连接,使用串行(9600,无奇偶校验,8 位,无硬件流)我在 PC 上打开了简单的终端(使用 teraterm),然后在 teraterm 和主板上输入密钥,我只需这样做
cat /dev/tty05
我在示波器中看到了按下的字符,但是只有在按下 teraterm 中的“enter”键后,我才能在板控制台中看到这些字符(就好像它们存储在 Linux 驱动程序中的某个 FIFO 中,只有输入触发输出)
为什么只有按下 Enter 键时 Linux 驱动程序才会收到字符?有没有办法在不按下 Enter 键的情况下接收字符?(我们使用一些 ascii 协议,因此将其作为虚拟字符发送是没有意义的)谢谢 Ran 的建议
答案1
该cat
程序使用行缓冲。这就是为什么您直到按下键才看到结果的原因。终端驱动程序在字符到达时看到它们,但cat
不会显示它们。不要使用 cat,而是尝试使用终端仿真器来查看到达的字符。
终端可能也处于cooked
morde 模式。您可以在运行 cat 之前运行该命令来禁用此功能stty raw < /dev/tty05
。您可以使用该命令重置设置stty sane < /dev/tty01
,尽管关闭终端时它可能会被重置。
使用终端的程序通常会在字符到达时读取它们。终端仿真器就是其中之一,更适合您的情况。
如果您只想读取数据,那么在大多数语言中,编写一个阻塞字符读取代码很简单。这可以在循环中运行,并在字符到达时进行回显。
编辑:以下 Python 脚本演示了如何逐个从终端设备读取字符。这要求终端处于原始模式,以禁用终端驱动程序中的缓冲。该stty
命令可用于将终端设置为原始模式,但此程序执行此操作。
#!/usr/bin/python
import termios
import tty
with open('/dev/tty', 'rb') as f:
fd = f.fileno()
old_settings = termios.tcgetattr(fd)
print "Enter characters (q to quit)"
tty.setraw(fd)
ch = ''
try:
while ch != 'q':
ch = f.read(1)
if not ch:
print "End of file"
break
print "Read a character:", ch, '\r'
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
答案2
谢谢 Bill,看来你帮我找到了答案。它与“线路缓冲”有关,也称为规范/非规范模式,也就是说,从 uart 读取的代码也可以支持或不支持“线路缓冲”:
In canonical mode:
* Input is made available line by line. An input line is available
when one of the line delimiters is typed (NL, EOL, EOL2; or EOF at
the start of line). Except in the case of EOF, the line delimiter
is included in the buffer returned by read(2).
* Line editing is enabled (ERASE, KILL; and if the IEXTEN flag is
set: WERASE, REPRINT, LNEXT). A read(2) returns at most one line
of input; if the read(2) requested fewer bytes than are available
in the current line of input, then only as many bytes as requested
are read, and the remaining characters will be available for a
future read(2).