我有一个串行设备,我正在尝试从中读取输入。我给它发送了一个字符串“ID\r”,它返回“ID XX\r”(其中\r 是ASCII 回车,十六进制0x0d)。
由于不再支持 serial.readline 上的 eol 选项,因此我使用 TextIOWrapper 从串行端口读取并一次返回一行。
我的问题是,它不是在看到回车后立即返回我的字符串,而是等到我打开串口时设置的超时时间的两倍。我希望它在读取整行后立即返回字符串,因为我可能有数百个这样的命令要发送到设备,而且我不想每次都等待超时。如果我将超时设置为 0,那么我根本不会得到任何输出(可能是因为我的脚本在设备有机会输出任何内容之前停止等待),如果我将超时设置为无,脚本将永远阻塞。
这是一个简单的测试脚本:
import serial
import io
import time
ser = serial.Serial("/dev/ttyUSB0", baudrate=9600,
bytesize=8, parity='N', stopbits=1,
xonxoff=0, rtscts=1, timeout=5)
sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser),
newline=None)
sio.write(unicode("ID\r"))
sio.flush()
print "reading..."
x = sio.readline()
print len(x)
print x
该脚本从它说“正在读取”到打印从串行端口读取的“ID XX”字符串总是需要 10 秒。
我确定设备正在输出回车,因为我使用 strace 来观看读取:
select(4, [3], [], [], {5, 0}) = 1 (in [3], left {4, 991704})
read(3, "I", 8192) = 1
select(4, [3], [], [], {5, 0}) = 1 (in [3], left {4, 999267})
read(3, "D", 8191) = 1
select(4, [3], [], [], {5, 0}) = 1 (in [3], left {4, 999420})
read(3, " ", 8190) = 1
select(4, [3], [], [], {5, 0}) = 1 (in [3], left {4, 999321})
read(3, "X", 8189) = 1
select(4, [3], [], [], {5, 0}) = 1 (in [3], left {4, 999355})
read(3, "X", 8188) = 1
select(4, [3], [], [], {5, 0}) = 1 (in [3], left {4, 999171})
read(3, "\r", 8187) = 1
select(4, [3], [], [], {5, 0}) = 0 (Timeout)
select(4, [3], [], [], {5, 0}) = 0 (Timeout)
您可以看到导致 10 秒延迟的 2 个 select() 超时,但您也可以清楚地看到正在读取的回车。我尝试将换行参数设置为“无”和“”(应该自动允许 \r、\n 和 \r\n)和“\r”,但每次的结果都相同。
我还尝试将 BufferedRWPair() 调用中的 buffer_size 设置为“1”,以防止它缓冲输入,但这并没有什么区别。
知道我做错了什么吗?
如果我不能让这个工作,我的下一步将是使用 serial.read() 一次读取一个字符并做我自己的行缓冲,但我想尝试用 textiowrapper 以“正确”的方式来做第一的。