从串行终端读取时识别\ r \ n工件的原因?

问题描述 投票:4回答:3

我正在尝试从串行终端读取时诊断\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'

打印读取的数据在字母\r周围有一个q

当在/dev/ttyUSB0上运行终端模拟器时,该行开始在80个字符后自行环绕,类似于this question。这个换行似乎是我在使用示例python代码直接阅读时得到的/r的一种表现形式。

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

shopt -s checkwinsize
resize

之后没有换行。我试图理解为什么会发生这种情况或者在哪里(/dev/tttyUSB0是添加它们的主机还是被访问的嵌入式设备添加的主机),以及如何在不必运行外部命令的情况下解决它。

以下候选人可能导致此行为:

  • /dev/ttyUSB0在镜头ps上的驱动程序设置
  • 目标嵌入式设备上/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'

设置/dev/S0

设置目标tty设备也不会影响工件的存在。

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'

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

linux serial-port pyserial
3个回答
1
投票

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

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

切换到主机和嵌入式shell上的原始输入应该修复它。

如果您想了解有关Linux终端如何处理输入(以及将输入回送到输出流)的更多详细信息,请参阅https://www.linusakesson.net/programming/tty/


0
投票

目前尚不清楚实际发生了什么,但这似乎是有效的解决方案。

它取决于目标板上shopt -s checkwinsizeresize的存在,因此它不是一个通用的解决方案,不能成为公认的答案。

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

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'

-1
投票

\ r \ n q正在发生,因为你的屏幕在q附近结束,所以它被移动到下一行它回车的Unix。 unix回车可以用作新线,转到下一行的两端。将\ r替换为空。尝试自动包装

\ r \ n(回车)→将光标移动到行的开头而不前进到下一行\ n(换行)→将光标向下移动到下一行而不返回到行的开头 - 在* nix中环境\ n移动到行的开头。 \ r \ n(行尾)→\ r和\ n的组合

© www.soinside.com 2019 - 2024. All rights reserved.