有关BPSK、QPSK调制信号的通信链路仿真,以及误码分析

之前简单叙述了一个随机序列如何使用MATLAB中内置函数进行数字调制,但是距离通信链路级仿真还仅仅是准备阶段,要想感受完整的通信仿真过程还有许多精细的模块需要学习。回顾通信的整个过程,大致分为三个部分,即发射机、信道、接收机,这个三个模块又包含了许多的细分的通信处理步骤,任何一个步骤的优化都是对通信技术的促进,只是有些步骤不是非必须的,只是为了满足用户需求而另外增设的(比如通信过程中的加密技术),所以在我们刚开始学习通信仿真的时候可以暂时忽略这些步骤,等学有余力的时候可以扩展我们的知识面而去学习。

这一次,我们主要是结合上次谈到的数字调制,然后增加上通信仿真中一些必要的通信过程,实现一个完整的通信仿真,通过误码曲线,来验证我们的代码书写正确性,并且在此基础上增加一些在通信仿真实验中经常涉及的非必要通信手段,观察这些通信手段的增加对我们的通信系统有何影响。

我们直接上代码,通过代码来谈相关的知识点。(本次代码主要参考知乎上“陈老湿”的讲解)

在开始代码之前,想要说的一点是,在我们代码学习的时候一定要养成好的书写习惯,因为我有时候在GitHub或者IMDN上下载代码学习,辛苦下完之后发现代码写的乱七八糟,瞬间头都大了,所以......

% ===============BPSK系统级仿真实验============
% 时间:2022.3.23
% 作者:华清小学生
% 环境:MATLAB 2019b
% =============================================
clear 
close all
clc

这是我写代码的习惯,最重要的是要写明你的仿真平台,因为有的函数在不同版本的仿真平台上无法运行。

接下来我们也根据发射机——>信道——>接收机的过程进行实验。

首先,设置我们实验需要的参数

% =====================参数设定================ 
sps = 16;           % 上采样倍数
fc = 2000;          % 载波频率
fs = 16000;         % 采样频率

需要注意,采样频率的设置需要满足奈奎斯特准则,这点很重要,忘记的赶紧去翻一下书。

% =======================发射机================
% 产生原始信息序列
signal_bit = [zeros(1,20) ones(1,20) randi([0 1],1,2000)];
% BPSK调制
mod = comm.BPSKModulator();       % bpsk调制器
demod = comm.BPSKDemodulator();   % bpsk解调器
% signal_mod = 2*signal_bit-1;    % 实数变换法
signal_mod = mod(signal_bit.');   % 对信号转置,保证输入为列向量
% 脉冲成型
% 插值(上采样)
up16_signal_mod = upsample(signal_mod.',16);
% 滚降滤波器
r_factor = 0.5;                   % 滚降系数
rcos_fir = rcosdesign(r_factor,6,sps);
% 滚降滤波
rcos_signal = filter(rcos_fir,1,up16_signal_mod);

以上代码中涉及到脉冲成型,其实对于脉冲成型,我是这样认为的,字面理解是,对传输信号进行塑型,更加适应信道特征,其实我们对信号的处理都是为了让传输信号更加适应信道的特征以此来减小信道对信号的损害。在课本中,我们总是假设有一个理想的滤波器,具有陡降的截断特性,可以截断我们的的信号,可是在现实生活中,具有理想截断特性的滤波器几乎无法实现,因此实际应用中大多用一个升余弦滚降滤波器对信号进行截断。

在脉冲成型前通常要进行上采样,上采样的方式一般都是插值。至于为什么插值,我想是增加容错率,我们在接收机部分对信号判决时,都是通过采样来对当前符号判决,上采样过后16个采样点表征原来一个符号,当我们采样发生偏差时,只要不偏离出当前符号采样点范畴,仍然能保证正确判决。

对于上采样函数upsample和滤波器设计函数rcosdesign具体的使用可以help一下,很好理解。

简单看一下滤波器设计函数

h = rcosdesign(0.5,6,8);
stem(h)

第一个参数是滤波器的滚降系数,第二个参数是截止频率,说实话我不太理解这个参数,反正就随意设一个,第三个参数是信号的上采样倍数,这里设置的上采样倍数跟程序中的不一样,如果设置成16倍上采样,图就看不清了。这点记住(6*16)/2=48就行了,后边会用到。

 在上载波之前我们看一下信号的波形。

% 波形观察
subplot(211);
plot(abs(rcos_signal));
title('时域波形');
subplot(212);
plot(abs(fft(rcos_signal)));
title('频域波形');
% 眼图
eyediagram(real(rcos_signal(49:end)),sps);
title('眼图');

 

 简单看一下信号的时域波形和频域波形,你可能看不出来什么,尤其是时域图,真让人一言难尽,但是眼图就好多了,看这卡姿兰大眼睛,眼图是观察信号的一种手段,从“眼睛”张开的程度和饱满性来判断信号的好坏,“眼睛”睁开的越大,越饱满代表信号越好,这跟我们现实生活一样,谁不喜欢水汪汪的大眼睛。你可能注意到我们观察眼图时是从[49:end],这一点便是滚降滤波的原因,由于滤波器的作用,信号延迟了48,这点呼应我上边让你记住的(6*16)/2=48,后边我们还会涉及到这个。如果不处理信号的延迟,那么眼图就会是下边这样,“眼睛”里出现了“红血丝”,那肯定是熬夜过渡了。

接下来便该上载波了,当时学习信号与系统课程是,调制便是乘上一个cos(2*pi*fc*t),其中fc很大,有多大,书上写的是远大于基带信号的频率,这个目的是为了什么,我想这或许跟天线设计有关,电磁波与微波技术中讲到天线的尺寸至少不小于1/4的波长,那么根据波长公式

\lambda =\frac{c}{f}

可知波长与频率成反比,c是波速近似于光速,因此我们可以乘一个高频率的载波信号提升我们的信号频率,来避免天线尺寸的尴尬。附上一张通信基站的照片,我想这里边应该是有天线的吧,我也不太清楚,通信常识短缺啊。

下边我们进行载波发送。

% 载波发送
time = 1:length(up16_signal_mod);
rcos_signal_carrier = rcos_signal.*cos(2*pi*fc.*time/fs);

接下来就进入到信道模块了

% ========================信道=====================
% 加噪声
% 设置信噪比
ebn0 = -5:10;
snr = ebn0 - 10*log10(16);
n = 100;
err_number = zeros(n,length(snr));
bit_err_ratio = zeros(n,length(snr));
for j = 1:n
for i = 1:length(snr)
    % 高斯白噪声信道
    rcos_signal_carrier_noise = awgn(rcos_signal_carrier,snr(i),'measured');

由于后边的接收机部分也是在for循环中执行,所以在参考代码时要注意与后边的结合,别说我for循环没有end

这里有个很重要的点就是信噪比的设置。

 这个是MATLAB文档中的解释,你也别翻译了,重点看公式就行,我给总结了一下,大概就是我手写的这些,不同情况选择不同的信噪比设置,如果设置的不对,你的仿真代码永远不会对,虽然有时候结果看着还行,但是终归差点意思,这都是我在学习过程中经历过的问题。

 字写得丑,莫怪。

接下来就是接收机部分了

%==================接收机=====================
% 载波恢复
% 相干解调
rcos_signal_noise = rcos_signal_carrier_noise.*cos(2*pi*fc.*time/fs);

% 滤波
% 低通滤波器
fir_lp = fir1(128,0.2);     % 截止频率为0.2*(fs/2)
rcos_signal_lp = filter(fir_lp,1,rcos_signal_noise);

解调的方式我们选用比较简单实用的相干解调,原理很简单,就是

Y = H*X+Z

这个是我们通信过程的一般表达式。

假设现在我们的基带信号为cos(2*pi*fs*t)载波信号为cos(2*pi*fc*t)其中fc远大于fs,暂时忽略噪声的存在,则接收天线收到的调制信号为,

cos(2*pi*fs*t)*cos(2*pi*fc*t)

在接收端我们再乘上一个同频同相的载波信号得到

cos(2*pi*fs*t)*cos^{2}(2*pi*fc*t)

利用三角公式变换得到

1/2*cos(2*pi*fs*t)+1/2*cos(2*pi*fs*t)*cos(4*pi*fc*t)

然后我们利用一个低通滤波器滤除高频部分得到cos(2*pi*fs*t),这便是相干解调。

详细的过程可以翻书看一下。

% 匹配滤波(根余弦滚降)
rcos_fir = rcosdesign(0.5,6,sps);
rcos_signal_MF = filter(rcos_fir,1,rcos_signal_lp);

% 选取最佳采样点
decision_pos = 160;  % (96+128+96)/2 = 160  三个滤波器的延迟
% 每个符号选取一个点作为判决
rcos_signal_MF_option = rcos_signal_MF(decision_pos:sps:end);

为了更好的接收信号,对信号准确的判决,我们采用了匹配滤波。

在我们进行判决前,我们要考虑如何能够准确的采取我们想要采样点,这便涉及到最佳采样点,估计最佳采样点的方法有很多,这里通过我们人为粗略估计得出采样点。可以发现最佳采样点设置的是160,为什么是这个位置,我们计算一下,我们总共用了三个滤波器,每个滤波器都会对信号造成延迟,因此(96+128+96)/2=160至于为什么这么计算,说实话我也不清楚,先记住吧。这一点也可以改变一下采样点,观察信号的误码变化。

接下来我们对信号进行判决也就是做数字解调。

% 判决
de_signal_bit = demod(rcos_signal_MF_option.');

% 误码性能对比
[err_number(j,i),bit_err_ratio(j,i)] = biterr(signal_bit(1:length(rcos_signal_MF_option_sign)),de_signal_bit.');


end
end

看见了吧,前边for循环的end在这里。

最后,对实验做误码分析。

err_number_mean = mean(err_number);
bit_err_mean = mean(bit_err_ratio);

% 仿真结果
ber = berawgn(ebn0,'psk',2,'nondiff');
semilogy(ebn0,bit_err_mean,'-*',ebn0,ber,'-+');
xlabel('ebn0');
ylabel('ber');
title('不同信噪比下的误码率曲线(BPSK)');
legend('BPSK实验曲线','BPSK理论曲线');
grid on

我们可以通过对比MATLAB中内置的berawgn函数中对应的调制方式的理论误码率曲线,来验证自己实验的正确性。

可以看出我们的实验误码率曲线与理论误码率曲线基本吻合,证明我们的实验没有问题。下边我们看一下偏离最佳采样点时的误码曲线。

 QPSK信号的仿真过程一样只是数据维度的差异,下面附上误码曲线。

  • 15
    点赞
  • 147
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值