ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

2MHz AMI/HDB3编码与功率谱密度分析的MATLAB仿真

2MHz AMI/HDB3编码与功率谱密度分析的MATLAB仿真 简介这是面向通信工程及相关专业学生的一份MATLAB仿真资源对应通信原理课程中AMI码与HDB3码的典型实验环节。程序在2MHz速率下完成两种线路编码的时域波形与功率谱密度分析能够直观呈现连续0串替换、交替反转等核心编码规律帮助学习者将教材抽象公式与图形化结果对应起来既适合本科实验教学也可用于课程设计前的算法验证。压缩包包含3个m文件其中AMI_HDB3.m为主程序f2t.m与t2f.m分别负责时域/频域变换包体仅3KB轻量易读、便于按需修改参数。目前已有215人学习下载可作为基带传输仿真的入门参考。运行后可得到编码波形图、功率谱密度曲线及典型参数设置读者可以借此核对编码规则、理解频谱特征并迁移到多速率基带传输仿真中是一份简洁实用的通信原理辅助资料。1. 2MHz AMI/HDB3实验的隐藏难点不是编码是功率谱坐标用2MHz码速率做AMI/HDB3实验第一关其实是坐标。单独跑一个FFT频谱图和理论功率谱密度经常对不上直流处不该有谱线的地方冒出一根2MHz整数倍附近也起伏不定。这个AMI_HDB3.rar实验包包含AMI_HDB3.m、f2t.m和t2f.m三个文件正好覆盖通信原理课里“2MHz速率AMI码和HDB3码时域及功率谱密度分析”这个需求。它能回答三个问题波形怎么生成、频域坐标怎么对齐、AMI和HDB3的功率谱密度差异在哪。适合正在补通信原理实验的学生也适合写MATLAB基带仿真前端时想快速拿到可用线路码的工程师。要提醒的是这里的AMI指Alternate Mark Inversion线路编码不是BMC/服务器管理里那个固件概念搜代码时不要混。2. AMI/HDB3编码规则与MATLAB编码函数2.1 为什么HDB3要破坏四连零AMI码的局限性AMI码的规则一句话讲完遇1翻转极性遇0输出0。优点是频谱里没有直流分量因为1和-1出现的统计概率相等序列均值接近0。缺点在工程里很实在当数据出现长串0线路持续输出0电平接收端的时钟提取电路拿不到跳变沿定时同步会失锁。HDB3码保留AMI无直流特性同时把连续四个0替换成带破坏脉冲的码型保证线上不会出现超过3个连续零。替换规则可以用一张表说明自上个破坏脉冲V后普通1码数替换结果替换规律奇数个1000VV与前面非零码同极性破坏AMI交替偶数个1B00VB与前面非零码反相V与B同极性实际编码时可以不number奇偶性直接比较两个状态量上一个非零码极性last和上一个破坏脉冲极性v。当lastv时走B00V分支当last-v时走000V分支。因为普通1总是翻转极性自上个破坏V以来普通1个数是偶数时当前极性一定和上个V相同奇数时则相反。例如1 0000 1在首码取1的约定下编成 0 0 0 -第四个0被V占用V与前面的1同极性从而破坏了AMI交替规则。2.2 ami_encode.m与hdb3_encode.m最简可运行实现下面给出可以直接放进实验文件夹的两个函数。ami_encode.m作为对照hdb3_encode.m是完整状态机。function y ami_encode(bits) % AMI编码 % 输入bits为0/1行向量输出y为-1/0/1行向量 y zeros(1, numel(bits)); last 1; % 上一个非零码极性1表示-1表示- for k 1:numel(bits) if bits(k) 1 last -last; % 遇见1就翻转极性 y(k) last; end end endfunction y hdb3_encode(bits) % HDB3编码 % 输入bits为0/1行向量输出y为-1/0/1行向量 y zeros(1, numel(bits)); last 1; % 上一个非零码极性 v 1; % 上一个破坏脉冲V的极性 run 0; % 连续零计数 for k 1:numel(bits) if bits(k) 1 last -last; % 普通1码 y(k) last; run 0; else run run 1; if run 4 if last v % 自上个V以来普通1为偶数个用B00V y(k-3) -last; % B码 y(k) -last; % V码与B同极性 last -last; % 线路上最后非零码是V v last; else % 自上个V以来普通1为奇数个用000V y(k) last; % V码 v last; end run 0; end end end end注意last和v初始都设为1所以第一个1编码结果是-1最前面出现四个0时走B00V分支。这不是错误因为线路码的绝对正负只取决于初始参考电位频谱形状不变。如果你希望第一个1是1把last和v都改成-1即可。y(k-3)不会越界因为run累计到4时k至少为4。代码里B00V分支把y(k-3)放在第一个零位置y(k-2)和y(k-1)保持0y(k)放V正好形成B00V四个码元。2.3 编码边界情况码长、连续零和连续1做实验时建议先生成随机二进制序列再编码不要用全0或周期太短的序列否则看不出AMI和HDB3的实际差异。一个20位随机序列就够观察bits randi([0 1], 1, 20); ami ami_encode(bits); hdb3 hdb3_encode(bits); figure stem(0:19, ami, o, MarkerFaceColor, b); hold on; stem(0:19, hdb3, x, color, r); legend(AMI, HDB3);运行后主要看三点HDB3中连续零最大个数不超过3V出现的码元位置破坏了AMI交替整个序列求和接近0。最后一点可以在地球上代码里加一个断言防止后面频谱分析时拿到带电平的序列run 0; for k 1:length(hdb3) run run * (hdb3(k) 0) (hdb3(k) 0); assert(run 3, HDB3编码结果出现四连零); end assert(abs(mean(hdb3)) 0.05, 直流分量偏大);run run * (hdb3(k)0) (hdb3(k)0)是一个连续零计数技巧遇到非零码会把run清零遇到0则在上一次计数基础上加1。这种做法比if-else嵌套短适合在实验里复用。3. 2MHz时域波形与f2t/t2f坐标体系3.1 采样率、码元宽度和频率分辨率怎么匹配2MHz码速率意味着一个码元宽度是0.5微秒。MATLAB里不能直接用模拟连续信号画图必须离散采样。每个码元采几个点决定了频谱分析的频率范围和分辨率。实验包里没有写死参数推荐按下表设置参数推荐值说明Rb2e6 Hz码元速率项目指定Tb0.5 us码元宽度1/Rbspc8每码元采样点数最少取2fs16e6 Hz采样率Rb*spcN1024或更大FFT点数spc取8是折中采样率够高频谱不会混叠数据量又不是太大画图流畅。频率分辨率是fs/N取N1024时约15.6kHz足够分辨2MHz码速率附近的频谱细节。如果spc2每个码元只采两个点矩形脉冲波形看起来会特别尖功率谱图也不够平滑。3.2 f2t.m从频域数据还原时域波形f2t.m是频域到时域的对应函数注意它和t2f.m是一对互逆操作不是用来生成波形的函数。实际作用是把经过频域修改的频谱重新还原为时域序列适合验证滤波器设计。function [t, x] f2t(f, X) % f2t 从频域数据还原时域波形 % 输入f为频率向量X为频谱值 df f(2) - f(1); % 频率间隔 N length(X); dt 1 / (N * df); % 时间间隔由频率分辨率反推 x ifft(ifftshift(X)) / dt; t (0:N-1) * dt; endifftshift的作用是把fftshift后的频谱恢复到ifft需要的顺序。如果输入频谱没有经过fftshift这里就要去掉ifftshift。/dt是补偿t2f里乘过的dt否则还原后的波形幅度会差一个采样周期倍数。这个细节是实验报告里最容易扣分的地方。3.3 t2f.mFFT频谱计算的细节t2f.m负责把时域波形变成频域数据是本次实验功率谱分析的核心前置步骤。function [f, X] t2f(t, x) % t2f 从时域波形计算频谱 % 输入t为时间向量x为采样值 dt t(2) - t(1); N length(x); X fftshift(fft(x)) * dt; df 1 / (N * dt); f (0:N-1) * df - (N * df) / 2; end这里乘dt是因为MATLAB的fft本质上是离散傅里叶变换连续频谱的近似需要乘采样间隔。fftshift把零频分量搬到频率轴中间让负频率在左、正频率在右这样画出来的功率谱密度曲线更直观。频率轴用的是(0:N-1)*df - (N*df)/2对应从负fs/2到正fs/2的区间。生成2MHz AMI和HDB3时域波形的完整片段如下rng(2024); Rb 2e6; % 2MHz码速率 spc 8; % 每个码元8个采样点 fs Rb * spc; % 采样率16MHz bits randi([0 1], 1, 256); ami ami_encode(bits); hdb3 hdb3_encode(bits); wave_ami kron(ami, ones(1, spc)); wave_hdb3 kron(hdb3, ones(1, spc)); t (0:length(wave_hdb3)-1) / fs; figure subplot(2,1,1) plot(t*1e6, wave_ami, LineWidth, 0.8) title(2MHz AMI码时域波形) ylabel(幅度) subplot(2,1,2) plot(t*1e6, wave_hdb3, LineWidth, 0.8) title(2MHz HDB3码时域波形) xlabel(时间/us) ylabel(幅度)kron(ami, ones(1, spc))把每个码元扩展成spc个相同样本是矩形脉冲建模最直接的方式。t*1e6把单位从秒换成微秒x轴读起来更符合码速率习惯。这里用rng(2024)固定随机种子保证每次运行生成的二进制序列一致实验报告里的截图可以复现。3.4 坐标对齐常见错误做t2f时最常见的错误是忘了fftshift画出来的频谱会左右分裂零频出现在图像两侧。另一个问题是t2f里漏乘dt频谱幅度会随N变化功率谱密度数值完全不对。验证坐标是否对齐的做法很简单给一个单位直流信号做t2f零频处应出现单根谱线幅度等于信号持续时间再做f2t应还原成原始直流波形。如果这两个方向能对得上后续功率谱计算就不会出坐标问题。4. 功率谱密度计算从理论公式到Welch估计4.1 AMI/HDB3功率谱密度长什么样AMI码的理论功率谱密度公式是S_AMI(f) Rb * |G(f)|^2 * sin^2(pi * f * Tb)其中G(f)是基带脉冲频谱。如果使用矩形脉冲G(f)Tb*sinc(f*Tb)。sin^2(pi*f*Tb)使得功率谱密度在零频和fk*Rb处出现零点也就是说AMI码没有直流分量也没有2MHz整倍数处的离散谱线。HDB3码由AMI码基础上加破坏脉冲得到低频特性略有变化但同样不存在直流分量。功率谱密度实验的目的就是验证这两个码型在频域上的这个差别。4.2 用t2f计算功率谱密度周期图法直接利用前面写好的t2f.m可以快速得到一个周期图形式的功率谱密度估计[f, X] t2f(t, wave_hdb3); T t(end) - t(1) 1/fs; Pxx abs(X).^2 / T; figure plot(f/1e6, 10*log10(Pxx eps)); xlabel(频率/MHz); ylabel(功率谱密度/dB); title(HDB3功率谱密度-周期图法);T是信号总时长abs(X).^2/T把FFT幅度平方换算成功率谱密度单位是V²/Hz。eps是为了避免零频附近的log10(0)产生-inf画图时更安全。用这个方法看AMI码零频处会出现明显凹陷看HDB3码凹陷同样存在但曲线会比AMI平缓一些。周期图法问题在于单次实现波动很大256个码元的随机数据只能得到一个“毛刺很多”的谱。这属于统计方差问题不是编码错误。要得到光滑曲线需要用Welch法做分段平均。4.3 用Welch法平滑窗长度、重叠和nfftMATLAB自带pwelch函数可以直接对接实验数据[Pxx_w, f_w] pwelch(wave_hdb3 - mean(wave_hdb3), ... hamming(256), 128, 1024, fs, centered); figure plot(f_w/1e6, 10*log10(Pxx_w eps)); xlabel(频率/MHz); ylabel(功率谱密度/dB); title(HDB3功率谱密度-Welch法);wave_hdb3 - mean(wave_hdb3)先去掉直流分量防止数值误差在零频形成虚假谱线。hamming(256)是窗函数建议参数窗函数主瓣宽度旁瓣衰减适用场景矩形窗最窄约-13dB分辨率优先但泄漏明显Hamming较宽约-42dB通用功率谱估计推荐Blackman最宽约-58dB强谱线附近要压低旁瓣pwelch的第2到第5个参数分别对应窗函数、重叠样点数、FFT点数和采样率。centered表示输出双边功率谱零频在频率轴中间。如果去掉centered默认输出单边谱频率只有正半轴直接看图会漏掉另一半负频率信息。4.4 为什么谱线会“多出来”窗泄漏和序列重复功率谱里多出不该有的谱线常见原因有两个。第一个是窗泄漏矩形窗旁瓣衰减只有约13dB强能量附近的旁瓣会掩盖零点导致AMI码在2MHz附近的凹陷不明显。改用Hamming或Blackman窗能明显改善。第二个是测试序列重复如果实验代码用了repmat(bits, 1, N)把同一段二进制序列重复多次序列周期性会在码速率整数倍处产生离散谱线。实验里应该用randi生成足够长的随机序列或者至少保证不循环重复。5. 验证和进阶让AMI/HDB3实验可复现5.1 三个顺序的自检拿到编码结果后不要急着画频谱先按顺序做三个自检% 自检1不允许出现四连零 run 0; for k 1:length(hdb3) run run * (hdb3(k)0) (hdb3(k)0); assert(run 3, 出现四连零); end % 自检2直流分量足够小 assert(abs(mean(hdb3)) 0.05, 直流分量偏大); % 自检3零频附近功率谱比主峰低20dB以上 [pxx, fx] pwelch(hdb3, hamming(128), 64, 512, fs, centered); dc_bin find(fx 0); peak max(10*log10(pxx eps)); dc 10*log10(pxx(dc_bin) eps); assert(peak - dc 20, 零频功率偏高);前两个自检保证编码正确第三个自检保证频谱形状符合理论预期。pwelch中的find(fx0)用来找零频位置如果频率轴有浮点误差可以改成find(abs(fx) 100)。5.2 眼图看什么HDB3实验可以顺带画眼图用来验证码间串扰和采样时刻选择spc 8; eye_len 100 * spc; eye_trace reshape(wave_hdb3(1:eye_len), spc, []); figure plot(eye_trace, LineWidth, 0.5); xlabel(采样点); ylabel(幅度); title(HDB3眼图-矩形脉冲);reshape把波形按每个码元spc个点重排每一列是一个码元叠加后就是眼图。矩形脉冲没有成形滤波眼图是一个矩形开口上升沿垂直、下降沿垂直开度很大。如果加了升余弦滤波器或信道失真眼图开口会变小这时就能直观看出均衡和滤波的重要性。5.3 给后续复用的小参数表同样的代码换码速率时只需要改一组参数场景spcWelch窗长重叠说明只看频谱形状412864点数少跑得快实验报告要平滑曲线8256128主瓣仍能看清观察2MHz附近细节16512256分辨率最高把AMI_HDB3.m里的这几个参数调到对应范围基本不会出现坐标对不上、谱线乱跳的情况。本文还有配套的精品资源点击获取
返回列表