MATLAB水下直接扩频通信仿真:多径信道与误码率分析
2026/9/16 12:09:18 网站建设 项目流程

简介:这是一套基于MATLAB的水下扩频通信系统研究代码包,面向水声通信、扩频信号处理方向的本科生、研究生及工程师。系统采用直接序列扩频(DSSS)方式,完整实现了PN码生成、数据调制,以及多径水声信道与无多径信道下的性能对比,适合用于课程设计、课题预研或算法验证。资源压缩包共19个文件,包含7个m脚本(主程序与各功能模块)、5个mat数据文件、2个fig图表和2个bmp结果图,另有说明文档与自动备份文件,整体仅41KB,结构紧凑、便于快速部署。当前已有101人学习下载。代码基于MATLAB 2020b编写,主函数main.m一键运行,注释与模块划分清晰,使用者可直接替换参数或数据开展实验;说明文档对运行步骤和文件用途做了梳理,能帮助理解DSSS系统在水声多径信道下的误码率表现与同步策略,具有较强的参考和复用价值。

1. 水下扩频系统为什么值得用直接扩频序列重新做一遍

浅海近程通信里,多径时延常达几十毫秒量级,几百符号每秒的调制信号在接收端会叠成一串拖尾,常规单载波体制很难在保持速率的同时保证可靠。直接扩频序列用带宽换处理增益,把窄带信息展宽到数kHz,接收端依靠相关性把能量重新收拢;多径虽然还在,但只要时延差大于一个码片宽度,多条路径不仅不再互相干扰,反而能被解扩后的相关峰分离成可用的分集来源。这套方案在水声遥测、水下无人平台数据传输中很常见,也是当前能落地到工程的低速稳健通信思路之一。用MATLAB把无多径和多径两条链路都跑一遍,理论看得清、代码改得动,是理解水声通信比较好的切入路径。

2. MATLAB下水声信道建模:从无多径AWGN到多径抽头延迟线

水声信道与射频无线信道最大的差别在于传播速度只有约1500 m/s,同等距离下时延比射频大五个数量级。因此多径时延差在符号周期里占比极大,仿真时不能用射频通信里“多径只是几个符号间干扰”的直觉去看,必须把每一条路径的时延当成分辨率的决定因素。MATLAB里做水声仿真,最常见的做法是基带等效模型:忽略载波频率的绝对数值,只关心符号速率、码片速率和多径时延的换算关系。

2.1 无多径水声信道:AWGN下的基带模型

无多径场景对应的不是“没有噪声”,而是信道里只有一条直达路径,加性噪声占主导。对直接扩频系统来说,这是性能上限的参照系。仿真里用awgn或手动生成高斯白噪声都可以,关键是统一信噪比的定义。

一个最小可跑的信道函数如下,输入基带信号x,返回加了噪声的接收信号:

function y = awgn_channel(x, snr_dB) % 基带等效AWGN信道 % snr_dB 是符号信噪比 Eb/N0,不是载波功率比 L = length(x); noise = randn(L, 1) + 1i * randn(L, 1); noise = noise / sqrt(2); % 单位功率 Es = mean(abs(x).^2); % 符号能量 N0 = Es / 10^(snr_dB / 10); y = x + sqrt(N0) * noise; end

这段代码的核心是N0 = Es / 10^(snr_dB/10),它把信噪比定义在符号能量与噪声功率谱密度的比值上。对BPSK符号,符号能量Es与比特能量Eb相等;如果是QPSK,Es = 2 * Eb,后面画误码率曲线时要注意换算。

2.2 多径水声信道的离散表示:抽头延迟线

工程上对水声多径最常用的模型是抽头延迟线(Tapped Delay Line),每个抽头代表一条可分辨的声线路径,包含时延、幅度和相位。在基带等效下,时延以采样点数为单位,幅度表示路径衰减,相位由exp(j*theta)给出。

function y = multipath_channel(x, taps, delays, snr_dB) % 多径信道:每条路径是复数增益 % x: 发送基带信号(列向量) % taps: 各路径幅度增益,例如 [0.8; 0.4; 0.2] % delays:各路径时延(采样点),例如 [0; 3; 7] L = length(x); y = zeros(L, 1); for k = 1:length(taps) d = delays(k); if d < L y(1+d:end) = y(1+d:end) + taps(k) * x(1:end-d); end end Es = mean(abs(x).^2); N0 = Es / 10^(snr_dB / 10); noise = (randn(L,1) + 1i*randn(L,1)) / sqrt(2); y = y + sqrt(N0) * noise; end

这里的时延参数用采样点直接表示。如果采样率是fs,实际物理时延tau秒就等于delays = round(tau * fs)。多径时延在水声环境里往往是几十到几百毫秒,如果采样率设在10 kHz,一次多径扩展就是几百个采样点,这比射频信道里的几个符号间隔大得多,所以代码里直接做时域叠加是合理的。

2.3 无多径与多径信道参数对比

参数无多径信道多径水声信道
路径数量13~5条可分辨路径
时延差0几ms ~ 几十ms
主要干扰高斯白噪声噪声 + 码间串扰
对DSSS影响达到理论性能上限受限于多径分辨能力
仿真模型AWGN抽头延迟线 + AWGN

参数选择上,我一般把时延差控制在码片间隔的整数倍附近,这是为了观察直接扩频对多径的抑制效果。真实水声信道里多径往往不是采样点的整数倍,但仿真先用整数倍能快速验证逻辑,后面再改成小数倍时延观察性能退化。

3. 直接扩频序列收发链路搭建:扩频码、BPSK调制与相关解扩

有了信道模型,下一步是把直接扩频收发链路在MATLAB里完整搭起来。链路从左到右依次是:信息比特 → 扩频 → BPSK映射 → 信道 → 解扩相关 → 判决。这里最容易出现的问题是扩频码没有归一化,导致能量随码长增长,误码率曲线乱套。

3.1 m序列生成与扩频码设计

直接扩频序列的核心是伪随机码,m序列是最常见的一种,周期为2^n - 1,具有良好的自相关特性。MATLAB里自带的通信工具箱有comm.PNSequence,但如果不想依赖工具箱,移位寄存器实现也很简单:

function code = generate_mseq(n, taps) % 生成n阶m序列,taps为反馈抽头索引 % 例:n=5, taps=[5,3]是常用本原多项式 len = 2^n - 1; reg = ones(1, n); % 初始寄存器状态 code = zeros(1, len); for i = 1:len code(i) = reg(n); fb = mod(sum(reg(taps)), 2); reg = [fb, reg(1:end-1)]; end code = 2 * code - 1; % 双极性:0->-1, 1->+1 end

参数说明:taps是反馈抽头,需要从m序列本原多项式表里查,n=5时常用抽头是[5 3][5 2]。函数返回的code是双极性序列,长度为31,后续直接用这个向量做扩频。双极性的好处是相关运算退化成乘法累加,解扩输出直接就是实数。

3.2 扩频与调制:把符号速率压到码片速率

扩频的本质是把一个信息比特与整段码序列相乘,输出len(code)个码片。BPSK调制在基带仿真里就是符号直接乘载波,但基带等效模型里可以省略实际载波,直接输出复数基带符号。

function tx = dsss_modulate(data, code) % data: 0/1比特流 % code:双极性扩频码,行向量 bits = 2 * data - 1; % 比特映射 sf = length(code); % 扩频增益 tx = reshape(bits' * code, [], 1); % 每比特复制成一段码片 end

这段代码里sf就是扩频增益,数值上等于码片速率与信息速率之比。若信息速率是100 bps,扩频增益是31,码片速率就是3100 chip/s。bits' * code是一个矩阵乘,得到num_bits × sf的矩阵,reshape后变成一列,等价于把每个比特扩展成一段完整码序列。

3.3 相关解扩与比特判决:滑动相关和峰值定位

接收端拿到带噪声的码片序列后,需要知道每个比特的起始位置才能正确解扩。这里就需要做码同步。最直观的方法是滑动相关:把本地参考码与接收序列逐点对齐,找到相关峰位置,即视为一个比特的起点。

function bits = dsss_demodulate(rx, code) sf = length(code); % 滑动相关找起始点 corr = conv(rx, fliplr(code), 'full'); % 相关峰会周期性出现,取第一个满足阈值的点 % 简化处理:取相关输出绝对值最大值附近的位置 [~, idx] = max(abs(corr)); start = mod(idx, sf) + 1; % 按起始位置逐段解扩 rx2 = rx(start:end); num_sym = floor(length(rx2) / sf); rd = reshape(rx2(1:num_sym*sf), sf, num_sym); soft = code * rd; % 相关累加 bits = soft(:) > 0; % 硬判决 end

conv(rx, fliplr(code), 'full')计算的是互相关,峰值位置对应本地码与接收码对齐的瞬间。把start = mod(idx, sf) + 1转成整数倍位置,是为了让后续reshape按完整符号切分。这个简化逻辑没有处理多径条件下的峰选择问题,在多径信道里,每一个可分辨路径都会产生一个相关峰,实际接收机需要选最大峰或做RAKE合并,这是第4章的重要内容。

4. 多径水声信道下的扩频系统误码率对比:仿真框架与曲线解读

直接扩频系统的多径性能不能只看单次波形,要用蒙特卡洛仿真把误码率曲线画出来。常规做法是固定扩频码和信道参数,遍历多个信噪比点,每个点发送足够多的比特,统计错误比例,最后与BPSK理论误码率对比。

4.1 蒙特卡洛仿真框架

下面的脚本把前面几节的函数组合成完整仿真流程:

function ber = run_dsss_sim(snr_dB, code, taps, delays, nbits) % 单个信噪比点的误码率估计 data = randi([0 1], nbits, 1); tx = dsss_modulate(data, code); if isempty(taps) rx = awgn_channel(tx, snr_dB); else rx = multipath_channel(tx, taps, delays, snr_dB); end rx = rx / max(abs(rx)); % 幅度归一化,避免大路径淹没 bits_rx = dsss_demodulate(rx, code); % 去掉符号起点偏差导致的长度差 n = min(length(data), length(bits_rx)); ber = sum(data(1:n) ~= bits_rx(1:n)) / n; end

这个函数把信道选择抽象成参数:多径信道传tapsdelays,无多径时传空数组。幅度归一化rx / max(abs(rx))很关键,因为多径叠加会让接收幅度超过1,如果不归一化,解扩后的软信息幅度会直方图偏移,误码率统计失真。

4.2 生成误码率曲线

snr_list = 0:2:16; sf = 31; code = generate_mseq(5, [5 3]); nbits = 20000; ber_awgn = zeros(size(snr_list)); ber_mp = zeros(size(snr_list)); for k = 1:length(snr_list) ber_awgn(k) = run_dsss_sim(snr_list(k), code, [], [], nbits); ber_mp(k) = run_dsss_sim(snr_list(k), code, [0.8; 0.4; 0.2], [0; 3; 7], nbits); end semilogy(snr_list, ber_awgn, 'o-', snr_list, ber_mp, 's-'); grid on; xlabel('Eb/N0 (dB)'); ylabel('BER'); legend('No multipath', '3-path channel', 'Location', 'southwest');

约20000比特在误码率低到1e-3时只能统计到20个错误,曲线尾部抖动正常。想得到更平滑的尾部,需要把nbits提到5万以上,但仿真时间也会线性增加。

4.3 性能差异的物理解释

无多径时,直接扩频系统的误码率曲线与理论BPSK曲线基本重合,扩频增益不改变比特级误码率,只改变带宽占用和抗干扰能力。多径信道下,3条路径带来的码间串扰不会因为解扩完全消失,时延差恰好是码片间隔整数倍时,每条路径的相关峰错开,但旁瓣仍会抬高噪声底,导致误码率曲线出现地板。

多径时延如果小于一个码片宽度,多径信号落在同一个相关峰内部,这时候直接扩频系统无法分辨路径,误码率退化会明显得多,这也是后面一排错时优先检查的参数。

5. 直接扩频系统参数调节与多径时延边界:该动哪个、不该动哪个

MATLAB仿真最占时间的地方不是写代码,而是参数之间互相牵制。扩频增益、码片速率、多径时延、滤波器占用和信噪比定义,任何一项改动都会传导到最终误码率。

参数典型值影响对象
扩频增益sf31、63、127处理增益、带宽占用、多径分辨力
码片速率3100 chip/s多径时延对应的采样点数
多径时延3~50 ms相关峰的错开程度
路径增益0.2~0.9各路径能量占比
调制方式BPSK理论误码率基线

5.1 扩频增益怎么选

扩频增益直接决定系统能抵抗多强的多径和干扰。增益为31时,处理增益约15 dB,这意味着即使一条干扰路径的功率比直达路径低15 dB以下,也会造成可见的误码率地板。实际设计里,扩频增益不能无限增大:码片速率随增益线性增长,水声信道的可用带宽有限,盲目增大会让系统带宽超出换能器响应范围。

一个常用的确认方法是看自相关旁瓣。m序列的自相关旁瓣为周期长度的倒数,对31位码,旁瓣约-30 dB,这构成了多径抑制的理论下限。

5.2 多径时延的三种情况

第一,时延为0:路径完全重叠,等效于幅度增强,无额外干扰。第二,时延为一个码片间隔:相关峰完全错开,系统能把多径当作独立路径,这种场景扩频增益发挥正常。第三,时延小于一个码片间隔:部分重叠,相关峰不能完全分离,系统性能介于两种极端之间。

仿真时如果想量化这种退化,可以把delays改成[0; 1; 2]这样的采样点间隔,并在同一张图里对比。

5.3 采样率与低通滤波的常见误区

很多初学者把采样率设得过高,导致delays需要几千个采样点,蒙特卡洛仿真速度急剧下降。基带等效仿真不需要还原载波波形,采样率只要高于码片速率即可,工程上调成码片速率的4倍到8倍足够。如果用了实信号模型,载波频率必须满足奈奎斯特条件,通常取载波频率的4倍以上做采样率。

接收端的匹配滤波在高斯信道里是可选优化,但对多径信道是必要环节。常见做法是用rcosdesign设计根升余弦滤波器做脉冲成形,发射端和接收端各放一个,让码片波形在采样点处保持正交,避免相邻码片互相叠加。

6. 用相关峰检测和分段蒙特卡洛快速验证DSSS链路是否可靠

仿真跑通不难,跑出可信的数据难。散点图、星座图这类宏观指标不能证明链路正确,我习惯先做一次单符号发送的波形级验证,再跑小样本蒙特卡洛,最后才放大数据量。

单符号验证的做法是发送一个已知比特,不加噪声,把解扩前和解扩后的信号画出来。解扩前的接收序列应该能看到明显周期性,解扩后只有一个尖锐相关峰,旁瓣远低于主峰。这一步可以确认扩频码、调制顺序、解扩起点三者的匹配关系,90%的链路逻辑错误都能在此时暴露。

蒙特卡洛小样本验证也很直接:先跑200比特、信噪比10 dB的单次仿真,错误的比特位置应该随机分布,而不是集中在前半段。集中分布说明符号起点同步逻辑有偏置,错误率统计结果没有参考价值。确认无误后,再按目标误码率量级决定样本数。工程经验是误码率要统计到10个错误以上才可信,想要看到1e-3的误码率,至少发2万比特。

最后一个值得尝试的技巧是固定随机种子。MATLAB里rng(2024)放在仿真脚本头部,能让同一段代码在多次运行中产生相同结果,这对调参时判断“性能变化到底是参数引起的还是随机性引起的”非常关键。调参前后用同一个种子跑,减小了蒙特卡洛方差造成的干扰。要多径场景做快速验证时,把路径数从3减到2、时延从7个采样点改成3个采样点,先看清趋势,再回归完整参数。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询