You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派Zero中GPS模块与Xbee共用UART引脚的解决方案咨询

树莓派Zero:UART引脚被Xbee占用时GPS模块的解决办法

问题背景

使用树莓派Zero,GPS模块需要的UART引脚已被Xbee占用,尝试用GPIO模拟UART通信但无法正常获取GPS数据,代码如下:

from gpiozero import DigitalOutputDevice, DigitalInputDevice
import time

gps_tx_pin = 17  # GPIO pin connected to the TX pin of the GPS module
gps_rx_pin = 26  # GPIO pin connected to the RX pin of the GPS module

gps_tx = DigitalOutputDevice(gps_tx_pin)
gps_rx = DigitalInputDevice(gps_rx_pin)

def gps_write(data):
    for char in data:
        binary = bin(ord(char))[2:].zfill(8)  # Convert character to binary string
        for bit in binary:
            gps_tx.value = int(bit)
            time.sleep(0.01)  # Adjust the delay as per the requirements

def gps_read():
    data = ""
    while True:
        if gps_rx.value:
            data += "1"
        else:
            data += "0"
        time.sleep(0.01)  # Adjust the delay as per the requirements
        if len(data) >= 8:  # Adjust the number of bits received per character
            break
    return data
while True:
    gps_write("AT\r\n")  # Send command to GPS module
    response = gps_read()  # Read response from GPS module

    response_char = chr(int(response, 2))  # Convert binary string to ASCII character

    if response_char.startswith("$GPGGA"):
        data_parts = response_char.split(",")
        if len(data_parts) >= 10:
            latitude = data_parts[2]
            longitude = data_parts[4]
            print("Latitude: {}".format(latitude))
            print("Longitude: {}".format(longitude))

time.sleep(1)  # Adjust the delay as per the requirements

可行解决方法

方法1:启用树莓派的辅助UART(Mini UART)

树莓派Zero自带两个UART接口:

  • 主UART(ttyAMA0):通常被Xbee占用
  • 辅助UART(ttyS0):默认未启用,可用于连接GPS

配置步骤:

  1. 编辑/boot/config.txt文件:
    sudo nano /boot/config.txt
    
  2. 在文件末尾添加对应内容:
    • 若为树莓派Zero(无蓝牙):
      enable_uart=1
      dtoverlay=uart1,txd1_pin=32,rxd1_pin=33
      
    • 若为树莓派Zero W(带蓝牙),先禁用蓝牙对主UART的占用,再启用辅助UART:
      enable_uart=1
      dtoverlay=pi3-disable-bt
      
  3. 保存并重启树莓派:
    sudo reboot
    
  4. 重启后将GPS模块的TX接GPIO15(RXD0)、RX接GPIO14(TXD0),之后可通过minicom或pyserial库直接读取/dev/ttyS0或/dev/ttyAMA0的GPS数据。

方法2:改进软件模拟UART代码

你当前的模拟代码存在两个核心问题:

  • 时序错误:time.sleep(0.01)对应100波特率,而GPS模块默认波特率为9600,单bit延迟应为1/9600 ≈ 0.000104秒
  • 未处理UART的起始位、停止位,仅读取8位数据,无法正确解析GPS的NMEA语句

改进方案:使用pigpio库实现高精度模拟UART(依赖硬件定时,比gpiozero更适合串口模拟):

  1. 安装pigpio:
    sudo apt-get install pigpio python3-pigpio
    sudo systemctl start pigpiod
    sudo systemctl enable pigpiod
    
  2. 替换代码为:
    import pigpio
    import time
    
    # 配置模拟UART引脚
    GPS_TX = 17
    GPS_RX = 26
    BAUD_RATE = 9600
    
    pi = pigpio.pi()
    if not pi.connected:
        exit()
    
    # 初始化模拟UART
    pi.set_mode(GPS_TX, pigpio.OUTPUT)
    pi.set_mode(GPS_RX, pigpio.INPUT)
    pi.bb_serial_read_open(GPS_RX, BAUD_RATE)
    pi.bb_serial_write_open(GPS_TX, BAUD_RATE)
    
    try:
        while True:
            # 读取GPS数据
            count, data = pi.bb_serial_read(GPS_RX)
            if count > 0:
                nmea_str = data.decode('ascii')
                for line in nmea_str.split('\n'):
                    if line.startswith('$GPGGA'):
                        parts = line.split(',')
                        if len(parts) >= 10:
                            lat = parts[2]
                            lon = parts[4]
                            print(f"纬度: {lat}, 经度: {lon}")
            time.sleep(0.1)
    finally:
        pi.bb_serial_read_close(GPS_RX)
        pi.bb_serial_write_close(GPS_TX)
        pi.stop()
    

方法3:使用USB转UART模块(最便捷)

无需占用GPIO引脚,直接将GPS模块通过USB转TTL模块连接到树莓派的USB口:

  1. 连接后,树莓派会识别出串口设备(通常为/dev/ttyUSB0或/dev/ttyACM0)
  2. 使用pyserial库读取数据:
    pip install pyserial
    
    import serial
    import time
    
    ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
    try:
        while True:
            line = ser.readline().decode('ascii').strip()
            if line.startswith('$GPGGA'):
                parts = line.split(',')
                if len(parts) >= 10:
                    lat = parts[2]
                    lon = parts[4]
                    print(f"纬度: {lat}, 经度: {lon}")
            time.sleep(0.1)
    finally:
        ser.close()
    

内容的提问来源于stack exchange,提问作者Aysu Mammadli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 19:05:41