基于MATLAB的FM调制解调
Posted 朽月
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于MATLAB的FM调制解调相关的知识,希望对你有一定的参考价值。
基于MATLAB的FM调制解调
参考文献
[1]、V3学院——尤老师(微信号:15921999232) (此博客有不少借鉴尤老师的内容,通过此界面或联系我购买尤老师的FPGA就业课或软件无线电课程会有优惠)
[2]、网易云课堂
项目简述
好久没写博客了,因为这段时间太忙,熟悉博客的同学都应该知道,我的博客每一篇都干货慢慢,从来不水博客。因为自己就是信号处理专业的学生所以对信号与通信的知识比较了解。最近学习了尤老师的FM调制,感觉对调制的原理有了更进一步的理解,这里想把自己的一些理解放出来做个记录以及载波恢复的扩展,想系统学习软件无线电的同学可以联系尤老师。 这个系列我将分为两个章节来完成,一个是载波已知的情况下的相干解调,另一篇博客关于如何从调制之后的信号恢复出载波信号。这篇博客我们讲解基于MATLAB的FM调制解调,这篇文章我们主要分为FM的调制与载波已知情况下的解调。
先验知识:
1、通信原理——忘记的同学可以翻看一下通信原理的课本,这篇博客中的代码将于书本上面的模型一摸一样。
本次实验所用到的软件环境如下:
1、MATLAB 2015b
FM调制数学模型
FM 调频是使载波的频率随调制信号的大小变化而变化, 而振幅保持不变的调制方式。 因为已调信号反映出载波矢量角度上的变化,所以又被称为调角(这里要重点区分一下FM与PM之间的联系与区别)。
上面最重要的知识是基带信号与瞬时频率偏移成线性对应关系 。通过这个知识瞬时频率偏移等于基带信号的线性放大,通过这句话可以直接确定瞬时频率偏移与基带信号的关系,进而确定最终调制之后信号的表达式。
那么首先以余弦信号的调制解调过程来讲解并且扩展到一般信号中去:
这里对于绝大多数同学不理解的一个地方是,连续域的积分变成了离散域的累加操作,这是符合离散数学原理的,如下:
这里的
k
f
k_f
kf被称为调频灵敏度,是FM中最常出现的一个信号,相信绝大多数的同学不明白调频灵敏度的含义。调频灵敏度说白了就是一个收缩因子,这个因子主要作用是线性控制调制信号所引起的瞬时频率偏移。
将上式转换为IQ调制,如下图:
在MATLAB与FPGA中
s
i
n
(
w
t
)
、
c
o
s
(
w
t
)
sin(wt)、cos(wt)
sin(wt)、cos(wt)主要式使用DDS产生的信号,那么这里就需要知道如何利用DDS产生如下信号:
1
、
s
i
n
(
w
c
t
)
1、sin(w_ct)
1、sin(wct)
2
、
c
o
s
(
w
c
t
)
2、cos(w_ct)
2、cos(wct) 3、
c
o
s
(
k
f
∗
∑
m
(
τ
)
)
cos(k_f*\\sum m(\\tau ))
cos(kf∗∑m(τ)) 4、
c
o
s
(
k
f
∗
∑
m
(
τ
)
)
cos(k_f*\\sum m(\\tau ))
cos(kf∗∑m(τ))。
这里需要注意,上述信号的产生使用MATLAB非常简单,但是我们之后需要进一步硬件实现该算法,那么进行MATLAB算法验证的失手应该尽可能逼近硬件实现。从博客之前的文章不难了解,FPGA实验正余弦波有两种方式,一种是使用DDS的方式控制频率与相位控制字产生,另一种是使用CORDIC算法。这里使用的MATLAB代码主要尽可能接近DDS的产生方式,如果同学们对DDS的原理不了解可以查看博主之前的文章,这里不再赘述。
FM调制代码
经过上面关于FM调制原理的介绍,相信同学们对FM调制的数学模型有了相应的认识。接下来将直接给出接近FPGA实现的MATLAB代码,与上述数学模型相互验证学习。
clc;
clear all;
close all;
%% ========================================================================================\\
%%******************************* System Parameter **********************************
%%========================================================================================/
fs = 16e6; %采样率 载波的采样率
fc = 1e6; %载波中心频率
df = 75e3; %最大频偏
fm = 16e3; %音频的采样率
kf = (df*2^32/fs)/32767;
AC= 1024;%幅度
%% ========================================================================================\\
%%******************************* Loaded modulated signal **********************************
%%========================================================================================/
load voice.mat
m_len=length(m)*fs/fm;%按照载波采样率的长度计算
%% ========================================================================================\\
%%******************************* carrier generator **********************************
%%========================================================================================/
w=fc*2^32/fs; %1Mhz 载波的频率控制字
% 载波的 ROM
n=0:1/1024:1023/1024;
s_rom=sin(2*pi*n);
c_rom=cos(2*pi*n);
w_r=0;%相位累加器
cw_sin=zeros(1,m_len);
cw_cos=zeros(1,m_len);
for i=1:m_len
w_r = w_r + w;
if(w_r > 2^32) % 做 32 位累加器的溢出判断
w_r= w_r - 2^32;
end
rrom_addr=round(w_r/2^22);%读查找表的地址
if rrom_addr == 0
rrom_addr =1;
end
cw_sin(i)=s_rom(rrom_addr);
cw_cos(i)=c_rom(rrom_addr);%载波
end
%% ========================================================================================\\
%%******************************* Modulation **********************************
%%========================================================================================/
m_t=zeros(1,m_len);
for i=1:length(m)
for j=1:fix(fs/fm)
m_t((i-1)*fix(fs/fm)+j)=m(i);%同一个 16k 的采样点复制 1000 次这样就是 16M 采样点
end
end
w_r=0;%相位累加器
rrom_addr=0;%
dac_i=zeros(1,m_len);
dac_q=zeros(1,m_len);
for i=1:m_len
w_r = w_r + kf*m_t(i);
if(w_r > 2^32) % 做 32 位累加器的溢出判断
w_r= w_r - 2^32;
elseif(w_r <0)
w_r = w_r + 2^32; % 负的溢出时
end
rrom_addr=round(w_r/2^22);%读查找表的地址
if rrom_addr == 0
rrom_addr =1;
end
dac_q(i)=AC*s_rom(rrom_addr);
dac_i(i)=AC*c_rom(rrom_addr);%载波
end
s_t=zeros(1,m_len);
for i=1:m_len
s_t(i) = dac_i(i)*cw_cos(i) + dac_q(i)*cw_sin(i)*(-1);
end
%% ========================================================================================\\
%%******************************* Plot Modulation **********************************
%%========================================================================================/
figure(1)
subplot(2,1,1);
plot(m_t);
title('调制信号');
subplot(2,1,2);
plot(s_t);
title('调制之后的信号');
这里简要介绍一下上述代码。上述代码是尽可能按照FPGA的语言来写的,每块的描述如下:
该块代码用来描述FM的参数配置;
上述代码加载FM调制的语音信号与根据载波的采样率计算采样之后的语音信号需要计算的点数。
根据DDS的原因产生FM调制所需要的载波
该部分的代码是根据DDS的原理产生
以上是关于基于MATLAB的FM调制解调的主要内容,如果未能解决你的问题,请参考以下文章
数字信号调制基于matlab GUI FSK调制+解调含Matlab源码 645期