Linux 识别从串行终端读取时\r伪影的原因?

Linux 识别从串行终端读取时\r伪影的原因?,linux,serial-port,pyserial,Linux,Serial Port,Pyserial,我正在尝试诊断从串行终端读取时产生\r伪影的原因 以下代码可能引发此问题。有一个嵌入式Linux设备连接到uart电缆的物理端 import serial ser = serial.Serial( port='/dev/ttyUSB0', baudrate=115200, timeout=5) ser.reset_input_buffer() ser.reset_output_buffer() b_NEW_LIN

我正在尝试诊断从串行终端读取时产生
\r
伪影的原因

以下代码可能引发此问题。有一个嵌入式Linux设备连接到uart电缆的物理端

import serial                      

ser = serial.Serial( 
    port='/dev/ttyUSB0', 
    baudrate=115200,  
    timeout=5) 

ser.reset_input_buffer()
ser.reset_output_buffer()

b_NEW_LINE_WRITTEN = b'\n'
b_alphabet = b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z'
ser.write(b_alphabet + b_NEW_LINE_WRITTEN)

raw_line = ser.readline()
print(raw_line)                                                                                  
# b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q\rq R r S s T t U u V v W w X x Y y Z z\r\n'
打印读取数据时,字母
q
周围有一个
\r

/dev/ttyUSB0
上运行终端仿真器时,该行在80个字符后开始环绕自身,类似于 . 这行代码似乎是直接阅读示例python代码时得到的
/r
的一种表现形式

当连接到终端仿真器(
picocom
)时,通过运行以下命令可以解决此问题:

shopt -s checkwinsize
resize
在那之后就没有线了。我试图理解为什么会发生这种情况,或者在什么地方(主机在哪里?
/dev/tttyUSB0
什么添加了它们,或者它们是被访问的嵌入式设备添加的),以及如何在不运行外部命令的情况下解决这一问题

以下候选者可能导致该行为:

  • 快照ps上
    /dev/ttyUSB0
    的驱动程序设置
  • 目标嵌入式设备上
    /dev/S0
    的驱动程序设置
  • 目标设备上的shell
设置
/dev/ttyUSB0

当python脚本使用设备时,尝试在单独的终端中修改
/dev/ttyUSB0
,不会显示任何更改

# Separate terminal on the host
stty -F /dev/ttyUSB0  cols 100
stty -F /dev/ttyUSB0 raw
stty -F /dev/ttyUSB0  -a
speed 115200 baud; rows 80; columns 100; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^A; eol = <undef>; eol2 = <undef>; swtch = <undef>;
start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O;
min = 1; time = 0;
-parenb -parodd -cmspar cs8 hupcl -cstopb cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany
-imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl -echoke
-flusho -extproc


#ipython
...
ser.write(b_alphabet + b_NEW_LINE_WRITTEN)
raw_line = ser.readline()
print(raw_line)                                                                                  
# b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q\rq R r S s T t U u V v W w X x Y y Z z\r\n'

例如,一种解决方法是在读取之前以某种方式设置200列的固定数量,以便串行终端停止尝试智能化

目前尚不清楚实际发生了什么,但这似乎是一个可行的解决方案

这取决于目标板上是否存在
shopt-s checkwinsize
resize
,因此它不是一个足够通用的解决方案,无法成为公认的答案

此外,它也没有提供如何应用非运行时修复(通过在bash中设置驱动程序默认值或某些配置)的细节


\发生RQ是因为您的屏幕在q附近结束,所以它被移动到下一行,返回Unix。unix回车符可以用作新行,转到下一行的末尾。将\r\n替换为空。 尝试自动换行

\r(回车)→ 将光标移动到行首,而不移动到下一行 \n(线路馈电)→ 将光标向下移动到下一行而不返回到行的开头-在*nix环境中\n移动到行的开头。
\r\n(行尾)→ 结合\r和\n

两行之间的读取,您正在嵌入式设备上运行类似Linux shell的东西

这将具有与主机相同的Linux app/TTY/驱动程序层次结构集,并且默认为对从应用程序接收的输入进行烹调模式处理。这就是为什么运行命令来更改列数(在嵌入式应用程序上)是有效的。它告诉该设备中的行规程将屏幕视为200列宽(因此行编辑逻辑不需要拆分行)

在主机和嵌入式shell上切换到原始输入应该可以解决这个问题


如果您想了解Linux终端如何处理输入(以及将输入回显到输出流)的更多详细信息,请参阅

使用Linux时,您的应用程序无法访问“串行端口”。而是从一个串行终端读取,该终端由设备名/dev/tty…表示。。。。您的应用程序从“串行端口”中删除了几层。看见使用Python和Pyserial,您添加了更多抽象层和失控层。使用包含相同文本字符串的文件的Send ASCII命令发送到远程设备,然后查看返回的内容。在串行通信中,有一个非常非常久远的惯例,即使用一对字符
\r\n
——一个ASCII
CR
(回车符),后跟一个ASCII
LF
(换行符)--表示一行文字的结尾。如果您不喜欢设备发送的
\r
,请让您的程序丢弃它。(您很幸运,该设备不需要您将其作为线路终止符发送。
\r\n
。显然,它只愿意在传入数据中接受一个
\n
作为线路结束标记。)您的串行线路设置是什么?串行设置之一可能是协调一个字节。核对stty@rm5248对于
/dev/ttyUSB0
/dev/S0
,哪些选项?在目标(嵌入式设备)tty选项上设置正确的设置可以解决问题。最后,我选择了无回声,这简化了所有问题。这意味着在目标上调用sttyraw-echo-echo-echok-echoctl-echoke(通过python脚本)
stty_cmd_set = b'stty cols 200'
ser.write(stty_cmd_set + b_NEW_LINE_WRITTEN)
ser.reset_input_buffer()
ser.reset_output_buffer()
stty_cmd_confirm = b'stty -a'
ser.write(stty_cmd_confirm + b_NEW_LINE_WRITTEN)

# After reading a few lines there is a confirmation that the tty device on the target has indeed been set to 200 
print(ser.readline())                           
b'speed 115200 baud; rows 56; columns 200; line = 0;\r\n'
ser.reset_input_buffer()
ser.reset_output_buffer()

ser.write(b_alphabet + b_NEW_LINE_WRITTEN)

raw_line = ser.readline()
print(raw_line)                                                                                  
# b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q\rq R r S s T t U u V v W w X x Y y Z z\r\n'
import serial             
import time         

ser = serial.Serial( 
    port='/dev/ttyUSB0', 
    baudrate=115200,  
    timeout=5) 

b_NEW_LINE_WRITTEN = b'\n'
b_NEW_LINE_READ = b'\r\n'
b_alphabet = b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z'

ser.write(b_alphabet + b_NEW_LINE_WRITTEN) 
print(ser.readline())
# b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q\rq R r S s T t U u V v W w X x Y y Z z\r\n'

shopt_cmd = b'shopt -s checkwinsize' 
ser.write(shopt_cmd + b_NEW_LINE_WRITTEN)
ser.readline()
ser.readline()

resize_cmd = b'resize' 
ser.write(resize_cmd + b_NEW_LINE_WRITTEN)
ser.readline()
ser.readline()

stty_cmd_set = b'stty cols 200'
ser.write(stty_cmd_set + b_NEW_LINE_WRITTEN)
ser.readline()
ser.readline()

ser.write(b_alphabet + b_NEW_LINE_WRITTEN) 
print(ser.readline())
# b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z\r\n'

ser.reset_output_buffer()
stty_cmd_set = b'stty cols 5'
ser.write(stty_cmd_set + b_NEW_LINE_WRITTEN)
ser.readline()
ser.readline()


ser.write(b_alphabet + b_NEW_LINE_WRITTEN) 
print(ser.readline())
# A a B \r b C c\rc D d \r E e F\rF f G \r g H h\rh I i \r J j K\rK k L \r l M m\rm N n \r O o P\rP p Q \r q R r\rr S s \r T t U\rU u V \r v W w\rw X x \r Y y Z\rZ z\r\n'