USRP B210运行时动态切换天线可行性咨询
USRP B210运行时动态切换子设备/天线可行性及实现方案
我正在开发一款基于USRP B210的基础收发功能C++程序,当前可通过单个子设备完成信号收发。但希望实现运行时动态切换天线,比如在子设备1的RX2与子设备2的RX2间切换,请问USRP运行时切换子设备是否可行?
可行性结论
运行时动态切换子设备对应的天线是完全可行的,UHD原生API提供了无需重启设备或流即可修改天线配置的接口,只需在切换时处理好流的启停逻辑,避免配置冲突。
实现要点
- 切换前必须暂停当前的接收/发射流,防止配置修改与正在进行的流操作冲突
- 使用
set_rx_antenna()/set_tx_antenna()接口,通过子设备索引参数区分不同子板的天线配置 - 切换完成后重新启动流,且可通过
get_rx_antenna()验证配置是否生效
修改后的实现代码
针对你提供的代码,补充天线切换逻辑并修复潜在问题:
#include <src/sdr/usrpdriver.h> #include <atomic> #include <chrono> #include <thread> #define DEBUG false #define NUM_SAMPS (1 << 16) // 修正原2^16的错误,用移位表示2的16次方 #define TXENABLED USRPDriver::USRPDriver() : m_bRxRunning(false) { try { usrp = uhd::usrp::multi_usrp::make(std::string("")); } catch(...) { int r = QMessageBox::warning(0, tr("Expedite"), tr("USRP Device Unreachable.\nContinue without Device?"), QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); if (r == QMessageBox::Yes) { m_bDeviceUp = false; return; } else if (r == QMessageBox::Cancel) { abort(); } } m_bDeviceUp = true; moveToThread(&m_Thread); QObject::connect(&m_Thread,SIGNAL(started()),this,SLOT(RxEventLoop())); // 锁相板时钟 usrp->set_clock_source("internal"); // 设置收发采样率 usrp->set_tx_rate(MIN_SAMP_RATE_USRP); usrp->set_rx_rate(MIN_SAMP_RATE_USRP); // 初始化流参数 uhd::stream_args_t stream_args("fc32"); tx_stream = usrp->get_tx_stream(stream_args); rx_stream = usrp->get_rx_stream(stream_args); // 重置时间戳 usrp->set_time_now(uhd::time_spec_t(0.0)); // 启动线程 Start(); } void USRPDriver::RxEventLoop() { if(!m_bDeviceUp) return; uhd::rx_metadata_t md; std::vector<std::complex<float>> fcpxIQ(NUM_SAMPS); while(true) { if(m_bRxRunning) { size_t num_rx_samps = rx_stream->recv(&fcpxIQ[0], NUM_SAMPS, md); // 处理流元数据错误(如溢出、超时) if(md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) { // 可选:添加错误日志逻辑 } emit ReceiveIQ(fcpxIQ); } else { // 暂停时休眠,避免空循环占用CPU std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } } void USRPDriver::UpdateTransceiverSettings(TransceiverSettings Settings) { if(!m_bDeviceUp) return; // 1. 暂停接收流,确保配置修改无冲突 m_bRxRunning = false; std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 2. 根据配置映射目标子设备与天线 size_t mboard_idx; std::string antenna; if(Settings.m_nTMAntenna == 1) { mboard_idx = 0; // 子设备1对应索引0 antenna = "RX2"; } else if(Settings.m_nTMAntenna == 2) { mboard_idx = 1; // 子设备2对应索引1 antenna = "RX2"; } else { // 默认使用子设备1的RX2 mboard_idx = 0; antenna = "RX2"; } // 3. 设置目标子设备的天线 usrp->set_rx_antenna(antenna, mboard_idx); // 验证配置是否生效 std::string current_antenna = usrp->get_rx_antenna(mboard_idx); if(current_antenna != antenna) { // 可选:添加配置失败处理逻辑 } // 4. 更新本地配置并重启接收流 m_Settings = Settings; m_bRxRunning = true; uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); stream_cmd.stream_now = true; rx_stream->issue_stream_cmd(stream_cmd); }
关键修改说明
- 修正了
NUM_SAMPS的定义错误:原2^16是按位异或运算,改为1 << 16表示65536个采样点 - 添加
std::atomic<bool> m_bRxRunning变量,安全控制接收流的启停,避免多线程冲突 - 在切换天线前暂停流,确保配置修改时无正在进行的收发操作
- 通过子设备索引参数
mboard_idx指定要修改的子板,USRP B210的两个子设备对应索引0和1
内容的提问来源于stack exchange,提问作者Moses Browne Mwakyanjala
相关产品推荐
相关产品推荐

