
1. 先把DVB-RCS的老底翻出来为什么值得专门建一个仿真做卫星通信仿真的人绝大多数时间都在和DVB-S/S2打交道下行链路的资料一抓一大把。但一提到DVB-RCSDigital Video Broadcasting – Return Channel via Satellite网上的开源代码少得可怜教材里的描述也含糊其辞经常是“采用MF-TDMA体制支持突发传输”一句话带过。我刚接触这个标准的时候光是搞明白它的回传信道怎么把多个用户的突发数据塞进同一个载波就花了整整一周。这个项目要做的就是基于Matlab搭建一个完整的DVB-RCS回传链路仿真核心是两个关键词双用户时隙和载波调制解调。通俗地讲就是模拟两个卫星终端站RCSTReturn Channel Satellite Terminal通过同一个卫星转发器向主站网关发送数据各自占用不同的时隙在接收端能正确解调出两路信号。为什么这件事值得专门做一次仿真因为DVB-RCS的物理层有个很烦人的特点——它不像DVB-S那样是连续载波调制而是突发burst模式用户只在分配到的时隙里发射信号平时保持静默。这意味着接收端不能简单地用一个固定的载波恢复环路去跟踪信号它必须在每个时隙开始时快速完成信号捕获、频偏估计、定时同步然后在该时隙结束时把相位状态“清零”准备迎接下一个用户。这种“间歇性”传输对解调器的鲁棒性要求极高正好暴露了很多人在连续信号仿真里根本碰不到的问题。这套仿真适合谁来参考如果你是通信专业的研究生正在做卫星通信方向的开题或者课程设计这篇内容能帮你少走很多弯路如果你是刚入职卫星通信公司的工程师需要快速理解MF-TDMA突发解调的工程实现细节这里面的参数设计和坑点同样有参考价值。后面我会把从帧结构设计、时隙分配到调制解调实现、误码率验证的全过程逐步拆开讲附上可以直接改的Matlab代码思路。关于DVB-RCS有一点必须先说清楚它规定的回传信道传输机制叫MF-TDMA多频时分多址意思是用户既可以在不同频率上区分也可以在同一频率下按时间切片区分。我们这次仿真的重点是后一种方式——单载波下的时分复用两个用户共享同一个载波靠时隙错开传输这是理解整个系统的最小可行示例。2. 仿真系统整体设计从信号流到参数选型2.1 顶层架构与信号流在设计仿真之前先把链路逻辑理清楚。一个完整的DVB-RCS回传仿真可以拆成三大块发射端两个用户各自独立、信道叠加噪声和频偏、接收端解调两路用户数据。发射端每个用户的处理流程是相同的都是“信源比特 → 信道编码 → 突发组帧 → 基带调制 → 成型滤波 → 搬移到中频”区别只在于各自的时隙偏移和扰码种子。接收端的处理恰好是发射端的逆过程但因为双用户是突发式接入接收端不能一直保持同一个解调状态而要在每个用户时隙到达时重新执行一轮同步。我最初犯的错误是直接把连续信号的接收结构搬过来——用一个锁相环从头锁到尾结果第二路用户的信号因为来的太晚要么捕获不到频偏要么把两个用户的中心频率估计混在一起。后来改成“时隙窗口化处理”先由帧同步模块判断当前时隙属于哪个用户再独立解调问题就解决了。这个“时隙窗口化处理”是整个接收端架构的灵魂后面我会在第三节里详细讲实现。2.2 关键参数怎么定下来仿真参数不能拍脑袋必须和DVB-RCS标准对得上同时兼顾Matlab仿真的计算复杂度。我用的参数组合如下参数数值说明符号速率 Rs1 Msps便于观察实际系统通常更高调制方式QPSK / 8PSKDVB-RCS必选调制滚降系数 α0.25标准中常用的根升余弦滚降每符号采样点数 sps4定时精度与计算量的折中用户数2双用户场景时隙数每帧2个时隙每用户1个简单清晰的1:1分配帧长度2000 符号每个时隙1000符号载波频率偏移用户12 kHz用户2-3 kHz模拟卫星链路多普勒及本振误差先说符号速率。1 Msps在DVB-RCS标准里属于偏低的档位标准支持从0.5 Msps到几十Msps的跨度但仿真和真实系统的区别在于我们更关心算法是否work而不是跑百万级符号验证吞吐量。用1 Msps配合每符号4个采样采样率就是4 MHz跑一次10万符号的误码率测试在普通PC上只要几秒钟非常适合反复调整参数。载波频偏的设置不是随意写的。真实卫星信道中RCST本振晶振偏差通常在几十到几百Hz量级加上卫星移动带来的多普勒频偏低轨卫星场景下可达数十kHz接收机必须有能力纠正这个偏移。我在这里故意设置为2 kHz和-3 kHz相对接收机标称中心频率相当于±0.2%的符号速率偏移处于常见的“需要频偏估计但又不至于让滤波器彻底失真”的区间。滚降系数0.25是DVB-S/RCS系统里最常见的选择这意味着信号带宽是符号速率的1.25倍即1.25 MHz带宽里传输1 Msps符号频谱效率0.8 bit/s/HzQPSK时。在实际卫星转发器中带宽是严格受限的资源选择较大的滚降系数会浪费宝贵的频谱选择太小的如0.15则对接收端定时误差更敏感。0.25是工程上最稳当的平衡点。2.3 用户时隙映射与突发结构DVB-RCS的突发结构不是简单地把比特塞进时隙它有一套固定格式。标准里定义了多种突发类型最常见的是**前导符preamble 数据净荷payload**的结构。前导符用于接收端的同步——包括频率捕获、定时恢复和相位参考。我们仿真的突发结构设计为前导符长度64符号固定为已知的伪随机序列QPSK映射数据长度936符号合计1000符号为什么前导符64符号这是权衡了同步性能和开销的结果。64个QPSK符号在1 Msps下只有64微秒带来的协议开销约6.4%但对载波频偏估计而言64个符号在低信噪比下用数据辅助估计能提供的精度也是够用的。如果你要做更高阶的8PSK调制建议把前导符加长到128符号因为8PSK的相位容限更小需要更长序列来压制估计方差。双用户的时隙在帧内的排布就是一个“排班表”的逻辑。一帧2000个符号第0~999符号是用户1的时隙第1000~1999符号是用户2的时隙。每个时隙起始处放一个固定的前导符序列但在仿真中我给两个用户设置了不同的扰码种子这样即便前导符序列在符号层面相同数据部分的扰码不同接收端可以据此区分用户。还有一种做法是给两个用户分配不同的前导符序列标准中确实存在不同的前导序列ID但为了演示起见我这里用了扰码区分时隙位置区分双重方案。3. 双用户时隙调度Matlab里的核心实现3.1 帧结构定义与时隙分配搞定参数后第一步是在Matlab里把帧结构定义出来。% 帧与突发参数 symbol_rate 1e6; % 符号速率 1 Msps sps 4; % 每符号采样数 rolloff 0.25; % 滚降因子 filter_order 40; % 滤波器阶数合理长度 burst_length 1000; % 每个突发的符号总数含前导 preamble_len 64; % 前导符号数 data_len burst_length - preamble_len; % 数据符号数 frame_slots 2; % 每帧2个时隙 frame_len burst_length * frame_slots; % 2000符号这里定义一个burst_length为1000符号两个burst组成一帧。没有直接定义一个大的帧数组然后把数据填进去而是每个用户单独生成自己的burst信号最后按时间维拼接。这样做的好处是代码逻辑和实际系统的发送过程一致——每个RCST是独立发送的它根本不知道另一个用户在干什么时隙管理由主站的MAC层负责物理层只是“到点就发”。时隙分配的代码更直白% 时隙起始时间符号位置 slot_offset [0, burst_length]; % 用户1从第0符号开始用户2从第1000符号开始但在实际生成信号时我们不是简单地把两个burst拼起来而是把每个burst扩展成整个帧长度让每个用户只在属于自己的时隙处有信号其余位置补零% 为每个用户生成完整的帧信号非占用时隙填零 tx_frame_user1 [tx_burst_user1, zeros(1, burst_length)]; tx_frame_user2 [zeros(1, burst_length), tx_burst_user2]; % 叠加两用户信号此时尚未加噪声 tx_frame_combined tx_frame_user1 tx_frame_user2;这是仿真中一个非常重要的细节在接收端看来双用户信号是“同时存在”于同一段数据里的只是能量分时出现。虽然两个用户没有在时间上交叠但叠加这步操作会引入一个潜在的数值问题——如果两路信号的载波频偏不同那么在拼接处会出现相位跳变这个跳变会在后续的滤波处理中产生频谱扩展。我在第一次仿真时没注意这一点结果在接收端频谱图上观察到时隙交界处的毛刺噪声后来单独对每个时隙做带通滤波才解决。3.2 发射端突发信号的生成流程生成一个用户突发信号的标准流程是随机生成数据比特数据长度 data_len × 调制阶数QPSK时2比特/符号加扰使用不同的扰码种子前导符序列生成固定PN序列QPSK映射QPSK/8PSK调制映射插入前导符形成完整burst符号序列根升余弦成型滤波加扰这一步是DVB-RCS物理层的一个关键环节目的有三个能量扩散避免长串0/1导致频谱线、数据随机化便于接收端时钟恢复、用户区分不同扰码种子。在标准中扰码序列由Gold序列生成器产生初始化种子跟用户标识相关。% 扰码实现示意 % scrambler: 简单PN序列异或 pn_gen comm.PNSequence(... Polynomial, [1 0 0 0 0 0 1 0 1], ... InitialConditions, user_seed_vec, ... SamplesPerFrame, total_bits); scramble_seq pn_gen(); scrambled_bits xor(data_bits, scramble_seq);注意这里的拓扑结构先加扰再调制调制得到的是复数符号序列。前导符序列也需要经过相同的调制映射但它不经过加扰前导符是收发双方已知的。在实际的发射机里前导符会经过相同的成型滤波但和数据的扰码互不相干。调制映射的定义参照DVB-RCS的星座图。QPSK星座点的映射是Gray编码的这样相邻星座点只差1个比特可以在误码率不理想时减小误比特率。8PSK则更复杂标准的8PSK星座是均匀分布在单位圆上每个符号3比特Gray编码后的相邻相位差对应单比特翻转。3.3 突发拼接和多用户信号合成两个用户burst生成后分别做成型滤波再各自做载波频偏搬移最后叠加% 用户1的调制和滤波 sym_tx_user1 [preamble_qpsk, mod_data_user1]; tx_sym_up_user1 upsample(sym_tx_user1, sps); tx_filtered_user1 filter(rrc_filter, tx_sym_up_user1); % 加入频偏叠加在基带复信号上 t_axis (0:length(tx_filtered_user1)-1) / (symbol_rate * sps); tx_freq_user1 tx_filtered_user1 .* exp(1j*2*pi*freq_offset_user1*t_axis); % 同样的操作对用户2做一遍 % 拼帧 叠加 tx_signal [tx_freq_user1, zeros(1, burst_length*sps), ...] [zeros(1, burst_length*sps), tx_freq_user2, ...];这里有一个容易踩坑的地方成型滤波会引入群延迟。根升余弦滤波器的群延迟等于滤波器阶数的一半乘以采样周期。当burst边界是精确对齐在1000符号整数倍的时候滤波器的延迟会导致burst起点和终点“拖尾”从而让信号泄漏到时隙边界之外。所以仿真时需要在burst前后各留出一段保护间隔否则接收端做时隙截取时会丢失信号能量。我用的保护符号数 filter_order / 2即20个符号因为sps4时滤波器阶数40对应10个符号的延迟。如果burst长度为1000符号那么实际送入信道的是“保护前缀 1000符号 保护后缀”接收端在解调时再把这些保护段舍弃。这里再补充一个我实测过的教训如果保护间隔留少了接收端误码率会在高信噪比时出现一个“平台效应”——无论怎么提高信噪比误码率都不再下降。原因是截断窗口把成型滤波器的拖尾切掉了一部分破坏了匹配滤波器的匹配条件形成固定的码间干扰。这个现象在连续信号仿真里几乎遇不到但在突发信号仿真里几乎必然出现建议一上来就把保护间隔留足。4. 载波调制解调核心链路的逐步拆解4.1 调制端映射、成型滤波与上变频调制端最重要的两个模块是星座映射和成型滤波。星座映射决定了信号的频谱效率和抗噪声能力——QPSK的星座点距离大误码率低但每符号只传2比特8PSK在相同带宽下每符号传3比特频谱效率提升50%但星座点之间的欧氏距离变小对噪声更敏感。仿真时我建议把两种调制都实现用参数切换方便后面做对比曲线。成型滤波器用的是根升余弦Root Raised CosineRRC在Matlab里可以直接用rcosdesign函数生成rrc_filter rcosdesign(rolloff, filter_order, sps, sqrt);成型滤波的本质是把矩形的符号脉冲变成带宽受限的平滑脉冲同时让发射端和接收端的RRC滤波器级联后形成升余弦RC响应满足奈奎斯特第一准则——即在最佳采样点上相邻符号的串扰为零。这里有个仿真里特别容易出问题的细节滤波器的归一化。rcosdesign默认输出幅值不是单位增益的直接对信号滤波会导致发射信号功率变小或变大。我通常在滤波之后对信号做功率归一化tx_filtered tx_filtered / sqrt(mean(abs(tx_filtered).^2));保持发射信号的平均功率为1这样后面加噪声时信噪比的定义才清晰可控。上变频这一步在仿真里通常以基带等效形式完成即直接用复数乘相位旋转来模拟频偏。真实系统中会有I/Q两路混频器但基带仿真的等效模型是把频偏乘在基带信号上信道就是叠加复高斯白噪声。这样仿真结果和真实通带系统的误码率是一致的但计算量小一个量级。4.2 接收端时隙截取、匹配滤波与定时恢复接收端处理的开始不是解调而是帧同步。因为接收机不知道时隙的精确起始位置需要从前导符中寻找定时基准。在仿真里我们假设已经完成了粗帧同步这本身就是另一个复杂课题直接从正确位置截取每个时隙的接收数据。截取之后信号依次经过匹配滤波用和发射端相同的RRC滤波器卷积匹配滤波的实质是最大化信噪比。在加性高斯白噪声信道中匹配滤波是最优的线性滤波。下变频/去频偏这里需要先估计残余频偏把载波搬回零频。定时恢复从每个符号的4个采样点中找到最佳采样时刻。定时恢复的经典实现是Gardner算法它是一种非数据辅助的前馈定时误差检测器特别适合突发模式的快速同步因为它收敛快、不需要载波同步的联合辅助。核心代码% Gardner定时误差检测简化示意 for n 1:N_symbols-1 mid y(n*sps sps/2); % 两个采样点中间点 err real(mid) * (real(y((n1)*sps)) - real(y((n-1)*sps))) ... imag(mid) * (imag(y((n1)*sps)) - imag(y((n-1)*sps))); end但我在实际使用中发现Gardner算法在滚降系数很小的系统中如0.15性能会明显下降因为定时误差信号幅度随滚降系数的减小而减小。0.25的滚降下工作良好这点要保持警惕。还有一个常见的工程技巧用前导符做数据辅助的定时估计。假设接收端已知前导符序列可以用相关法计算出精确的定时偏移然后用这个初始值去初始化Gardner的插值器通常用Farrow结构的分数延迟滤波器实现。这样既保留了Gardner的跟踪能力又能快速锁定。4.3 载波频偏估计与相位校正频偏估计是本项目中最具挑战性的模块因为双用户各自的频偏不同且突发的持续时间短不能用连续信号那种长时间积分的方法。我把频偏估计分成了两步粗估计和细估计。粗估计利用前导符与本地序列做滑动相关相关峰的相位随时间变化的斜率就是频偏。数学上接收信号可以建模为 y(n) s(n)·exp(j2πΔfnTφ)用已知前导 s(n) 共轭相乘后得到 z(n) |s(n)|²·exp(j2πΔfnTφ)对 z(n) 做FFT其峰值位置对应频偏。% 粗频偏估计基于前导的FFT法 rx_preamble rx_signal(1:preamble_len*sps); z rx_preamble .* conj(local_preamble_tx); % 去调制后做谱估计 Z fftshift(fft(z, N_fft)); [~, idx] max(abs(Z)); freq_est (idx - N_fft/2 - 1) * (symbol_rate*sps) / N_fft;这里注意FFT分辨率的问题假设时隙长度1000符号前导64符号做4096点FFT频率分辨率大约是4 MHz/4096 ≈ 977 Hz。这个精度不足以支撑解调需要细估计。细估计用数据辅助的相位差分法。在前导符号已知的情况下计算相邻前导符号的相位差然后取平均% 细频偏估计前导差分相位 phase_diff angle(z(2:end) .* conj(z(1:end-1))); freq_est_fine mean(phase_diff) / (2*pi*sps*symbol_rate);这种方法的估计方差与信噪比成反比且随着前导长度增加而减小。仿真中64个符号的前导在Eb/N010 dB时频率估计的标准差能压到几十Hz量级足够满足QPSK解调需求。频偏补偿后还有一个恒定相位偏移需要消除。由于频偏估计的残余误差信号可能还存在整体相偏。对PSK解调来说一个简单的办法是使用判决引导环。但在突发模式中更常用的是在去频偏后对前导符做平均相位估计因为前导符全部已知phase_est angle(sum(rx_preamble_corrected .* conj(local_preamble))); rx_sym_corrected rx_sym .* exp(-1j * phase_est);这样一次性把频偏和相偏都修正到位后面就可以直接做符号判决了。注意如果前导符有残留的频偏估计误差那么前导末端和数据的相位旋转量不同细估计时要用加权平滑或者只取数据部分的判决引导算法来兜底。5. 从误码率看仿真结果性能验证这么做才靠谱5.1 E_b/N_0 与信噪比的换算在加噪声之前先明确仿真中信噪比的定义。我习惯用 E_b/N_0每比特能量与噪声功率谱密度之比作为自变量因为它可以公平地对比不同调制方式。E_b/N_0 和仿真中的复高斯噪声方差换算关系是N_0 E_b / (E_b/N_0) 换算成功率域为Noise_power symbol_power / (2 * bits_per_symbol * EbN0_linear)因为复噪声每维度I/Q各一维功率为 N_0/2所以总噪声功率为 N_0。在Matlab里加噪声时function rx_signal add_awgn(tx_signal, EbN0_dB, bits_per_symbol, sps) EbN0 10^(EbN0_dB/10); signal_power mean(abs(tx_signal).^2); % 每符号能量 Es Eb * bits_per_symbol % 噪声单边功率谱密度 N0 Eb / EbN0_linear N0 signal_power / (bits_per_symbol/2 * EbN0); % 注意实信号归一化 noise_power N0 * (symbol_rate * sps) / (symbol_rate * sps); % 等效计算 noise sqrt(noise_power/2) * (randn(size(tx_signal)) 1j*randn(size(tx_signal))); rx_signal tx_signal noise; end这里有个容易混淆的点信号功率用的是所有采样点含过采样的平均功率但噪声功率密度 N_0 是每Hz的功率。在离散域中噪声方差 N_0 × 采样带宽而采样带宽就是采样率。所以复AWGN样本的方差就是 N_0I和Q维各 N_0/2 的方差。仿真里一个很实用的小技巧不要每次循环都重新生成信道系数而是固定一组随机种子让同一个数据帧在不同Eb/N0下遍历一遍。这样可以显著降低误码率曲线的抖动曲线更平滑看起来也更专业。5.2 双用户场景的误码率仿真循环整个仿真的主循环结构如下users struct(id, {1, 2}, freq_off, {2000, -3000}, ... scramble_seed, {randi(10000,1), randi(10000,1)}); EbN0_dB_list 0:2:12; BER_user1 zeros(size(EbN0_dB_list)); BER_user2 zeros(size(EbN0_dB_list)); for idx 1:length(EbN0_dB_list) error_bits [0 0]; total_bits [0 0]; for frame 1:num_frames % 生成两用户的发射帧 tx_combined generate_frame(users, mod_order); % 加噪声 rx_combined add_awgn(tx_combined, EbN0_dB_list(idx), mod_order, sps); % 接收端处理 for u 1:2 rx_burst extract_slot(rx_combined, u, filter_delay); rx_burst match_filter(rx_burst, rrc_filter); rx_burst coarse_freq_est_correct(rx_burst, preamble); rx_burst fine_freq_est_correct(rx_burst, preamble); rx_burst timing_recovery(rx_burst, sps); rx_burst phase_correction(rx_burst, preamble); rx_bits demodulate_hard(rx_burst, mod_order); % 解扰并统计误码 end end end特别注意每帧仿真时两用户的数据是独立随机生成的而且每次都要重新随机化。这是为了模拟真实系统中数据不断变化的情况避免因为测试数据过拟合接收机特性。我跑完整个仿真的经验是每个Eb/N0点至少重复200帧每帧2×936个数据符号才能在误码率10^-3量级获得可接受的统计置信度。乍一看200帧很多但1 Msps符号率、4倍过采样下一个200帧的循环在普通笔记本上也就几分钟完全在可接受范围。5.3 结果怎么解读双用户在相同Eb/N0下的误码率曲线基本重合因为它们各自独立处理互不影响。但如果你仔细观察会发现用户1和用户2的曲线有极小的差异通常在一两个百分点。这是正常的原因是两用户的频偏符号不同残余频偏经过相位校正模块后的残差略微不同。这个差异在仿真图中几乎不可见但如果你的曲线差异超过0.5 dB那说明接收端模块里大概率有bug——常见的是把一个用户的同步参数串到了另一个用户上。和理论曲线对比也是一种必要的验证手段。QPSK在AWGN信道下的理论误比特率是BER_QPSK Q(sqrt(2·E_b/N_0))在Eb/N08 dB时理论上QPSK误码率约10^-4量级。如果仿真结果和理论值差1 dB以上需要回头检查是不是噪声功率算错了或者滤波器归一化没做好。我见过很多新手在这里栽跟头——明明代码看起来每个模块都正确但误码率就是离理论曲线差一截最后发现是rcosdesign的滤波增益导致信号功率统计偏大实际注入的噪声“相对偏小”看上去信噪比虚高曲线左移。6. 实战中最容易踩的五个坑和排查技巧6.1 时隙边界串扰这个坑在仿真里极其隐蔽。成型滤波器的记忆效应使得每个burst的滤波输出会延伸到时隙边界之外如果接收端的时隙截取窗口严格等于burst长度那么窗口边缘的信号能量会被截掉导致匹配滤波器看到的不是一个完整的突发脉冲定时估计出现偏差。排查方法在接收端截取信号后Visualize一下信号幅度包络如果看到前后20个采样点幅度急剧衰减到0那就是截断问题了。加上“保护前缀/后缀”并补偿滤波器延迟即可解决。6.2 频偏估计产生了“负反馈”在粗频偏估计里如果FFT峰值搜索的范围包含镜像频率即负频偏被误判为正频偏后续的细估计和相位校正全部会错。特别是双用户频偏一正一负时如果一个用户的频偏被估计成另一个用户的频偏值那个用户整帧数据全都解不出来。排查方法检查每个用户的频偏估计结果打印出来和真实值对比。如果出现“正好等于另一个用户的频偏”这种情况大概率是FFT搜索范围设置不对或者粗估计前没有做带通滤波把另一个时隙的泄漏信号滤掉。我的做法是在粗估计前加一个简单的低通滤波器通带宽度大约是符号速率1.2倍这样可以先把时隙外的噪声和邻道泄漏压掉再估计频偏。6.3 Gardner定时恢复在低信噪比下失效Gardner算法在Eb/N0低于3 dB时定时误差信号会被噪声淹没导致定时追踪发散。这在双用户突发系统中是一个真实威胁——如果信令时隙的信噪比很低定时没锁住后面数据全解错。解决方案两个思路。第一种是用前导符辅助第二个是把定时误差信号用滑动窗口平均比如16个符号窗口提高估计稳定性。实测下来加上16个符号的滑动平均后Gardner在2 dB左右的Eb/N0仍然能保持锁定。6.4 滤波器群延迟不一致导致星座图旋转发射端和接收端的RRC滤波器参数必须完全一致否则级联响应不满足升余弦性质最佳采样点处会有残余码间干扰。这个坑看起来低级但不同时刻版本的代码可能改了滤波器阶数或采样率发射端和接收端引用的变量不是同一个就在性能曲线种“莫名变差”。排查方法把接收端匹配滤波后的星座图画出来如果星座点是“云团状”而非清晰的四个点簇大概率是滤波器不匹配。检查发射端和接收端是否引用同一个rrc_filter变量或者滤波器阶数和滚降系数是否一致。6.5 误码率曲线出现平台错误平层当误码率在高信噪比区域不再随Eb/N0增加而下降时首先是检查时隙截取窗口是否切掉了信号拖尾这会导致不可消除的码间干扰。这个现象我前面提到过它与滤波器群延迟未补偿直接相关。再有一个原因相位模糊无法消除。QPSK解调存在4重相位模糊如果前导符的相位估计落在错误的象限相差90度/180度/270度整个数据符号会全部翻转或等量旋转误码率锁死在0.5。用差分调制或者在数据中插入已知导频符号可以解决。DVB-RCS标准中专门定义了导频符号来翻解相位模糊这里如果用绝对相位编码就必须解决模糊问题。一个实用的变通方案在解调判决前对几个已知导频符号判决并与真实值比对如果发现旋转了90度倍数就反向旋转回去。这是实际系统中常用的“导频辅助相位解模糊”思路。从一次双用户仿真的调试过程说起最后说说我个人在这次仿真调试中的体会。最花时间的部分不是编写调制解调代码而是排查“间歇性出现的错误”——有时候用户1解调正确、用户2全错有时候两人都错有时候只在某个Eb/N0点出错。后来发现问题根源是频偏估计模块在低信噪比下偶尔把估计值“崩”到远离真实频偏的位置形成偶发的恶劣事件。这种错误在连续信号里几乎不会发生但突发信号的短时长特性放大了估计误差的概率密度。解决办法是在频偏估计后加一个“合理性检查”估计值与粗估计的最大可能偏差应在一个先验范围内如果超出就保留粗估计结果。这个简单粗暴的逻辑在工程中反而比复杂的鲁棒估计算法更稳定。这套仿真的扩展方向也很多把时隙数从2扩展到8甚至更多时隙的多用户竞争接入加入信道编码DVB-RCS标准中有Turbo码或LDPC码选项看编码增益以及引入实际卫星信道的多径衰落。关键框架已经在这里了换参数和换模块都是水到渠成的事。