介绍
QPSK是一种四进制相位调制,具有良好的抗噪特性和频带利用率,广泛应用于卫星链路、数字集群等通信业务。
产生
QPSK信号的正弦载波有4个可能的离散相位状态,每个载波相位携带2个二进制符号,其信号表示式为:
解调
QPSK数字解调包括:模数转换、抽取或插值、匹配滤波、时钟和载波恢复等。
代码
下面代码基于matlab实现了QPSK系统的仿真,系统框图如下。考虑到部分功能需要多次重复使用,设计了一个子程序。主程序负责实现GUI,具体的仿真过程全都在子程序中实现。
主程序
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);
这里转置只是为了方便处理数据,没有实际意义。下面是部分仿真结果。
由于本人才疏学浅,精力也有限,可能有一些做的不好的地方,甚至一些错误。希望大家指正,万分感谢。
有人需要可以自取代码。评论区对一下暗号即可。口令:效法羲和御天马。