如果你在接收机项目里调过 GLONASS,大概率有过这种经历:频谱上明明有一排非常明显的尖峰,捕获却总是报错;信号强度看着不错,伪距解出来却跳变几十米。GLONASS 的 FDMA 信号体制跟 GPS、北斗的 CDMA 差别很大,不是简单把协议栈换一下就能跑通的。这篇我按一条完整链路——采样、捕获、跟踪、电文解调、伪距归算——把每个环节的流程、参数、坑点逐个过一遍。内容主要服务正在做 GNSS 基带开发、或者想把单模接收机扩展到 GLONASS 双模的同学,也会穿插一些实际调试时该看哪个量、该改哪个参数的判断方法。
1. GLONASS 信号体制与处理链路总览
1.1 FDMA 体制到底特殊在哪
GLONASS 传统民用信号在 L1 和 L2 频段,最突出的特点是采用频分多址,每颗卫星都有自己独立的标称频率,用频率来区分卫星。以 L1 为例,标称频点按下面这个关系排列:
- L1 频率 = 1602 MHz + 0.5625 × k,其中 k 是频道号
- L2 频率 = 1246 MHz + 0.4375 × k
现阶段大部分卫星的频道号在 -7 到 6 之间,新一代卫星还有继续扩展的趋势。这意味着接收机必须先知道每颗卫星对应的频道号,才能把本地载波频率大致对准。GPS 是全网共用同一个频率,靠不同的 C/A 码序列区分卫星;GLONASS 是码序列本身大家都一样,用频率做第一层区分。这个差异直接决定了捕获策略完全不同,很多从 GPS 代码改过来的同学第一版 GLONASS 捕获十有八九会找不到卫星,正是因为默认了“一个频点搜所有卫星”。
另一个容易被忽略的点是码序列。GLONASS 民用 L1 的测距码是一个 9 级移位寄存器生成的 m 序列,码长 511,码率 0.511 Mcps,码周期刚好 1 ms。这个特性非常有意思,它让 GLONASS 和 GPS 在相关处理上有一个重要差异:码周期同样是 1ms,但码长短,所以相关峰更尖锐,对多普勒误差也更敏感。换句话说,GLONASS 捕获搜索时频率步进必须比 GPS 更小心,否则很容易把真实的峰值漏掉。
1.2 一条完整 GLONASS 链路有哪些环节
从天线口到定位输出,典型的 GLONASS 处理链路大致是:
天线 → 低噪声放大 → 射频下变频到中频 → ADC 采样 → 数字下变频按频道号分离 → 多通道并行捕获 → 码环 + 载波环跟踪 → 比特同步与帧同步 → 电文译码 → 伪距 / 载波相位测量 → PVT 解算
与 GPS 相比,整个链路里多了一个关键的“按频道号做数字下变频和频率补偿”环节。GPS 接收机通常只需要处理一个中心频率,然后靠码相位去区分卫星;GLONASS 接收机则必须处理一组相隔 0.5625 MHz 的载波。如果你用窄带前端一次只能抓住一颗或几颗卫星,那么后级的跟踪通道配置也要跟着变,不能沿用 GPS 那种“所有通道同一频率基准”的设计。
再往后,定位解算还有个容易被忽视的差异:GLONASS 电文采用自己的时间基准和坐标系。伪距测量用的是 GLONASS 系统时间,它和 GPS 时间之间存在秒级和整秒级偏差;星历坐标是 PZ-90 系,与 WGS-84 或 CGCS2000 之间还存在数十厘米到米级的系统差。到了 PVT 阶段,这些不一致必须显式建模,否则会出现“每颗星伪距都对,解算位置偏偏差”的怪现象。
提示:FDMA 不是负担,但对基带而言它意味着更灵活的通道分配。工程上建议提前把频道号管理做成一张动态表,而不是写死在代码里,因为 GLONASS 的频道号会随星座更新变化。
2. 前端采样与捕获准备:先把手里的数据摸清楚
2.1 采样率、中频和前端带宽怎么选
GNSS 接收机前端一般把射频信号搬到几十 MHz 的中频,再用 ADC 数字化。GLONASS 处理时,采样率的选择比 GPS 更有讲究,原因是码率 0.511 Mcps 这个数值,跟常见 GNSS 时钟不是严格的整数关系。
我见过不少实际板子用 2.048 MHz、4.096 MHz、8.184 MHz 甚至 16.368 MHz 作为采样率。这些数字不是随手定的,它们都近似是 0.511 Mcps 的整数倍,或者与码周期存在固定关系。这样处理最简单:每个码片对应固定的采样点数,码相位搜索时不需要做重采样,相关器实现会清爽很多。
如果用 10 MHz、20 MHz 这种“整数好找”的晶振采样,也完全可行,但捕获前必须增加一个重采样环节,把采样率换算到与码率对齐的网格上,否则码相位计算会很别扭。我踩过这个坑:直接用 20 MHz 采样流跑捕获,码相位峰值总是出现在两个相邻 bin 之间,后来才发现是本地码生成速率跟数据流速率没对齐。
前端带宽对 GLONASS 影响更大。L1 频段跨度本身就有十几 MHz,如果想一次采样覆盖所有可见卫星,中频滤波器带宽得开到十几 MHz 以上,这样做的好处是单通道模拟前端就行,坏处是会把带外干扰一起收进来。窄带前端则只能一次覆盖少量几个频道,需要通过多次扫描或者多个下变频支路来覆盖全星座。具体取舍取决于板卡资源和功耗,我的建议是:如果做手持设备,中频带宽覆盖 ±6 MHz 比较折中,能同时收多颗卫星,又不用面对太宽的噪声底。
2.2 直流偏置、量化位数与数据格式的坑
ADC 采样后的数据格式是另一个容易翻车的地方。GNSS 前端输出的中频信号一般有直流偏置,也就是频谱上的零频分量,在数字域表现为一个固定的直流项。这个直流项对普通模数转换可能没什么影响,但进入相关器后会污染零频附近的搜索结果,尤其 GLONASS 的 FDMA 信号本来就分布在多个频点上,直流偏置会让某些频点的峰背景抬高。解决办法很土但很有效:数字域先做一个直流估计并扣除,或者在捕获前对数据做高通滤波。
量化位数方面,1 bit 采样在低成本接收机上很常见,理论上有 2 dB 左右的信噪比损失;2 bit 量化已经比较均衡;4 bit 以上基本接近理想采样。如果前端带宽比较宽、频道数多,我建议至少用 2 bit,因为当多个 FDMA 信号同时进入时,1 bit 量化会产生更多的互调失真,不同频点之间的交叉干扰会被放大。
注意:数据格式必须和捕获模块约定一致。比如信号数据用有符号整数还是补码,本地码表用什么方式索引,这些细节出了问题,捕获结果是完全乱的,而且非常难排查。
3. 二维搜索捕获:把卫星从噪声里捞出来
3.1 搜索空间:码相位、多普勒、频道号三维量的确定
GLONASS 捕获本质是在码相位、多普勒频率、频道号三个维度上做搜索,比 GPS 多了一个维度。码相位搜索范围是 0 到 510.75 个码片,步长一般取半个码片,这样不管真实码相位落在哪个采样点附近,都能保证有足够的相关增益。多普勒搜索范围取 ±10 kHz 比较保险,因为卫星运动产生的多普勒在 L1 上大约 ±5 kHz,再叠加接收机晶振误差和频道号误差,±10 kHz 才能覆盖所有情况。
频率搜索步长怎么定?这个直接关系到捕获灵敏度。对于一个 1 ms 的相干积分,频率误差会导致相关峰幅度按 Sinc 函数衰减。为了保证衰减不超过约 3 dB,频率步长最好取相干积分时间倒数的一半,也就是 1/(2×T),T=1 ms 时约等于 500 Hz。如果你做非相干累加,比如累加 5 次、10 次,可以稍微放宽到 400~500 Hz,但不要过度放宽,GLONASS 码周期短,多普勒误差导致峰值损失比 GPS 更快。
还有一个非常容易踩的坑:GLONASS 各卫星的标称频率本身随频道号不同,搜索中心要做一次搬移。假设卫星频道号 k=3,那么搜索中心频率就是以 1602+0.5625×3=1603.6875 MHz 为基准,再往两边扫多普勒。如果把卫星频点忽略了,只按 1602 MHz 中心去搜,那所有卫星都会偏出搜索范围。
3.2 FFT 相关器到底是怎么实现的
现在主流实现都是用 FFT 做码相位并行搜索。核心思路很简单:把接收信号和本地码做循环相关,相关峰的位置就是码相位。
具体流程我一般这么写:
- 读取 1 到 2 个码周期长度的采样数据,也就是 1~2 ms 数据
- 生成本地 GLONASS 码序列,长度与数据对齐,补零到合适的 FFT 点数
- 对接收数据和本地码分别做 FFT
- 接收频谱与本地码频谱取共轭后相乘
- IFFT 回到时域,取模得到相关结果
- 对得到的码相位谱做峰值检测
这里有个细节:GLONASS 码序列是周期 1 ms 的 m 序列,FFT 长度选择要尽量覆盖整数个码周期。如果你用 1 ms 数据,码序列刚好一个周期,做循环相关没有边界问题;如果用更长数据做相干积分,就要注意跨周期的码连续性,通常做法是生成连续周期码流,而不是单独一个周期重复填充。
非相干累加是提高捕获灵敏度的重要手段。单独一个 1 ms 的相干积分对弱信号来说远远不够,一般要累加 4 到 20 个周期。做法是先做一次 FFT 相关,把结果取模,再累加。累加次数增加,噪声被平均,信号峰值逐渐突出。要注意的是,累加过程中如果本地频率没有精确对准信号,峰值会出现在不同的码相位 bin 上,导致累加效果变差,所以非相干累加前一定要把频率步长控制好。
3.3 峰值判决与多步确认
捕获判决不能只看“有没有峰”,而要判断“峰是不是真的卫星信号”。最简单的做法是取相关谱的峰值与均值之比。纯噪声时,这个比值服从一定的统计分布;有信号时,峰值会明显高于背景。实际项目里我常用判决门限 6~10 dB,低于这个值基本算可疑,不能直接进入跟踪。
GLONASS 捕获还有一个特殊的假峰现象:因为 FDMA 卫星频率不同,宽带前端收到的信号里可能同时存在多颗卫星,如果搜索某个频道时本地码谱跟另一个频道信号的残余频谱发生了较大的重叠,会形成旁瓣假峰。处理办法一个是增加非相干累加次数,另一个是捕获确认时把峰值对应的频率和码相位拿去做一次短时间跟踪,看跟踪鉴相器输出是否稳定收敛。两步确认法虽然慢一点,但能过滤掉大部分假峰。
经验:捕获模块的调试,先用仿真信号把理论链路跑通,再用真实中频文件回放。不要一上来就拿着天线在窗口边试,否则信号弱、干扰多、卫星数少,你根本分不清是捕获算法问题还是环境问题。
4. 跟踪环路设计:稳定锁住才是真功夫
4.1 载波环与码环怎么配合
捕获只是把信号从噪声里捞出来,真正让接收机持续输出高精度伪距的是跟踪环路。GLONASS L1 是数据通道,上面调制了 50 bps 的导航电文,所以载波环必须用 Costas 环而不是纯 PLL。Costas 环对 180° 相位翻转不敏感,正好匹配导航电文符号跳变。
码环用标准超前减滞后结构,相关器间距取 0.5 码片。本地生成三个码:超前、即时、滞后。三个相关器的输出经过鉴相器得到码相位误差,再送入码环滤波器更新码 NCO。积分时间一般取 1 ms,也就是一个码周期,这样与码周期对齐,为后面比特同步打基础。如果信噪比足够,可以把积分时间拉长到 10 ms 甚至 20 ms,提高抗噪能力,但拉长积分时间的代价是位边界处的符号跳变会破坏环路稳定性,通常需要先完成位同步再做长积分。
这里我特别想说一下环路滤波器带宽的选取。载波环带宽一般取 15~30 Hz,窄带宽能滤除更多噪声但动态响应差,宽带宽跟踪动态强但噪声大。对于静态场景,载波环取 20 Hz 左右比较均衡;对于车载高动态场景,可能要放宽到 30 Hz 以上。码环带宽通常比载波环窄得多,2~5 Hz 即可,因为码环的动态主要由卫星几何变化引起,比载波缓慢。
4.2 环路滤波器参数计算的完整步骤
数字环路滤波器的参数计算网上有很多公式,但往往省略了具体推导,这里我以二阶码环和三阶载波环为例给出可直接抄作业的系数计算流程。
首先要理解环路带宽与滤波器系数之间的关系。这里用常见的三角积分器结构,码环用二阶,载波环用三阶,公式如下:
二阶环的阻尼系数取 0.707,噪声带宽 Bn 对应滤波器系数
这里直接给出结果:如果环路更新时间 T=1ms,载波环带宽 Bn=20Hz,则角频率 ω0 = Bn / 0.53 ≈ 37.7 rad/s,比例系数 K1 = 2×ω0×T,积分系数 K2 = ω0²×T²。代入计算可以得到 K1 和 K2 都在 0.001~0.1 这个量级,具体数值取决于电机参数。
这种通过带宽反推角频率、再乘上环路更新周期的做法,是目前数字接收机里最常用的工程简化。实际调试时,我会先在仿真里把带宽参数跑通,再拿到真实中频文件上微调,一般不需要改太大,因为环路带宽对信号质量的敏感度远高于对参数精密度的敏感度。
三阶载波环需要额外一个加速度误差系数,公式比二阶环复杂一些,但多数工程场景下用二阶环就够了。只有当载体动态很大、加速度明显时,三阶环才显示优势。不过三阶环容易在高信噪比时发生自激振荡,调试难度大,我对初学者的建议是先做二阶环,等系统稳定了再升级。
4.3 FDMA 带来的跟踪特殊问题
GLONASS 跟踪环路比 GPS 多一个隐藏任务:本地载波 NCO 的频率基准要随频道号变化。GPS 所有通道的 NCO 可以共用同一个载波频率,GLONASS 则每个通道都要单独设置一个频道中心频率,再叠加多普勒跟踪值。代码里如果用的是 GPS 那种“载波频率全局常量”,GLONASS 卫星进来后跟踪环路输出的频偏就会异常大。
还有一个实际工程里经常被忽略的问题:相邻频道之间的频谱泄漏。GLONASS 相邻频道间隔只有 0.5625 MHz,而民用信号的带宽大约 ±0.511 MHz,主瓣非常接近。如果前端滤波器不够陡,一个频道的强信号会泄漏到相邻频道,导致该频道跟踪环路里出现明显的高频干扰。解决思路是在数字域加一级窄带带通滤波或者自适应干扰对消,至少也要保证前端选频不是太松。
注意:GLONASS 跟踪环路里的鉴频器输出有时会出现“频率锁定但相位未锁定”的状态,这往往是 Costas 环在低信噪比下把数据符号相位锁到了 90° 位置。判断方法是看环路滤波器输出的相位误差是否围绕 0 或 ±90° 波动,必要时强制重新进入频率牵引加相位锁定流程。
5. 电文解调与伪距归算:定位精度的最后一道关
5.1 比特同步和帧同步的实现细节
跟踪环路稳定后,输出的是 1 ms 相同步数据,接着要做两件关键的事:比特同步和帧同步。
GLONASS 的数据速率为 50 bps,也就是说一个导航比特占 20 ms。比特同步的任务就是确定 20 ms 中哪个 1 ms 是比特边界。常见方法是滑动直方图法:对每个 1 ms 位置统计一定时间内数据翻转的次数,翻转次数最多的位置就是比特边界。这个方法的优势是实现简单,不需要额外的硬件模块,缺点是耗时比较长,通常需要几百 ms 才能可靠收敛。
位同步完成之后是帧同步。GLONASS 帧结构有自己的特点:每帧时长 2 秒,含 100 个比特,每帧又分成 5 个串,每个串 1.7 秒即 85 比特,后面跟 0.3 秒空闲段。这与 GPS 的子帧结构有明显差异,GPS 子帧是连续流,没有空闲段;GLONASS 的 0.3 秒空闲段里面没有数据,跟踪环路在这个时间段内如果不做特殊处理,积分结果会没有意义。
帧同步一般通过搜索电文中的时间标记实现。GLONASS 的帧起始位置有一个固定的比特定界标志,接收机在比特流里滑动搜索这个标志,一旦连续几个帧都能对上,就认为帧同步锁定。此时你知道了当前电文在超帧中的位置,可以开始译码星历、历书和时间参数。
5.2 伪距测量与时间系统转换
伪距计算的基本公式并不复杂:伪距 = 接收时刻(接收机本地时标) - 发射时刻(卫星时标)。但 GLONASS 在数据落地时有一堆需要小心处理的时间基准问题。
GLONASS 系统时间基于莫斯科时间,也就是 UTC(SU)+3 小时,这与 GPS 时间系统基于 UTC(USNO) 不同。GPS 时间有整秒跳变(闰秒)的概念,GLONASS 时间则直接与 UTC(SU) 关联,存在一个可以由电文参数修正的偏差。如果你在组合定位时直接用 GPS 时间的伪距和 GLONASS 时间的伪距混合解算,不估计一个系统间偏差,定位结果会带有一个可观的固定偏差。
我习惯的做法是:在 PVT 解算里为每个 GNSS 系统估计独立的接收机钟差参数,也就是说对 GPS 和 GLONASS 分别设一个钟差未知量,而不是共用一个钟差。这样虽然增加了状态量,但避免了跨系统时间基准不严格一致带来的误差。
另一个关键是整数毫秒模糊度处理。GLONASS 伪距测量同样面临“整 ms 模糊”,也就是码相位只能给毫秒内的部分,整毫秒数需要通过电文里的时间信息或星历推算来确定。GLONASS 的测距码是 1 ms 周期,如果整毫秒数错了,伪距误差就是约 300 km,定位结果完全不可用。
最后是坐标系转换。GLONASS 的广播星历用的是 PZ-90 坐标系统,与 WGS-84 之间存在米级的系统差异。现代接收机一般使用一个固定的七参数转换模型,有的电文里也直接提供转换参数。单模 GLONASS 定位时影响不算大,但组合 GPS+GLONASS 定位时如果忘了做这个转换,定位结果会出现系统性的偏移,靠单纯调整接收机钟差是补偿不干净的。
6. 实测问题排查与经验速查表
6.1 常见问题与解决思路
我把调试 GLONASS 链路过程中最常遇到的问题列成了一个速查表,每一条基本都在真实项目里见过。
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 某个频道卫星总是搜不到 | 频道号表错误或者该频点被干扰 | 查看星历里的频道号,确认搜索中心频率是否正确 |
| 捕获峰值在,但跟踪很快失锁 | 频率步进过粗,峰值在频域上偏移太大 | 缩小频率搜索步长,先做频率牵引再切相位锁定 |
| 伪距连续跳变几十米 | 比特同步不准确,或者跨符号积分 | 检查位同步直方图是否收敛,积分时间是否跨越位边界 |
| 同时刻 GPS 定位正常,加 GLONASS 后偏差变大 | 时间系统/坐标系未统一 | PVT 里增加系统间时间偏差参数,并做坐标转换 |
| 跟踪环路在特殊时刻失锁 | 0.3 秒空闲段内环路被破坏 | 空闲段做特殊标志处理,暂停积分或调整环路保持 |
| 频谱存在明显假峰 | 其他频道强信号泄漏 | 增加前端滤波或数字域窄带预滤波 |
6.2 调试过程中最值得注意的三件事
第一,始终把频道号当作第一优先级去核对。GLONASS 跟 GPS 最大的不同就是频率算法。如果你发现本地生成的卫星频率跟电文里不一致,再好的环路也锁不住。我习惯在捕获模块前面打一个内部频点表,每次冷启动后先解出星历字符串里的频道号,再动态更新捕获列表,这样能避免很多莫名其妙的“信号不存在”问题。
第二,环路带宽不要照搬 GPS 参数。很多人把 GPS 的载波环带宽原样搬到 GLONASS 上,结果发现实际效果变差,原因很简单:GLONASS 码周期短、调制方式相同但频点间隔不同,信号动态分配下的相位噪声特性有区别。正确做法是先算出理论带宽范围,再用仿真和中频文件回放各测一组数据,选一个综合表现最好的点。调试中你会发现,对 GLONASS 来说,码环带宽比 GPS 要更保守一点,否则电平波动会让位同步经常重捕。
第三,时间系统处理要提前规划。直接用 GPS 单模的 PVT 模型去跑 GLONASS 数据,肯定会遇到伪距残差过大的问题。这不一定是基带信号处理有问题,而是你少了一个系统间钟差状态。建议从架构上就把多 GNSS 时间同步机制设计好,而不是等到出现偏差了再临时打补丁。
6.3 一条适合快速验证的排错顺序
如果你拿到一段 GLONASS 中频数据,想快速判断整个链路是否正常,我建议按以下顺序排查:
- 先看频谱,确认能看到多个卫星信号的明显峰值,峰的位置和电文中频道号对应
- 选择一个中高仰角的卫星,单通道捕获,确认相关峰干净、无假峰干扰
- 进入跟踪,观察载波环相位误差和码环鉴相器输出是否在零附近抖动,环路应能在 2~3 秒内收敛
- 观察比特同步结果,查看位边界是否稳定,翻转位置是否始终集中在同一个 1 ms bin
- 帧同步后,立刻检查时间标记和星历子帧号是否连续
- 最后用单星伪距输出做观测,确认伪距序列光滑、无明显跳变,再做多星定位
这套顺序看起来简单,但确实能节省大量排查时间,因为每一步都验证了上一步的输出,崩在哪一环马上就能定位。
最后再分享一点个人体会
做了几年 GNSS 基带,我的感觉是 GLONASS 信号处理的难点不在某个单一算法,而在 FDMA 带来的系统性差异。它不像 GPS 那样“一个套路打天下”,而是要求你对频率、码、时间三个维度都有清晰的认识。真正上手调试时,有几个习惯帮我少走了很多弯路:
调试 GLONASS 时我总是把相关器输出导出来画成热力图,多看一眼信号在码相位和频率平面上的形状,比盯着代码猜要高效得多。很多看似是环路失锁的问题,其实在捕获阶段就已经把初始频率偏得太远了。
GLONASS 的 511 位短码让我对“信号强弱”这件事有了更直观的认知:码越短,越容易捕获,但也越容易产生误捕。弱信号下不要拼命拉长相干积分时间,先保证本地频率足够准,再去考虑累加次数,这才是正路。
这篇文章涉及的内容,整个链路都是从信号采样一路贯穿到定位解算,没有哪一步是可以省掉的。如果你正打算在现有接收机里加入 GLONASS 支持,建议先把这篇梳理的流程对应到自己代码里,确认每个环节都有清晰的接口和调试输出,然后再动手改结构。这样接下去每一步都会顺利很多。