【通信系统仿真设计】基于Matlab的2Q-FSK移频键控通信系统仿真

前言

感觉有好久一段时间没有发博文了,看到忽然又多了几个人的关注,不发一篇文章过意不去,嘻嘻嘻。疫情在家,之前做过这个移频键控系统的实物实验,但还没有做理论分析,趁着这个机会,把实验仿真做了吧。

仿真原理

为正
为负
信道
信道
低频载波
载波1调制
用户双极性码元
高频载波
载波2调制
混合
发射
加入高斯噪声
接收
低频带通滤波
高频带通滤波
分块比较
码元判决

系统采用两个频率不同,起始相位一致的正弦波信号作为载波。对用户码元判断为正时,使用频率较高的载波;反之则使用频率较低的载波。调制后混合调制结果,然后发射出去。模拟经过高斯信道,人为加入高斯噪声,然后接收。
接收后,把信号分别进行带通数字滤波,两个滤波器的通带频率不一样。滤波后,对结果进行幅度比较,即可码元判决出用户发送的码元。

实验原理

载波

载波波形图如下图所示:
载波信号
低频载波采用100Hz的正弦波,高频载波采用200Hz的正弦波,这两个载波起始相位与结束相位一致。
因为matlab只能处理数字信号,所以需要把以上载波离散化,代码中对这两个载波使用了【采样率:5000Hz,采样点数:50】的参数进行采样,从而把连续载波离散化。

调制

频率调制结果图
图中可见疏密程度不一样的正弦波,每50个点表示一个用户码元,密集部分的高频正弦波表示正码元1,稀疏部分表示负码元-1。这是根据码元的极性,把各个部分的载波连接在一起的结果。

接收端接收

加入高斯噪声
在实验中,模拟高斯信道,人为地给调制结果在解调前加入高斯噪声。以上图片就是调制结果加入高斯噪声的结果。

加噪实现

人为加入噪声使用的是matlab自带的“awgn”函数,该函数可以自动地为数据按照信噪比加上高斯白噪声。代码如下所示:

meanPower = powerCnt(modulat)/length(modulat);
send = awgn(modulat,snr,meanPower);

解调

在加入高斯噪声后,使用双带通滤波器法对信号进行解调。

滤波器

滤波器采用凯塞尔窗函数法设计,产生一个FIR滤波器。
下图是通带为80~120Hz的带通滤波器的分析图。
低频带通滤波器分析图
下图是通带为180~220Hz的带通滤波器的分析图。
高频带通滤波器分析图
可见这两个滤波器在通带处有线性相位特征,使得信号通过时,结果不会出现相位失真。
把接收信号分别与两个滤波器进行卷积,即可得到滤波结果。

滤波实现

滤波使用matlab自带的“conv”函数,把数字滤波器与信号进行卷积,从而得到滤波结果。

	%滤波,接收到的信号与fir滤波器进行卷积
    res_high = conv(send,highFilter);
    res_low = conv(send,lowFilter);

滤波结果图

带通滤波结果图
滤波结果中,两边趋于平滑的部分对于判决是无意义的,所以要按照 码元数量*载波采样数 的结果居中截取有效部分,如下图所示。
截取

码元判决

居中截取
居中截取
高频>低频
高频<低频
低频带通滤波输出
分组
高频带通滤波输出
分组
组内取绝对值求和
组内取绝对值求和
比较
码元判决
正极性码元
负极性码元

把居中截取出来的信号,按照载波一个码元对应采样点的个数分组,对每一组取绝对值求和,高频滤波输出与低频滤波输出的每一个组分别对应比较求和结果,如果高频的求和结果大,则该组被判决成正极性码元;反之则被判决为负极性码元。

实验结果

每个对应的信噪比,传输1万个码元作为测试。
信噪比从-30dB到10dB,以0.1dB为步进进行测试。
误码率随信噪比变化曲线
从实验结果可以看出,误码率曲线呈现S形下滑,在信噪比大于5时,系统基本可以无误码率传输。

实验结果拟合

对实验结果使用罗杰斯蒂(logistic)模型进行拟合。模型公式如下:
y ~ = a 1 + b e − c x \widetilde{y}=\frac{a}{1+be^{-cx}} y =1+becxa
公式中,a、b、c为拟合参数,e为自然常数。
使用MATLAB拟合结果如下:
拟合结果
根据结果可以得到仿真模型通过信噪比估计误码率的经验公式:

General model:
     f(x) = a/(1+b*exp(-c*x))
Coefficients (with 95% confidence bounds):
       a =       49.38  (49.31, 49.45)
       b =       13.52  (13.34, 13.7)
       c =     -0.2842  (-0.2857, -0.2826)

Goodness of fit:
  SSE: 38.88
  R-square: 0.9998
  Adjusted R-square: 0.9998
  RMSE: 0.313

仿真代码

完整代码下载

GitHub:https://github.com/highskyno1/2Q-FSK-simulation
链接:https://pan.baidu.com/s/1pJFMnORXCH8NoEqtR_IvKg?pwd=ixwg
提取码:ixwg

主函数

main.m

%{
    本项目用于移频键控通信系统的仿真
    解调使用双滤波器方案,即对输入的信号分别进行通带不同的两个FIR滤波器,
    对输出进行块判决,实现码元复现。
    2020/4/9 21:20
%}
clear all;
%是否原理展示
%0时表示做误码率随信噪比变化实验
%1时表示原理展示,绘制原理图与分析图
isPlot = 0;
%测试码元数
if isPlot
    %如果绘制原理图,就减少码元数
    codeSize = 5;
else
    codeSize = 1e5;
end
%生成要发送的码元
sourceCode = bipolarGen(codeSize);

%生成两个不同频率的载波信号
%采样率取5000Hz,根据奈奎斯特定理,采样率至少为频率的两倍
sampleRate = 5000;
%采样点数,过大可能会产生寄生扩频,影响实验结果
sampleSize = 50;
%100Hz低频载波
carrierLow = carrierGen(100,sampleRate,sampleSize);
%200Hz高频载波
carrierHigh = carrierGen(200,sampleRate,sampleSize);
%绘制载波图形
if isPlot
    figure(1)
    plot(carrierLow)
    hold on;
    plot(carrierHigh)
    title('载波信号');
    legend('低频载波','高频载波');
end

%%调频调制%%
modulat = modulation(sourceCode,carrierLow,carrierHigh);
if isPlot
    figure(2)
    %绘制调频结果
    plot(modulat)
    title('频率调制结果');
end

%生成80~120Hz的带通滤波器
fcuts = [0 80 120 150]; %定义通带和阻带的频率
mags = [0 1 0];             %定义通带和阻带
devs = [0.1 0.01 0.1];      %定义通带或阻带的纹波系数
lowFilter = getFilter(fcuts,mags,devs,sampleRate);
%生成180~220Hz的带通滤波器
fcuts = [150 180 220 250]; %定义通带和阻带的频率
mags = [0 1 0];             %定义通带和阻带
devs = [0.1 0.01 0.1];      %定义通带或阻带的纹波系数
highFilter = getFilter(fcuts,mags,devs,sampleRate);
%滤波器分析
if isPlot
    figure(4)
    freqz(lowFilter)
    title('低频带通滤波器分析图');
    figure(5) 
    freqz(highFilter)
    title('高频带通滤波器分析图');
end

if ~isPlot
    %开始信噪比
    startSnr = -30;
    %结束信噪比
    endSnr = 10;
    %信噪比测试间隔
    divSnr = 0.1;
    %误码率记录器
    errorRate = zeros(1,(endSnr-startSnr)/divSnr);
    %研究误码率与信噪比的关系,开启多线程
    parfor index = 1:(endSnr-startSnr)/divSnr
        %%通过高斯信道,人为添加高斯噪声%%
        %信噪比(db)
        snr = startSnr + (index-1)*divSnr;
        %平均功率(dbW)
        meanPower = powerCnt(modulat)/length(modulat);
        send = awgn(modulat,snr,meanPower);
        
        %%解调,使用两个带通滤波器%%
        %滤波,接收到的信号与fir滤波器进行卷积
        res_high = conv(send,highFilter);
        res_low = conv(send,lowFilter);
        
        %%一个载波周期内比较绝对幅度%%
        %截取滤波结果中间部分
        low_input = arrayCut(res_low,codeSize*sampleSize);
        high_input = arrayCut(res_high,codeSize*sampleSize);
        %判决
        result = compare(low_input,high_input,sampleSize);
        
        %与发送前生成的码元进行比较,得到正确率
        rightRate = rightRateCnt(result,sourceCode);
        disp(['当前信噪比',num2str(snr),'dBW,','正确率',num2str(rightRate*100),'%']);
        %记录错误率
        errorRate(index) = (1 - rightRate)*100;
    end
    %绘制误码率曲线
    figure(7)
    plot(linspace(startSnr,endSnr,length(errorRate)),errorRate);
    xlabel('信噪比(dB)');
    ylabel('误码率(%)');
    title('误码率随信噪比的变化曲线');
else
    %%通过高斯信道,人为添加高斯噪声%%
    %信噪比(db)
    snr = 5;
    %平均功率(dbW)
    meanPower = powerCnt(modulat)/length(modulat);
    send = awgn(modulat,snr,meanPower);
    if isPlot
        figure(3)
        %绘制噪声结果
        title('接收端接收到的波形');
        plot(send);
    end
    
    %%解调,使用两个带通滤波器%%
    %滤波,接收到的信号与fir滤波器进行卷积
    res_high = conv(send,highFilter);
    res_low = conv(send,lowFilter);
    if isPlot
        figure(6)
        plot(res_low)
        hold on;
        plot(res_high)
        title('滤波结果');
        legend('低频带通滤波输出','高频带通滤波输出');
    end
end

双极性码生成模块

bipolarGen.m

function [code] = bipolarGen(size)
%bipolarGen 产生指定长度的二进制双极性码元数组
%   码元的产生采用随机函数
    foo = rand(1,size);
    for i = 1:length(foo)
        if foo(i) > 0.5
            foo(i) = 1;
        else
            foo(i) = -1;
        end
    end
    code = foo;
end

载波生成模块

carrierGen.m

function [res] = carrierGen(freq,sampleRate,size)
%carrierGen 产出载波
%   参数:freq:频率 sampleRate:采样率 size:载波长度
    n=0:size-1;
    t=n/sampleRate;%时间序列
    res=sin(2*pi*freq*t);
end

调制模块

modulation.m

function [res] = modulation(code,carrierLow,carrierHigh)
%modulation 调频调制函数
%   参数: code:码元 carrierLow:低频载波 carrierHigh:高频载波
    res = zeros(1,length(code)*length(carrierLow));
    for i = 1:length(code)
        if code(i) > 0
            res((i-1)*length(carrierLow)+1:i*length(carrierLow)) = carrierHigh;
        else
            res((i-1)*length(carrierLow)+1:i*length(carrierLow)) = carrierLow;
        end
    end     
end

滤波器生成器

getFilter.m

function result = getFilter(fcuts,mags,devs,freq)
%getFilter 获取切尔雪夫等幅纹滤波器
%   fcuts:定义通带和阻带的频率
%   mags:定义通带和阻带
%   devs:定义通带或阻带的纹波系数
%   freq:采样率
%{
    demo
    fcuts = [200 900 1100 2000]; %定义通带和阻带的频率
    mags = [1 0 1];             %定义通带和阻带
    devs = [0.1 0.01 0.1];      %定义通带或阻带的纹波系数
%}
    [n,Wn,beta,ftype] = kaiserord(fcuts,mags,devs,freq);  %计算出凯塞窗N,beta的值
    result = fir1(n,Wn,ftype,kaiser(n+1,beta),'noscale');   %生成滤波器
end

功率计算模块

powerCnt.m

function res = powerCnt(input)
%powerCnt 功率计算函数
%参数 input:需要计算功率的数组
    res = 10*log10(sum(input.*input));
end

数组居中截取模块

arrayCut.m

function res = arrayCut(array,size)
%arrayCut 根据需要的长度,居中截取数组
%   因为在FIR滤波之后,结果会增长,对于解调来说,
%   滤波卷积结果两端的部分是多余的,应该去除。
    start = floor((length(array)-size)/2+1);
    res = array(start:start+size-1);
end

码元判决模块

compare.m

function [res] = compare(inputLow,inputHigh,samplePoint)
%compare 比较一个周期内的低通与高通的输出,并通过判决还原出原波形
%   inputLow:低通滤波器的输出
%   inputHigh:高通滤波器的输出
%   samplePoint:载波的采样点数
    %初始化结果数组
    res = zeros(1,length(inputLow)/samplePoint);
    for i = 1:length(inputLow)/samplePoint
        low_amp = sum(abs(inputLow((i-1)*samplePoint+1:i*samplePoint)));
        high_amp = sum(abs(inputHigh((i-1)*samplePoint+1:i*samplePoint)));
        if(low_amp > high_amp)
            res(i) = -1;
        else
            res(i) = 1;
        end
    end
end

正确率计算模块

rightRateCnt.m

function res = rightRateCnt(arg0,arg1)
%rightRateCnt 统计两个数组的相识程度
    rightCnt = 0;
    for i = 1:length(arg0)
        if(arg0(i) == arg1(i))
            rightCnt = rightCnt + 1;
        end
    end
    res = rightCnt / length(arg0);
end

后语

经过仿真,算是补齐了当年实物实验所缺的东西。本来以为可以很快回到学校,没想到一场疫情,使得开学时间一拖再拖,我过了一个历史上最长的寒假!
之前在“枪战王者”游戏仿真的时候说过要考研,但结果参加了2019年“TI杯”国赛,国赛结束后还有北京的“农建杯”,比完赛后在北京玩了两个星期,那两个星期真的是我大学期间最开心的时间。其实参加国赛前就已经提前对考研失败这一结果做好了心里准备,与考研每天对着一大堆书做对比,国赛才是我内心真正喜欢的。
大四上学期开学了,这也可以说大学期间最失败的事,“保研”失败了!在舍友的动员下,我开始真正的买书,加入考研大军,但奈何课设多,培训多,真正准备考研的时间只有不足两个月!结果数学复习完,英语刷了一套题,政治把考前500题刷完,专业课基本没复习,就这样准备非常不充分的情况下上了考场!
到现在(2020/4/10)真的看到自己考研成绩,尽管国家线还没出来,但估计是没戏了。
考研初试结束后我开始了实习,过年前还可以到公司实地实习,过年后,因为疫情,只能在家远程实习上班,现在也还是一样,已经远程上班两个多月了。说实在的我有点喜欢上了远程上班,不用挤地铁,宅家有熟悉的办公环境。
看着舍友在为考研复试做准备,我在远程上班,心里有种奇怪的感觉,这可能就是马哲所说的:“同一性越强,斗争性就越强”吧。对于考研我已经不太想二战了,考研真的好累,关键是要准备的东西太偏向书面,那不是我感兴趣的。
我真正想要的,其实是该工作就工作,有自己的闲暇时间做一点自己感兴趣的研究,周末一家人去喝茶、闲谈。生活如此足矣!
看到这的都是朋友了吧,点个赞呗

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值