![串行端口上的换行符错误(CR 而不是 LF)](https://linux22.com/image/1397085/%E4%B8%B2%E8%A1%8C%E7%AB%AF%E5%8F%A3%E4%B8%8A%E7%9A%84%E6%8D%A2%E8%A1%8C%E7%AC%A6%E9%94%99%E8%AF%AF%EF%BC%88CR%20%E8%80%8C%E4%B8%8D%E6%98%AF%20LF%EF%BC%89.png)
我正在尝试使用 Linux 上的 USB 转串口转换器与设备通信。驱动程序正在运行,设备位于 /dev/ttyUSB0。
有一个奇怪的问题(使用空调制解调器电缆连接到另一台计算机进行检查):无论我使用什么程序连接到设备(putty、minicom、screen),它们都会在输入时发送 CR (\r)。我(和我的设备)希望在输入时发送 LF (\n)。
当我使用控制台发送命令时,它会发送一个 LF:
# echo Hello World > /dev/ttyUSB0
结果为“Hello World\n”。我还编写了经典的 C 语言 hello world 程序 (printf("Hello, world!\n");),并将输出重定向到 /dev/ttyUSB0 - 线路另一端也输出“Hello world\n”。
但是所有其他终端程序在输入时都会发送 \r。
这里发生了什么?
答案1
我猜你说的“enter”是指Return键盘上的键,可能标有↵。
简短回答:
putty、minicom 和 screen 之所以在你按下时发送 CR, Return是因为该Return键实际上意味着“回车”(CR)。
echo
和之所以printf("Hello, world!\n");
发送 LF,是因为它们的输出以 结束\n
,这意味着 LF。请注意,这些程序不会按下任何Return键:它们甚至不会触碰键盘。
长答案:
早在七十年代,我们就在从终端s 到基于 CRT 的计算机终端。早期的终端键盘有单独的 CR 和 LF 键。在 DECVT05,这些都贴上了标签,非常恰当, CR而且LF。在VT50和VT100系列中,它们被标记RETURN为 和LINE FEED。后来的型号放弃了该LINE FEED键,最终我们得到了 Return和 LF 键。如今,这些笨重的终端已被终端仿真器(如 rxvt 或 gnome-terminal)取代。然而,顾名思义,终端仿真器的工作是……模拟终端!因此,情况并没有发生太大变化:该 Return键仍然代表 CR,就像 1975 年一样。
另一方面,Unix 将 LF 作为行尾指示符进行了标准化。无论是在文本文件还是在用户空间程序中,文本行始终以 LF 结尾。这就引出了一个问题:我们如何使用终端与 Unix 系统进行交互,而终端使得发送 LF 比发送 CR 困难得多?答案是……这取决于我们正在与哪个特定程序进行交互。
当我们与“简单”程序(或者更确切地说,不费心处理终端的程序)交互时,内核终端驱动程序处于“规范”(或“熟”)模式。在此模式下,它将来自终端的 CR 字符转换为 LF,将传出的 LF 转换为 CR+LF 序列。这些转换可以看作 输出中的icrnl
和标志。onlcr
stty -a
有些程序更喜欢自己处理终端:它们指示终端驱动程序避免进行字符转换(它们将其设置为“原始”模式)并自行处理这些转换。这通常是在库中完成的,例如
阅读行或者ncursesexec()
。Bash 就是其中一个程序(它使用 readline),但幸运的是,它在运行其他程序之前会将终端重置为 ripen 模式 。
现在,假设你想与某种通过串行端口说文本的设备对话。你去阁楼拿你的旧VT420它已经在那里积尘近 30 年了。你用交叉(“零调制解调器”)电缆将它连接到你的设备上,然后就好了!你的设备有一个终端!这有多酷?希望这个设备设计得能与经典终端很好地配合使用:它需要 CR 终止的消息。如果它需要 LF,那么你必须通过输入Ctrl-来结束你的行J,因为 VT420 没有专用LINE FEED键。
如果你没有这些可爱的老式终端,你可以使用模拟终端,例如 gnome-terminal 或酷复古术语您可以使用 minicom 等通信程序将其连接到您的设备,或者微微通信以及 USB 转串口转换器。在默认配置下,这些通信程序不会干扰您的数据流:它们将 tty 驱动程序配置为原始模式(两端均如此),并在模拟终端和设备之间忠实地转发字节,就像零调制解调器电缆对 VT420 所做的那样。但与零调制解调器电缆不同,picocom 可以配置为在需要时动态转换行尾。
答案2
如果使用picocom
,则需要将串行输出从 映射CR
到CR+LF
。
例子:
picocom /dev/ttyS0 --baud 19200 --omap crcrlf --echo
现在实际上就可以向设备发送命令了!
答案3
请确保您已将 ttyUSBx 端口设置为原始模式。否则,在接收端可能会出现一些字符替换,例如 和\r
。\n
答案4
我知道这已经过时了,但它已经让我沮丧了很久。正如@MRule提及,这个问题似乎没有用这里给出的任何答案来解决。Unix & Linux exchange 上的类似问题有更好的回答。因此,如果将来有人来到这里,这可能会有所帮助。
python-pyserial
附带的它miniterm
似乎对 cr 和 lf 做了“正确的事情”。应该可以在您的发行版的存储库或 pypi 上找到。
pyserial-miniterm /dev/ttyUSB0 115200