我正在 Ubuntu 上写一些类似短信门的东西。该设备是华为 E173 调制解调器。
我使用 pyserial 向设备写入/读取内容。这是我的代码:
import serial
import time
port = '/dev/ttyUSB0'
ser = serial.Serial(port,
stopbits=serial.STOPBITS_ONE,
parity=serial.PARITY_NONE,
bytesize=serial.EIGHTBITS
)
ser.write(b'AT\r\n')
time.sleep(0.1)
print(ser.read(ser.in_waiting))
这段代码有效。但有时当我重新连接设备时,我发现它无法读取任何内容。 (ser.in_waiting=0,即使我将 n 设置得更大,也不会发生任何变化)。
但是我仍然可以使用 minicom 来使用该端口。
我的问题:为什么 pyserial 不能工作,而 minicom 可以?他们之间有什么区别吗?
我猜发生的情况是,您使用的延迟以及打开端口时设置的超时与调制解调器处理命令所需的时间相结合。
为了避免这种情况,请尝试使用循环重复读取数据一段时间:
...
ser.write(b'AT\r\n')
timeout=time.time()+3.0
while ser.inWaiting() or time.time()-timeout<0.0:
if ser.inWaiting()>0:
data+=ser.read(ser.inWaiting())
timeout=time.time()+3.0 print(data)
使用 minicom 或任何其他终端,您始终在端口上监听,因此无论调制解调器处理命令需要多长时间,您总能得到答案。在代码中,您发送命令,等待 100 毫秒,然后在超时设置定义的时间段内侦听端口。由于您没有定义超时,因此您有默认的永远等待,但该行为会通过使用缓冲区中的字节作为参数来覆盖。如果您碰巧在数据到达缓冲区之前检查缓冲区(因为该命令花费的时间比您指定的 100 毫秒长),则超时将变为零。
考虑到上一段,并假设您知道字节数,最好定义一个有限超时并使用
ser.read(n)
和 n
读取预期字节。
就我而言,(在 BeagleBone Black 上),上述答案帮助我获得了 some 字节,但不是全部。我意识到,由于某些原因,minicom 正在读取端口并(可能)刷新它。所以,PySerial 没有什么可读的。 我只是关闭了 minicom 终端,现在一切都很好了:)
您可以使用以下命令查看端口还附加了哪些内容:
sudo lsof /dev/ttyUSB0
如果您看到除您的申请之外的任何附加内容,则可能会给您带来问题。
我在我的机器上禁用了调制解调器管理器(在这种情况下,我试图向调制解调器发送 AT 命令,并且每次我第一次尝试 minicom 时都会失败):
systemctl disable ModemManager.service
systemctl stop ModemManager.service