测试USRP发送接收的时候完整的程序在benchmark_tx.py 和 benchmark_rx.py里面。其中调用了很多外面的分支如transmit_path.py.exe和 ofdm.py等。
在USRP发送端,执行的是benchmark_tx.py程序,在该程序里定义了发送数据包的相关参数,包括USRP发送频率、增益、天线、时钟源等,通过调用send_pkt函数来发送数据包。在程序中调用transmit_path和uhd_transmitter函数,它们分别定义在transmit_path.py和uhd_interface.py模块。调用ofdm_mod函数进行OFDM调制,然后将生成的基带调制信号传送给uhd_transmitter函数,即USRP射频模块,每成功发送一个数据包,屏幕上会输出一个‘.’。
在USRP接收端,执行的是benchmark_rx.py程序,在该程序中定义了接收数据包的相关参数,包括USRP接收频率、增益、天线、时钟源等,定义了rx_callback函数,当接收到数据包就会触发该函数,每调用一次rx_callback函数,变量n_rcvd加1;再通过CRC检验收到的数据包,如果无误则变量n_right加1。在程序中调用receive_path和uhd_receiver函数,它们分别定义在receive_path.py和uhd_interface.py模块。调用ofdm_demod函数进行相应的OFDM解调,数据包接收成功后,会显示接收端接收情况,在屏幕上输出当前数据包的编号(pktno)、已接收到的数据包的数量(n_rcvd)和其中正确的数据包的数量(n_right)。
(在gnuradio3.4中确实有文中的例子,而且也在相应的目录下,在gnuradio3.7.1中,基于GMSK的是在/usr/local/share/gnuradio/examples/digital/narrowband目录下,基于OFDM的是在/usr/local/share/gnuradio/examples/digital/ofdm目录下,本文讲的应该是在3.4下的,但看了3.7的感觉大同小异)
OFDM Tunnel是GNU Radio中很经典的例子。Tunnel有两个,一个是基于GMSK 调 制 的 (gnuradio-examples\python\digital) , 另 一 个 基 于 OFDM 调 制 的 (gnuradio-examples\python\ofdm)。它们都由物理层和MAC层构成,提供一个虚 拟的Ethernet接口,使得基于IP的各种应用程序都可以加载在这个tunnel 上面, 它的主要作用是负责数据的传输。我们主要研究后者。因为MIMO/OFDM 在当前最 新一代的通信系统中,几乎是必选的两个关键技术,因此很多做物理层研发的GNU Radio用户都会从这两个例子开始着手。
系统框图和MAC帧的构成
下图是Tunnel的系统框图。Tunnel的物理层由发射机,接收机和一个载波侦 听(sensing probe)三部分构成,完成由信息比特到基带波形之间的转换,以 及通过能量检测判断当前信道是否空闲。MAC 层是一个基于CSMA的简单的MAC。 MAC 层与PHY 层之间传递的是一个在IP包的基础上加了一些包头和包尾的数据 包。
了解了Tunnel的系统框图,我们来看一下MAC帧的结构和数据打包过程。图2 说明了一个IP数据包是如何打包成MAC数据包的。
首先,IP包被加上了4字节的校验比特,算法是CRC32。然后数据部分,加上 CRC比特和尾比特(X55),都被白化处理,使得数据具有随机均匀分布的特性。 最后,加上一个4字节的包头。包头包含两个信息:白化参数4 比特和数据包长 度12比特。包头采用了重复发送的方法,以增加可靠性。到此,一个完整的MAC 数据包就包装完成了。
OFDM Tunnel 发射部分解读
下面以ofdm tunnel为例来解读一下物理层。Ofdm tunnel的代码除了在 gnuradio-examples\python\ofdm 目 录 下 以 外 , 还 有 一 些 在 gnuradiocore\src\python\gnuradio\blks2impl目录下。
说明其中包含两个模块,ofdm_tx是一个ofdm_mod类,amp是一个乘法器。 进入ofdm_mod类看一下,其代码在文件ofdm.py中。Ofdm_mod中,数据包首
先经过一个send_pkt函数,完成MAC包的打包过程。 send_pkt(self,payload='',eof=False)
然后MAC包被放进一个队列 self._pkt_input.msgq().insert_tail(msg)
后面的ofdm_mapper_bcv模块从队列中取出数据包,根据OFDM调制的参数映 射成一个个OFDM symbol,再送到后续模块,添加preamble,IFFT变换,添加cyclic prefix,最后调整一下幅度,发送出去。这里想特别提一下的是,在ofdm_mapper 之后是流图的形式,在这之前是通过一个message queue与MAC层联系在一起。这 种连接方式使得“异步的”MAC层数据(而且数据包长不定),跟与系统时钟“同 步的”物理层连接在一起。这种连接方式是一个很好的例子,值得参考。
接收机部分如图4所示。receive_path.py包含了ofdm_demod和probe两个模 块。Ofdm_demod显然就是ofdm接收机部分。而probe是一个信号检测模块,当usrp 收到的信号幅度大于门限时,就认为无线信道已经被其他用户占用。Ofdm_demod类的代码在文件ofdm.py中,主要分成同步模块(ofdm_receiver),解调模块 (ofdm_frame_sink),和MAC帧拆包部分。与发射部分类似,物理层与MAC层也是 通过一个队列self._rcvd_pktq连接在一起的。Ofdm_receiver部分比较复杂,是 用python写的,完成了帧同步,频偏估计,频偏纠正,FFT的功能。ofdm_frame_sink是一个C写成的模块,完成了从调制符号到比特的解映射过程。
下面就详细介绍一下接收解调框图中各个模块的具体作用。
1)OFDM Receiver 部分。Filter(gr_fft_filter_ccc.cc)模块完成对 USRP 接收信号的匹配滤波功能;sync(gr_ofdm_sync_pn.py)模块的主要功能是完成 接收符号的窗口匹配,匹配成功时发送匹配成功标志给 sampler 模块;Nco (gr_frequency_modulator_fc.cc)模块完成细频偏纠正功能,相当于锁相环 PLL;Sig_mix(gr_multiply_cc.cc)模块对接收到的 OFDM 符号进行处理(将输 入符号相乘后输出),然后送给 sampler 模块;sampler(gr_ofdm_sampler.cc)
模块根据 sync 模块的匹配标志信号寻找 preamble,将 preamble 和 data 分离, 并给出二者的边界标志,然后把每个帧前面的循环前缀(Cycle Prefix)去除, 最后将 OFDM 符号送给 fft 模块,同时发送帧时序信号(Frame timing signal) 给 Frame acquisition 模块;fft(gr_fft_vcc.cc)模块对接收到的数据进行 fft 变换后输出给 Frame acquisition 模块(当查看 gr_fft_vcc.cc 时,你会发 现 该 模 块 并 没 有 做 实 际 的 fft 变 换 , 而 真 正 的 fft 和 ifft 变 换 在 gr_fft_vcc_fftw.cc 中进行);Frame acquisition(gr_ofdm_frame_acquisition)模块接收来自 FFT 的星座映射点向量,使用已知的 pn 码和接收到的 pn 码序列进 行比较得到信道增益,然后使用的到的增益修正其后的数据帧,进行相关和均衡。
2)ofdm_frame_sink(解调)模块。该模块接收 OFDM 符号,把他们接映射 成 0、1 比特流数据,再将这些比特流打包发送到接收消息序列,完成从调制的 OFDM 信号到实际发送比特数据的解映射过程。
3)MAC 帧拆包部分。主要功能是对解映射后的数据(还是帧结构的)进行帧 拆包,最终获得实际的有用数据信息。
开发和调试方法
整个ofdm tunnel 的物理层还是比较简单的。它模仿了802.11 的物理层, 在不定长的burst 前面添加一个定长的preamble,依靠这个preamble 完成时间 同步和频率同步。但它没有信道编码,因此抗噪声性能较差。
gnuradio-examples\python\ofdm 目录下,除了tunnel 调用的函数外,还
有许多其他的函数。这些函数都是程序的开发过程中需要用到的,它们教会了我 们如何一步步的进行程序开发。特别是对于利用GNU Radio 做物理层研发的人来 说,是很好的参考。下面简单说明一下。
ofdm_mod_demod_test.py——用于物理层收发模块的仿真测试。
benchmark_ofdm.py——加上MAC 层以后,做收发的仿真测试。
benchmark_ofdm_tx.py,benchmark_ofdm_rx.py——加上USRP 之后,做单 向收发的测试。分别测试了连续的数据包传输,和不连续的突发数据包传输。
当单向传输没有问题之后,就可以实验双向的传输了:tunnel.py。
另外,还有一些matlab程序,帮助调试程序。当我们把log标志设为True时, 就会产生很多.dat文件。这些文件把各个block的输出都记录下来:同步之前, 频率同步之后,FFT之后,解映射之后等等。然后用Matlab程序一一检查,就可 以发现究竟哪一步出了问题。
总结这个例子的开发方法,要创建一个自定义的无线连接程序,
第一步:用Matlab写一个物理层收发程序,设计各个功能模块,确定参数等。
第二步:用GNU Radio写一个不包括USRP 的收发程序,与Matlab程序一致, 方便把GNU Radio中的数据导入Matlab 中调试。
第三步:当物理层没有问题之后,再添加MAC层。
第四步:加入USRP。先调试单向通信,再调试双向的。
下图是ofdm_loopback.grc,实现了一个简单的OFDM回环。
更详细的示例可以参见/usr/local/share/gnuradio/examples/digital/ofdm/里的其它框图。
---------------------
作者:天一涯
来源:CSDN
原文:https://blog.csdn.net/yuan1164345228/article/details/17584045
版权声明:本文为博主原创文章,转载请附上博文链接!