USRP-OFDM通信系统实验报告.docx
《USRP-OFDM通信系统实验报告.docx》由会员分享,可在线阅读,更多相关《USRP-OFDM通信系统实验报告.docx(42页珍藏版)》请在冰点文库上搜索。
实验一利用GNU-Radio和USRP搭建OFDM通信系统
图1,基于GNU-Radio和USRP的OFDM通信系统示意图
1实验设备
l设备清单
设备型号
数量
1
EttusUSRPN210
2
2
SBX-40子板
2
3
VERT2450
2
4
计算机
2
l开发环境
操作系统:
Ubuntu14.0464bit
软件平台:
GNU-Radiov3.7.8UHDrelease_003_009_001
2实验目的
l理解OFDM信号的调制和解调原理;
l熟悉使用GNU-Radio软件并对信号进行处理;
l学会使用软件GNU-Radio和硬件USRP来完成点对点设备的通信。
3实验内容
本实验是在Linux桌面应用系统Ubuntu上进行的,使用到的包括一款免费的无线电和信号处理开发软件—GNU-Radio,和通用软件无线电外设硬件—USRPN210。
实验的任务是在GUN-Radio和USRP组成的软硬件平台,搭建了基于OFDM调制的无线通信环境,以便更好的了解OFDM通信原理和信号在无线信道中传播的特点。
实验主要包括三部分:
发送端、信道和接收端。
其中发送端主要包括信源、符号映射、子载波分配、IFFT并加CP、USRPTX;无线信道所处的是室内环境,也被称为准静态信道环境(这也为接收端的均衡提供了思想);接收端主要包括USRPRX、同步、去CPFFT、信道估计和均衡、解符号映射、信宿。
4实验步骤
4.1发送端
在OFDM通信系统中,发送端需要完成以下几个功能:
信源编码、数据打包、符号映射、子载波分配、IFFT变换、加CP、USRP发送射频信号等。
除USRP模块外其它几个模块中的信号处理都是在GNR-Radio中完成的,也即在主机中完成。
USRP模块拥有单独的DSP和FPGA模块,因此可以独立对输入数据进行处理。
在USRP模块里面需要完成很多的功能,比如抽取、数字上变频、A/D转换、混频等功能都是在其中完成的。
发送端的主要目的是完成信号的调制、上变频、功放,最后通过专用天线将其发送到无线信道中去。
考虑到若上变频后的信号幅度过大,在经过功放后可能导致信号失真,因此需要在USRP模块前增加一个限幅器模块。
图2,OFDM通信系统的发送端实验流程图
4.1.1数据帧结构
实验开始时一帧数据的长度规定为96个字节,其中每个字节包含8个比特。
信源不断地产生0和1的比特序列,经过数据打包模块(B模块)后变成上述固定长度的帧数据。
数据流经过CRC校验后,会在一帧数据的末尾增加4个字节,这时一帧数据便变成了100字节。
这些有用的信息称为payload,其采用的是QPSK调制方式,注意经过QPSK映射后一帧数据的长度变成了100*8/2=400个QPSK符号。
接着,针对每一帧数据需要生成一个帧头,用来记录当前帧的一些信息,比如帧长、这是第几帧等信息。
实验中帧头信息长度为6个字节共48个比特,帧头中的信息称为Header,采用BPSK方式调制,故其长度不变。
Payload和Header需要复合在一起才能进行传输,一般将Header置于Payload之前形成新的帧结构,这时一帧数据的长度又发生了变化,变成了400+48=448个符号。
在实验中一个OFDM符号的长度设定为64(即总载波个数为64),除去虚拟载波、直流子载波和射频子载波还有48个有效数据子载波。
因此,一个OFDM符号可以负载48个Payload的符号,也就是这是一帧数据需要10(448/48=9.333)个OFDM符号。
另外,根据文献【1】为了接收端能正常解调信号,需要在一帧数据前加上两个OFDM符号的同步字。
所以,一帧数据中包含12个OFDM符号。
图3数据帧结构示意图
4.1.2发送端各模块功能的介绍
A.VectorSource:
实现的功能是循环产生同一组向量,并将该向量转化成无符号整形变量(即uchar型变量),所以其输出是一连串的0和1的数据流。
输入变量:
1,Vector,range(packet_len)。
其中packet_len是个变量指一帧数据的长度,单位字节,试验中该变量的值设为96。
所以,根据python语法规则range(Packet_len)就是产生一组0到95的向量。
2,Veclength,1。
产生一个向量。
可选变量:
是否循环:
Yes。
输出:
一串0和1的数据流,数据类型byte。
图3,向量信源模块
B.StreamtoTaggedStream:
该模块实现的功能是将输入数据流进行打包,形成一定长度的帧数据流,并给数据贴上标签。
因此,试验中设定一帧数据长度为96个字节,则该模块按该长度输出打包好的帧数据流,共96个字节96*8个比特。
输入变量:
1,Vectorlength:
1,输入向量的个数,默认为1个;
2,2,packetlength:
packet_len,定义一帧数据的长度,在流程图的变量模块中packet_len设定为96;
3,3,LengthTagKey:
length_tag_key,给输出数据打上标签,其标签名为length_tag_key,值为96.
输出:
带标签的帧数据流,数据类型byte.
图4,数据打包模块
C.StreamCRC32:
该模块实现的功能是对输入的每帧数据进行校验,并将形成的4个字节的校验字附在每帧数据的末尾。
注意:
经过该模块后输出的一帧数据长度较输入之前增加了4个字节,所以一帧数据长度变成100个字节共100*8个比特。
输入变量:
1,Lengthtagname:
length_tag_key,输入的标签名,该模块需要知道一帧数据的长度是多少;
可选变量:
Mode:
GenerateCRC。
这里是发送端,所以选产生CRC校验码,而不是校验接收到的数据。
Packed:
Yes。
告诉模块输入的数据是否是打包好的数据。
输出:
带标签的帧数据流,数据类型byte.
图5,CRC校验模块
D.PackerHeaderGenerator:
该模块用来记录一帧数据中的信息,即形成帧头,共6个字节6*8个比特,其中字节1代表一帧数据的长度,字节2和3一起表示当前帧的帧号,字节2每16个加一帧,到255字节3便加1;其它三个字节还不知道具体表示什么。
输入变量:
1,FormatterObject:
header_formatter.formatter().指定形成的帧头格式;
2,LengthTagName:
"packet_len".标签名。
该模块在对数据进行处理时需要知道一帧数据的长度。
输出:
帧头数据流,数据类型byte,暂存到HeaderBits模块中.
图6,帧头生成模块
E.RepackBits:
该模块实现的功能是将8比特一组的数据变成2比特一组,由最低位到最高位依次转换。
因此,在解码的时候需要特别注意每个比特在一个字节中的位置。
输入变量:
1,Bitsperinputbyte:
8,输入端口每个字节中包含的比特数,指定为8;
2,Bitsperoutputbyte:
payload_mod.bits_per_symbol(),输出端口每个字节中所包含的比特数,payload_mod.bits_per_symbol中的payload_mod在流图的变量模块中设定为QPSK,因此每个符号应包含2个比特数。
3,LengthTagKey:
length_tag_key.标签名。
该模块在对数据进行处理时需要知道帧长。
可选变量:
PacketAlignment:
input.选择需要进行该操作的端口,这里只有一个input端口可选。
Endianness:
LSB.从一个字节的最低位开始操作。
输出:
带标签的帧数据流,数据类型byte,但每个byte包含2个字节.
图7,字节重生成模块
F.ChunkstoSymbols:
符号映射模块,完成数据块到符号流的转换。
这里可选的符号参数为-1+0j和1+0j,因此该模块的功能是实现BPSK映射。
输入变量:
1,SymbolTable:
header_mod.points(),该值在变量模块中已定义,其映射规则是输入0时输出-1+0j,输入1时输出1+0j;
2,Dimension:
1,整个流图始终处理的都是一维数据,所以这里同样是1维。
3,NumPorts:
1.端口数,同样这里选1。
可选变量:
InputType:
Byte:
输入数据类型与前一模块的数据类型相同。
OutputType:
Complex.输出数据类型为复数。
输出:
带标签的帧数据流,数据类型complex。
图8,BPSK映射模块
G.ChunkstoSymbols:
符号映射模块,完成数据块到符号流的转换。
这里可选符号参数包括-0.707+0.707j,-0.707-0.707j,0.707-0.707j和0.707+0.707j,因此该模块实现的功能是QPSK映射。
输入变量:
1,SymbolTable:
payloas_mod.points(),该值在变量模块中已定义,其映射规则是输入10时输出-0.707+0.707j,输入00时输出-0.707-0.707j,输入01时输出0.707-0.707j,输入11时输出0.707+0.707j。
2,Dimension:
1,整个流图始终处理的都是一维数据,所以这里同样是1维。
3,NumPorts:
1.端口数,同样这里选1。
可选变量:
InputType:
Byte:
输入数据类型与前一模块的数据类型相同。
OutputType:
Complex.输出数据类型为复数。
输出:
带标签的帧数据流,数据类型complex。
图9,QPSK映射模块
H.TaggedStreamMux:
该模块的功能是增大或减小数据流标签中值的大小,从而达到增加或缩减一帧数据长度的目的。
这里需要将两路信号合并,因此需要增加数据帧的长度。
之前我们分析过数据帧长为100个字节共100*8个比特,经QPSK映射后为100*4个符号;同样针头有6个字节共48个比特,经BPSK映射后变成48个符号。
因此,将这两路信号进行合并后得到的一帧数据长度为100*4+48=448个符号。
输入变量:
1,NumberofInput:
2,输入端口数,有两路信号输入,因此这里应填。
2,Lengthtagnames:
length_tag_key,输入数据帧的长度,96。
3,VectorLength:
1.和信源保持一致;
可选变量:
IOType:
complex,端口输入数据类型。
输出:
带标签的帧数据流,数据类型complex。
图10,信号合成模块
I.OFDMCarrierAllocator:
OFDM子载波分配模块,也即串并转换模块。
该模块的作用是给每个子载波分配相应的值,数据相应地实现串并转换。
这里设总载波个数为64,载波类型包括以下几种:
数据子载波(Occupiedcarriers)、导频子载波(Pilotcarriers)、虚拟子载波(Virtualcarriers,VC)和直流子载波(DCcarrier)。
其中占用载波可以用来携带数据和同步字,导频载波用于发射特定符号数据,空载波的值默认为0.在试验中发送端OFDM子载波的编号规则是:
为了保持左右对称,将64个子载波编号为[-32,31]。
其中,最左边6个子载波[-32,-27]和最右边的5个子载波[26,31]称为虚拟载波,即不使用的载波它的值默认为0,其作用是为了减少带外功率和抑制ACI。
编号为[-26,-22]、[-20,-8]、[-6,-1]、[1,6]、[8,20]、[22,26]都是数据子载波;编号为-21、-7、7、21为射频子载波;编号为0为直流子载波,作用是降低OFDM信号的峰值信噪比以及硬件电路的复杂度【3】。
由此可知,64个子载波中有效子载波只有48个。
这样我们便可以计算出承载一帧有效数据(包括帧头和负载共448个符号)所需要的OFDM符号数(将64个子载波组成的并行数据称为一个OFDM符号),即448/48=9.33个OFDM符号,也就是说传输一帧有效数据需要10个OFDM符号。
另外,为了接收端解调方便,本实验中的OFDM信号需要加入2个符号的同步字置于一帧有效数据的开头。
所以,最后传输的一帧数据中包含了12个OFDM字符,2个同步字和10个有效数据。
输入变量:
1,FFTlength:
fft_len,傅里叶变换的长度,fft_len在流图变量模块中指定为64。
2,OccupiedCarriers:
occupied_carrieds,数据子载波编号,occupied_carrieds在流图变量模块中指定为[-26,-22]、[-20,-8]、[-6,-1]、[1,6]、[8,20]、[22,26]。
3,PilotCarriers:
pilot_carrieds,导频子载波编号,pilot_carrieds在流图变量模块中指定为-21、-7、7、21。
4,PilotSymbols:
pilotsymbols,导频子载波上对应的符号(值),pilotsymbols在流图变量模块中对应上述载波编号指定为:
1,1,1,-1。
5,Sync_words:
(sync_word1,sync_word2),同步字信息,sync_word1,sync_word2是在流图变量模块中指定信息。
其中同步数组1的值为[0.,0.,0.,0.,0.,0.,0.,1.41421356,0.,-1.41421356,0.,1.41421356,0.,-1.41421356,0.,-1.41421356,0.,-1.41421356,0.,1.41421356,0.,-1.41421356,0.,1.41421356,0.,-1.41421356,0.,-1.41421356,0.,-1.41421356,0.,-1.41421356,0.,1.41421356,0.,-1.41421356,0.,1.41421356,0.,1.41421356,0.,1.41421356,0.,-1.41421356,0.,1.41421356,0.,1.41421356,0.,1.41421356,0.,-1.41421356,0.,1.41421356,0.,1.41421356,0.,1.41421356,0.,0.,0.,0.,0.,0.];同步数组2的数据为[0,0,0,0,0,0,-1,-1,-1,-1,1,1,-1,-1,-1,1,-1,1,1,1,1,1,-1,-1,-1,-1,-1,1,-1,-1,1,-1,0,1,-1,1,1,1,-1,1,1,1,-1,1,1,1,1,-1,1,-1,-1,-1,1,-1,1,-1,-1,-1,-1,0,0,0,0,0]。
可选变量:
无
输出:
OFDM符号流,数据类型complex。
图11,OFDM子载波分配模块
J.FFT:
傅里叶变换模块。
对已分配好的子载波符号进行傅里叶变换,完成OFDM调制。
输入变量:
1,FFTSize:
fft_len,傅里叶变换的长度,fft_len在流图变量模块中指定为64。
2,Windows:
(),傅里叶变化的窗函数,不清楚()代表什么。
3,Num.Threads:
1,线程数设为1,C++中多线程数在任务量大时才有效,当任务量小时采用多线程会消耗额外的通信开销而导致其效率比单线程还低。
因此,这里64点DFT采用单线程较好。
可选变量:
1,InputType:
Complex,输入的数据类型为复数。
2,Forward/Reverse:
Reverse,FFT变换类型,Forward表示FFT变换,Reverse表示IFFT(逆傅里叶)变换。
3,Shift:
shift,傅里叶变换后是否将频率点(下标)移动,shift表示需要移动,移动规则如下图所示。
这里需要注意的是在接收端FFT模块中需要做同样的设置,否则无法正常解调信号。
输出:
OFDM符号流,数据类型complex。
图12,FFT/IFFTShift变换过程
图13,FFT变换模块
K.OFDMCyclicPrefixes:
给OFDM符号添加循环前缀。
OFDM信号中加循环前缀的目的是为了防止OFDM符号间干扰(ISI),但需要保证循环前缀的长度大于信道卷积长度。
输入变量:
1,FFTLength:
fft_len,傅里叶变换的长度,fft_len在流图变量模块中指定为64。
2,CPLength:
fft_len/4,循环前缀的长度,其值为fft_len/4=16。
3,Rolloff:
rolloff,成形滤波器参数设置,rolloff为升余弦滚降。
4,LengthTagKey:
length_tag_key,数据帧的长度,同之前模块中的值一样。
可选变量:
无。
输出:
OFDM符号流,数据类型complex。
图14,OFDM循环前缀模块
L.MultiplyConst:
衰减器模块。
该模块通常将输入的数据乘上一个常数,从而达到改变输入信号幅度的目的。
在这里为了防止调制好的OFDM信号在进入功率放大器后产生非线性失真,需要将输入信号乘上一个小于1的常数。
输入变量:
1,Constant:
M_const,一个小于1的浮点型常数,为方便将其设为仿真中可变的值,设置如图15所示,默认值为0.02,变动范围[0,0.1],步进为0.001。
2,VecLength:
1.同上。
可选变量:
1,IOType:
complex。
输出:
OFDM符号流,数据类型complex。
图15,衰减器模块
M.UHD:
USRPSink:
信号发送模块。
该模块实现信号从软件到硬件转换的桥梁作用,将信号送到硬件再经射频天线将信号发送出去。
本实验中所用的硬件是USRPN210和其搭载的母板SBX_v2,它们主要的任务是完成插值、上变频、D/A转换、功放、混频、最后经射频天线发射出去。
USRPN210有一个千兆以太网端口,可以通过网线和主机连接实现最高50MS/s的通信速率。
需要设置的参数:
1,DeviceAddress:
usrp_addr,输入USRP设备的地址,通常一台设备对应一个IP地址,其储存在芯片EPROM中,主机通过寻找该地址来实现通信。
usrp_addr是流图变量模块中的一个变量名,其值为“addr=192.168.10.2”。
另外,要想完成主机和设备通信还需要对主机进行设置,具体参见文献【4】中的PDF资料。
2,SampRate(Sps):
samp_rate,采样率。
通常可以理解为主机和设备之间传输数据速率,最大为50MS/s(8bit)或25MS/s(16bit)。
samp_rate的值在流图的变量模块中设为1MHz。
3,CenterFreq(Hz):
c_freq,中心频率。
指信号在无线环境中传播的频率,也即射频。
c_freq的值在流图的变量模块中设为433MHz。
4,GainValue:
Tx_gain,USRP发送增益,单位是dB。
Tx_gain的值在流图的变量模块中设为25dB。
可选变量:
1,其它变量采用默认值。
输出:
射频信号,数据类型:
模拟信号。
图16,USRP信号发送模块
4.2接收端
与发送端相对应,接收端主要由以下几个模块组成:
USRPSource模块、同步模块、载波频偏估计及消除模块、FFT模块、信道估计及均衡模块、逆子载波分配模块、解QPSK和BPSK模块、CRC校验模块等。
同样除了USRP模块外其它几个模块中的信号处理都是在GNR-Radio中完成的,也即在主机中完成。
USRP模块由于拥有单独的DSP和FPGA模块,因此可以独立对输入数据进行处理。
在USRP模块中需要完成混频、D/A转换、字下变频、插值数等功能。
接收端的主要功能是将射频信号从无线信道中接收下来,模数转换,再经过一系列信号处理模块最终将信号解调出来。
图1,OFDM通信系统的接收端实验流程图
4.2.1工作原理
首先,USRP模块将无线信道中的信号接收下来,IQ两路A/D采样变成数字信号,之后经过数字下变频、抽取等得到一连串的复信号流。
输出的数据分成两路,一路经过同步模块B和调制模块D进入相乘模块E。
模块B有两个输出端口分别输出小数倍载波频偏和定时脉冲,小数倍载波频偏输入到模块D中进行调制,用于消除接收信号中的载波频偏,定时脉冲输入到模块F中用于触发一帧数据的起始点;另一路数据流经过模块C延迟一个OFDM符号(包括CP)后进入相乘模块。
在模块E中两路信号相乘从而使得小数倍的载波频偏得以纠正,消去载波频偏后的数据流进入F模块来将一帧数据中的Header和Payload分开。
但是,接收端一开始不知道接收信号中的数据帧结构,所以在解调时需要先读出Header中信息,才能将接收信号正常解调。
因此,我们先分析Header这路信号。
信号首先进入了FFT模块做傅里叶变换,之后进入信号估计模块,经过该模块后会得到整数倍载波频偏和系统频谱响应两个参数。
接着信号流带着这两个参数进入模块I中进行频域均衡同时纠正整数倍的载波频偏,这时接收信号中的载波频偏已完全消除了。
数据之后经过串并转换模块(即逆子载波分配模块J)和解星座映射模块K得到所需的信息(包括帧头信息、整数载波频偏和系统频域响应等参数),在将其以PMT字典格式的数据储存并输入到模块F中。
模块F的作用之前已经提到,它将一帧数据的Header和Payload分开,其具体工作原理见下一节的模块分析。
Header和Payload数据分开后,现在主要考虑Payload这路数据流,这部分功能大体和接收端是对称的。
首先,它同样进入FFT模块中进行傅里叶变换,后经过模块N来进行信道均衡和去载波频偏,然后在模块O中做逆子载波分配,之后是解QPSK映射。
这之后的步骤便完全是发送端实现过程的逆过程了,直到信号完全解调出来。
另外,最后信号输出的是标签,包括载波频偏,信道均衡系数(即系统频率响应)、当前数据帧的帧号、接收时间等信息。
4.2.2接收端各模块功能的介绍
A.UHDUSRPSource:
该模块可以实现硬件和软件之间的连接。
具体是将硬件USRPN210接收到的信号(经过一系列处理后得到的信号)传送到主机。
需要设定的参数是USRP设备地址,采样频率以及中心频率。
输出是复数类型的I/Q数据流。
B.Schmidl&CoxOFDMsynch:
该模块实现两个功能,第一实现符号定时同步;第二去除小数部分的载波频偏。
该模块所使用的方法是根据文献【1】编写的,但是整数倍频偏纠正的方法没在该模块中给