当前位置:   article > 正文

【OFDM】基于 802.11a 的 OFDM 系统仿真实验 (Matlab 实现+原理+注释)_leo ofdma 优化配置 仿真

leo ofdma 优化配置 仿真

目录

前言

一、Basic OFDM

1.1 系统流程

1.2 基本步骤

1.2.1 系统参数

1.2.2 训练序列

1.2.3 信道编码与信道译码

1.2.4 调制与解调

1.2.5 插入导频

1.2.6 映射与解映射

1.2.7 循环前缀

二、Pkt detect + Freq Sync + Time Sync + ChaEst

2.1 包检测 (Packet Detection)

2.1.1 实现原理

2.1.2 代码实现

2.1.3 仿真结果

2.2 频率同步 —— 基于自相关的方法

2.2.1 实现过程

2.2.3 仿真结果  

2.3 时间精同步

2.3.1 实现原理

2.3.2 实现代码

2.3.3 仿真结果

2.4 信道估计

2.4.1 实现原理

2.4.2 实现代码(关键语句)

2.4.3 仿真结果

三、Complete OFDM System

3.1 仿真步骤

3.2 仿真结果

3.3 实现代码

四、补充材料

4.1 rx_timed_to_freqd.m

4.2 tx_freqd_to_timed.m

4.3 frequencysync.m

4.4 finetimesync.m

参考文献


前言

        光阴似箭,岁月如梭,还记得当时上完 OFDM 就未再作理会了。如今临界毕业,整理学习资料时发现了 OFDM 相关内容,遂加以整理,并在 CSDN 纪念一下。当时 OFDM 是英文授课的,学习资料同理也都是英文的,加之 OFDM 中有许多专业名词术语、网上资料层次不齐,以致学来一头雾水,不得要领。好在后来自己整理了不少中文学习资料和代码,很好地加深了对 OFDM 的理解,遂感叹 “实践出真知”。而此处将分享某次基于 802.11a 的 OFDM 实验报告稿件 (因此没失踪的原件详细),后续有机会还会上传更多资料。(更新:部分资料链接)  (更新:有些遗漏的内容,会根据读者反馈补充到文末的补充材料中,所以不下载根本不影响)

        本文主要分为四部分介绍,同时给出呕心沥血的实现 (含注释)。(注:需要 MATLAB 2016a 及更高版本)

  • 第一部分:实现了一个 OFDM 基本系统。关键词:前导训练序列 (Preamble training symbol)、长/短训练序列 (Long/Short training symbol)、卷积码、4QAM 调制、导频 (Pilot)、映射 (Mapping) 与逆/解映射 (Demapping)、循环前缀 (CP) 等。
  • 第二部分:实现了对 OFDM 系统进行功能拓展。关键词:包检测 (Packet detection)、频率同步、时间精同步、信道估计等。
  • 第三部分:将各功能集成到统一的系统中,并给出实现过程及注释。
  • 第四部分:根据需求补充的若干函数代码

        事实上,学习的原理主要来自《宽带无线通信OFDM技术 - 第二版》和《OFDM移动通信技术原理与应用》这两本书及课件,虽然它们有一定年代了,但基本原理和经典内容等都是通用的、不过时的。网上搜索很容易找到资源下载,建议有不明白的概念就查阅学习一下。

        最后,原本是一字一句敲,可惜效率低下,遂用截图代之 T T。不论如何,如能一字一句读懂,必能豁然开朗,希望对读者有帮助 ^ ^ 。


一、Basic OFDM

1.1 系统流程

1.2 基本步骤

1.2.1 系统参数

1.2.2 训练序列

1.2.3 信道编码与信道译码

1.2.4 调制与解调

1.2.5 插入导频

1.2.6 映射与解映射

1.2.7 循环前缀


二、Pkt detect + Freq Sync + Time Sync + ChaEst

2.1 包检测 (Packet Detection)

2.1.1 实现原理

2.1.2 代码实现

  1. function detected_packet = FindPacket(rx_signal)  
  2.   
  3. win_size = 700;   % 搜索窗大小 (理论上大于噪声长度500就行)   
  4. LTB = 16;   % 每个短训练序列符号长度LTB  
  5.   
  6. % 一次性计算所有相邻符号相关性  
  7. xcorr = rx_signal(1:win_size+2*LTB).* ...  
  8.               conj(rx_signal(1*LTB+1:win_size+3*LTB));  %(732,1)  
  9. % (1:700+2*16)   .*   (1*16+1:700+3*16    =    1;732  .*  17:748  
  10. %-------------------------------------------------------------------------  
  11. % 逐对计算所有相邻符号相关性mn(的分子|Cn|)  
  12. Cn_xcorr = zeros(700,1);  
  13. for i = 1:700  
  14.     recorder = 0;  
  15.     for j = i : (i+2*LTB- 1)       
  16.         recorder = recorder + (xcorr(j+1));        
  17.     end  
  18.     Cn_xcorr(i) = abs(recorder);  
  19. end  
  20. %-------------------------------------------------------------------------  
  21. % 逐对计算所有相邻符号相关性mn(的分母Pn)  
  22. rx_pwr = abs(rx_signal(1*LTB+1 : win_size+3*LTB)).^2 ;   %17-748  
  23. Pn_xcorr = zeros(700,1);  
  24. for i = 1:700  
  25.     recorder = 0;  
  26.     for j = i : (i+2*LTB-1)                    
  27.         recorder = recorder + rx_pwr(j+1);   
  28.     end  
  29.     Pn_xcorr(i) = recorder;  
  30. end  
  31. %-------------------------------------------------------------------------  
  32.                     
  33. % 一次性计算所有相邻符号相关性mn=|Cn|/Pn  
  34. x_len = length(Cn_xcorr);    % 700*1  
  35. mn = Cn_xcorr(1:x_len)./Pn_xcorr(1:x_len);      
  36. plot(mn);    % 绘图  
  37.   
  38. % 判断有无检测到包  
  39. threshold = 0.75;   % 判决门限值     
  40. thres_idx = find(mn > threshold);  % 查询满足条件(相关性大于门限值)元素的id  
  41. if isempty(thres_idx)      
  42.   thres_idx = 1;          
  43. else     
  44.   thres_idx = thres_idx(1);   % 若有多个id满足条件,则取首个作为检测到包的起点  
  45. end  
  46.   
  47. % 根据id取出数据包  
  48. detected_packet = rx_signal(thres_idx:length(rx_signal));    

2.1.3 仿真结果

2.2 频率同步 —— 基于自相关的方法

2.2.1 实现过程

  1. clc;  
  2. fs = 20e6;  
  3. gi = 1/4;                  
  4. fftlen = 64;  
  5. gilen = gi*fftlen;            
  6.   
  7.   
  8. ShortTrain = sqrt(13/6) * [0 0 1+j 0 0 0 -1-j 0 0 0 1+j 0 0 0 -1-j ...  
  9.                        0 0 0 -1-j 0 0 0 1+j 0 0 0 0 0 0 -1-j 0 0 0 ...  
  10.                        -1-j 0 0 0 1+j 0 0 0 1+j 0 0 0 1+j 0 0 0 1+j 0 0].';  
  11.   
  12. short_demap = zeros(641);  
  13. short_demap([7:32 34:59],:) = ShortTrain;  
  14. short_demap([33:64 1:32],:) = short_demap;    
  15. % 将频域的短训练序列转化到时域  
  16. ShortTrain=sqrt(64)*ifft(sqrt(64/52)*short_demap);    
  17. ShortTrain =ShortTrain(1:16);  
  18. transmit=[ShortTrain;ShortTrain;ShortTrain;ShortTrain;ShortTrain;  
  19.           ShortTrain;ShortTrain;ShortTrain;ShortTrain;ShortTrain];  
  20.   
  21. phase=zeros(1,1);  
  22. mse=zeros(1,1);  
  23. error = zeros(1,500);  
  24. snr = 0:1:20;  
  25. for snr_idx = 1:length(snr)  
  26.     for n = 1:500    
  27.         len = length(transmit);   % 计算传输信号长度  
  28.         noise =sqrt(1/(10^(snr(snr_idx)/10))/2)*( randn(len,1)+j*randn(len,1));  
  29.         % 加噪声  
  30.         transmit1 = transmit + noise;   
  31.         % 加频偏 [0:total_length-1]/fs=nTs    ▲f=0.2*fs/fftlen  
  32.         cfo = 0.2*fs/fftlen/fs*[0:len-1];  
  33.         phase_shift = exp(j*2*pi*cfo).';  
  34.         transmit2 = transmit1.*phase_shift;   % 将频偏加到传输的信号上  
  35.   
  36.         LTE = 16;  %长度为16的窗口  
  37.         phase=0;  
  38.           
  39.         for i=1:(len-LTE)       
  40.             %每一个数据与d个数据后的数据共轭相乘,求总和  
  41.             phase=phase+transmit2(i).*conj(transmit2(i+LTE));  
  42.         end   
  43.           
  44.         %求估计出的频偏  
  45.         cfo_est = -angle(phase) / (2*LTE*pi/fs);    
  46.         %求频偏估计误差  
  47.         error(n) = (cfo_est - (0.2*fs/fftlen))/(0.2*fs/fftlen);   
  48.     end  
  49.    
  50. mse(snr_idx) = mean(abs(error).^2);  
  51. end  
  52.   
  53. semilogy(snr,mse,'-o');  
  54. xlabel('SNR/dB');  
  55. ylabel('MSE');  
  56. grid on;  

2.2.3 仿真结果  

2.3 时间精同步

2.3.1 实现原理

2.3.2 实现代码

  1. clear all; clc;  
  2. gi = 1/4;                  
  3. fftlen = 64;  
  4. gilen = gi*fftlen;            
  5.   
  6. ShortTrain = sqrt(13/6) * [0 0 1+j 0 0 0 -1-j 0 0 0 1+j 0 0 0 -1-j ...  
  7.                        0 0 0 -1-j 0 0 0 1+j 0 0 0 0 0 0 -1-j 0 0 0 ...  
  8.                        -1-j 0 0 0 1+j 0 0 0 1+j 0 0 0 1+j 0 0 0 1+j 0 0].';  
  9.   
  10. short_demap = zeros(641);  
  11. short_demap([7:32 34:59],:) = ShortTrain;  
  12. short_demap([33:64 1:32],:) = short_demap;  
  13. % 将频域的短训练序列转化到时域并进行功率归一化  
  14. ShortTrain=sqrt(64)*ifft(sqrt(64/52)*short_demap);   
  15. ShortTrain =ShortTrain(1:16);  
  16. short_train_blks=[ShortTrain;ShortTrain;ShortTrain;ShortTrain;ShortTrain;  
  17.                   ShortTrain;ShortTrain;ShortTrain;ShortTrain;ShortTrain];  
  18.   
  19. longTrain = [1 1 -1 -1 1 1 -1 1 -1 1 1 1 1 1 1 -1 -1 1 1 -1 1 -1 1 1 1 ...  
  20.      1 1 -1 -1 1 1 -1 1 -1 1 -1 -1 -1 -1 -1 1 1 -1 -1 1 -1 1 -1 1 1 1 1].';  
  21.    
  22. long_demap = zeros(641);  
  23. long_demap([7:32 34:59],:) = longTrain;  
  24. long_demap([33:64 1:32],:) = long_demap;  
  25.   
  26. % 将频域的长训练序列转化到时域并进行功率归一化  
  27. longTrain=sqrt(64)*ifft(sqrt(64/52)*long_demap);  
  28. % 取长训练序列的后32位作为cp前缀  
  29. long_train_syms = [longTrain(33:64,:); longTrain; longTrain];  
  30. % 构成发送序列  
  31. transmit = [short_train_blks; long_train_syms];   
  32.   
  33. len = length(transmit);  
  34. error = zeros(500,1);  
  35. time_est = zeros(500,1);  
  36. snr = 0:1:10;  
  37. for snr_idx = 1:length(snr)  
  38.     for n = 1:500  
  39.         noise = sqrt(1/(10^(snr(snr_idx)/10))/2)* ...  
  40.                     (randn(len,1)+j*randn(len,1));  
  41.         transmit1 = transmit + noise;   % 加噪声  
  42.         i_matrix=zeros(64,1);  
  43.         j_matrix=zeros(51,1);  
  44.         for j=150:200        % 正确的同步位置在160+32+1处,选择范围包括193  
  45.             for i=1:64       % 长训练序列的64位  
  46.                 % 接受序列与长训练序列共轭相乘  
  47.                 i_matrix(i)=transmit1(j-1+i).*conj(longTrain(i));   
  48.                 % 以每一个bit为起始计算出一个和  
  49.                 j_matrix(j-149)=j_matrix(j-149)+i_matrix(i);  
  50.             end  
  51.         end  
  52.         [a,b] = max(abs(j_matrix));   % 求和最大的,相关程度最高  
  53.   
  54.         time_est(n) = 149 + b;    % 求计算出的同步位置  
  55.         error(n) = time_est(n) - 193;    % 估计位置偏差  
  56.     end  
  57. end  
  58.   
  59. mse(snr_idx)= mean(abs(error).^2); % 求mse  
  60. semilogy(snr,mse);  
  61. xlabel('SNR/dB');  
  62. ylabel('MSE');  
  63. grid on;  

2.3.3 仿真结果

2.4 信道估计

2.4.1 实现原理

2.4.2 实现代码(关键语句)

channel_est = mean(freq_tr_syms,2).*conj(LongTrain);  

2.4.3 仿真结果


三、Complete OFDM System

3.1 仿真步骤

3.2 仿真结果

3.3 实现代码

  1. %% ************************** Preparation part ************************** 
  2. clear all; clc;  
  3.   
  4. % 系统参数  
  5. fs = 8e6;                    % 抽样频率  
  6. ml = 2;                      % 调制阶数 = 2 —— QPSK调制  
  7. NormFactor = sqrt(2/3*(ml.^2-1));  
  8. gi = 1/4;                    % 保护间隔比例 = 1/4  
  9. fftlen = 64;                 % FFT长度 = 64 points/chips  
  10. gilen = gi*fftlen;           % 保护间隔/循环前缀长度 = 16 points/chips  
  11. blocklen = fftlen + gilen;   % OFDM符号长度 = 80 points/chips  
  12.   
  13.   
  14. % 子载波标号  
  15. DataSubcPatt = [1:5 7:19 21:26 27:32 34:46 48:52]'; % 数据子载波位置标号  
  16. PilotSubcPatt = [6 20 33 47]; % 导频子载波位置标号  
  17. UsedSubcIdx = [7:32 34:59]; % 共用52个子载波  
  18.   
  19.   
  20. % 信道编码参数  
  21. trellis = poly2trellis(7,[133 171]); % 卷积码  
  22. tb = 7*5;  
  23. ConvCodeRate = 1/2;       % 码率 = 1/2  
  24.   
  25.   
  26. % 训练序列  
  27. % 短训练序列 (NumSymbols = 52)  
  28. ShortTrain = sqrt(13/6) * [0 0 1+j 0 0 0 -1-j 0 0 0 1+j 0 0 0 -1-j ...  
  29.                        0 0 0 -1-j 0 0 0 1+j 0 0 0 0 0 0 -1-j 0 0 0 ...  
  30.                        -1-j 0 0 0 1+j 0 0 0 1+j 0 0 0 1+j 0 0 0 1+j 0 0].';  
  31. NumShortTrainBlks = 10;     % 短训练序列符号数 = 10  
  32. NumShortComBlks = 16*NumShortTrainBlks/blocklen;    % 160/80=2  
  33.   
  34. % 长训练序列 (NumSymbols = 52)  
  35. LongTrain = [1 1 -1 -1 1 1 -1 1 -1 1 1 1 1 1 1 -1 -1 1 1 -1 1 -1 1 1 1  ...  
  36.      1 1 -1 -1 1 1 -1 1 -1 1 -1 -1 -1 -1 -1 1 1 -1 -1 1 -1 1 -1 1 1 1 1].';  
  37. NumLongTrainBlks = 2;       % 长训练序列符号数 = 2  
  38. %短训练序列加长训练序列共相当于4个OFDM符号  
  39. NumTrainBlks = NumShortComBlks + NumLongTrainBlks;   
  40.   
  41. short_train = tx_freqd_to_timed(ShortTrain);   % 把短训练序列从频域转换到时域  
  42. %plot(abs(short_train));  
  43. short_train_blk = short_train(1:16);    % 每个短训练序列长度16  
  44. % 共10个短训练序列 -- 总长度为10*16=160  
  45. short_train_blks = repmat(short_train_blk,NumShortTrainBlks,1);    
  46.   
  47. long_train = tx_freqd_to_timed(LongTrain);     % 把长训练序列从频域转换到时域  
  48. long_train_syms = [long_train(fftlen-2*gilen+1:fftlen,:);      % 加循环前缀  
  49.                    long_train; long_train];  
  50.  % 构成前导训练序列  
  51. preamble = [short_train_blks; long_train_syms];   
  52.   
  53.   
  54. % 包信息  
  55. NumBitsPerBlk = 48*ml*ConvCodeRate;      
  56. % 每个OFDM符号信息量=48个*2(调制阶数,每个数2bit信息)*卷积码效率  
  57. NumBlksPerPkt = 50;        % 每个包符号数50  
  58. NumBitsPerPkt = NumBitsPerBlk*NumBlksPerPkt;      % 每个包信息量位50*48  
  59. NumPkts = 250;             % 总包数250  
  60.   
  61. % 信道与频偏参数  
  62. h = zeros(gilen,1);  % 定义多径信道  
  63. h(1) = 1; h(3) = 0.5; h(5) = 0.2;   % 3径  
  64. h = h/norm(h);  
  65. CFO = 0.1*fs/fftlen;    % 频偏  
  66.   
  67. % 定时参数  
  68. ExtraNoiseSamples = 500;   % 包前加额外500长度的噪声  
  69.   
  70. %% ************************** Loop start ************************************* 
  71. snr = 0:1:20;                   % 用于检测的信噪比值  
  72. ber = zeros(1,length(snr));     % 0值初始化误码率  
  73. per = zeros(1,length(snr));     % 0值初始化误包率  
  74.   
  75. for snr_index = 1:length(snr)    
  76.     num_err = 0;  
  77.     err = zeros(1,NumPkts);  
  78.     for pkt_index = 1:NumPkts   % 250个包  
  79.   
  80. %% *****************************  Transmitter ********************************  
  81.         % 生成信息序列  
  82.         inf_bits = randn(1,NumBitsPerPkt)>0;     % 生成48*50个信息比特  
  83.         CodedSeq = convenc(inf_bits,trellis);    % 卷积编码  
  84.           
  85.         % 调制  
  86.         paradata = reshape(CodedSeq,length(CodedSeq)/ml,ml); % 分为两路:  
  87.         ModedSeq = qammod(bi2de(paradata),2^ml)/NormFactor;  % 4QAM调制  
  88.           
  89.         mod_ofdm_syms = zeros(52, NumBlksPerPkt);   
  90.         mod_ofdm_syms(DataSubcPatt,:) = reshape(ModedSeq,48,NumBlksPerPkt);  
  91.         %调制后信号48行50列对应子载波id [1:5 7:19 21:26 27:32 34:46 48:52]';  
  92.         mod_ofdm_syms(PilotSubcPatt,:) = 1% 加导频  
  93.           
  94.         % 对OFDM符号做Mapping及IFFT(输出64行50列)  
  95.         tx_blks = tx_freqd_to_timed(mod_ofdm_syms);  
  96.           
  97.         % 加循环前缀  
  98.         % 每个OFDM符号后16位重复放在前面做cp  
  99.         tx_frames = [tx_blks(fftlen-gilen+1:fftlen,:); tx_blks];  
  100.           
  101.         % 并串转换  
  102.         tx_seq = reshape(tx_frames,NumBlksPerPkt*blocklen,1);   % 50*80  
  103.         tx = [preamble;tx_seq];     % 在50个OFDM符号前加前导序列,构成一个包  
  104.           
  105. %% ****************************** Channel *********************************  
  106.         FadedSignal = filter(h,1,tx);     % 包通过多径信道  
  107.         len = length(FadedSignal);  
  108.         noise_var = 1/(10^(snr(snr_index)/10))/2;  
  109.         noise = sqrt(noise_var) * (randn(len,1) + j*randn(len,1));  
  110.         % 加噪声  
  111.         rx_signal = FadedSignal + noise;   
  112.         %包前侧加500长度的噪声  
  113.         extra_noise = sqrt(noise_var) * (randn(ExtraNoiseSamples,1) +  ...  
  114.                       j*randn(ExtraNoiseSamples,1));    
  115.         %包后侧加170长度的噪声  
  116.         end_noise = sqrt(noise_var) * (randn(170,1) + j*randn(170,1));    
  117.           
  118.         % 接收信号  
  119.         rx = [extra_noise; rx_signal; end_noise];   
  120.           
  121.         % 引入频偏  
  122.         total_length = length(rx);   % 计算接收信号长度  
  123.         t = [0:total_length-1]/fs;  
  124.         phase_shift = exp(j*2*pi*CFO*t).';    % 加载波频率偏移  
  125.         rx = rx.*phase_shift;  
  126.   
  127. %% *******************************   Receiver  *****************************  
  128.         % 包检测  
  129.         %rx_signal去掉包前噪声的接收信号,pkt_offset包前噪声的偏移量  
  130.         rx_signal = FindPacket(rx);  
  131.           
  132.         % 频偏估计与纠正  
  133.         %rx_signal补偿频率偏移后的接收信号,cfo_est频率偏移量  
  134.         rx_signal = FrequencySync(rx_signal,fs);   % 注意文末补充材料的 frequencysync.m
  135.           
  136.         % 时间精同步  
  137.         % 时间同步位置  
  138.         fine_time_est = FineTimeSync(rx_signal, long_train);   % 注意文末补充材料的 finetimesync.m
  139.         % Time synchronized signal  
  140.         % 期望去掉短训练序列及长序列前cp后,  
  141.         % 得到长度即长训练序列64*2个+80*50个OFDM符号  
  142.         expected_length = 64*2+80*NumBlksPerPkt;  
  143.         % 去掉短训练序列以及长序列前cp  
  144.         fine_time_est_end = fine_time_est+expected_length-1;  
  145.         sync_time_signal = rx_signal(fine_time_est:fine_time_est_end);  
  146.           
  147.         [freq_tr_syms, freq_data_syms, freq_pilot_syms] = ...  
  148.                                        rx_timed_to_freqd(sync_time_signal);     
  149.         % freq_tr_syms取出长训练序列48行n_data_syms列  
  150.         % freq_data_syms取出信息48行n_data_syms列  
  151.         % freq_pilot_syms取出导频4行n_data_syms列  
  152.           
  153.         % 信道估计  
  154.         % 接收longtrain freq_tr_syms取行!  
  155.         % 平均 H(k) = freq_tr_syms * conj(LongTrainingSyms)    
  156.         channel_est = mean(freq_tr_syms,2).*conj(LongTrain);         
  157.           
  158.         % Data symbols channel correction  
  159.         % 扩展信息序列对应的H(k),同接收OFDM符号个数相同  
  160.         chan_corr_mat = repmat(channel_est(DataSubcPatt), ...  
  161.                                1size(freq_data_syms,2));  
  162.         % 用估计的H(k)共轭乘接受信息序列,得到估计的发送信息序列                     
  163.         freq_data_syms = freq_data_syms.*conj(chan_corr_mat);  
  164.         % 对导频部分做同样的处理  
  165.         chan_corr_mat = repmat(channel_est(PilotSubcPatt), ...  
  166.                                1size(freq_pilot_syms,2));  
  167.         freq_pilot_syms = freq_pilot_syms.*conj(chan_corr_mat);  
  168.   
  169.         % 幅度归一化  
  170.         % 信息序列对应的H(k)绝对值平方行求和  
  171.         chan_sq_amplitude = sum(abs(channel_est(DataSubcPatt,:)).^22);  
  172.         %扩展至估计的发送信息序列列数  
  173.         chan_sq_amplitude_mtx = repmat(chan_sq_amplitude, ...  
  174.                                        1size(freq_data_syms,2));  
  175.         data_syms_out = freq_data_syms./chan_sq_amplitude_mtx;  % 幅度归一化   
  176.          
  177.         % 对导频序列做同样处理  
  178.         chan_sq_amplitude = sum(abs(channel_est(PilotSubcPatt,:)).^22);  
  179.         chan_sq_amplitude_mtx = repmat(chan_sq_amplitude, ...  
  180.                                        1size(freq_pilot_syms,2));  
  181.         pilot_syms_out = freq_pilot_syms./chan_sq_amplitude_mtx;  
  182.   
  183.         phase_est = angle(sum(pilot_syms_out)); % 计算导频  
  184.         phase_comp = exp(-j*phase_est);  
  185.         data_syms_out = data_syms_out.*repmat(phase_comp, 481);  
  186.   
  187.         Data_seq = reshape(data_syms_out,48*NumBlksPerPkt,1); % 48*50  
  188.           
  189.         % 解调  
  190.         DemodSeq = de2bi(qamdemod(Data_seq*NormFactor,2^ml),ml);    
  191.         deint_bits = reshape(DemodSeq,size(DemodSeq,1)*ml,1).';  
  192.           
  193.         % 卷积码译码  
  194.         DecodedBits = vitdec(deint_bits(1:length(CodedSeq)), ...  
  195.                              trellis,tb,'trunc','hard');  % 维特比译码  
  196.         % 误差计算  
  197.         err(pkt_index) = sum(abs(DecodedBits-inf_bits)); % 计算误码个数  
  198.         num_err = num_err + err(pkt_index);  
  199.     end  
  200.     ber(snr_index) = num_err/(NumPkts*NumBitsPerPkt);   % 误码率  
  201.     per(snr_index) = length(find(err~=0))/NumPkts;  % 误包率  
  202. end  
  203. %% 绘制 SNR-BER 和 SNR-PER曲线  
  204. semilogy(snr,ber,'-b.');  
  205. hold on;  
  206. semilogy(snr,per,'-re');  
  207. xlabel('SNR (dB)');  
  208. ylabel('ERROE');  
  209. grid on;  
  210. legend('BER','PER')  

四、补充材料

4.1 rx_timed_to_freqd.m

  1. function [freq_tr_syms, freq_data_syms, freq_pilot_syms] = rx_timed_to_freqd(time_signal)
  2. UsedSubcIdx = [7:32 34:59];
  3. DataSubcIdx = [7:11 13:25 27:32 34:39 41:53 55:59];
  4. PilotSubcIdx = [12 26 40 54];
  5. % Long Training symbols
  6. long_tr_syms = time_signal(1:2*64);
  7. long_tr_syms = reshape(long_tr_syms, 64, 2);
  8. % to frequency domain
  9. freq_long_tr = fft(long_tr_syms)/(64/sqrt(52));
  10. reorder = [33:64 1:32];
  11. freq_long_tr(reorder,:) = freq_long_tr;
  12. % Select training carriers
  13. freq_tr_syms = freq_long_tr(UsedSubcIdx,:);
  14. % Take data symbols
  15. data_syms = time_signal(129:length(time_signal));
  16. data_sig_len = length(data_syms);
  17. n_data_syms = floor(data_sig_len/80);
  18. % Cut to multiple of symbol period
  19. data_syms = data_syms(1:n_data_syms*80);
  20. data_syms = reshape(data_syms, 80, n_data_syms);
  21. % remove guard intervals
  22. data_syms(1:16,:) = [];
  23. % perform fft
  24. freq_data = fft(data_syms)/(64/sqrt(52));
  25. %Reorder pattern is [33:64 1:32]
  26. freq_data(reorder,:) = freq_data;
  27. %Select data carriers
  28. freq_data_syms = freq_data(DataSubcIdx,:);
  29. %Select the pilot carriers
  30. freq_pilot_syms = freq_data(PilotSubcIdx,:);

4.2 tx_freqd_to_timed.m

  1. function time_syms = tx_freqd_to_timed(mod_ofdm_syms)
  2. num_symbols = size(mod_ofdm_syms,2);
  3. UsedSubcIdx = [7:32 34:59];
  4. resample_patt=[33:64 1:32];
  5. syms_into_ifft = zeros(64, num_symbols);
  6. syms_into_ifft(UsedSubcIdx,:) = mod_ofdm_syms;
  7. syms_into_ifft(resample_patt,:) = syms_into_ifft;
  8. % Convert to time domain
  9. time_syms = sqrt(64)*ifft(sqrt(64/52)*syms_into_ifft);

4.3 frequencysync.m

  1. function out_signal = frequencysync(transmit,fs)
  2. len = length(transmit);
  3. pha=zeros(1,1);
  4. D = 16;%长度为16的窗口
  5. pha=0;
  6. for i=1:(len-D-20)
  7. %每个数据与d个数据后的数据共轭相乘,求总和
  8. pha=pha+transmit(19+i).*conj(transmit(i+D));
  9. end
  10. cfo_est = -angle(pha) / (2*D*pi/fs);%求估计出的频偏
  11. cfo = cfo_est/fs*[0:len-1];%加频偏
  12. %[0:total_length-1]/fs=nTs ▲f=0.2*fs/fftlen
  13. phase_shift = exp(-j*2*pi*cfo)';
  14. out_signal= transmit.*phase_shift;%将频偏加到传输的信号上

4.4 finetimesync.m

  1. function fine_time_est = finetimesync(transmit,longTrain);
  2. i_matrix=zeros(64,1);
  3. j_matrix=zeros(71,1);
  4. for j=150:220 %正确的同步位置在160+32+1处,选择范围包括193
  5. for i=1:64 %长训练序列的64位
  6. i_matrix(i)=transmit(j-1+i).*conj(longTrain(i)); %接受序列与长训练序列共轭相乘
  7. j_matrix(j-149)=j_matrix(j-149)+i_matrix(i); %以每一个bit为起始计算出一个和
  8. end
  9. end
  10. [a,b] = max(abs(j_matrix)); %求和最大的,相关程度最高
  11. fine_time_est = 149 +b;

        赠人玫瑰,手有余香~  如果觉得有用,请为我点个赞吧~   ^  ^ 


参考文献

    《OFDM移动通信技术原理与应用 》人民邮电出版社,佟学俭、罗涛,2003

    《宽带无线通信OFDM技术 - 第二版》人民邮电出版社,王文博、郑侃,2007

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/627999
推荐阅读
相关标签
  

闽ICP备14008679号