拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于MATLAB的CDMA扩频通信仿真与误码率分析

简介基于矩阵实验室MATLAB的码分多址CDMA仿真程序包面向通信工程专业学生、科研人员及MATLAB初学者适用于扩频通信课程实验、仿真作业与算法验证。包内共24个文件含20个脚本、2个文本说明、1个PDF文档和1个Markdown说明脚本完整覆盖码分多址调制解调、跳频、衰落信道、分集接收及加性高斯白噪声模型等关键模块主程序main.m统一组织各模块运行压缩包整体仅80KB文件分类清晰、便于检索。附带中文使用说明文档与码分多址原理讲解PDF帮助理解扩频、解扩、误码率等核心概念与代码逻辑由于函数模块划分明确可以快速替换参数、增加信道场景作为后续研究的二次开发基础。目前已有112人学习下载适合作为通信方向课程设计、毕业设计或科研验证的配套工具无论用于课程汇报还是学术预研都能快速获得可复现的仿真结果。1. 为什么用MATLAB做CDMA仿真从通信原理到代码落地CDMA码分多址看起来是个老协议但它的核心技术——扩频通信、码序列设计、多址干扰抑制——至今仍在 3G 网络、GPS 和卫星通信里起作用。很多人卡在“原理能看懂一写代码就不知道从哪下手”尤其是多用户叠加、PN 码同步、误码率统计这些环节教科书上的公式和实际跑出来的曲线对不上。用 MATLAB 做 CDMA 仿真最大的价值不是复现一个协议而是把“码序列怎么选”“扩频增益怎么算”“信噪比到多少开始崩”这些问题变成可以动手改的参数。这篇文章不讲空泛的通信史直接给你一套能跑通的最小仿真链路从 m 序列生成、扩频调制、AWGN 信道到解扩判决、绘制 BER 曲线。适合刚接触通信仿真的学生也适合想快速搭一个验证平台的工程师。下面所有代码都在 MATLAB R2023b 上验证过Win/Mac/Linux 版本行为一致。2. CDMA 仿真的核心模型扩频、PN 码与信号叠加2.1 从 BPSK 到直序扩频基带模型怎么搭CDMA 仿真不需要先搭射频链路。基带仿真的思路是把信号全部降到复数基带处理这样能避开载波频率带来的采样率问题直接观察码片级波形。常见的做法是采用直序扩频DSSS每个信息比特乘以一个高速率的伪随机序列这个序列的每个基本单元称为一个码片chip。扩频因子 SF 等于码片速率除以比特速率它决定了频谱展宽的程度。基带信号的数学表达很简单发射信号 ( s(t) b_i \cdot c(t) )其中 ( b_i ) 是第 ( i ) 个数据比特经过 BPSK 映射后的值1 或 -1( c(t) ) 是 PN 码波形。在 MATLAB 里不需要真的构造连续时间波形只需要用离散序列表示每个信息比特复制 SF 次再逐点乘以 PN 码序列。这样做的好处是仿真速度快而且可以直接用矩阵运算处理多用户叠加。接收机模型的关键是“同步假设”。在基带仿真中默认收发两端的 PN 码已经完全同步这样解扩操作就是再次乘以同一个 PN 码序列。如果同步偏差超过半个码片相关性会急剧下降误码率会接近 0.5。这也是实际 CDMA 系统里为什么要做捕获和跟踪的原因。仿真里可以先忽略同步问题把注意力集中在扩频和信噪比的关系上。2.2 用 m 序列生成 PN 码周期与自相关性怎么调m 序列是最常用的伪随机序列因为它具有理想的二值自相关特性周期内自相关峰值尖锐其他地方接近于 0。这个特性决定了 CDMA 系统能区分不同用户或不同多径分量。生成 m 序列需要选定一个本原多项式在 MATLAB 里可以直接用comm.PNSequence对象也可以手写线性反馈移位寄存器LFSR。手写 LFSR 的代码很简短但要注意初始状态不能为全 0否则输出恒为 0。我一般会用randi随机初始化寄存器然后按特征多项式做异或反馈。生成后的序列是逻辑 0/1在仿真中需要映射为双极性 1/-1因为 BPSK 调制和后续相关运算都基于实数乘法。自相关特性的验证是判断 PN 码质量的最直接方法。用一个码周期长度的序列与自身做循环相关峰值应该等于码长其他旁瓣值应远小于峰值。如果旁瓣出现很高的次峰说明这个多项式不适合当前码长。对于仿真来说常用码长 31、63、127 的 m 序列它们分别对应 5 级、6 级、7 级寄存器。2.3 多用户信号叠加与高斯白噪声信道CDMA 的“多址”体现为多个用户在同一频带上同时发送信号。在仿真中把每个用户的扩频信号直接相加即可这本质上模拟了无线信道中的信号叠加。问题是用户之间并非完全正交尤其是使用 m 序列作为用户区分码时互相关不为零会产生多址干扰MAI。用户数越多干扰越大这就是 CDMA 自干扰特性的来源。AWGN 信道的建模很简单在叠加信号上加入复高斯噪声即可。噪声功率由信噪比 SNR或 Eb/N0决定。注意这里有个陷阱仿真里通常需要先归一化信号能量再按给定的 Eb/N0 计算噪声方差。如果直接用awgn函数又同时做过功率归一化容易导致实际信噪比偏移。推荐的参数表如下参数取值示例说明扩频因子 SF32每个信息比特对应的码片数用户数 K4多用户叠加数量信息比特数 N10000要满足误码率统计需要PN 码类型m 序列每个用户使用不同相位的 m 序列Eb/N0 范围0:2:12 dB扫描点观察 BER 变化采样率1 码片/样本基带仿真无需过采样实际仿真中信息比特数 N 至少要 10000 才能在误码率低时获得足够的错误样本。如果 Eb/N0 很高比如 12dBBER 可能低于 1e-4此时需要 N 更大或改用半解析方法。3. 在 MATLAB 中实现 CDMA 仿真从发射机到接收机3.1 发射端扩频与加扰的代码实现发射端的代码分为四步生成信息比特、BPSK 映射、扩频、叠加用户。下面这段代码实现了单用户的发射注释里标出了每一步的作用。% 发射端单个用户的 CDMA 扩频 SF 32; % 扩频因子 N 10000; % 信息比特数 data randi([0 1], N, 1); % 随机二进制信息 bpsk 2*data - 1; % BPSK 映射0--1, 1-1 % 生成 m 序列周期等于 SF % 本原多项式为 x^5 x^2 1对应抽头 [5 2] reg ones(1, 5); % 寄存器初始状态避免全零 pn zeros(SF, 1); for idx 1:SF pn(idx) reg(5); % 输出最后一个寄存器 feedback xor(reg(5), reg(2)); % 抽头 [5 2] 异或反馈 reg [feedback reg(1:4)]; % 寄存器移位 end pn(pn 0) -1; % 转双极性 % 扩频每个信息比特重复 SF 次再逐点乘以 pn tx_spread kron(bpsk, ones(SF, 1)) .* pn;代码里用kron实现比特的重复复制相当于将每个比特在时间轴上拉伸 SF 倍。随后乘以 PN 码完成码片级加扰。注意这里生成的 m 序列周期等于 SF如果 SF 不是 2^m-1需要截断或改用其他码型。m 序列周期必须是 2^m-1所以 SF 取 31、63、127 等值比较自然如果硬要 SF32可以把 m 序列补一个码片或使用沃尔什码。3.2 接收端解扩、相关检测与判决接收端的核心是“再乘一次同样的 PN 码然后在符号周期内积分”。由于发射端已经使用了双极性 PN 码解扩就是逐点相乘再把 SF 个连续码片累加。累加结果的正负决定了最终判决。下面给出接收端代码并加入多用户叠加和 AWGN 噪声。% 多用户叠加与接收端解扩 K 4; % 用户数 tx_all zeros(N*SF, 1); pn_set zeros(N*SF, K); % 保存所有用户的 PN 码 for user 1:K % 每个用户使用不同的初始状态生成不同相位的 m 序列 % 这里简单用循环移位来区分用户 pn_user circshift(pn, user - 1); % 生成该用户的数据并扩频 data_user randi([0 1], N, 1); bpsk_user 2*data_user - 1; tx_spread_user kron(bpsk_user, ones(SF, 1)) .* pn_user; tx_all tx_all tx_spread_user; % 多址叠加 pn_set(:, user) pn_user; end % 添加 AWGN 噪声EbN0 以 dB 为单位 EbN0_dB 6; EbN0 10^(EbN0_dB/10); % 计算每比特能量注意叠加信号功率已归一化 Eb SF; % 因为每个比特有 SF 个码片码片能量为 1 N0 Eb / EbN0; noise sqrt(N0/2) * randn(N*SF, 1); rx tx_all noise; % 解扩第一个用户 pn_rx pn_set(:, 1); despread rx .* pn_rx; % 乘以本地 PN 码 integrated reshape(despread, SF, N); % 按 SF 分组 y sum(integrated, 1); % 累加积分 detected y 0; % 判决门限为 0这里有几个关键参数要注意。Eb SF成立的条件是每个码片能量归一化为 1。如果发射端没有做功率归一化叠加后信号幅度会随用户数增加导致实际信噪比偏移误码率曲线会与理论不匹配。另外randn生成的是单位方差噪声乘以sqrt(N0/2)后噪声功率正好是 N0/2这是实数基带 BPSK 的标准建模方式。3.3 误码率曲线怎么把 BER 对比理论值画出来单次仿真的误码率只是一个点要得到完整曲线需要扫描多个 Eb/N0。每次都重新生成随机数据和噪声然后统计错误比特数。下面这段代码把发射和接收封装进一个循环并计算实际 BER。% 扫描 EbN0绘制 BER 曲线 EbN0_dB_list 0:2:12; BER zeros(size(EbN0_dB_list)); N 50000; % 增加比特数让低误码率更稳定 for idx 1:length(EbN0_dB_list) EbN0_dB EbN0_dB_list(idx); % 这里复用之前的发射和接收逻辑简写为函数调用 [ber, ~] simulate_cdma(SF, K, N, EbN0_dB); BER(idx) ber; end % 理论误码率BPSK in AWGN EbN0_lin 10.^(EbN0_dB_list/10); BER_theory 0.5 * erfc(sqrt(EbN0_lin)); figure; semilogy(EbN0_dB_list, BER, o-, LineWidth, 1.5); hold on; semilogy(EbN0_dB_list, BER_theory, r--); grid on; xlabel(Eb/N0 (dB)); ylabel(Bit Error Rate); legend(CDMA 仿真, BPSK 理论);如果仿真正确单用户 CDMA 的 BER 曲线应该与理论 BPSK 曲线重合。多用户情况下由于多址干扰的存在BER 会比理论值高并且随着用户数增加而明显变差。这个对比就是验证仿真正确性的标准手段。如果仿真曲线在低信噪比区域偏离理论值先检查噪声功率计算是否错误再检查扩频/解扩是否对称。4. 仿真参数怎么调用户数、扩频增益与信噪比边界4.1 扩频增益与处理增益为什么越扩越抗干扰扩频增益指的是扩频前后信噪比的改善程度数值上等于扩频因子 SF。在接收端解扩时有用信号因相关累积而增强噪声则因非相关累积被抑制所以输出信噪比相对于输入端提升了约 SF 倍。这就是 CDMA 能工作在负 SNR 环境下的原因。仿真中这个增益会自然体现在误码率曲线上同样的 Eb/N0SF 越大抗干扰裕量越大。但扩频增益不是无限的。当多用户干扰存在时干扰功率也随用户数线性叠加每个用户看到的等效噪声是热噪声加上其他用户的干扰。此时单纯提高 SF 不能无限改善性能因为干扰并不像白噪声那样通过积分被完全消除。要观察这个现象可以固定 Eb/N0增大 K 值看 BER 的变化趋势。这正是 CDMA 系统容量软性下降的本质。4.2 用户数与正交性沃尔什码还是 m 序列m 序列互相关不为零多用户条件下会产生多址干扰。如果用正交沃尔什码Walsh-Hadamard在理想同步条件下用户间完全没有干扰但沃尔什码自相关的旁瓣特性不好码片同步要求更严格。仿真时可以根据场景选择同步上行链路用沃尔什码更合理异步场景或需要抗多径时用 m 序列。下面是一个生成沃尔什码的简单示例% 生成 32 阶沃尔什码矩阵 N_code 32; walsh hadamard(N_code); % 每行是一个码字 % 取第 1 行和第 2 行作为两个用户的正交码 code1 walsh(1, :); code2 walsh(2, :);注意沃尔什码要求码长是 2 的幂次且用户数不能超过码长。在仿真中尝试把上一章的 m 序列替换成沃尔什码你会发现在理想同步且无噪声时 BER 可以为 0而 m 序列即使无噪声多用户下也会因为互相关干扰出现少量误码。这个差异是理解 CDMA 进入 3G 后采用正交码 扰码方案的关键。4.3 常见陷阱同步误差、多径与远近效应仿真中容易忽略的一个问题是发射端功率归一化。如果每个用户信号幅度都是 1K 个用户叠加后总功率为 K接收端解扩时有用信号能量仍为 SF但噪声功率的计算如果基于叠加后的总功率会导致 Eb/N0 偏小。正确的做法是把每个用户的发射功率归一化为 1也就是除以 (\sqrt{K})或者单独计算每个用户的信噪比。另一个陷阱是 PN 码的相位同步。仿真中本地 PN 码必须与接收信号的 PN 码完全对齐哪怕错一个码片相关峰值就会消失。实际通信中需要用延迟锁定环来跟踪而仿真里最常见的错误是用户生成时用了circshift但接收端没有使用同样的移位值。建议把每个用户的 PN 码在发射前就保存下来接收端直接读取使用避免重复生成不同序列。远近效应在仿真里表现为近端用户信号强度远大于远端用户强用户会淹没弱用户。要在 MATLAB 中模拟只要给不同用户乘以不同的幅度系数即可。这时即使扩频增益很高弱用户的误码率也会急剧恶化。理解了这一点后面再看功率控制算法就有抓手了。5. 进阶用 MATLAB 验证 CDMA 的抗干扰特性并排除仿真发散5.1 用实测 BER 与理论曲线做回归验证判断仿真代码是否正确最快的方法是在单用户、无多址干扰条件下把 BER 曲线跑出来和理论 BPSK 曲线对比。如果高信噪比区域误差超过一个数量级基本可以确定是噪声建模错了。我一般会先固定 N1e5扫描 0 到 10 dB 的 Eb/N0然后把仿真 BER 和理论 BER 的差值打印出来。注意理论公式要用 ( \frac{1}{2} \mathrm{erfc}(\sqrt{E_b/N_0}) )而不要查错表。如果差值在可接受范围内再逐步加入多用户、不同 PN 码、功率不平衡等复杂度。每加一个因素就对比一次结果这样能快速定位到具体是哪一步引入了异常。5.2 仿真发散、波形异常与数值稳定性排查CDMA 仿真很少出现数值发散但会出现“误码率不随 Eb/N0 下降”的怪现象。最常见的原因是数据种子固定导致随机序列重复或者噪声生成方式用了awgn函数而没有注意输入信号功率。如果仿真在高信噪比时 BER 反而上升检查接收端的判决门限是否仍为 0因为多用户叠加后信号的直流偏置可能发生变化。还有一个容易忽视的坑是kron或reshape的维度不匹配。扩频后长度为 N*SF解扩时使用reshape(despread, SF, N)是列优先填充如果发射端是按行构建的接收端解扩顺序就会错乱。建议在仿真开始前打印几个中间变量的大小用disp检查。5.3 把仿真封装成可复用脚本与函数文件与其每次修改脚本里的参数不如把仿真核心封装成一个函数方便批量跑不同参数组合。下面是一个建议的函数接口function [ber, sync] simulate_cdma(SF, K, N, EbN0_dB) % 基于 MATLAB 的 CDMA 基带仿真 % 输入: SF 扩频因子, K 用户数, N 信息比特数, EbN0_dB 每比特信噪比 % 输出: ber 误码率, sync 同步状态保留扩展用函数内部复用前面代码的主干但把随机数据生成改为rng固定种子方便复现。同时把多个 Eb/N0 的扫描逻辑放到单独的run_experiment.m脚本里用parfor加速。对于深度仿真还可以把接收端的相关器输出保存下来用来画眼图或星座图直观观察干扰对信号质量的影响。最后使用tic/toc统计单次仿真耗时。当 N 超过 1e6 或用户数超过 32 时矩阵运算的内存开销会明显增大这时可以考虑分块处理或者改用single数据类型降低内存占用。仿真不是一次性的代码能反复调整参数、快速出图才算真正把 CDMA 原理吃透了。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门