
简介这是一套基于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相等如果是QPSKEs 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(1d:end) y(1d: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为反馈抽头索引 % 例n5, 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序列本原多项式表里查n5时常用抽头是[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; % 硬判决 endconv(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这个函数把信道选择抽象成参数多径信道传taps和delays无多径时传空数组。幅度归一化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个采样点先看清趋势再回归完整参数。本文还有配套的精品资源点击获取