树莓派4通过UART读取GM875二维码扫描器数据异常求助
问题
使用GM875二维码/条形码阅读器通过UART连接树莓派4 Model B时,出现以下异常:
- 初始读取到大量乱码字节(如
b'\x00\x00...') - 多次扫描后偶尔能获取正确数据,但随后脚本抛出
OSError: [Errno 5] Input/output error并终止 - 该阅读器在ESP32上可正常工作,已开启树莓派UART功能,改用C++代码也会出现乱码问题
所用Python代码
import serial # Configure the serial connection (adjust parameters as needed) ser = serial.Serial( port='/dev/serial0', # Use /dev/serial0 for the Raspberry Pi UART baudrate=9600, # Adjust baudrate to match your barcode reader's settings timeout=1 # Timeout in seconds for read operations ) def read_from_scanner(): try: while True: if ser.in_waiting > 0: # Read data from the barcode scanner data = ser.readline() if data: print(f"Barcode Data: {data}") except KeyboardInterrupt: print("Program interrupted. Closing..") finally: ser.close() if __name__ == "__main__": read_from_scanner()
报错信息
Traceback (most recent call last): File "/home/pi/qrcode_project/qrcode_rpi/t1.py", line 24, in <module> read_from_scanner() File "/home/pi/qrcode_project/qrcode_rpi/t1.py", line 13, in read_from_scanner if ser.in_waiting > 0: ^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 549, in in_waiting s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ OSError: [Errno 5] Input/output error
解决方案
1. 修复树莓派UART的映射冲突
树莓派4的serial0默认可能和蓝牙共享硬件UART,导致串口不稳定:
- 执行
sudo raspi-config,进入Interface Options → Serial Port,选择「否」关闭串口控制台,选择「是」开启串口硬件支持 - 编辑
/boot/config.txt,添加以下内容:dtoverlay=disable-bt enable_uart=1 - 重启树莓派:
sudo reboot
2. 确保串口参数完全匹配GM875默认配置
GM875默认参数为9600波特率、8位数据位、1停止位、无校验(8N1),需在代码中明确指定,避免参数不匹配导致乱码:
修改后的串口初始化代码:
ser = serial.Serial( port='/dev/serial0', baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=1 )
3. 检查硬件连接与电平
- 确认交叉连接:GM875的TX引脚接树莓派的RX(GPIO15),GM875的RX引脚接树莓派的TX(GPIO14),必须共地(GND引脚相连)
- GM875支持3.3V/5V电平,树莓派UART是3.3V,建议使用3.3V供电,避免电平不匹配损坏硬件或干扰信号
4. 代码优化:捕获IO错误并重连
in_waiting调用可能触发IO错误,可添加异常捕获逻辑,实现自动重连:
import serial import time def init_serial(): try: ser = serial.Serial( port='/dev/serial0', baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=1 ) return ser except Exception as e: print(f"Failed to open serial port: {e}") return None def read_from_scanner(): ser = init_serial() if not ser: return try: while True: try: # 直接读取,避免in_waiting的IO错误 data = ser.read_until(b'\n') # 假设扫描器返回以换行结尾的数据 if data: # 过滤无效的空字节 cleaned_data = data.strip(b'\x00').decode('utf-8').strip() if cleaned_data: print(f"Barcode Data: {cleaned_data}") except OSError as e: print(f"IO Error occurred: {e}, reconnecting...") ser.close() time.sleep(2) ser = init_serial() if not ser: break except KeyboardInterrupt: print("Program interrupted. Closing..") finally: if ser and ser.is_open: ser.close() if __name__ == "__main__": read_from_scanner()
5. 排查硬件干扰
- 更换质量较好的杜邦线,避免信号衰减或干扰
- 若条件允许,用逻辑分析仪或示波器检测UART信号波形,确认数据传输是否稳定
内容的提问来源于stack exchange,提问作者AMIR
相关产品推荐
相关产品推荐

