GPS L1 C/A信号(1575.42 MHz,BPSK调制,1.023 MHz码率)是软件定义无线电(SDR)入门经典案例。借助RTL-SDR / HackRF / USRP + GNURadio或Python,可完成从原始IQ到NMEA语句的完整处理链路。本文聚焦工程实现要点。

一、硬件与前端参数设置

• 中心频率:1575.42 MHz

• 采样率:常选 2.048 Msps 或 4.096 Msps(整数倍于C/A码率1.023M)

• 增益:RTL-SDR约 30~40 dB(防ADC饱和)

- 天线:有源GPS天线(需DC馈电,RTL-SDR dongle通常可提供偏置T)

⚠️ 注意:GPS信号到达地面约 -130 dBm,接近噪底,前端增益与屏蔽至关重要。

二、捕获阶段(Acquisition)—— 核心难点

C/A码是长度1023的Gold码,卫星PRN 1~32各对应不同Gold序列。捕获即找(PRN编号 , 多普勒频偏) 使相关峰最大。

2.1 串行搜索流程(Python概念)

import numpy as np

from scipy.signal import resample_poly

# ca_code[prn] : length 1023, ±1

def correlate_prn(iq, prn, doppler_hz, fs):

   # 下变频到基带(粗略)

   t = np.arange(len(iq))/fs

   iq_dc = iq * np.exp(-1j*2*np.pi*doppler_hz*t)

   # 分段相关(每段1023点,需匹配码片率)

   corr = []

   ca = ca_code(prn)

   for start in range(0, len(iq_dc)-1023, 1023):

       seg = iq_dc[start:start+1023]

       corr.append(np.abs(np.sum(seg * ca)))

   return np.max(corr)

# 搜索范围:多普勒 ±10kHz,步长500Hz

for prn in range(1,33):

   for fd in np.arange(-10000, 10001, 500):

       pk = correlate_prn(iq_block, prn, fd, fs)

       if pk > threshold:

           print(f"PRN {prn} acquired, fd={fd} Hz")

实际工程常用 FFT并行相关(频域相乘) 加速:

\[

R(k) = \mathcal{F}^{-1}\{\mathcal{F}(rx(k))\cdot\mathcal{F}^*(ca(k))\}

\]

2.2 经验值

• 相干积分1ms通常足够初捕

• 非相干累积(平方和)2~5次可提高弱信号检测

三、跟踪(Tracking)—— 细化载波与码相位

捕获成功后转锁相环(PLL)+ 延迟锁定环(DLL):

- 载波环:Costas环,跟踪残余多普勒

• 码环:Early-Prompt-Late相关器,调整本地C/A码相位

• 每ms输出导航位(50 bps) 经过汉ming码校验与奇偶位校验

GNURadio提供 gpsd 或可用 gr-gps 模块;纯Python可用 gnss-sdr 开源框架。

四、解码与NMEA输出(概念)

跟踪得到的50bps比特流经:

1. 帧同步(前导字 1000100110000001)

2. 子帧解析(按IS-GPS-200标准解星期数/卫星健康/星历)

3. 伪距计算(基于码相位 + 周数翻转解算)

4. PVT解算 → 经纬度/海拔 → NMEA $GPRMC/$GPGGA

开源工具 gnss-sdr 可直接输出RINEX或NMEA:

gnss-sdr --config_file=gps_l1_ca.conf

五、GNURadio快速验证流程

[UHD: USRP Source / RTL-SDR Source]

     │ 中心频 1575.42M, 采率 2.048M

     ▼

[Low Pass Filter (1.5M)] → [Multiply Const (归一化)]

     ▼

[GPS Acquisition Block (自定义或 gr-gps)]

     ▼

[GPS Tracking / Nav Decode]

     ▼

[File Sink / Socket (NMEA)]

在 gr-gps 中勾选 Acquisition + Tracking + Navigation 即可看到卫星列表与定位结果。

六、常见失败原因排查

现象 原因 对策

无任何PRN捕获 天线未馈电 / 增益太低 / 频偏 > ±10kHz 确认有源天线供电;室外开阔天空测试

捕获偶尔成功但不跟踪 晶振偏差大(>5ppm)致载波失锁 用TCXO或外接高稳时钟

解出帧但经纬度跳变 周数翻转未处理 / 星历过期 用最新星历(almanac/ephemeris via A-GPS或自收)

RTL-SDR底噪过高 使用无屏蔽线 / 靠近WiFi 加金属屏蔽盒,远离2.4G干扰

七、结语

基于SDR做GPS信号捕获与解码可拆为三步:① 下变频并粗搜(PRN,doppler)获相关峰 → ② PLL/DLL精细跟踪得50bps导航位 → ③ 按IS-GPS-200解子帧得PVT。利用RTL-SDR + gnss-sdr或GNURadio gr-gps,可在普通PC上完整复现该流程,是理解卫星导航接收机基带算法的极佳实战。