OFDM和OCDM-QAM对应的代码

结果

加入LFM同步信号,通过相关序列确定数据起始点
在这里插入图片描述

QAM-OCDM

%设置发送端bit数据的传输速率,每秒1bit
%1000Hz
%细同步
%16QAM
%OCDM
clc;clear;close all;

carrier_count=100;
symbols_per_carrier=12;  %OCDM符号个数
bits_per_symbol=4;    %OCDM符号的每个子载波上传输的比特数。4bit通常采用16QAM调制
IFFT_bin_length=800;  %FFT长度,也即一个OCDM符号子载波个数
PrefixRatio=1/4;  %循环前缀的比值,即循环前缀与OCDM符号长度的比值,通常在1/6~1/4之间
GI=PrefixRatio*IFFT_bin_length;  %保护间隔的长度,这里为128
beta=1/32;  %升余弦窗的滚降系数
GIP=beta*(IFFT_bin_length+GI);  %循环前缀的长度,这里为20
SNR=30;   %本程序考虑加性高斯白噪声信道,这里信噪比为30dB

%细同步序列
T = 1;  %符号持续时间
fs = 1000;
t = (1:T*fs)/fs;

Kr = 100;
STF = cos(2*pi*100*t+pi*Kr*t.^2);

%------------------OCDM信号的产生------------------------
baseband_out_length=carrier_count*symbols_per_carrier*bits_per_symbol; %计算传输数据总的比特数,10×12×4bit=480bit。
carriers=(1:carrier_count) + (floor(IFFT_bin_length/4) - floor(carrier_count/2)); %计算OCDM符号子载波的序号,carriers中存放的序号是124-133
conjugate_carriers=IFFT_bin_length - carriers + 2;  %计算OCDM符号子载波的序号,conjugate_carries中存放的序号是381-390

baseband_out=round(rand(1,baseband_out_length));  %产生480bit待传输的二进制比特流。
% baseband_out = zeros(1,baseband_out_length);

%16QAM调制并绘制星座图
complex_carrier_matrix=qam16(baseband_out);
%调用子程序qam16进行16QAM调制。将baseband_out中的二进制比特流,每4bit转换为一个16QAM信号,即将二进制比特流每4bit转换为-3-3j,-3+3j,3-3j,3+3j,-1-3j
%-1+3j,1-3j,1+3j,-3-j,-3+j,3-j,3+j,-1-j,-1+j,1-j,1+j中的一个。转换后complex_carrier_matrix为1×120矩阵
complex_carrier_matrix=reshape(complex_carrier_matrix',carrier_count,symbols_per_carrier)';
%转换complex_carrier_matrix中的数据为carrier_count*symbols_per_carrier矩阵,这里为12×10矩阵


 Rs = T/(IFFT_bin_length+GI);
%IFFT,即进行OCDM调制
IFFT_modulation=zeros(symbols_per_carrier,IFFT_bin_length);   %将symbols_per_carrier*IFFT_bin_length矩阵赋0值,这里将20×512矩阵赋0值
%这里512是IFFT的长度,也是OCDM符号的子载波个数
IFFT_modulation(:,carriers)=complex_carrier_matrix; %将20×200的complex_carrier_matrix的数据赋给IFFT_modulation的第29-228列,
%即给512个子载波中的29-229个子载波赋值
IFFT_modulation(:,conjugate_carriers) = conj(complex_carrier_matrix); %将20×200的complex_carrier_matrix的数据赋值给512个子载波中的的282-481个
%子载波这段程序构造了512个子载波的OCDM符号,并且各个子载波上的数据是共轭对称的。这样做的目的是经过IFFT后形成的OCDM符号均为实数。
%另外,在512个子载波中,仅有400个子载波为数据,其余为0值,相当于补0。补零的目的是通常IFFT的长度应该为2的整数次幂
% signal_after_IFFT=ifft(IFFT_modulation,IFFT_bin_length,2);     

%%  菲涅尔变换
Phi_1 = zeros(IFFT_bin_length, IFFT_bin_length);
Phi_2 = zeros(IFFT_bin_length, IFFT_bin_length);
for m = 0:IFFT_bin_length-1
    Phi_1(m+1,m+1) = exp(-1j*pi/4) * exp(1j * pi * m^2 / IFFT_bin_length);
    Phi_2(m+1,m+1) = exp(1j* pi * m^2 / IFFT_bin_length);
end

signal_after_idfnt =  IFFT_modulation * conj(Phi_2);
signal_after_idfnt = ifft(signal_after_idfnt,IFFT_bin_length,2);
signal_after_idfnt =  signal_after_idfnt  * conj(Phi_1);
time_wave_matrix=signal_after_idfnt;


%%  添加循环前缀

XX=zeros(symbols_per_carrier,IFFT_bin_length + GI );
for k=1:symbols_per_carrier
    for i=1:IFFT_bin_length
        XX(k,i+GI)=signal_after_idfnt(k,i);
    end
    for i=1:GI
        XX(k,i)=signal_after_idfnt(k,i+IFFT_bin_length - GI);
%添加循环前缀
    end
    
end
time_wave_matrix_cp=XX;  %带循环前缀与循环后缀的OCDM符号

% figure;stem(1:baseband_out_length,baseband_out);ylim([0,1]);xlabel('n');title('发送数据流');
% figure;plot(complex_carrier_matrix,'*r');axis([-4,4,-4,4]);title('16QAM调制后星座图');grid on;
% 
% figure;plot((0:IFFT_bin_length-1),time_wave_matrix(1,:));grid on;ylabel('Amplitude');xlabel('n');title('一个符号,IFFT时域');
% 
% figure;plot((0:length(time_wave_matrix_cp)-1)*Rs,time_wave_matrix_cp(1,:)); 
% grid on;ylabel('Amplitude');xlabel('Time');title('一个符号,GI,OCDM时域');

% 生成发送信号,并串转换

T_gap = 0.5;
Tx_data_OCDM=reshape(time_wave_matrix_cp',(symbols_per_carrier)*(IFFT_bin_length+GI) ,1)';
Tx_data = [zeros(1,500),STF,zeros(1,T_gap*fs),Tx_data_OCDM,zeros(1,T_gap*fs),STF,];

temp_timel=(symbols_per_carrier)*(IFFT_bin_length+GI);


figure;plot((1:length(Tx_data))/fs,real(Tx_data));   
grid on;ylabel('Amplitude (volts)');xlabel('Time/s');title('OCDM Time Signal')

%播放
% sound(Tx_data, 1000,16);
% [S3,P3,T3,F] = spectrogram(Tx_data, 1000,700, length(Tx_data), 1000);
% figure;imagesc(T3,P3,abs(S3));set(gca, 'YDir', 'normal');
% title('发送信号频谱');xlabel('时间/s');ylabel('f/Hz');


%%
%==============OCDM信号解调===========================
% load("sig_test12.mat");


for i = 1:1000
      Af = Tx_data(1,i:i+1000-1);
      STF_xcor = xcorr(Af,STF);
end
[~, ind] = find(STF_xcor == max(STF_xcor));
Rx_data_OCDM = Tx_data(ind+(1.5*fs):ind+(1.5*fs)+symbols_per_carrier*fs-1);
Rx_data_matrix = reshape(Rx_data_OCDM, IFFT_bin_length+GI,symbols_per_carrier).';

Rx_data_complex_matrix = Rx_data_matrix(:,GI + 1:GI + IFFT_bin_length);
%去掉循环前缀与循环后缀,取出OCDM符号传输的数据
% Y1 = fft(Rx_data_complex_matrix,IFFT_bin_length,2);
signal_after_idfnt =  Rx_data_complex_matrix * Phi_1;
signal_after_idfnt = fft(signal_after_idfnt,IFFT_bin_length,2);
Y1 =  signal_after_idfnt*Phi_2;



%求FFT,即OCDM信号解调
Rx_carriers = Y1(:,carriers);


%% 取出carriers序号对应的子载波上的发送数据,去掉加入的零及共轭对称部分
Rx_phase = angle(Rx_carriers);  %计算接收信号的相位特性
Rx_mag = abs(Rx_carriers);     %计算接收信号的幅度特性
[M,N] = pol2cart(Rx_phase,Rx_mag);   %转换极坐标数据为直角坐标数据
Rx_complex_carrier_matrix = complex(M,N);   %两个直角坐标的实数据为构成复数据


figure;plot(Rx_complex_carrier_matrix,'*r'); 
title('接收数据星座图');grid on

%16QAM解调
Rx_serial_complex_symbols = reshape(Rx_complex_carrier_matrix',size(Rx_complex_carrier_matrix,1)*size(Rx_complex_carrier_matrix,2),1)';
%将矩阵Rx_complex_carrier_matrix转换为1的数组
Rx_decoded_binary_symbols = demoduqam16(Rx_serial_complex_symbols);
%进行16QAM解调
baseband_in = Rx_decoded_binary_symbols;
%将解调恢复的二进制信号存放在baseband_in
%误码率计算
bit_errors = find(baseband_in ~= baseband_out);
%解调恢复的二进制信号与发送二进制信号比较,查找误码
bit_error_count = size(bit_errors,2)   %计算误码个数
ber = bit_error_count/baseband_out_length   %计算误码率

%{
%未加窗发送信号频谱
%对发送数据分段,分段计算频谱,去平均作为OCDM信号的频谱
symbols_per_average=ceil(symbols_per_carrier/3);   
avg_temp_time=IFFT_bin_length *symbols_per_average;    %分成五段,每段的长度
averages = floor(temp_timel/avg_temp_time);
%将发送数据分5段,每段数据长度为avg_temp_time
average_fft(1:avg_temp_time) = 0;  %存放平均后的OCDM信号的谱,先置零
 for a=0:(averages - 1)
     subset_OCDM = Tx_data(((a*avg_temp_time)+1):((a+1)*avg_temp_time));    %分段
     subset_OCDM_f = abs(fft(subset_OCDM));   %对分段后的OCDM信号计算频谱
     average_fft = average_fft + (subset_OCDM_f/averages);  %取平均
 end
 average_fft_log = 20*log10(average_fft+eps(1));   %求对数平均谱
 figure(6);
 plot((0:(avg_temp_time-1))/avg_temp_time,average_fft_log);
 %画未加窗OCDM符号对数平均谱
 grid ons
 axis([0 0.5 -320 max(average_fft_log)])
 ylabel('Magnitude (dB)')
 xlabel('Normalized Frequency (0.5 = fs/2)')
 title('OCDM Signal Spectrum')
%}
% N_fft = 2*1024;
% sig_fft = fftshift(fft(Tx_data(1:1000), N_fft));
% fs = 1000;
% figure;plot((0:N_fft/2-1)/N_fft*fs,abs(sig_fft(N_fft/2+1:end)));
% title('一个符号的频谱');xlabel('f/Hz');
% 

QAM-OFDM

%==============================================
%有可能出错的地方:载波间隔大,共轭转置
%===============================================
%设置发送端bit数据的传输速率,每秒1bit
%1000Hz,细同步,16QAM
clc;clear;close all;

carrier_count=100; %这个程序中OFDM子载波个数为512,其中400即carrier_count*2为数据符号,其余赋值为0
symbols_per_carrier=12;  %每个子载波上的符号数,在这里即为OFDM符号个数
bits_per_symbol=4;    %OFDM符号的每个子载波上传输的比特数。4bit通常采用16QAM调制
IFFT_bin_length=800;  %FFT长度,也即一个OFDM符号子载波个数
PrefixRatio=1/4;  %循环前缀的比值,即循环前缀与OFDM符号长度的比值,通常在1/6~1/4之间
GI=PrefixRatio*IFFT_bin_length;  %保护间隔的长度,这里为128
beta=1/32;  %升余弦窗的滚降系数
GIP=beta*(IFFT_bin_length+GI);  %循环前缀的长度,这里为20
SNR=30;   %本程序考虑加性高斯白噪声信道,这里信噪比为30dB

%细同步序列
T = 1;  %符号持续时间
fs = 1000;
t = (1:T*fs)/fs;

Kr = 100;
STF = cos(2*pi*100*t+pi*Kr*t.^2);



%------------------OFDM信号的产生------------------------
baseband_out_length=carrier_count*symbols_per_carrier*bits_per_symbol; %计算传输数据总的比特数,10×12×4bit=480bit。
carriers=(1:carrier_count) + (floor(IFFT_bin_length/4) - floor(carrier_count/2)); %计算OFDM符号子载波的序号,carriers中存放的序号是124-133
conjugate_carriers=IFFT_bin_length - carriers + 2;  %计算OFDM符号子载波的序号,conjugate_carries中存放的序号是381-390

% baseband_out=round(rand(1,baseband_out_length));  %产生480bit待传输的二进制比特流。
baseband_out = ones(1,baseband_out_length);

%16QAM调制并绘制星座图
complex_carrier_matrix=qam16(baseband_out);
%调用子程序qam16进行16QAM调制。将baseband_out中的二进制比特流,每4bit转换为一个16QAM信号,即将二进制比特流每4bit转换为-3-3j,-3+3j,3-3j,3+3j,-1-3j
%-1+3j,1-3j,1+3j,-3-j,-3+j,3-j,3+j,-1-j,-1+j,1-j,1+j中的一个。转换后complex_carrier_matrix为1×120矩阵
complex_carrier_matrix=reshape(complex_carrier_matrix.',carrier_count,symbols_per_carrier).';
%转换complex_carrier_matrix中的数据为carrier_count*symbols_per_carrier矩阵,这里为12×10矩阵


 Rs = T/(IFFT_bin_length+GI);
%IFFT,即进行OFDM调制
IFFT_modulation=zeros(symbols_per_carrier,IFFT_bin_length);   %将symbols_per_carrier*IFFT_bin_length矩阵赋0值,这里将20×512矩阵赋0值
%这里512是IFFT的长度,也是OFDM符号的子载波个数
IFFT_modulation(:,carriers)=complex_carrier_matrix; %将20×200的complex_carrier_matrix的数据赋给IFFT_modulation的第29-228列,
%即给512个子载波中的29-229个子载波赋值
IFFT_modulation(:,conjugate_carriers) = conj(complex_carrier_matrix); %将20×200的complex_carrier_matrix的数据赋值给512个子载波中的的282-481个
%子载波这段程序构造了512个子载波的OFDM符号,并且各个子载波上的数据是共轭对称的。这样做的目的是经过IFFT后形成的OFDM符号均为实数。
%另外,在512个子载波中,仅有400个子载波为数据,其余为0值,相当于补0。补零的目的是通常IFFT的长度应该为2的整数次幂
signal_after_IFFT=ifft(IFFT_modulation,IFFT_bin_length,2);     %IFFT实现OFDM调制
time_wave_matrix=signal_after_IFFT;

%添加循环前缀

XX=zeros(symbols_per_carrier,IFFT_bin_length + GI );
for k=1:symbols_per_carrier
    for i=1:IFFT_bin_length
        XX(k,i+GI)=signal_after_IFFT(k,i);
    end
    for i=1:GI
        XX(k,i)=signal_after_IFFT(k,i+IFFT_bin_length - GI);
%添加循环前缀
    end
    
end
time_wave_matrix_cp=XX;  %带循环前缀与循环后缀的OFDM符号

figure;stem(1:baseband_out_length,baseband_out);ylim([0,1]);xlabel('n');title('发送数据流');
figure;plot(complex_carrier_matrix,'*r');axis([-4,4,-4,4]);title('16QAM调制后星座图');grid on;

figure;plot((0:IFFT_bin_length-1),time_wave_matrix(1,:));grid on;ylabel('Amplitude');xlabel('n');title('一个符号,IFFT时域');

figure;plot((0:length(time_wave_matrix_cp)-1)*Rs,time_wave_matrix_cp(1,:)); 
grid on;ylabel('Amplitude');xlabel('Time');title('一个符号,GI,OFDM时域');

% 生成发送信号,并串转换

T_gap = 0.5;
Tx_data_ofdm=reshape(time_wave_matrix_cp.',(symbols_per_carrier)*(IFFT_bin_length+GI) ,1).';
Tx_data = [zeros(1,500),STF,zeros(1,T_gap*fs),Tx_data_ofdm,zeros(1,T_gap*fs),STF];
temp_timel=(symbols_per_carrier)*(IFFT_bin_length+GI);


figure;plot((1:length(Tx_data))/fs,real(Tx_data));   
grid on;ylabel('Amplitude (volts)');xlabel('Time/s');title('OFDM Time Signal')

%播放
% sound(Tx_data, 1000,16);
[S3,P3,T3,F] = spectrogram(Tx_data, 1000,700, length(Tx_data), 1000);
figure;imagesc(T3,P3,abs(S3));set(gca, 'YDir', 'normal');
title('发送信号频谱');xlabel('时间/s');ylabel('f/Hz');


%%
%==============OFDM信号解调===========================
% load("sig_test12.mat");


for i = 1:1000
      Af = Tx_data(i:i+1000-1);
      STF_xcor = xcorr(Af,STF);
end
[~, ind] = find(STF_xcor == max(STF_xcor));
Rx_data_ofdm = Tx_data(ind+(1.5*fs):ind+(1.5*fs)+symbols_per_carrier*fs-1);
Rx_data_matrix = reshape(Rx_data_ofdm, IFFT_bin_length+GI,symbols_per_carrier).';

Rx_data_complex_matrix = Rx_data_matrix(:,GI + 1:GI + IFFT_bin_length);
%去掉循环前缀与循环后缀,取出OFDM符号传输的数据
Y1 = fft(Rx_data_complex_matrix,IFFT_bin_length,2);
%求FFT,即OFDM信号解调
Rx_carriers = Y1(:,carriers);


%取出carriers序号对应的子载波上的发送数据,去掉加入的零及共轭对称部分
Rx_phase = angle(Rx_carriers);  %计算接收信号的相位特性
Rx_mag = abs(Rx_carriers);     %计算接收信号的幅度特性
[M,N] = pol2cart(Rx_phase,Rx_mag);   %转换极坐标数据为直角坐标数据
Rx_complex_carrier_matrix = complex(M,N);   %两个直角坐标的实数据为构成复数据


figure;plot(Rx_complex_carrier_matrix,'*r'); 
axis([-4,4,-4,4]);title('接收数据星座图');grid on

%16QAM解调
Rx_serial_complex_symbols = reshape(Rx_complex_carrier_matrix.',size(Rx_complex_carrier_matrix,1)*size(Rx_complex_carrier_matrix,2),1).';
%将矩阵Rx_complex_carrier_matrix转换为1的数组
Rx_decoded_binary_symbols = demoduqam16(Rx_serial_complex_symbols);
%进行16QAM解调
baseband_in = Rx_decoded_binary_symbols;
%将解调恢复的二进制信号存放在baseband_in
%误码率计算
bit_errors = find(baseband_in ~= baseband_out);
%解调恢复的二进制信号与发送二进制信号比较,查找误码
bit_error_count = size(bit_errors,2)   %计算误码个数
ber = bit_error_count/baseband_out_length   %计算误码率

%{
%未加窗发送信号频谱
%对发送数据分段,分段计算频谱,去平均作为OFDM信号的频谱
symbols_per_average=ceil(symbols_per_carrier/3);   
avg_temp_time=IFFT_bin_length *symbols_per_average;    %分成五段,每段的长度
averages = floor(temp_timel/avg_temp_time);
%将发送数据分5段,每段数据长度为avg_temp_time
average_fft(1:avg_temp_time) = 0;  %存放平均后的OFDM信号的谱,先置零
 for a=0:(averages - 1)
     subset_ofdm = Tx_data(((a*avg_temp_time)+1):((a+1)*avg_temp_time));    %分段
     subset_ofdm_f = abs(fft(subset_ofdm));   %对分段后的OFDM信号计算频谱
     average_fft = average_fft + (subset_ofdm_f/averages);  %取平均
 end
 average_fft_log = 20*log10(average_fft+eps(1));   %求对数平均谱
 figure(6);
 plot((0:(avg_temp_time-1))/avg_temp_time,average_fft_log);
 %画未加窗OFDM符号对数平均谱
 grid on
 axis([0 0.5 -320 max(average_fft_log)])
 ylabel('Magnitude (dB)')
 xlabel('Normalized Frequency (0.5 = fs/2)')
 title('OFDM Signal Spectrum')
%}
N_fft = 2*1024;
sig_fft = fftshift(fft(Tx_data(1:1000), N_fft));
fs = 1000;
figure;plot((0:N_fft/2-1)/N_fft*fs,abs(sig_fft(N_fft/2+1:end)));
title('一个符号的频谱');xlabel('f/Hz');

QAM16调制

function [complex_qam_data]=qam16(bitdata)
%16QAM调制子程序,子程序名称:qam16.m
%将二进制数目流转换为16QAM信号
%输入参数:bitdata为二进制数码流
%输出参数:complex_qam_data为16QAM复信号
X1=reshape(bitdata,4,length(bitdata)/4)';    %将二进制数码流以4比特分段
d=1;
%转换4比特二进制码为十进制码1~16,生成mapping映射表中的索引
for i=1:length(bitdata)/4;
    for j=1:4
        X1(i,j) = X1(i,j)*(2^(4-j));
    end
    source(i,1)=1+sum(X1(i,:));
end
%16QAM映射表,该表中存放的是16对,每队两个实数,表示星座位置
mapping=[-3*d 3*d;-d 3*d;d 3*d;3*d 3*d;-3*d d;-d d;d d;3*d d;-3*d -d;-d -d;d -d;3*d -d;-3*d -3*d;-d -3*d;d -3*d;3*d -3*d];
for i=1:length(bitdata)/4;
    qam_data(i,:) = mapping(source(i),:);   %数据映射
end
complex_qam_data=complex(qam_data(:,1),qam_data(:,2));
%组合为复数形式,形成16QAM信号
end

QAM16解调

%16QAM信号的解调子程序,子程序名称:demoduqam16.m
%转换16QAM信号为二进制信号
function [demodu_bit_symble] = demoduqam16(Rx_serial_complex_symbols)
%输入参数:Rx_serial_complex_symbols为接收端接收到的复16QAM信号
%输出参数:demodu_bit_symble为二进制数码流
complex_symbols = reshape(Rx_serial_complex_symbols,length(Rx_serial_complex_symbols),1);
d=1;
mapping=[-3*d 3*d;-d 3*d;d 3*d;3*d 3*d;-3*d d;-d d;d d;3*d d;-3*d -d;-d -d;d -d;3*d -d;-3*d -3*d;-d -3*d;d -3*d;3*d -3*d];
complex_mapping=complex(mapping(:,1),mapping(:,2));
%将数据映射表转换为16QAM信号,即3组合为复数
for i=1:length(Rx_serial_complex_symbols);
    for j=1:16;
        metrics(j) = abs(complex_symbols(i,1) - complex_mapping(j,1));
    end
    [min_metric decode_symble(i)] = min(metrics);
    %将接收数据与标准16QAM信号比,找到差最小的,将其对应恢复成标准的16QAM信号
end
decode_bit_symble=de2bi((decode_symble-1)',4,'left-msb');
%16QAM转为二进制
demodu_bit_symble=reshape(decode_bit_symble',1,length(Rx_serial_complex_symbols)*4);    %转换为一行
end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值