理论内容基本在上一堂课讲清楚了,那么现在就该来看仿真程序了!通过程序来进一步的消化位定时算法!
每一次写仿真程序都是一次完善的过程,仿真程序写的再好,它也会出现或多或少的问题,同时还要必须不断地向实际的情况去靠拢,这才是写程序最终的目的仿真,这是基础,最终能够和实际产品应用才是目的,所以我们在学仿真的时候,一定要清楚程序和实际产品最终还有多大的距离。因此,每次写程序都是一个长时间的不断修订的过程!大家如果走上算法研究的道路,务必记住:不断的完善仿真环境是一个漫长的过程,也是不断深化自己理解的过程!
先看看网络上的一段程序!
close all;clear all;
%%************** 程序主体 **************%%
N=20000; % 符号数
K=4; % 每个符号采4个样点
Ns=K*N; % 总的采样点数
w=[0.5,zeros(1,N-1)];
%环路滤波器输出寄存器,初值设为0.5
n=[0.7 zeros(1,Ns-1)];
%NCO寄存器,初值设为0.9
n_temp=[n(1),zeros(1,Ns-1)];
u=[0.6,zeros(1,2*N-1)];
%NCO输出的定时分数间隔寄存器,初值设为0.6
yI=zeros(1,2*N);
%I路内插后的输出数据
yQ=zeros(1,2*N);
%Q路内插后的输出数据
time_error=zeros(1,N);
%Gardner提取的时钟误差寄存器
i=1;
%用来表示Ts的时间序号,指示n,n_temp,nco,
k=1;
%用来表示Ti时间序号,指示u,yI,yQ
ms=1;
%用来指示T的时间序号,用来指示a,b以及w
strobe=zeros(1,Ns);
% 环路滤波器系数
c1=5.41*10^(-3);
c2=3.82*10^(-6);
%%% %%% PSK基带数据 %%% %%%
bitstream=(randi(2,N,1)-1);
psk2=pskmod(bitstream,2);
xI=zeros(1,Ns);
xQ=zeros(1,Ns);
xI(18*N) = real(psk2);
%8倍插值,后面2倍抽取实现输入采样信号是输出插值符号速率的4倍
%即4个采样点确定一个插值
xQ(18*N) = imag(psk2);
% 截短后的根升余弦匹配滤波器
h1 = rcosfir(0.8,[-8,8],4,1,'sqrt');
aI1 = conv(xI,h1);
bQ1 = conv(xQ,h1);
L = length(aI1);
%仿真输入数据
aI = [aI1(22L),0,0]; %2倍抽取
bQ = [bQ1(22L),0,0];
%%%%%%% Gardner算法
ns=length(aI)-2;
while(i
n_temp(i+1) = n(i)-w(ms);
if(n_temp(i+1)>0)
n(i+1)=n_temp(i+1);
else
n(i+1)=mod(n_temp(i+1),1);
% 内插滤波器
FI1 = 0.5*aI(i+2)-0.5*aI(i+1)-0.5*aI(i)+0.5*aI(i-1);
FI2 = 1.5*aI(i+1)-0.5*aI(i+2)-0.5*aI(i)-0.5*aI(i-1);
FI3 = aI(i);
yI(k) = (FI1*u(k)+FI2)*u(k)+FI3;
FQ1 = 0.5*bQ(i+2)-0.5*bQ(i+1)-0.5*bQ(i)+0.5*bQ(i-1);
FQ2 = 1.5*bQ(i+1)-0.5*bQ(i+2)-0.5*bQ(i)-0.5*bQ(i-1);
FQ3 = bQ(i);
yQ(k) = (FQ1*u(k)+FQ2)*u(k)+FQ3;
strobe(k) = mod(k,2);
% 时钟误差提取模块
if(strobe(k)==0)
% 每个符号计算一次时钟误差
if(k>2)
time_error(ms) = yI(k-1)*(yI(k)-yI(k-2))+yQ(k-1)*(yQ(k)-yQ(k-2));
else
time_error(ms) = (yI(k-1)*yI(k)+yQ(k-1)*yQ(k));
end
%环路滤波器,每个数据符号计算一次环路滤波器输出
if(ms>1)
w(ms+1)=w(ms)+c1*(time_error(ms)-time_error(ms-1))+c2*time_error(ms);
else
w(ms+1)=w(ms)+c1*time_error(ms)+c2*time_error(ms);
end
ms=ms+1;
end
k=k+1;
u(k)=n(i)/w(ms);
end
i=i+1;
编辑:jq
全部0条评论
快来发表一下你的评论吧 !