OCDM通信系统设计(三)(信道估计和信道均衡)(MATLAB)

一、相关名词概念简要介绍

1、OCDM

        OCDM信号是正交线性调频波分复用(Orthogonal Chirp Division Multiplexing)(可以去IEEE 官网上搜其原文,原文名字就是Orthogonal Chirp Division Multiplexing),OCDM 信号由Ouyang 于2016 年首次提出。由一组在时域与频域上重叠的啁啾(chirp)信号组成,且每一个啁啾信号在啁啾维度相互正交,在传输时不会互相干扰。因为其在多径传播中具有更好地鲁棒性,所以其被认为是正交频分复用(Orthogonal Frequency Division Multiplexing,OFDM)技术的替代方案。

接下来会讲简单通俗能够理解代码的理解(即便可能说得没那么到位)。

2、信道估计

目的:估计出信道的信道频域响应(CFR),

方法:通过导频信号处理

3、信道均衡

目的:消除因为多径信道产生的频率选择性衰落

方法:通过信道估计出的信道频率响应(CFR),通过MMSE均衡器来使得消除信道频率响应对接收信号影响。

4、信道估计和信道均衡必要性理解

在多径信道下,如果没有信道估计和信道均衡,通信是基本上无法进行的,自己试试就知道了。

二、通信系统框图

在OCDM通信系统设计(二)一节代码中给出的是DFnT解调法,注意这里改用FFT解调器,同时能更容易加入信道均衡。

三、MATLAB代码

%% 2023年12月13日
%% author: YOU
%% OCDM通信系统设计
echo off
close all;
clear;
%********************************************************%
%                       相关参数数据                          %
%********************************************************%
fs = 6.4e3; %基带采样频率,同时也是基带带宽
Ts = 40e-3; %OFDM符号长度
DeltaFreqMin = 1/Ts; %最小子载波间隔(非实际)
Tcp = Ts/4; %保护间隔长度
Tpilot = Ts; %保护间隔长度
Tscp = Ts+Tpilot + Tcp*2; %总符号长度包括导频信号
Ncarrier = 128; %有效子载波数
NIDFnT = fs*Ts; %ifft点数

%********************************************************%
%                       生成数据                          %
%********************************************************%
num_byte=32;

numbers =  0:num_byte-1; 
numbers =  randi([0, 255], 1, num_byte);  %一个数据为一个字节 一个字节8bit
data_num=num_byte*8/2;  %由于进行QPSK映射数据数量为 16*8/2
binaryArray = dec2bin(numbers, 8);
binaryArray = flip(binaryArray, 2);
for i = 1:numel(binaryArray)
    DataArray(i) = bin2dec(binaryArray(floor((i-1)/8)+1,mod(i-1,8)+1));%生成比特流
end
DataArray = reshape(DataArray, 2, data_num);% 使用 reshape 函数将 DataArray 重新排列成 2*64
DataArray = DataArray'; %按顺序一行一行排列,如果不进行转置是按列主序排列,就不对了
DataArray = reshape(DataArray, data_num, 2);%最后会得到左边为低位,两个bit为一行的结果。



%********************************************************%
%                       QPSK映射                          %
%********************************************************%
% 定义Qpsk映射表
Img_QpskMapping_Vector = [-45i,  45i];
Real_QpskMapping_Vector =[-45,45];
% Img_QpskMapping_Vector = [0,0];
% Real_QpskMapping_Vector =[0,0];
MappedData = zeros(1, num_byte*8/4);
% 创建一个新的数组,用于存储Qpsk映射后的值
QpskArray = zeros(1, numel(DataArray) * 2);
row_col=size(DataArray);

%Qpsk16映射
MappedData=zeros(1,NIDFnT);
for i=1:row_col(1)
    real_index=DataArray(i,1);
    img_index=DataArray(i,2);
    MappedData(i*2-1)=Real_QpskMapping_Vector(real_index+1)+Img_QpskMapping_Vector(img_index+1); 
end

MappedData=MappedData.';


%插入导频
Pilot =zeros(NIDFnT,1);
Pilot(1) = 45;



figure(1);
subplot(2,1,1);
plot(real(MappedData));
title('QPSK映射后的实部信号(I路信号)')
subplot(2,1,2);
plot(imag(MappedData));
title('QPSK映射后的虚部信号(Q路信号)')



%********************************************************%
%                       菲捏尔逆变换实现OCDM调制           %
%********************************************************%
%数据信号OCDM调制
SigIn=MappedData;
Phi_1 = zeros(NIDFnT, NIDFnT);
Phi_2 = zeros(NIDFnT, NIDFnT);
for m = 0 : NIDFnT-1
    Phi_1(m+1, m+1) = exp(-1i* pi/4)*exp(1i*(pi/NIDFnT)*m^2);
    Phi_2(m+1, m+1) = exp(1i*(pi/NIDFnT)*m^2);
end
SigOut = zeros(size(SigIn));
for n = 1 : ceil(size(SigIn, 1)/ NIDFnT)
        SigOut((n-1)*NIDFnT + 1 : n*NIDFnT) = conj(Phi_1) * SigIn((n-1)*NIDFnT + 1 : n*NIDFnT);
        SigOut((n-1)*NIDFnT + 1 : n*NIDFnT) = sqrt(NIDFnT) * ifft(SigOut((n-1)*NIDFnT + 1 : n*NIDFnT), NIDFnT);
        SigOut((n-1)*NIDFnT + 1 : n*NIDFnT) = conj(Phi_2) * SigOut((n-1)*NIDFnT + 1 : n*NIDFnT);
end
%导频符号OCDM调制
SigIn  =Pilot;
Pilot_out = zeros(size(SigIn));
for n = 1 : ceil(size(SigIn, 1)/ NIDFnT)
        Pilot_out((n-1)*NIDFnT + 1 : n*NIDFnT) = conj(Phi_1) * SigIn((n-1)*NIDFnT + 1 : n*NIDFnT);
        Pilot_out((n-1)*NIDFnT + 1 : n*NIDFnT) = sqrt(NIDFnT) * ifft(Pilot_out((n-1)*NIDFnT + 1 : n*NIDFnT), NIDFnT);
        Pilot_out((n-1)*NIDFnT + 1 : n*NIDFnT) = conj(Phi_2) * Pilot_out((n-1)*NIDFnT + 1 : n*NIDFnT);
end

SigOut_OCDM=SigOut;
SigOut=SigOut*15;
Pilot_out=Pilot_out*20*15;
figure(2);
subplot(2,1,1);
plot(real(SigOut));
title('菲涅尔逆变换后的OCDM实部信号');
subplot(2,1,2);
plot(imag(SigOut));
title('菲涅尔逆变换后的OCDM虚部信号');

SigOut_CP = [Pilot_out(NIDFnT*3/4+1:NIDFnT);Pilot_out;SigOut(NIDFnT*3/4+1:NIDFnT);SigOut];%加入循环前缀
figure(3);
subplot(2,1,1);
plot(real(SigOut_CP));
title('加入循环前缀后的OCDM实部信号');
subplot(2,1,2);
plot(imag(SigOut_CP));
title('加入循环前缀后的OCDM虚部信号');



%***************************************************************************%
%                       载波调制(将基带信号搬移到通带(频带))                %
%***************************************************************************%
% 载波调制参数
fsw = 96e3;    %采样率
baud_rate=6.4e3; %定义QPSK映射后的码元速率,目的与载波采用率换算后得到插值数,对基带信号进行线性插值

fc = 25.6e+03; %载波频率25.6kHz
tt = 0 : 1/fsw : Tscp-1/fsw;
upcarrier = exp(1i * 2 * pi * fc * tt);
fc = 25.60e+03; %载波频率25.6kHz
downcarrier = exp(-1i * 2 * pi * (fc) * tt);
upcarrier= upcarrier.';
downcarrier = downcarrier.';  %定义下变频载波,.'是操作为了防止 转置后会同时取共轭。
%% 数据帧前-后的chirp信号,用于同步和信道估计
% chirp信号参数
fsw_chirp=96e3;
fl = 22.4e3;
fh = 28.8e3;
B = fh - fl;
Tc = 10e-3;
k = B/Tc;
Tg = 10e-3;

Nchirp = Tc*fsw_chirp;
Ng = Tg*fsw_chirp;
Ng =0;
GP = zeros(Ng, 1);

t=0:1/fsw_chirp:Tc-1/fsw_chirp;
phi=12/16*0.5333*pi;
%phi=0*pi;
lfm_sig = 64*cos(2*pi*fl*t+pi*k*t.^2+phi);
chirp = lfm_sig';


% 插值因子
interpFactor = fsw/baud_rate; % 将采样率增加两倍
t_original = linspace(0, 1, length(SigOut_CP) );
t_new = linspace(0, 1, length(SigOut_CP) * interpFactor);
SigOut_interpolated = interp1(t_original, SigOut_CP, t_new, 'linear');



figure(4);
subplot(2,1,1);
plot(real(SigOut_interpolated));
title('基带信号进行线性插值后的实部波形');
subplot(2,1,2);
plot(imag(SigOut_interpolated));
title('基带信号进行线性插值后的虚部波形');

SigOut_interpolated=conj(SigOut_interpolated');




Sigout_convert=SigOut_interpolated.*upcarrier;
Sigout_convert =Sigout_convert*exp(1i*phi)/16.5;%人为相位偏移
Sigout_convert = [chirp; GP; Sigout_convert]; % reshape成发射向量


figure(5);
plot(real(Sigout_convert));
title('载波调制后的实信号波形');  %这里不管虚部是因为,发射的信号只发实部。

% %***************************************************************************%
% %                       通过信道                                            %
% %***************************************************************************%

SNR =10; % 信噪比为 10dB
samplingFrequency = 96e3; % 采样频率
channel = comm.RayleighChannel(...
    'SampleRate', samplingFrequency, ...
    'PathDelays', [0 1e-4 2e-4 4e-4 6e-4], ... % 五条多径的时延
    'AveragePathGains', [0 -5 -10 -15 -20], ... % 五条多径的平均路径增益
    'MaximumDopplerShift', 0, ...
    'PathGainsOutputPort', true);

Sigout_convert = channel(Sigout_convert);

Sigout_convert = awgn(Sigout_convert, SNR, 'measured');

% %***************************************************************************%
% %                       通过由导频信号设计的匹配滤波器实现同步                    %
% %***************************************************************************%
figure(14);
plot(real(Sigout_convert));
title('接收到的信号');


lfm_sig = 64*cos(2*pi*fl*t+pi*k*t.^2);
chirp1 = lfm_sig';
y=chirp1';
match_filter = fliplr(y); %由导频位置设计的匹配滤波器

match_filter_out=conv(match_filter,real(Sigout_convert));
figure(7);
plot(match_filter_out);
title('匹配滤波器输出')
[maxValue, index] = max(match_filter_out);


figure(12);
plot(match_filter_out);
index=960;
%根据匹配滤波器获得位置
a=index+Ng+1;
b=index+Ng+(Tcp/Ts*256+256)*interpFactor;
c=index+Ng+(Tcp/Ts*256+256)*interpFactor+1;
d=index+Ng+(Tcp/Ts*256+256)*interpFactor*2;
signal_pilot=real(Sigout_convert(a:b));

if b>8640
    pad=zeros(b-8640,1);
    b=8640;
    signal_in=[Sigout_convert(a:d);pad];
else
    signal_in=[Sigout_convert(a:d)];
end




figure(8);
subplot(2,1,1);
plot(real(signal_in));
title('同步后的实部信号');

subplot(2,1,2);
plot(imag(signal_in));
title('同步后的虚部信号');
signal_in=signal_in/24*256;


%***************************************************************************%
%                       接收机接受信号(载波解调)(下变频)                    %
%***************************************************************************%
signal_receive=real(signal_in)*23.4793/248*256;
figure(13)

% %相位偏移校正
phi_correct=-12/16*0.5333*pi;
downcarrier=downcarrier*exp(phi_correct*1i)*128;


subplot(2,1,1);
plot(real(downcarrier));
subplot(2,1,2);
plot(imag(downcarrier));
Sigout_down0=signal_receive.*downcarrier; 
Sigout_down0=Sigout_down0;
figure(23);
plot(real(Sigout_down0));




Hd=load('untitled.mat');      %Hd.mat是通过filterdesigner设计的滤波器参数,采用率6.4e4,Fp:Baudrate/2, Fs:Baudrate
% Sigout_down_Real=filter(Hd.LF.Numerator,1,real(Sigout_down));   %通过理论分析,OCDM的基带带宽为Baudrate/2
% Sigout_down_Imag=filter(Hd.LF.Numerator,1,imag(Sigout_down));   %通过理论分析,OCDM的基带带宽为Baudrate/2
coef=round(fliplr(Hd.LF.Numerator)*100000);
Sigout_down_Real=conv(real(Sigout_down0),fliplr(coef));
Sigout_down_Imag=conv(imag(Sigout_down0),fliplr(coef));

Sigout_down=Sigout_down_Real+Sigout_down_Imag*1i;
figure(6);
subplot(2,1,1);
plot(real(Sigout_down));
title('解调后的基带信号实部');
subplot(2,1,2);
plot(imag(Sigout_down));
title('解调后的基带信号虚部');
% %***************************************************************************%
% %                       同步由低通滤波导致的误差                              %
% %***************************************************************************%
new_index=14+Tcp/Ts*NIDFnT*interpFactor;                                      %14这个参数用于去除滤波器时延偏差
Signal_Pilot=[Sigout_down(new_index:new_index+NIDFnT*interpFactor-1)];

new_index=index-(NIDFnT*2-0.6)*interpFactor;
new_index=21+Tcp/Ts*NIDFnT*interpFactor+NIDFnT*interpFactor+Tcp/Ts*NIDFnT*interpFactor;%21这个参数去除滤波器时延偏差

signal_in=[Sigout_down(new_index:new_index+NIDFnT*interpFactor-1)];
figure(8);
subplot(2,1,1);
plot(real(signal_in));
title('同步后的实部信号');
subplot(2,1,2);
plot(imag(signal_in));
title('同步后的虚部信号');





% ***************************************************************************%
%                       对接收到的信号进行下采样                              %
% ***************************************************************************%
signal_in=signal_in/4000000/272;
t_original = linspace(0, 1, length(signal_in) );
t_new = linspace(0, 1, length(signal_in) /interpFactor);

SigIn = interp1(t_original, signal_in, t_new, 'linear');
SigIn=SigIn(1:NIDFnT);
figure(9);
subplot(2,1,1);
plot(real(SigIn));
title('下采用后信号实部波形')
subplot(2,1,2);
plot(imag(SigIn));
title('下采用后信号虚部波形')

Signal_Pilot=Signal_Pilot/4000000/272;
t_original = linspace(0, 1, length(Signal_Pilot) );
t_new = linspace(0, 1, length(Signal_Pilot) /interpFactor);

SigIn_Pilot = interp1(t_original, Signal_Pilot, t_new, 'linear');
SigIn_Pilot=SigIn_Pilot(1:NIDFnT);

%***************************************************************************%
%                                信道估计                                    %
%***************************************************************************%
 %均衡器选择
 ZF = 0;
 MMSE = 1;
 EQ = MMSE;
 SigIn_Pilot=SigIn_Pilot/25;
 SigIn_Pilot=SigIn_Pilot.';
 figure(20);
 subplot(2,1,1);
 plot(real(SigIn_Pilot));
 subplot(2,1,2);
 plot(imag(SigIn_Pilot));


%DFnT  求解
NDFnT=NIDFnT;
hest = zeros(size(SigIn_Pilot));
for n = 1 : ceil(size(SigIn_Pilot, 1)/ NDFnT)
        hest((n-1)*NDFnT + 1 : n*NDFnT) = Phi_1 * SigIn_Pilot((n-1)*NDFnT + 1 : n*NDFnT);
        hest((n-1)*NDFnT + 1 : n*NDFnT) = fft(hest((n-1)*NDFnT + 1 : n*NDFnT), NDFnT) ./ sqrt(NDFnT);
        hest((n-1)*NDFnT + 1 : n*NDFnT) = Phi_2 * hest((n-1)*NDFnT + 1 : n*NDFnT);
end
figure(21)
subplot(2,1,1);
plot(real(hest))
subplot(2,1,2);
plot(imag(hest))


 AA = diag(fft(hest,NIDFnT)); 
 if EQ == ZF
     G = AA^(-1);%迫零均衡
 else
     G = conj(AA) * (conj(AA)*AA + eye(NIDFnT, NIDFnT))^(-1);
 end

%***************************************************************************%
%                                FFT 解调器                                 %
%***************************************************************************%
SigIn=SigIn.';
SigOut = zeros(size(SigIn));
NDFnT=NIDFnT;
yk = fft(SigIn, NIDFnT);
Phi = zeros(NIDFnT, NIDFnT);
for m = 0 : NIDFnT-1
    Phi(m+1, m+1) = exp(-1i*(pi/NIDFnT)*m^2);
end
SigOut = ifft(G*Phi*yk, NIDFnT);%信道均衡



figure(10);
subplot(2,1,1);
plot(real(SigOut));
title('基带解调信号实部');
subplot(2,1,2);
plot(imag(SigOut));
title('基带解调信号虚部');
% 
% % %***************************************************************************%
% % %                       误码率分析                                            %
% % %***************************************************************************%
% 
% 绘制星座图
for i=1:NDFnT/2
real_part(i) = real(SigOut(i*2-1));
imaginary_part(i) = imag(SigOut(i*2-1));
end
figure(15);
scatter(real_part, imaginary_part, 'filled');
title('星座图');
xlabel('实部');
ylabel('虚部');
grid on;
% 设置坐标轴范围并使坐标轴位于图形中间
axis equal;
axis([-max(abs(real_part)), max(abs(real_part)), -max(abs(imaginary_part)), max(abs(imaginary_part))]);


for i=1:NDFnT
    judge_data=0;
    if real(SigOut(i))>0
       judge_data=judge_data+45;
    else
       judge_data=judge_data-45;
    end
    if imag(SigOut(i))>0
       judge_data=judge_data+45i;
    else
       judge_data=judge_data-45i;
    end
    SigOut(i)=judge_data;
end


error_cnt=0;
for i=1:NDFnT/2
    out(i*2-1)=SigOut(i*2-1)-MappedData(i*2-1);
    if out(i*2-1)~=0
        error_cnt=error_cnt+1;
    end
end
error_cnt
error_rate=(error_cnt)/128
figure(11);
subplot(2,1,1);
plot(real(out));
title('实部误码位置曲线');
subplot(2,1,2);
plot(imag(out));
title('虚部误码位置曲线');









四、结果分析

在10dB信噪比和 5条多径干扰情况下,获得星座图如下。大多情况下没有出现误码。

六、总结

本文设计OCDM通信系统,相比上一章通信系统,信道引入多径干扰,并加上了信道估计和信道均衡方法。最后得到了比较结果,同样这些代码会进行FPGA设计。

  • 11
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值