基于matlab的QPSK系统仿真及应用

介绍
QPSK是一种四进制相位调制,具有良好的抗噪特性和频带利用率,广泛应用于卫星链路、数字集群等通信业务。
产生
QPSK信号的正弦载波有4个可能的离散相位状态,每个载波相位携带2个二进制符号,其信号表示式为:
QPSK信号表达式

解调
QPSK数字解调包括:模数转换、抽取或插值、匹配滤波、时钟和载波恢复等。

代码
下面代码基于matlab实现了QPSK系统的仿真,系统框图如下。考虑到部分功能需要多次重复使用,设计了一个子程序。主程序负责实现GUI,具体的仿真过程全都在子程序中实现。
基于matlab的QPSK系统仿真及应用_第1张图片
主程序

clc;close all;clear all;

%---------------------------GUI------------------------------

%------------------------genertae figure---------------------
h0=figure('position',[800 150 600 600],...
    'resize','off',...
    'name','显示各种图形');
%-------------------------genertae axes----------------------
a1=axes('parent',h0,...
'position',[0.1,0.45,0.5,0.5]);
%-------------------------genertae text----------------------
tx_SNR=uicontrol('parent',h0,...
    'style','text',...
    'string','添加噪声后信噪比(dB)',...
    'position',[400 515 100 40]);
tx_N=uicontrol('parent',h0,...
    'style','text',...
    'string','输入序列长度',...
    'position',[400 465 100 40]);
tx_ifconv=uicontrol('parent',h0,...
    'style','text',...
    'string','使用卷积编码',...
    'position',[400 415 100 40]);
tx_rayle=uicontrol('parent',h0,...
    'style','text',...
    'string','添加瑞利衰落',...
    'position',[400 365 100 40]);
tx_ber=uicontrol('parent',h0,...
    'style','text',...
    'string','误码率',...
    'position',[400 315 100 40]);
%-------------------------genertae edit----------------------
ed_SNR=uicontrol('parent',h0,...
    'style','edit',...
    'position',[500 530 60 40]);
ed_N=uicontrol('parent',h0,...
    'style','edit',...
    'position',[500 480 60 40]);
ra_ifconv=uicontrol('parent',h0,...
    'style','radiobutton',...
    'position',[520 430 60 40]);
ra_rayle=uicontrol('parent',h0,...
    'style','radiobutton',...
    'position',[520 380 60 40]);
%----------------------genertae pushbutton-------------------
pt_sv=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[420 280 60 40],...
    'string','保存参数',...
    'callback',[...
    'SNR=str2num(ed_SNR.String);',...
    'ifconv=ra_ifconv.Value;',...
    'rayle=ra_rayle.Value;',...
    'N=str2num(ed_N.String);',...
    '[I,Q,Iwave,Qwave,Ins,Qns,Imt,Qmt,ber,Isam,Qsam,Ijg,Qjg,lencc]=QPSK_c(SNR,ifconv,N,rayle);',...
    'ed_ber.String=ber;']);
ed_ber=uicontrol('parent',h0,...
    'style','edit',...
    'position',[500 330 60 40]);
pt_ber=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[500 280 60 40],...
    'string','误码率曲线',...
    'callback',['cla;',...
    'N=10000;',...
    'rayle=ra_rayle.Value;',...   
    'for SNR=0:2:14,',...
    '[I,Q,Iwave,Qwave,Ins,Qns,Imt,Qmt,ber,Isam,Qsam,Ijg,Qjg,lencc]=QPSK_c(SNR,1,N,rayle);',...
    'ber_conv(SNR/2+1)=ber;',...
    '[I,Q,Iwave,Qwave,Ins,Qns,Imt,Qmt,ber,Isam,Qsam,Ijg,Qjg,lencc]=QPSK_c(SNR,0,N,rayle);',...
    'ber_unconv(SNR/2+1)=ber;',... 
    'end,',...
    'SNR_ideal=0:0.01:14;',...
    'snr=10.^(SNR_ideal./10);',...
    'if rayle==1,',...
    'ber_ideal=1-1./sqrt(1+1./snr);',...
    'else,',...
    'ber_ideal=0.5*erfc(sqrt(snr./2));',...
    'end,',...
    'axis auto;',... 
    'axis([0 14 10^(-5) 10^0]);',... 
    'semilogy((0:2:14),ber_conv,''r'',(0:2:14),ber_unconv,''*'',SNR_ideal,ber_ideal,''black'');',...
    'legend(''使用卷积码误码率'',''实际仿真误码率'',''理论误码率'',''location'',''southwest'');',... 
    'xlabel(''SNR(dB)'');',... 
    'ylabel(''BER'');',...  
    'title(''误码率曲线'');']);

pt_sc_st=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[30 30 100 40],...
    'string','编码后星座图',...
    'callback',[...
    'cla;',...
    'plot(a1,I,Q,''*'');',...
    'title(''编码后星座图'');',...
    'axis(a1,[-2 2 -2 2])']);
pt_wv_st=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[30 80 100 40],...
    'string','成型滤波后星座图',...
    'callback',[...
    'cla;',...
    'plot(a1,Iwave,Qwave,''*'');',...
    'title(''成型滤波后星座图'');',...
    'axis(a1,[-2 2 -2 2])']);
pt_awgn_st=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[30 130 100 40],...
    'string','信道中星座图',...
    'callback',[...
    'cla;',...
    'plot(a1,Ins,Qns,''*'');',...
    'title(''信道中星座图'');',...
    'axis(a1,[-2 2 -2 2])']);
pt_mt_st=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[30 180 100 40],...
    'string','匹配滤波后星座图',...
    'callback',[...
    'cla;',...
    'plot(a1,Imt,Qmt,''*'');',...
    'title(''匹配滤波后星座图'');',...
    'axis(a1,[-2 2 -2 2])']);
pt_sam_st=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[140 30 100 40],...
    'string','抽样后星座图',...
    'callback',[...
    'cla;',...
    'plot(a1,Isam,Qsam,''*'');',...
    'title(''抽样后星座图'');',...
    'axis(a1,[-2 2 -2 2])']);
pt_jg_st=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[250 30 100 40],...
    'string','判决后星座图',...
    'callback',[...
    'cla;',...
    'plot(a1,Ijg,Qjg,''*'');',...
    'title(''判决后星座图'');',...
    'axis(a1,[-2 2 -2 2])']);

pt_bI_eye=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[140 80 100 40],...
    'string','成型滤波后I支路眼图',...
    'callback',[...
    'cla;',...
    'for i=1:fix(lencc/40)-1,',...
    'plot(Iwave((i-1)*40+1:(i-1)*40+41),''b'');',...
    'hold on;',...
    'xlim([1 41]);',...
    'end,',...
    'title(''成型滤波后I支路眼图'');']);
pt_cI_eye=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[140 130 100 40],...
    'string','信道中I支路眼图',...
    'callback',[...
    'cla;',...
    'for i=1:fix(lencc/40)-1,',...
    'plot(Ins((i-1)*40+1:(i-1)*40+41),''b'');',...
    'hold on;',...
    'xlim([1 41]);',...
    'end,',...
    'title(''信道中I支路眼图'');']);
pt_dI_eye=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[140 180 100 40],...
    'string','匹配滤波后I支路眼图',...
    'callback',[...
    'cla;',...
    'for i=1:fix(lencc/40)-1,',...
    'plot(Imt((i-1)*40+1:(i-1)*40+41),''b'');',...
    'hold on;',...
    'xlim([1 41]);',...
    'end,',...
    'title(''匹配滤波后I支路眼图'');']);

pt_bQ_eye=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[250 80 100 40],...
    'string','成型滤波后Q支路眼图',...
    'callback',[...
    'cla;',...
    'for i=1:fix(lencc/40)-1,',...
    'plot(Qwave((i-1)*40+1:(i-1)*40+41),''b'');',...
    'hold on;',...
    'xlim([1 41]);',...
    'end,',...
    'title(''成型滤波后Q支路眼图'');']);
pt_cQ_eye=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[250 130 100 40],...
    'string','信道中Q支路眼图',...
    'callback',[...
    'cla;',...
    'for i=1:fix(lencc/40)-1,',...
    'plot(Qns((i-1)*40+1:(i-1)*40+41),''b'');',...
    'hold on;',...
    'xlim([1 41]);',...
    'end,',...
    'title(''信道中Q支路眼图'');']);
pt_dQ_eye=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[250 180 100 40],...
    'string','匹配滤波后Q支路眼图',...
    'callback',[...
    'cla;',...
    'for i=1:fix(lencc/40)-1,',...
    'plot(Qmt((i-1)*40+1:(i-1)*40+41),''b'');',...
    'hold on;',...
    'xlim([1 41]);',...
    'end,',...
    'title(''匹配滤波后Q支路眼图'');']);

pt_sc_wv=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[360 30 100 40],...
    'string','编码后I路波形图节选',...
    'callback',[...
    'cla;',...
    'plot(a1,I(1:100));',...
    'xlim([1 100]);',...
    'title(''编码后I路波形图节选'');']);
pt_wv_wv=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[360 80 100 40],...
    'string','成型滤波后I路波形图节选',...
    'callback',[...
    'cla;',...
    'plot(a1,Iwave(1:400));',...
    'xlim([1 400]);',...
    'title(''成型滤波后I路波形图节选'');']);
pt_awgn_wv=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[360 130 100 40],...
    'string','信道中I路波形图节选',...
    'callback',[...
    'cla;',...
    'plot(a1,Ins(1:400));',...
    'xlim([1 400]);',...
    'title(''信道中I路波形图节选'');']);
pt_mt_wv=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[360 180 100 40],...
    'string','匹配滤波后I路波形图节选',...
    'callback',[...
    'cla;',...
    'plot(a1,Imt(1:400));',...
    'xlim([1 400]);',...
    'title(''匹配滤波后I路波形图节选'');']);

pt_sc_psd=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[470 30 100 40],...
    'string','编码后I路功率谱',...
    'callback',[...
    'cla;',...
    'periodogram(I);',...
    'axis auto;',...
    'title(''编码后I路功率谱'');']);
pt_wv_psd=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[470 80 100 40],...
    'string','成型滤波后I路功率谱',...
    'callback',[...
    'cla;',...
    'periodogram(Iwave);',...
    'axis auto;',...
    'title(''成型滤波后I路功率谱'');']);
pt_awgn_psd=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[470 130 100 40],...
    'string','信道中I路功率谱',...
    'callback',[...
    'cla;',...
    'periodogram(Ins);',...
    'axis auto;',...
    'title(''信道中I路功率谱'');']);
pt_mt_psd=uicontrol('parent',h0,...
    'style','pushbutton',...
    'position',[470 180 100 40],...
    'string','匹配滤波后I路功率谱',...
    'callback',[...
    'cla;',...
    'periodogram(Imt);',...
    'axis auto;',...
    'title(''匹配滤波后I路功率谱'');']);
    

子程序

%---------------------------calculation function------------------------------
function [I,Q,Iwave,Qwave,Ins,Qns,Imt,Qmt,ber,Isam,Qsam,Ijg,Qjg,lencc] = QPSK_c(SNR,ifconv,N,rayle)
%----SNR is the SNR of awgn singal
%----ifconv is whether to use convolution code
%----N is the length of m sequence
%----I is the in_phase sequence of m sequence
%----Q is the quadrature sequence of m sequence
%----Iwave is the in_phase singal after generating waveform
%----Qwave is the quadrature singal after generating waveform
%----awgnI is the in_phase singal after adding Gaussian channel noise
%----awgnQ is the quadrature singal after adding Gaussian channel noise
%----Imt is the in_phase singal after match filter
%----Qmt is the quadrature singal after match filter
%----ber is the bit error rate
%----Isam is the in_phase singal after sampling
%----Qsam is the quadrature singal after sampling
%----Ijg is the in_phase singal after decision
%----Qjg is the quadrature singal after decision
%----lencc is the length of channel code


%-------------generate binary m sequence-----------
mseq = idinput( N ,'prbs',[0 1],[0 1]);
mseq = mseq.';
lenmseq=length(mseq);


%-----------------channel coding------------------
if ifconv==1
    Trellis=poly2trellis(3,[5,7]);%with convolution code
    code=convenc(mseq,Trellis);
else
    code=mseq;%without convolution code
end


%---------------constellation mapping--------------
lencc=length(code); 
for i=1:lencc
    if rem(i,2)==1
        if code(i)==1
            I(fix(i/2)+1)=1;
        else
            I(fix(i/2)+1)=-1;
        end
    else
        if code(i)==1
            Q(fix(i/2))=1;
        else
            Q(fix(i/2))=-1;
        end
    end
end


%------------insert zero with 4 times------------
zerotimes=4;
for i=1:zerotimes*(lencc/2)
    if rem(i,zerotimes)==1
        Iins(i)=I(fix((i-1)/zerotimes)+1);
        Qins(i)=Q(fix((i-1)/zerotimes)+1);
    else
        Iins(i)=0;
        Qins(i)=0;
    end
end


%---generate waveform with square-root raised cosine roll-off filter--
beta=0.5;          %roll-off factor
span=2;            %truncation symbols range
fd=2.5;            %symbol rate
fs=10;             %sample rate
sps=fs/fd;         %each symbol period contains sps samples
shape='sqrt';      %square-root raised c
mtfilt=rcosdesign(beta,span,sps,shape);
Iwave=conv(Iins,mtfilt);
Qwave=conv(Qins,mtfilt);


%------------------add channel noise----------------------- 
if rayle==1
    R=raylrnd(0.5,1,length(Iwave));
    Irl=Iwave.*R;
    Qrl=Qwave.*R;
else
    Irl=Iwave;
    Qrl=Qwave;
end
Ins=awgn(Irl,SNR,-3);%'measured');%,10*log10(pI+pQ));
Qns=awgn(Qrl,SNR,-3);%'measured');%,10*log10(pQ+pQ));


%-------------------------match filter------------------------
Imt=conv(Ins,mtfilt);
Qmt=conv(Qns,mtfilt);


%--------------------sampling and decision--------------------
M=span*zerotimes;  
Ishf=Imt(M:2*lencc+M);
Qshf=Qmt(M:2*lencc+M);
for i=1:(lencc/2)
Isam(i)=Ishf((i-1)*zerotimes+1);
Qsam(i)=Qshf((i-1)*zerotimes+1);
end


%-------------------decode constellation mapping----------------
if rayle==1
    threshold=0;%mean((Ins+Qns)./2)
else
    threshold=0;
end
for i=1:(lencc/2)
    if Isam(i)>=threshold
        Ijg(i)=1;
    else
        Ijg(i)=-1;
    end
    if Qsam(i)>=threshold
        Qjg(i)=1;
    else
        Qjg(i)=-1;
    end
end
for i=1:lencc
    if rem (i,2)==1
        if Ijg(fix(i/2)+1)==1
            convcode_r(i)=1;
        else
            convcode_r(i)=0;
        end
    else
        if  Qjg(fix(i/2))==1
            convcode_r(i)=1;
        else
            convcode_r(i)=0;
        end
    end
end
   

%--------------------channel decoder--------------------------
if ifconv==1
    mseq_r=vitdec(convcode_r,Trellis,15,'trunc','hard');
else
    mseq_r=convcode_r;
end
 
%-----------------calculate bit error rate--------------------
ber=sum(abs(mseq_r-mseq))/lenmseq;
end

单单实现系统仿真是比较简单枯燥,而且对误码率对系统的影响理解也不够直观,大家可以尝试传输文件,对误码率可以理解更深一点。Matlab可以很方便的实现文件读取与存储,这里附上其中一种代码。

file_t=fopen('image1.jpeg','rb');
data=fread(file_t,'bit1');
fclose(file_t);

数据存储在data中。

file_r=fopen('image1_new.jpeg','wb');
data_r=data_r.';
data_r=data_r.*-1;        
fwrite(file_r,data_r,'bit1')
fclose(file_r);

这里转置只是为了方便处理数据,没有实际意义。下面是部分仿真结果。
基于matlab的QPSK系统仿真及应用_第2张图片
基于matlab的QPSK系统仿真及应用_第3张图片
基于matlab的QPSK系统仿真及应用_第4张图片
由于本人才疏学浅,精力也有限,可能有一些做的不好的地方,甚至一些错误。希望大家指正,万分感谢。
有人需要可以自取代码。评论区对一下暗号即可。口令:效法羲和御天马。

你可能感兴趣的:(基于matlab的QPSK系统仿真及应用)