【MATLAB函数系列】fskmod函数参数及源代码详解

本文详细解析了MATLAB的fskmod函数,重点在于理解其相位不连续和相位连续两种调制方式的实现原理。通过源码分析,介绍了如何生成FSK调制信号的相位变化量,并提供了关键代码的解释。内容涵盖函数参数、调制过程和调制信号的生成方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关注回复【fskmod】可看

在这里插入图片描述
在用matlab仿真生成fsk信号时,发现matlab库提供fskmod函数可以直接生成fsk信号,但生成的信号为复信号,于是查看其源码,结果对其原理看了好久都没明白,在网上查询资料也少得可怜,唯一有一篇也是对其中部分代码进行解释,且觉得该原函数提供的方法无法理解,然后文章作者最后进行了改动,得到了他想要的结果(笔者没仔细看,而是主要研究matlab库源码),且只是对参数和部分英文帮助进行了说明,并没有解释核心源码的含义。经过查阅相关资料后,笔者终于明白了其调制原理,现分享如下。

函数原型中重要代码如下:

function y = fskmod(x,M,freq_sep,nSamp,varargin)
  • x:输入信号01比特
  • M:调制进制数,比如2fsk调制M=2,4fsk调制M=4
  • freq_sep:Δf=|f1-f2|,即相邻频率间隔
  • nSamp:nSamp=Fs/RB,即每符号的采样点数
  • varargin:可变参数,第一个为Fs,第二个为phase_cont

核心源码解释:

if (nargin >= 6)
    phase_type = varargin{2};
    %check the phase_type string
    if ~( strcmpi(phase_type,'cont') ||  strcmpi(phase_type,'discont') )
        error(message('comm:fskmod:phaseCont'));
    end
else
    phase_type = 'cont';
end

if (strcmpi(phase_type, 'cont'))
    phase_cont = 1;
else
    phase_cont = 0;
end

FSK调制分为相位不连续和相位连续2种方式,不指定默认的话是相位连续调制。这几句主要使判断Fs后是否还有参数,如果有(也就是>=6),那么判断字符串是’cont’还是’discont’,从而给变量phase_cont赋值为1(连续)或0(不连续)。

[nRows, nChan] = size(x);

获取输入数据的总数,即行数和列数,因此可以是2路或多路信号比特输入。

phaseIncr = (0:nSamp-1)' * (-(M-1):2:(M-1)) * 2*pi * freq_sep/2 * samptime;

在刚看到这一句时,完全想不明白这句是如何来的,更不清楚这句代码的目的是什么。通过查资料,先来看看FSK信号调制的原理。

以2FSK调制为例,信号表达式为

S(t)=m1(t)Acos⁡(2πf1t+φ1)+m2(t)Acos⁡(2πf2t+φ2)S(t)={{m}_{1}}(t)A\cos (2\pi {{f}_{1}}t+{{\varphi }_{1}})+{{m}_{2}}(t)A\cos (2\pi {{f}_{2}}t+{{\varphi }_{2}})S(t)=m1(t)Acos(2πf1t+φ1)+m2(t)Acos(2πf2t+φ2)

式中,m1(t)=∑n=−∞∞bng(t−nTb){{m}_{1}}(t)=\sum\limits_{n=-\infty }^{\infty }{{{b}_{n}}g(t-n{{T}_{b}})}m1(t)=n=bng(tnTb)

m2(t)=∑n=−∞∞bn‾g(t−nTb){{m}_{2}}(t)=\sum\limits_{n=-\infty }^{\infty }{\overline{{{b}_{n}}}g(t-n{{T}_{b}})}m2(t)=n=bng(tnTb)

实际上,在理想情况下,载波振荡的频率是随基带信号线性变化的,此时,调频信号可表示为

s(t)=Acos⁡[2πfct+πΔf∫∞tm′(t)dt′+θc]s(t)=A\cos [2\pi {{f}_{c}}t+\pi \Delta f\int_{\infty }^{t}{{m}'(t)}d{t}'+{{\theta }_{c}}]s(t)=Acos[2πfct+πΔftm(t)dt+θc]

其中, fcf_cfc是未调载波频率,θcθ_cθc是载波的初始相位,Δf\Delta fΔf是相邻频率间隔。

频率调制是用调制信息去控制载波的频率,由于瞬时相位是瞬时频率的积分,在上式中具体体现就是生成一个瞬时相偏πΔf∫∞tm′(t)dt′\pi \Delta f\int_{\infty }^{t}{{m}'(t)}d{t}'πΔftm(t)dt,对其数字化即可变为

pi∗(0:nSamp−1)′∗(−1,+1)∗Δf/Fspi*(0:nSamp-1)'*(-1, +1)* Δf/Fspi(0:nSamp1)(1,+1)Δf/Fs

因此这一句就是初始化一个码元符号内每个采样点信号相位的变化量(正1增加,负1减少)。

phIncrSym = phaseIncr(end,:);

phIncrSym就表示在一个码元结束时相位的总变化量

phIncrSamp = phaseIncr(2,:);

phIncrSamp表示相邻采样点之间的相位变化量

Phase = zeros(nSamp*nRows, nChan);

其中nChan表示输入信号路数,一般情况都是1路。输入信号总码元数为nRowsnChan,所以最后生成的相位总数为每符号的采样点码元总数,即nSampnRowsnChan,该句就是初始化一个变量用来存储最后的相位。主要分为2种情况:

一、相位不连续,此时又可分为2种情况。

(1) 当一个码元持续时间相偏总量πΔf∫∞tm′(t)dt′\pi \Delta f\int_{\infty }^{t}{{m}'(t)}d{t}'πΔftm(t)dt为2π的整数倍即

if ( (~phase_cont) &&( floor(nSamp*freq_sep/2 * samptime) == nSamp*freq_sep/2 * samptime ) )

此时由于相位变化是周期性的,可以直接用以下2句代码生成调制信号的相位y。

exp_phaseIncr = exp(1i*phaseIncr);
y = reshape(exp_phaseIncr(:,x+1),nRows*nSamp,nChan);

(2) 当一个码元持续时间相偏总量πΔf∫∞tm′(t)dt′\pi \Delta f\int_{\infty }^{t}{{m}'(t)}d{t}'πΔftm(t)dt不是2π的整数倍时,当前符号的初始相位是:(前一符号最后采样点相位+每采样点相位变化量)mod 2π,即

OscPhase = zeros(nChan, M);

OscPhase是针对这种情况设置的变量,存放下一符号开始时(第1个采样点)的相位,初始化为0。

OscPhase(iChan,:) = rem(OscPhase(iChan,:) + phIncrSym + phIncrSamp, 2*pi);
ph1 = OscPhase(iChan, x(iSym,iChan)+1);

其中ph1中存放的就是当前符号开始时的相位。

二、相位连续

相位连续时,当前符号开始时(第1个采样点)的相位时:前一符号最后采样点相位+每采样点相位变化量,与相位不连续相比,此处少了模2π运算,即

prevPhase = Phase(nSamp*iSym,iChan) + phIncrSamp(x(iSym,iChan)+1);
ph1 = prevPhase;

综上所述,最后再用统一的方法计算每个采样点的相位

Phase(nSamp*(iSym-1)+1:nSamp*iSym,iChan) = ph1*ones(nSamp,1)+ phaseIncr(:,x(iSym,iChan)+1);

最后,再生成FSK调制信号的正交基带数据

y = exp(1i*Phase);

以上就是整个fskmod函数的关键核心代码解读,得到调制的基带数据之后,再将基带信号数据正交上变频至中频,即乘以 即可。
在这里插入图片描述

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

codersnote

对学生党 赞赏是鼓励也是鞭策!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值