2FSK调制解调实验

您所在的位置:网站首页 2fsk调制解调框图 2FSK调制解调实验

2FSK调制解调实验

2023-07-19 23:13| 来源: 网络整理| 查看: 265

一,2FSK原理

频移键控是利用载波的频率变化来传递数字信息。数字频率调制是数据通信中使用较 早的一种通信方式,由于这种调制解调方式容易实现,抗噪声和抗衰减性能较强,因此在 中低速数字通信系统中得到了较为广泛的应用。在2FSK中,载波的频率随着二进制基带 信号在 f1 和 f2 两个频点间变化。故表达式

由图我们可以看出,一个 2FSK 信号可以看成是两个不同载频的 2ASK 信号的叠加。因 此 2FSK 的时域表达式又可以写成 :

2FSK 信号的产生主要利用键控法来实现,即在二进制基带矩形脉冲序列的控制下通 过开关电路对两个不同的独立频率进行选通,使其在每一个码元Ts 期间输出 f1或 f2 两个 载波之一,如下图所示。键控法产生的 2FSK 信号其相邻码元之间的相位不一定连续。

 在本实验中,我们可以直接发送不同频率的载波信号,也就是已经调制好的 2FSK 信 号,以两个频率来表示码元‘1’和‘0’即可。 2FSK 信号常用的解调方法是采用相干解调和非相干解调。其解调原理是将 2FSK 信号 分解为上下两路 2ASK 信号分别进行解调,然后进行判决。这里的抽样判决是直接比较两 路信号抽样值的大小,可以不专门设置门限。判决规则应与调制规则相呼应,调制时若规 定‘1’符号对应载波频率 f1 ,则接收时上支路的样值较大,应判为‘1’;反之,判为 码元‘0’。

除此之外,2FSK 信号还有其他解调方法,比如鉴频法、差分检测法、过零检测法等。 由于 2FSK 的信号比较简单,只有f1 和 f2 两个频率,且分别对应码元‘1’和‘0’。因此 在本实验中,我们选择的解调方法为滤波法,即设计一个滤波器,将频率成分为 f1 或 f2 的 信号滤除掉,只剩下 f1或 f2 的信号分量。然后设置一个阈值,将大于该值的判为码元‘1’, 则小于该值的即为码元‘0’。注意,这种判决必须和调制时所规定的码元一致。

二,matlab相关代码解析

1,发送端

发送端,我们直接发送调制好的 2FSK 信号。由上述原理可知,当基带信号为 0 时, 发送频率为 f0 的载波信号;当基带信号为 1 时,发送频率为  f1的载波信号。

 调制的映射规则即为‘1’—>1MHz,‘0’—>2MHz,参考代码如下:

for i=1:length(bit_trans) if bit_trans(i)==1 m=carrier_1M; else m=carrier_2M; end m1=[m1 m]; end mod_data=m1;

mod_data 即为 2FSK 已调信号。我们可以画出它的频谱,由下图可以清晰的看出 2FSK 信 号有两根谱线,即两个频率值。

2,接收端

对于接收端,我们需要接收发送端的 2FSK 调制信号,因此 AD9361 的采样率和频点必 须与发送端一致,即samp_hex=dec2hex(20e6,8);  freq_hex=dec2hex(999e6,10);

帧到达检测完毕之后,接收到的信号应该是两路正交的 IQ 正弦波信号,他们的频率 为 1MHZ 和 2MHZ,分别对应码元‘0’和码元‘1‘(本实验中为 a1 和 a2)。 前面已经指出,2FSK 包含有两个频率成分(  f0和 f1),对于它的解调方式,本实验 采用滤波法,即设计一个滤波器,将频率成分为 f1的信号分量滤除掉,只剩下频率为  f1的信号(即是码元’1‘)。根升余弦滤波器是数字信号 处理过程中最常用的滤波器,在此我们利用 matlab 函数设计一个滤波器,将接收到的 信号中的 2MHz 的频率成分滤除掉,保留1MHz 频率。

%-----解调,采用滤波法,滤除 2MHz 频率成分-----% flt1=rcosine(1,8,'fir/sqrt',0.05,1); st_flt = rcosflt(frame_data, 1, 1, 'filter', flt1); data_abs=abs(st_flt);

从图上可以看出,滤波效果比较好,只保留了 1MHz 频率分量,我们也可以从时域 观察一下滤波效果,可以更加直观的看出 2MHz 频率被滤除。此时,这就相当于一个 2ASK 信号了,对其取模判决即可解调。

data_re=(data_abs>1e4); data_ex=data_re(4:20:end);

 判决阈值设为 1e4,然后进行 20 倍的抽取,即可还原出原始基带二进制码元信号。

 

 三,代码

运行发送端程序tx_2FSK.m,matlab命令行端显示“data transfer done”时,表明数据正常发送完毕

clc; clear all; close all; warning off; %****************ht7600*******************// %ref_hex 1=external ref;0=internal ref %vco_cal_hex 1=AUXDAC1;0=ADF4001 %fdd_tdd_hex 1=FDD 0=TDD %trx_sw_hex 1=TX 0=RX %****************ht7600*******************// rcount=dec2hex(10,4);%reference clock divide ncount=dec2hex(26,4);%internal vctcxo divide ref_hex=dec2hex(0,8);%1=external ref 0=internal ref vco_cal_hex=dec2hex(1,8);%1=auxdac 0=reference clock aux_dac1_hex=dec2hex(0,8); fdd_tdd_hex=dec2hex(1,8); trx_sw_hex=dec2hex(1,8); samp_hex=dec2hex(20e6,8); bw_hex=dec2hex(18e6,8); freq_hex=dec2hex(999e6,10); %%for ad9361 tx_att1=dec2hex(5000,8); tx_att2=dec2hex(30000,8); tx_chan=3;%1=tx1;2=tx2;3=tx1&tx2 %=====以下为数据调制部分=====% %-----数据源数量-----% bit_Num = 500; %-----产生随机数据帧,length=500-----% bit_trans = randint(1,bit_Num); %-----产生两个载频,分别为1MHz和2MHz carrier_I1=round(cos(2*pi/20*[0:19]).*30000); carrier_Q1=round(sin(2*pi/20*[0:19]).*30000); carrier_1M=carrier_I1+1i*carrier_Q1; carrier_I2=round(cos(2*pi/10*[0:9]).*30000); carrier_Q2=round(sin(2*pi/10*[0:9]).*30000); carrier_2M=carrier_I2+1i*carrier_Q2; %-----2MHz载波扩展为20bit,和1MHz载波等宽 carrier_2M=repmat(carrier_2M,1,2); %-----键控调频,1-->1MHz,0-->2MHz m1=[]; for i=1:length(bit_trans) if bit_trans(i)==1 m=carrier_1M; else m=carrier_2M; end m1=[m1 m]; end mod_data=m1; %-----创建帧同步训练序列-----% [training]=creat_training(); %-----数据组帧-----% txdata=[training mod_data]; %% copy to 2chanel if tx_chan==1 || tx_chan==2 txdata2=txdata; elseif tx_chan==3 txdata2=zeros(1,length(txdata)*2); txdata2(1:2:end)=txdata; txdata2(2:2:end)=txdata; end %% iq mux txdatas=zeros(1,length(txdata2)*2); txdatas(1:2:end)=real(txdata2); txdatas(2:2:end)=imag(txdata2); %% add pad rem=-1; i=0; while (rem1e4); data_ex=data_re(4:20:end); demod_data=data_ex(2:end)'; %-----计算误码率-----% bit_err=biterr(demod_data,bit_trans); %-----画图显示-----% h=figure(1); clf; set(h,'name','2FSK调制解调系统'); subplot(221); plot(a1,'g'); hold on; plot(a2,'r'); ylim([-1e4 1e4]); axis square; title(['接收到的2FSK调制信号 cyc=',num2str(cyc)]); subplot(222); plot(bit_trans ,'b'); ylim([-0.2 1.2]); title(['原始基带信号序列 Total = ',num2str(length(bit_trans)),'bit']); subplot(223); plot(syn_symbol,'black'); ylim([0 1.2]); axis square; title('帧同步相关性曲线'); subplot(224); plot(demod_data ,'m'); ylim([-0.2 1.2]); title(['解调序列 Bit\_err = ',num2str(bit_err),';Demod\_times=',num2str(cyc)]); %-----接收次数变量值累加-----% cyc=cyc+1; %-----设置z键为停止键-----% if strcmpi(get(gcf,'CurrentCharacter'),'z') break; end pause(0.1); end %% send handshake2 cmd to stop adc thread handshake=[hex2dec('ff') 1 hex2dec('17') hex2dec('f0') 0 0 0 0]; fwrite(ctrl_link,handshake,'uint8'); %% close all link fclose(data_link); delete(data_link); clear data_link; fclose(ctrl_link); delete(ctrl_link); clear ctrl_link;

其中,cyc 显示接收数据次数,下方画出了帧同步曲线,原始基带信号和长度也示于上面, 解调序列显示误码率和解调次数,可以看到 bit_err 为 0,解调完全正确。 下图为2FSK调制解调图:

 creat_tream.m

function [training]=creat_training() Ns=128; N1=320; Nx=512; x1=randn(1,Ns); x2=randn(1,Ns); x3=x1+x2.*i;%生成随机128点复数序列 y=x3(65:128);%x3的后64点用作循环前缀 y1=randn(1,N1); y2=randn(1,N1); y3=y1+y2.*i;%生成随机320点复数序列用作数据符号 train1=[y3 y x3 x3 y3];%帧结构,共三个符号 training=train1/sqrt(12); %数据量化为16bit index=30000./max([abs(real(training)),abs(imag(training))]); training=round(training.*index); end

rx_frame_sync.m

function [ frame_data,syn_symbol] = rx_frame_sync(receive_data,data_I,data_Q,txdata_x) % receive_data=receive_data'; [xx,PS]=mapminmax(receive_data); frame_all=xx'; syn_symbol=syn_time(frame_all); [s1,s2]=max(syn_symbol(1:length(syn_symbol)/2)); frame_begin=s2+576; frame_end=frame_begin+length(txdata_x); %------------找到帧位置后组成一帧数据------------------------------ frame_data_I=data_I(frame_begin:frame_end); frame_data_Q=data_Q(frame_begin:frame_end); frame=frame_data_I+1i*frame_data_Q; frame_data=frame(2:end); end

sync_time.m

function [C]=syn_time(data) Ns=128; N=length(data); N1=320; r=data; t1=zeros(1,N); t2=zeros(1,N); C=zeros(1,N);%原相关值对能量值归一化 C1=zeros(1,N+4);%用循环前缀进一步归一化 tt=0; for timing=1:N-700 for m=1:2*Ns t1(timing)=t1(timing)+0.5*((abs(r(m+timing)))^2);%整个序列能量值,除了1/2 end for m=1:Ns t2(timing)=t2(timing)+conj(r(m+timing))*r(m+Ns+timing);%前半序列和后半序列相关值 end C(1,timing)=(abs(t2(timing))^2)/(t1(timing)^2);%相关值对能量值归一化 end for timing=65:N-700 %利用训练序列的循环前缀设定一个滑动运算窗口对序列进行归一化 for i=-64:0 C1(1,timing)= C1(1,timing)+(1/65)*C(1,i+timing); end end [Y,I]=max(abs(C1)); timing_coarse=I-384; C=abs(C1); end



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3