You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 07:25:16