![如何使用屏幕作为串行终端,按键模拟 CR+LF 自动模式](https://linux22.com/image/75982/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E5%B1%8F%E5%B9%95%E4%BD%9C%E4%B8%BA%E4%B8%B2%E8%A1%8C%E7%BB%88%E7%AB%AF%EF%BC%8C%E6%8C%89%E9%94%AE%E6%A8%A1%E6%8B%9F%20CR%2BLF%20%E8%87%AA%E5%8A%A8%E6%A8%A1%E5%BC%8F.png)
我想使用屏幕作为串行终端,但我的输出格式不正确。我使用这个命令:
sudo screen /dev/ttyACM0 9600,cs8
认为上面的配置就像 9600 8N1,没有奇偶校验和流量控制配置,我得到了这个输出:
This program runs since 135 seconds.
This program runs since 136 seconds.
This program runs since 137 seconds.
This program runs since 138 seconds.
This program runs since 139 seconds.
This program runs since 140 seconds.
This program runs since 141 seconds.
在 QTKTerm 中,我得到了相同的结果,直到我CR LF auto mode
在配置菜单中设置:
This program runs since 759 seconds.
This program runs since 760 seconds.
This program runs since 761 seconds.
如何在屏幕上得到相同的结果?
感谢您的帮助。
答案1
TLDR:你不能; stty
屏幕启动时将覆盖通过设置的任何选项。它不支持ocrnl/onlcr/icrnl/inlcr
配置回车符与换行符所需的选项。它以独占模式打开终端设备,因此在 screen 启动后您无法使用 stty 更改这些选项。对于 2020 年 2 月 5 日的 Screen 版本 4.08.00 (GNU) 来说也是如此。
长表:
我遇到了同样的问题,并在堆栈交换领域搜索了几个相关的问题和答案。我被迫得出这样的结论您无法让屏幕发送换行符(LF; \n
)而不是回车符(CR; \r
),至少在不更改源代码并重新编译的情况下是这样。
这个问题询问如何从屏幕发送 LF 而不是 CR。目前还没有答案。这个答案
是错的 (stty -F /dev/YOURSERIALDEVICE YOURBAUDRATE raw
不会改变屏幕配置 tty 的方式)。这个答案建议使用 picocom,但没有回答如何让屏幕发送正确的换行符的问题。然而,它确实有效:
picocom /dev/YOURSERIALDEVICE --baud YOURBAUDRATE --omap crcrlf --echo
# (press Control+a Control+x to exit)
有一些关于如何解决这个问题的提示屏幕在 stty 手册页中。 Screen 将 tty 文件后的以逗号分隔的选项列表转发到 stty,因此其中一些选项可能会有所帮助:
> man stty
# (output abridged..)
Input settings:
[-]icrnl translate carriage return to newline
[-]inlcr translate newline to carriage return
Output settings:
[-]ocrnl translate carriage return to newline
[-]onlcr translate newline to carriage return-newline
[-]onlret newline performs a carriage return
但是,将输入和输出设置为替换\r
为\n
,确保\n
不替换为\r
,并确保onlret
未设置...并没有什么区别,
screen /dev/YOURSERIALDEVICE YOURBAUDRATE,ocrnl,-onlcr,icrnl,-inlcr,-onlret
行为与以前相同。我不确定为什么屏幕似乎不应用这些选项。这个答案对于一个模糊相似的问题建议使用 stty 来更改选项。
> stty -F /dev/YOURSERIALDEVICE YOURBAUDRATE ocrnl -onlcr icrnl -inlcr -onlret
> screen /dev/YOURSERIALDEVICE
这不会执行任何操作,因为 screen 会在启动时重置 stty 执行的所有配置。这个答案声称可以运行 stty后屏幕启动,但当我这样做时,出现错误Device or resource busy
。
这个答案还解决了屏幕中 CR/LF 的问题。它指的是窗户类型screen 在线文档的部分。
“尝试在节点上进行独占打开以将连接线路标记为忙”-- 所以我们不应该能够在启动屏幕后更改 tty 选项。
仅
baud_rate
、cs8/cs7
(每字节位数)、ixon/off
和istrip
是已记录的选项。这可能意味着屏幕无法识别/支持 ocrnl 等。
总之:如何让 screen 发送 LF ( \n
) 而不是 CR ( \r
) 的问题已在各种堆栈交换站点上被问过多次。所提供的答案都不起作用,并且仔细阅读文档表明目前这是不可能的。
答案2
如果将 tty(字符特殊设备)名称(例如
"/dev/ttya"
)指定为第一个参数,则窗口直接连接到该设备。这种窗口类型类似于"screen cu -l /dev/ttya"
.设备节点上需要读取和写入访问,尝试在节点上进行独占打开以将连接线路标记为繁忙。允许使用可选参数,该参数由逗号分隔的标志列表组成,其表示法为 'stty(1)':
它继续列出了一些可能的标志,但添加了
您可能需要指定尽可能多的适用选项。未指定的选项会导致终端驱动程序构成连接的参数值。这些值取决于系统,并且可能是默认值或从先前连接保存的值。
查找更多信息的通常位置是stty
手动,因为伪终端连接支持这些附加标志stty
。
onlcr
您的问题最相似的不当行为应通过添加“输出设置”下列出的标志来修复:
[-]
onlcr
将换行符转换为回车符-换行符
例如:
sudo screen /dev/ttyACM0 9600,cs8,onlcr
然而,正如评论中指出的,screen
自己处理这些信息。这tty.sh
脚本生成源代码(对于stty模式) 哪个屏幕用于处理命令行选项,例如CS8。它对任何一个都没有任何作用stty
该函数中的 CR/NL 映射。基于一个评论在源中,
if (!ttyflag) { /* 甚至可能对 ptys 没有好处.. */ #如果已定义(ICRNL) m->tio.c_iflag |= ICRNL; #endif /* ICRNL */ #如果已定义(ONLCR) m->tio.c_oflag |= ONLCR; #万一
开发人员似乎发现这种事情实施起来很困难,所以干脆选择不支持它。
答案3
这对我很有帮助,您可以在屏幕中启用/禁用 crlf: