简介:本资源是一份面向卫星导航信号处理初学者与MATLAB仿真实践者的北斗B1I路扩频码生成与基础接收链路仿真代码包,聚焦北斗系统核心调制技术,解决扩频码构造、BPSK调制、AWGN信道建模及粗同步(捕获)等关键环节的动手实现问题。压缩包共3个MATLAB源文件(.m),总大小仅7KB,轻量紧凑,涵盖BD2B1_Acquisition(B1I信号粗捕获模块)、BD2B1_SoftReceiver(软接收机主流程)及配套GPS_Tracking参考函数,便于理解北斗与GPS扩频体制差异并开展对比实验。已有575人学习下载,代码严格依据北斗公开接口规范设计,完整实现Gold长码生成、短码叠加、扩频调制、噪声注入与相关峰检测全流程,可直接运行观察扩频序列自相关特性、捕获门限响应及不同SNR下的同步性能,是开展北斗信号处理课程设计、毕业设计或算法验证的理想起点。 北斗B1I的扩频码,是做接收机基带仿真绕不开的一个基础模块。很多刚接触GNSS方向的同学一开始都会去翻文档、找现成代码,结果发现网上的实现五花八门,生成的码要么跟资料对不上,要么自己都没法验证对错。这篇文章用matlab把B1I扩频码的生成原理、完整代码和相关特性验证一次讲透,提供一套可以直接跑的完整实现,也会分享一些我实际调试时踩过的坑。适合正在做北斗信号仿真、课程设计,或者接收机捕获跟踪算法验证的读者参考。
1. 北斗B1I信号与扩频码基础
1.1 B1I信号的关键参数
北斗B1I信号是北斗二号、北斗三号系统公开服务信号中的一种,工作在L频段。很多人第一次接触这个信号时,容易被一堆参数搞得一头雾水。这里先列出一张核心参数表,把后续生成扩频码需要关注的信息都放进去。
| 参数名称 | 参数值 | 说明 |
|---|---|---|
| 载波频率 | 1561.098 MHz | B1I信号的中心频率 |
| 码速率 | 2.046 Mcps | 扩频码的码片速率 |
| 码长 | 2046 chips | 一个完整扩频码周期的码片数 |
| 调制方式 | BPSK(2) | 二进制相移键控 |
| 测距码类型 | 截短Gold码 | 由两个m序列模2加生成 |
| 主瓣带宽 | 约4.092 MHz | 主瓣零点间带宽 |
从这张表可以看到,B1I信号的码速率是2.046 Mcps,码长是2046个码片,所以一个完整码周期的时间正好是1毫秒。这个1毫秒的周期跟北斗的导航电文速率、比特对齐方式都有直接关系,接收机在做捕获的时候,通常就是按1毫秒的相干积分长度来处理扩频码的。
1.2 为什么导航信号选Gold码
GPS的C/A码用的是Gold码,北斗B1I也用了Gold码,这背后是有明确工程考虑的。扩频码在导航信号里承担两个核心任务:一是通过码分多址区分不同卫星,二是作为测距的标尺。要测距,码的自相关性要好,主峰要尖锐;要区分卫星,不同卫星的码之间互相关性要尽量低。
如果用单一m序列,虽然自相关性很好,但m序列的互相关特性不稳定,不同相位偏移下会出现比较大的互相关峰值,用户量一多就容易误捕。Gold码是由两个优选m序列模2加生成的码族,它的巧妙之处在于:码族内任意两个码的互相关值都被限制在一个已知的范围内,不会出现离谱的尖峰。这就像给每颗卫星发了一个身份证号,接收机靠这个号码来识别是哪颗卫星在发信号,同时号码之间足够“不相似”,不会认错人。
北斗B1I选择Gold码还有一个细节,就是码长取2046而不是标准的2047。标准的m序列周期是2的11次方减1,等于2047,B1I在生成后截短了一位变成2046码片。这样做一方面是为了码周期刚好等于1毫秒,与整毫秒的帧结构对齐;另一方面也说明,B1I的码不是教科书上标准的完整周期Gold码,在相关特性、频谱特性上会有一些细微变化,这个在后面验证环节会提到。
1.3 B1I扩频码的组成结构
B1I的扩频码结构可以用一句话概括:两个11级线性反馈移位寄存器分别生成m序列G1和G2,再把G1与经过相位调整的G2逐位模2加,得到某颗卫星的测距码。
更具体地说,G1和G2的生成多项式在北斗ICD文件里有明确规定。G1的生成多项式是:
1 + x + x^3 + x^4 + x^8 + x^9 + x^11G2的生成多项式是:
1 + x + x^2 + x^3 + x^4 + x^5 + x^8 + x^9 + x^11两个寄存器都是11级,初始状态为全1。G1序列直接输出,G2序列则根据不同卫星的PRN号做不同的相位偏移或抽头组合,再和G1模2加,就得到了该卫星独有的扩频码。
这个结构跟GPS C/A码的生成方式非常像,只是寄存器级数、生成多项式和码长不同。理解了这个框架,再看matlab代码就会清晰很多:无非是把这两个多项式翻译成代码,再把PRN到G2相位的映射表整理好。
2. matlab生成B1I扩频码的设计思路
2.1 线性反馈移位寄存器实现原理
在matlab里生成m序列,最直接的方式就是模拟线性反馈移位寄存器(LFSR)的工作过程。一个11级的LFSR,本质上是一个11位的状态存储器,每个时钟周期做两件事:输出当前状态中的某一位,同时根据反馈抽头计算一个新的输入位,放到寄存器的入口。
用代码来表示,就是维护一个长度为n的向量,每次循环取向量最后一位作为输出,然后根据参与反馈的位置做模2加(也就是异或),再把寄存器整体右移一位,把异或结果放到最前面。这个“取模2加”的过程,对应了生成多项式中各位的系数。
这里有个容易混淆的点:多项式里的x^i对应的是寄存器中的第几个位置。在我的实现里,规定寄存器向量reg的第1位到第n位,对应多项式中的x^1到x^n项,输出取reg(n)。而生成多项式中除了常数项1之外的非零项,就是反馈抽头的位置。比如G1多项式从x^1到x^11的非零项在1、3、4、8、9、11这些位置,那么反馈计算就是把这些位置的寄存器状态取出来做异或。
2.2 G1、G2生成多项式的matlab映射
把上面的原理翻译成matlab代码,就是下面这个核心函数。这个函数可以复用于G1和G2,只需要传入不同的抽头向量。
function seq = lfsr_generate(taps, n, len) % LFSR生成m序列 % taps: 反馈抽头位置向量,如[1 3 4 8 9 11] % n: 寄存器级数 % len: 输出序列长度 reg = ones(1, n); seq = zeros(1, len); for i = 1:len seq(i) = reg(n); fb = mod(sum(reg(taps)), 2); reg = [fb, reg(1:n-1)]; end end对于G1,抽头向量是[1 3 4 8 9 11];对于G2,抽头向量是[1 2 3 4 5 8 9 11]。调用方式如下:
n = 11; len = 2046; G1_taps = [1 3 4 8 9 11]; G2_taps = [1 2 3 4 5 8 9 11]; G1 = lfsr_generate(G1_taps, n, len); G2 = lfsr_generate(G2_taps, n, len);这一段代码跑完之后,G1和G2就是两条长度为2046的m序列。注意,初始状态全部为1,输出取的是寄存器最高位,这两点决定了序列的相位和极性。如果你的实现里初始状态或者输出位定义不一致,生成的序列可能会跟别人的实现差一个反向或者差一个循环移位,后面会专门讲这个问题。
2.3 卫星号到G2相位的对应关系
有了G1和G2的基础序列,接下来就是最关键的一步:如何根据PRN号得到该卫星的扩频码。北斗ICD中,每颗卫星的PRN号都对应一个G2序列的相位配置。这个配置在工程实现上有两种常见形式。
第一种是延迟移位方式。就是ICD直接给出该PRN对应的G2延迟码片数,比如PRN 1对应延迟d个码片,那么在软件里把G2序列做循环移位,再跟G1异或即可。这种方式非常直观,适合在matlab里实现。
第二种是抽头组合方式。这种方法跟GPS C/A码的经典做法一致,在G2寄存器运行过程中,同时取两个抽头位置的状态做异或,将这个异或结果作为与G1相加的G2相位序列。数学上,这个序列等价于G2序列的某个延迟版本,但实现上不需要先缓存完整的G2再移位,而是可以边跑边输出,更贴近硬件实现。
下面代码用延迟移位方式实现,PRN到G2延迟的映射表需要参考你手头的ICD版本。我在代码里放了一个示例配置,正式开发时请务必核对ICD原文。
% PRN号到G2延迟量映射表(示例数据,以实际ICD为准) g2_delay_table = [ 1; % PRN 1 2; % PRN 2 3; % PRN 3 4; % PRN 4 5; % PRN 5 % ... 后续按ICD补齐 ]; function code = beidou_b1i_code(prn) n = 11; len = 2046; G1_taps = [1 3 4 8 9 11]; G2_taps = [1 2 3 4 5 8 9 11]; G1 = lfsr_generate(G1_taps, n, len); G2 = lfsr_generate(G2_taps, n, len); delay = g2_delay_table(prn); G2_shifted = circshift(G2, [0, delay]); code = mod(G1 + G2_shifted, 2); end这个实现的优点是代码短、逻辑清楚,替换查表数据即可。缺点是需要一次性生成完整的G2序列再移位,对于2046码片的长度来说完全没有性能压力。如果你希望用更接近硬件的方式实现抽头组合,可以在LFSR循环中同时取G2寄存器的两个位置做异或,效果是等效的。
3. 完整matlab实现与相关特性验证
3.1 一套可直接运行的生成代码
为了方便读者直接跑通流程,我把前面的代码整合成一个完整的脚本。这个脚本会生成指定PRN的B1I扩频码,并画出它的时域波形。
%% 北斗B1I扩频码生成脚本 clear; clc; close all; n = 11; len = 2046; G1_taps = [1 3 4 8 9 11]; G2_taps = [1 2 3 4 5 <p> <a href="https://download.csdn.net/download/wouderw/87444338" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>