我有一个简单的程序来测试串行功能。我的串行设备对两个输入作出反应。如果用户输入“a”,则以“fg”响应。如果用户输入任何其他字符/字节,则以“z”响应。如果我将'b'发送到串行设备,它将返回'z'就好了。当我发送'a'时,它应该返回'f'和'g',所以两个字节而不是一个。
见下面的代码。
#!/usr/bin/env python
import serial
ser = serial.Serial(
port = '/dev/ttyUSB0',
baudrate = 9600,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS
)
ser.write('a')
byteData = ser.read(1) # read one, blocking
moreBytes = ser.inWaiting()
if moreBytes:
byteData = byteData + ser.read(moreBytes)
print byteData
print byteData
ser.close()
输出结果为:
user@ubuntu:~/code/native$ ./serialTesting.py
f
inWaiting()给出值0,因此它永远不会读取第二个字节。如果我对代码做了一些小改动,并手动读取了两个预期的字节,那么它可以正常工作。
#!/usr/bin/env python
import serial
ser = serial.Serial(
port = '/dev/ttyUSB0',
baudrate = 9600,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS
)
ser.write('a')
byteData = ser.read(2) # read two expected bytes for the result 'fg'
print byteData
ser.close()
输出符合预期:
user@ubuntu:~/code/native$ ./serialTesting.py
fg
答案 0 :(得分:3)
这有两个不错的解决方案。对于其中任何一个,你需要设置一个像jramirez已建议的超时:
ser = serial.Serial(
port = '/dev/ttyUSB0',
baudrate = 9600,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
timeout=0.5, # IMPORTANT, can be lower or higher
inter_byte_timeout=0.1 # Alternative
)
byteData = ser.read(size=800) #Set size to something high
这将读取最多800个字节,并且不会超过您设置的timeout
。如果您改为设置inter_byte_timeout
,read()
将等待每个单字节的时间。
这是一个快速解决方案,适用于您只收到已知最大大小的数据块的情况。
def read_all(port, chunk_size=200):
"""Read all characters on the serial port and return them."""
if not port.timeout:
raise TypeError('Port needs to have a timeout set!')
read_buffer = b''
while True:
# Read in chunks. Each chunk will wait as long as specified by
# timeout. Increase chunk_size to fail quicker
byte_chunk = port.read(size=chunk_size)
read_buffer += byte_chunk
if not len(byte_chunk) == chunk_size:
break
return read_buffer
上面的代码段在CC0 1.0下获得许可。
然后,阅读:
byteData = read_all(ser)
基本上,这将以块的形式读取您的数据并每次等待以查看是否出现新字符。如果在timeout
设置的时间内读取的字符较少,则认为传输已完成。
此解决方案始终有效,即使您收到大量数据或收到的数据非常缓慢。
答案 1 :(得分:1)
可能是因为波特率非常慢。在第二个字节到达缓冲区之前,您正在处理inwaiting()调用。当你执行ser.read(2)时,它会等待(阻塞),直到收到2个字节为止它的工作原理。尝试设置超时1秒,这应该可以解决您的问题。
ser = serial.Serial(
port = '/dev/ttyUSB0',
baudrate = 9600,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
timeout=1 # add this
)
ser.write('a')
byteData = ser.read(1) # read one, blocking
byteData += ser.read(ser.inWaiting())
print byteData
ser.close()