⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 v06_03_dem_2up_arrange.m

📁 完美的OFDM仿真程序MATLAB(带导频),可直接运行
💻 M
📖 第 1 页 / 共 4 页
字号:

wtp(1:Max_symbols)=0;
wtpp(1:Max_symbols)=0;

wnAp=0.05; % 信道幅度响应跟踪的环路带宽
SsAp=0.7;
fAp=1;
G1Ap=2*wnAp*SsAp;
G2Ap=wnAp.^2/fAp;
KsAp=1;

wtAp(1:Max_symbols)=0;
wtAp2(1:Max_symbols)=0;


% 读取发送的数据,与解调出来的数据进行比较
% 这是发送端调制在各个子载波上的原始符号,将解调出来的符号跟其比较可进行误符号率测试
fid=fopen('OFDM_mod_original_data_I_ser_2up_sam_50.dat','r');
Imapped_temp=fscanf(fid,'%f');
Imapped=Imapped_temp';
st=fclose(fid);

fid=fopen('OFDM_mod_original_data_Q_ser_2up_sam_50.dat','r');
Qmapped_temp=fscanf(fid,'%f');
Qmapped=Qmapped_temp';
st=fclose(fid);

% 误符号率测试参数设置
counts_I_error=0;
counts_Q_error=0;
counts_I_total=0;
counts_Q_total=0;



% ------------------------------------------------------------------------------------
% 测试参数设置
error_f_test = -1*0.2/(2*(Nfft)*2); % 模拟加入的频偏量

phase_channel_test(1:256) = 0;  % 模拟加入的信道相位响应
Ap_channel_test(1:256) = 1;     % 模拟加入的信道幅度响应

phase0 = 0; % 模拟加入的初始相位


% ------------------------------------------------------------------------------------
% 读取接收到的i,q两路参数
% 是用malab程序生成的2倍上采样的OFDM时域信号,共50个符号
fidi=fopen('OFDM_mod_I_ser_2up_sam_50.dat','r');
fidq=fopen('OFDM_mod_Q_ser_2up_sam_50.dat','r');



% ------------------------------------------------------------------------------------
% 解调部分
%for s_no = 1:Max_symbols
for s_no = 1:48

    % 加入一定的高斯白噪声
    % 这里matlab函数加入噪声的信噪比与实际的信噪比有一个换算关系
    % SNR(实际)=SNR(这里)+3    
    SNR = 12;
    
    % 信号轮流写入两个缓冲区,每个缓冲区的大小为一个OFDM符号的长度
    if(rem(s_no,2) == 1)
        MI_IN_1=fscanf(fidi,'%f',Ntotal*2*2);
        MQ_IN_1=fscanf(fidq,'%f',Ntotal*2*2);
     
%       I_INnoised_1=MI_IN_1;
% 	    Q_INnoised_1=MQ_IN_1; % 不加高斯白噪声
        
        I_INnoised_1=awgn(MI_IN_1,SNR,'measured');
        Q_INnoised_1=awgn(MQ_IN_1,SNR,'measured'); % 加入高斯白噪声
    else
        MI_IN_2=fscanf(fidi,'%f',Ntotal*2*2);
        MQ_IN_2=fscanf(fidq,'%f',Ntotal*2*2);
        
%     	I_INnoised_2=MI_IN_2;
% 	    Q_INnoised_2=MQ_IN_2; % 不加高斯白噪声
        
        I_INnoised_2=awgn(MI_IN_2,SNR,'measured');
        Q_INnoised_2=awgn(MQ_IN_2,SNR,'measured'); % 加入高斯白噪声         
    end

    % 一个大循环内处理一个OFDM符号长度的数据 
    for i=1:Ntotal*2*2
        % 加入一定的频偏
        i_total = (s_no-1)*Ntotal*2*2 + i;  % 变量 i_total 用来加入模拟频偏,是与解调无关的测试量
        	
        % 这里对2取模,是为了区分两个两个缓冲区,即确认当前是在处理哪个缓冲区内的数据    
        if(rem(s_no,2) == 1)
            % 加入一定的频偏
            I_INnoised_error_f_1(i)=cos(rem(i_total*error_f_test*2*pi+phase0,2*pi))*I_INnoised_1(i) - sin(rem(i_total*error_f_test*2*pi+phase0,2*pi))*Q_INnoised_1(i);           
		    Q_INnoised_error_f_1(i)=sin(rem(i_total*error_f_test*2*pi+phase0,2*pi))*I_INnoised_1(i) + cos(rem(i_total*error_f_test*2*pi+phase0,2*pi))*Q_INnoised_1(i); 
		  
		    IDEMOD_1(i)=I_INnoised_error_f_1(i);
		    QDEMOD_1(i)=Q_INnoised_error_f_1(i);   
        else
            % 加入一定的频偏
            I_INnoised_error_f_2(i)=cos(rem(i_total*error_f_test*2*pi+phase0,2*pi))*I_INnoised_2(i) - sin(rem(i_total*error_f_test*2*pi+phase0,2*pi))*Q_INnoised_2(i);           
		    Q_INnoised_error_f_2(i)=sin(rem(i_total*error_f_test*2*pi+phase0,2*pi))*I_INnoised_2(i) + cos(rem(i_total*error_f_test*2*pi+phase0,2*pi))*Q_INnoised_2(i); 
		  
		    IDEMOD_2(i)=I_INnoised_error_f_2(i);
		    QDEMOD_2(i)=Q_INnoised_error_f_2(i);               
        end
                       
               % 进行内插滤波 
               % 具体算法参考Floyd M. Gardner关于内插器的两篇文章
               % "Interpolation in Digital Modems - Part I: Fundamentals"
               % "Interpolation in Digital Modems - Part II: Implementation and Performance"            
               Ix(1:3) = Ix(2:4);
               Qx(1:3) = Qx(2:4);
               
                % 这里对2取模,是为了区分两个两个缓冲区,即确认当前是在处理哪个缓冲区内的数据 
                if(rem(s_no,2) == 1)
                    Ix(4) = IDEMOD_1(i);
                    Qx(4) = QDEMOD_1(i);
                else
                    Ix(4) = IDEMOD_2(i);
                    Qx(4) = QDEMOD_2(i);
                end
                
	           reg0 = reg;
	           reg = reg - wint;

	           if (reg<=0)    
 
                    
                   % k3是对内插后缓冲区的位置的指示,k3_total则记录了总共处理的内插后的点数
                   % 为了便于仿真和测试,这里使用了变量k3_total
                   % 在matlab仿真程序中,关于k3_total的计算,在ccs程序中将会使用k3来计算,程序会增加一定的复杂性                                                            
                   k3_total = k3_total + 1; 
                   
	               u(k3)=reg0/wint;
	               IV=B*Ix';
	               QV=B*Qx';
	               Upower=[1 u(k3) u(k3).^2];
                   
                   reg=reg+1; 
                   
                   IInter_2(k3)=Upower*IV;                
	               QInter_2(k3)=Upower*QV;	                                            	                                  
	               c_2(k3) = IInter_2(k3) + j*QInter_2(k3); % c_2() 只在仿真程序中出现,便于复数计算
                                    
                        % 调试和测试时观察的中间变量
                        IInter_test(k3_total)=IInter_2(k3);
                        QInter_test(k3_total)=QInter_2(k3);
                   
                        
                   % 检测短训练字到达
                   % 当短训练字相关值大于门限的次数小于预先设置的次数时候,
                   % 认为信号到达检测还没有到达,继续进行到达检测	               
	               if(short_tr_timed < Times_short_should_find)	                   
	                   %if( k3_total > (2*Ng)*2)
                       if( k3_total > 0 )                           
                           short_tr_correlator(k3_total) = 0;
                           short_tr_power(k3_total) = 0;
                           
                           % 进行相关运算以及功率计算
                           % 相关长度为Ng*2
                           for ii=1:1:Ng*2 
                               % 由于缓冲区c_2是循环使用,当数据填到最后一个位置后,重新从第一个位置填起
                               % 所以当k3所指示的位置超出了c_2缓存区的范围时,需要进行取模运算,计算出去k3所对应的缓存区内的实际位置
                               if(k3-2*Ng+ii<=0)
                                   temp_ii = k3-2*Ng+ii+Ntotal*2*2;
                               else
                                   temp_ii = k3-2*Ng+ii;
                               end
                               
                               if(k3-2*Ng-2*Ng+ii<=0)
                                   temp_jj = k3-2*Ng-2*Ng+ii+Ntotal*2*2;
                               else
                                   temp_jj = k3-2*Ng-2*Ng+ii;
                               end
                               
                               short_tr_correlator(k3_total) = short_tr_correlator(k3_total) + c_2(temp_ii)*(c_2(temp_jj))'; % 求相关值
                               short_tr_power(k3_total) = short_tr_power(k3_total) + real(c_2(temp_ii)*(c_2(temp_ii))');     % 求相关长度内信号的能量                               
                           end
                           
	                       short_tr_mm(k3_total) = abs( short_tr_correlator( k3_total) );                          
                           %short_tr_threshold = short_tr_power(k3_total)*(19/20);
                           short_tr_threshold = short_tr_power(k3_total)*(9/10); % 设置一个比较相关值的门限
                                                          
                           % 寻找最后一个极大值点
                           if(k3_total>2)
		                       if(short_tr_threshold < short_tr_mm(k3_total-1))	
                                    if(short_tr_mm(k3_total-1) >= short_tr_mm(k3_total-2)  &  short_tr_mm(k3_total-1) >= short_tr_mm(k3_total))
                                        Timing_short_index(t_short) = k3_total - 1;
                                        short_tr_detected = 1;
                                    end
		                       end
                           end
                           
                                                  
	                   end  % end of if(short_tr_timed < Times_short_should_find)
                       
                       
	                   % 每经过一个短训练字的长度的数据点进行一次判断
	                   if(rem(k3_total,2*Ng) == 0)
	                       if(short_tr_detected == 1)
	                           short_tr_timed = short_tr_timed + 1;	                           

                               % 如果两次检测到大于门限的极大值之间的距离大于一定的距离,认为前面检测到的信号到达错误的,重新开始信号到达检测
	                           if(t_short > 1)
                                   if( Timing_short_index(t_short) - Timing_short_index(t_short-1) > 2*Ng+2*Ng)
	                                   short_tr_timed = 1;
	                               end
	                           end
	                         
                               % 如果短训练字相关值大于门限的次数小于预先设置的次数,相关参数清0,继续进行到达检测
	                           if(short_tr_timed < Times_short_should_find)
	                               short_tr_detected = 0;
	                           end
	                           
	                           t_short = t_short + 1;

	                       end 
	                   end 
	                   
	               end % end of if if(short_tr_timed < Times_short_should_find)
	               	               
	               % 当连续检测到大于门限的极大值的次数达到一定值后,认为信号到达,开始检测长训练字,检测FFT窗口的起始位置
	               if (short_tr_timed == Times_short_should_find)  
                       % 如果符号同步标志表示没有完成符号同步,则继续进行符号同步估计
	                   if(symbol_timed < 1)
	                       
                           PP(k3_total)=0;
                           RR(k3_total)=0;

                           for ii=1:1:Nfft
                               % 由于缓冲区c_2是循环使用,当数据填到最后一个位置后,重新从第一个位置填起
                               % 所以当k3所指示的位置超出了c_2缓存区的范围时,需要进行取模运算,计算出去k3所对应的缓存区内的实际位置
                               if(k3-Nfft+ii<=0)
                                   temp_ii = k3-Nfft+ii+Ntotal*2*2;
                               else
                                   temp_ii = k3-Nfft+ii;
                               end
                               
                               if(k3-Nfft-Nfft+ii<=0)
                                   temp_jj = k3-Nfft-Nfft+ii+Ntotal*2*2;
                               else
                                   temp_jj = k3-Nfft-Nfft+ii;
                               end
                               
                               PP(k3_total) = PP(k3_total) + c_2(temp_ii)*(c_2(temp_jj))';       % 求相关值

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -