基于UHD源码实现的四通道收发实例
作者:互联网
1. Introduction
本次项目所用的PC环境为Ubuntu16.04,USRP型号为 N310。具体的N310设备简介可以参考ETTUS官网的用户手册(https://files.ettus.com/manual/page_usrp_n3xx.html)
图1
如图1所示,USRP-N310共具有四个收发通道,可以同时实现四路信号的收发。从LTE系统开始,MIMO技术已经逐渐开始应用。在未来的5G-R(5G for Railway)系统中也将采用MIMO技术。目前基于USRP的多通道收发范例都是通过Labview实现的,该语言由美国国家仪器(NI)公司研制开发,类似于C和BASIC开发环境,但是Labview与其他计算机语言的显著区别是:其他计算机语言都是采用基于文本的语言产生代码,而Labview使用的是图形化编程语言。同时Labview入门较困难,不适合SDR(Software-Defined Radio)初学者,因此推荐使用UHD( USRP Universal Hardware Driver)范例进行二次开发。UHD范例全部是由C++编写,适合SDR初学者阅读和开发。
2. UHD安装教程
CSDN上可以查找到很多关于UHD安装的资料,此部分不做详细阐述。具体的安装流程可以参考ubuntu16.04下安装uhd与gnuradio
需要注意的是,博主采用的UHD版本是v3.15.0.0,克隆UHD源码后,需要采用git checkout进行分支切换。
3. 官方实例
UHD范例所在路径如下:XXX/uhd/host/build/examples (XXX为 第2部分中源码所在位置)
图2
本博客的四通道收发范例基于UHD基础范例:tx_waveforms编写,因此先介绍tx_waveforms范例的功能和代码架构。
相关范例的CPP文件在路径: XXX/uhd/host/example下,修改完相应的CPP文件后,需要重新进行
sudo make
sudo make install
sudo ldconfig
进行编译,编译通过后便可运行相关的范例实例。
uhd_tx_waveforms可以通过USRP实现简单的波形发送(方波、正弦波、斜波等波形),该范例可以通过用户命令行配置,实现振幅、中心频率、带宽、天线等选择、设置。
范例功能:自定义带宽、采样率、频率、天线等参数,进行固定波形发送。
--args arg 指定USRP IP地址
--spb arg (=0) 指定每个buffer的采样数
--nsamps arg (=0) 发送的总采样数
--rate arg 采样发送速率
--freq arg 射频中心频率
--lo-offset arg (=0) LO偏移频率
--ampl arg (=0.300000012) 发送波形幅值 [0 to 0.7]
--gain arg 射频增益
--ant arg 选择天线端口
--subdev arg 主板选择
--bw arg 模拟前端滤波器
--wave-type arg (=CONST) 固定波形选择 (CONST, SQUARE, RAMP, SINE)
--wave-freq arg (=0) 发送波形频率
--ref arg (=internal) 时钟源 (internal, external, mimo, gpsdo)
--pps arg PPS source (internal, external, mimo, gpsdo)
--otw arg (=sc16) over-the-wire sample mode 线缆采样模式
--channels arg (=0) 指定数据流传输通道
--int-n tune USRP with integer-N tuning (具体功能不太懂,百度可以查到相关论文,貌似是可以降低低频处的噪声信号)
范例的代码架构如图3所示,时间有点紧迫,因此这个框图采用在线软件画的,可能不是很清楚,需要的朋友可以私聊我,可以给你发具体的PDF文件。
图3
- sig_int_handler [ void sig_int_handler(int) ]
此函数可以实现ctrl + c强行结束程序
- po::variables_map vm 、 po::store(po::parse_command_line(argc, argv, desc), vm)、po::notify(vm)
通过调用boost库,可以实现从命令行直接读取参数,对变量进行赋值。
- create a usrp device
uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args)
通过读取命令行设置的args (usrp 地址)实现对USRP的选择、驱动
- 选择USRP子板
usrp->set_tx_subdev_spec(subdev);
通过读取命令行设置的subdev 实现对USRP子板的选择
- 确定已用通道编号
boost::split(channel_strings, channel_list, boost::is_any_of("\"',"));
C++标准库,boost:split(存储切割结果的容器,要分割的内容,分割条件“\” 将channel list按照分割条件切割,存进channel_strings
- 确定通道总数
利用for循环,channel_nums.push_back(std::stoi(channel_strings[ch])); 将channel_strings转换为十进制放入vector channel_num的尾部,以便后续读取
- 锁定母板时钟
usrp->set_clock_source(ref)
- 设定发送速率 & 实际发送速率
// 输出命令行预设速率
std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate / 1e6) << std::endl;
// 输出实际发送速率
usrp->set_tx_rate(rate);
std::cout << boost::format("Actual TX Rate: %f Msps...") % (usrp->get_tx_rate() / 1e6)
- 设定发送频率 & 实际发送频率
// 预设频率
std::cout << boost::format("Setting TX Freq: %f MHz...") % (freq / 1e6)
// 实际发送频率
利用for循环( size_t ch = 0; ch < channel_nums.size(); ch++ ),遍历每个通道
usrp->set_tx_freq(tune_request, channel_nums[ch]);
std::cout << boost::format("Actual TX Freq: %f MHz...")
% (usrp->get_tx_freq(channel_nums[ch]) / 1e6)
- 设定发送增益
usrp->set_tx_gain(gain, channel_nums[ch]);
std::cout << boost::format("Actual TX Gain: %f dB...")
% usrp->get_tx_gain(channel_nums[ch])
- 设定模拟前置滤波器带宽
usrp->set_tx_bandwidth(bw, channel_nums[ch]);
std::cout << boost::format("Actual TX Bandwidth: %f MHz...")
% usrp->get_tx_bandwidth(channel_nums[ch])
- 设定天线
usrp->set_tx_antenna(ant, channel_nums[ch]);
- 创建发送数据流 (Create a transmit streamer)
uhd::stream_args_t stream_args("fc32", otw);
// stream_args_t (cpu, otw)
cpu是指内存中的数据格式
fc64 - complex<double>
fc32 - complex<float>
sc16 - complex<int16_t>
sc8 - complex<int8_t>
otw是指在线缆上传输的数据类型
sc16 - Q16 I16
sc8 - Q8_1 I8_1 Q8_0 I8_0
sc12 (Only some devices)
uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args);
从usrp中提取成员 get_tx_stream赋值给 tx_stream
创建buffer,通过通道间复用buffer实现多通道数据流发送
std::vector<std::complex<float>> buff(spb);
std::vector<std::complex<float>*> buffs(channel_nums.size(), &buff.front());
数据发送模式(先存再发)
利用for循环,向buff里存波表数据
for (size_t n = 0; n < buff.size(); n++) {
buff[n] = wave_table(index += step); }
发送数据
num_acc_samps += tx_stream->send(buffs, buff.size(), md)
4. 基于UHD源码编写的四通道实例
本实例是基于标准范例tx_waveforms编写,主要框架与第3部分框架相同,具体的程序逻辑可以参考图3。
本实例修改了部分help提示信息,便于使用者理解,同时代码里也有少量的英文注释。
--file arg 支持发送用户自定义的波形、信号信息。(文件后缀需要为.bin类型)使用者可以采用Matlab生成信号波形,然后经过USRP发送,连接示波器进行性能验证。
--otw arg 代表了线缆上传输的数据类型(Over the wire type)
sudo ./tx_samples_from_file --args "addr=192.168.20.2" --file "zp10M.bin" --rate "15.36e6" --freq "2100e6" --gain "15" --ant "TX/RX" --channels "0,1,2,3" --otw "sc8" --int-n 4
(实验室的师姐使用该范例验证了Matlab 5G toolbox下的FRC信号,具体的IQ排列可以参考Matlab代码)
图4
终端运行状态:
图5
USRP N310运行状态
红灯亮代表该通道已激活,处在运行状态
图6 N310运行状态图
(范例完整代码将上传Github,但是今天梯子挂掉了,明天换个新的加速器后上传代码)
Github 链接如下:
XXXX
标签:范例,UHD,tx,--,收发,源码,usrp,arg,channel 来源: https://blog.csdn.net/zp54630499/article/details/118497390