前言
本文作为实验结果记录及测试,方便后面回顾所做的工作。本文基于一台电脑和一台 USRP 设备实现了 OFDM 自发和自收功能
一、收发代码
ofdm_tx_rx_test.m
核心代码:
%% USRP initation if strcmp(SYS.Platform, 'N320/N321') radio_tx = comm.SDRuTransmitter(... 'Platform', SYS.Platform, ... 'SerialNum', SYS.Address, ... 'MasterClockRate', SYS.MasterClockRate, ... 'CenterFrequency', SYS.USRPCenterFrequency, ... 'Gain', SYS.USRPGain, ... 'InterpolationFactor', SYS.USRPInterpolationFactor); radio_rx = comm.SDRuReceiver(... 'Platform', SYS.Platform, ... 'SerialNum', SYS.Address, ... 'MasterClockRate', SYS.MasterClockRate, ... 'CenterFrequency', SYS.USRPCenterFrequency, ... 'Gain', SYS.USRPGain, ... 'DecimationFactor', SYS.USRPDecimationFactor, ... 'SamplesPerFrame', SYS.USRPFrameLength, ... 'OutputDataType', 'double'); else error(message('sdru:examples:UnsupportedPlatform',platform)); end radio_tx.ChannelMapping = [1]; % Use both TX channels radio_tx.UnderrunOutputPort = true; radio_rx.ChannelMapping = [2]; % Use both TX channels radio_rx.OverrunOutputPort = true;
二、截取一帧 OFDM
process_ofdm.m
核心代码:
function fft_data = process_ofdm(data_filename, Tx_cd) load(data_filename) % load('rx_recv_test.mat') rxmimo2x2 = rx_recv_test; %% 修改 Ng=64; Nfft=256; N_fft=Nfft; P_f_inter=6; %导频间隔 nn=1:Ng; i=1; for delay=0:5e5 yy(i) = rxmimo2x2(nn+delay)'*(rxmimo2x2(delay+nn+Nfft)); i=i+1; end plot(abs(yy)) val=zeros(1,1010); pos=zeros(1,1010); % 找到第一个峰 [val1,pos1]=max(yy(66910:66930)); val(1)=val1; pos(1)=pos1+66910-1; % 记录每个峰值对应的索引 for cnt=1:1010-1 [val1,pos1]=max(yy(pos(cnt)+250:pos(cnt)+390)); % 250和390是试出来的 val(cnt+1)=val1; pos(cnt+1)=pos1+pos(cnt)+250; end
这里需要手动修改几个参数,按照下面步骤做:
- 注释第 1、2 两行,放开第 3 行
- 在第 17 行打个断点
- 运行程序 process_ofdm.m,其中黄框内的就是我们发送的一帧 OFDM
- 将图片放大,找到其中的第一个峰值,这里是 66923
因此上面程序第 19~22 行的 66910 和 66930 是为了将 66923 峰值索引包含在其范围内
% 找到第一个峰 [val1,pos1]=max(yy(66910:66930)); val(1)=val1; pos(1)=pos1+66910-1;
- 将第 17 行断点取消,运行 process_ofdm.m,保证程序运行无报错
- 放开第 1、2 两行,注释第 3 行
三、执行主函数
在这里我们对传输的 OFDM 进行误码率计算
main.m
核心代码:
%% 插入保护间隔、循环前缀 Tx_cd=[ifft_data(N_fft-N_cp+1:end,:);ifft_data];%把ifft的末尾N_cp个数补充到最前面 %% 相关峰处理 fft_data = process_ofdm(data_filename, Tx_cd); %% 信道估计与插值(均衡) data3=fft_data(1:N_fft,:); Rx_pilot=data3(P_f_station(1:end),:); %接收到的导频 h=Rx_pilot./pilot_seq; H=interp1( P_f_station(1:end)',h,data_station(1:end)','linear','extrap');%分段线性插值:插值点处函数值由连接其最邻近的两侧点的线性函数预测。对超出已知点集的插值点用指定插值方法计算函数值 % factor_64QAM = [3.5361 4.0446 4.7685 5.5782 6.7192 7.6219 8.5716 7.5685 6.4031 4.1531]; %% 信道校正 data_aftereq=data3(data_station(1:end),:)./H; %% 并串转换 data_aftereq=reshape(data_aftereq,[],1); data_aftereq=data_aftereq(1:length(spread_data)); data_aftereq=reshape(data_aftereq,N_sc,length(data_aftereq)/N_sc); %% 解扩 demspread_data = despread(data_aftereq,code); % 数据解扩 %% QPSK/16QAM/64QAM解调 De_Bit = demodulation(demspread_data, MODE); %% 信道译码(维特比译码) trellis = poly2trellis(7,[133 171]); rx_c_de = vitdec(De_Bit,trellis,tblen,'trunc','hard'); %硬判决 %% 计算误码率 [err,Ber2] = biterr(De_Bit(1:length(code_data)),code_data);%译码前的误码率 [err, Ber] = biterr(rx_c_de(1:length(P_data)),P_data);%译码后的误码率
四、运行结果
以发送和接收的前 30 个数据为例:
误码率计算:
五、资源自取
链接:https://mbd.pub/o/bread/ZZqak5xq