UHD庫 C/C++ USRP發送、接收數據

UHD庫 C/C++ USRP發送、接收數據

更多SDR LTE相關博客請鏈接 blog.csdn.net/jxwxg

1. UHD庫函數簡介

發送函數

新建一個usrp設備

std::string args = " "; args指定USRP地址,配置USRP參數等 uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);

設置時鐘源和時鐘頻率

std::string ref = "internal"; // internal, external, MIMO. usrp->set_clock_source(ref); double rate = 40e6; usrp->set_master_clock_rate(rate);usrp->get_clock_source() //獲取當前的時鐘源 usrp->get_clock_sources() //獲取所有可用的時鐘源 usrp->get_master_clock_rate(); //獲取時鐘頻率

設置採樣率

double samp_rate = 20e6; usrp->set_tx_rate(samp_rate);usrp->get_tx_rate() //獲取當前的採樣率 usrp->get_tx_rates() //獲取採樣率的採樣範圍

設置發射中心頻點

double freq = 2.412e9; usrp->set_tx_freq(freq);usrp->get_fe_tx_freq_range(); usrp->get_tx_freq(); usrp->get_tx__freq_range();

設置發射增益

double tx_gain = 60; usrp->set_tx_gain(tx_gain);

設置發射天線

默認情況下無需設置發射天線,如需指定特定發射天線時設置。

usrp->set_tx_antenna(0); usrp->get_tx_antenna(); usrp->get_tx_antennas();

創建發送流

新建發送流參數

std::string cpu_format = "fc32"; 目前cpu_format支持的類型有:fc64 - complex fc32 - complex sc16 - complex sc8 - complex std::string wire_format = "sc16"; 目前wire_format支持的類型有:sc16 - Q16 I16 sc8 - Q8_1 I8_1 Q8_0 I8_0

uhd::stream_args_t stream_args(cpu_format, wire_format); uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args);

中頻數據管理

uhd::tx_metada_t md; //結構體描述接收到的中頻信號 md.start_of_burst = false; // 設置為真的時候發送第一個數據包 md.end_of_burst = false; // 設置為真的時候發送最後一個數據包 md.has_time_spec = false; // 設置為false時立即發送,設置為真的時候在特定時間發送

接收函數

創建一個usrp

std::string args = " "; uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);

設置時鐘源和時鐘頻率

std::string ref = "internal"; //internal, external and MIMO usrp->set_clock_source(ref);

double clock_rate = 40e6; usrp->set_master_clock_rate(clock_rate);

設置採樣率

double rate = 20e6; usrp->set_rx_rate(rate);

設置中心頻率

double freq = 2.412e9; usrp->set_rx_freq(freq);

設置增益

double rx_gain = 50; usrp->set_rx_gain(rx_gain);

創建接收流

std::string cpu_format = "fc32"; std::string wire_format = "sc16"; uhd::stream_args_t stream_args(cpu_format, wire_format); uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);

設置接收模式

uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);//UHD_STREAM_MODE_START_CONTINUOUS=97, //UHD_STREAM_MODE_STOP_CONTINUOUS=111, //UHD_STREAM_MODE_NUM_SAMPS_AND_DONE=100, //UHD_STREAM_MODE_NUM_SAMPS_AND_MORE=109

stream_cmd.num_samps = 1000; // 接收採樣點數 stream_cmd.stream_now = true; //現在開始接收 rx_stream->issue_stream_cmd(stream_cmd); //配置rx_stream參數

2. USRP發送數據

  代碼實現USRP發送二進位文件802.11a_BUPT41.seg內的數據。裡面的數據為float complex類型,複數的實部和虛部交替存儲。即如下圖所示。用戶可以把要發送的數據生成對應的二進位文件,也可以直接寫成數組放在代碼中。注意:float類型數據的單位1就是 「1」。

源碼

#include <uhd/usrp/multi_usrp.hpp>#include <signal.h>#define SAMPLE_PER_BUFF 2000int stop_signal_called = 0;void sig_int_handle(int){stop_signal_called = 1;printf("stop tx.........
");exit(0);}int main(){std::string addr_args = " ";uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(addr_args);printf("Create a usrp......
");// set the ref and clock ratestd::string ref = "internal";usrp->set_clock_source(ref);float clock_rate = 40e6;usrp->set_master_clock_rate(clock_rate);printf("set the clock rate %0.2f
", usrp->get_master_clock_rate() );// set the sample ratefloat samp_rate = 20e6;usrp->set_tx_rate(samp_rate);printf("set the tx sample rate to %0.2f
", usrp->get_tx_rate());// set the center frequencyfloat center_freq = 2.412e9;usrp->set_tx_freq(center_freq);printf("set the tx center freq to %0.2f
", usrp->get_tx_freq());// set the rf gainfloat tx_gain = 90;usrp->set_tx_gain(tx_gain);printf("set the tx gain to %0.2f
", usrp->get_tx_gain());// create a tx streamstd::string cpu_format = "fc32";std::string wire_format = "sc16";uhd::stream_args_t stream_args(cpu_format, wire_format);uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args);uhd::tx_metadata_t md;// catch the INT signalsignal(SIGINT, sig_int_handle);float read_buff[SAMPLE_PER_BUFF * 2] = {0};while(!stop_signal_called){FILE *fp = fopen("802.11a_BUPT41.seg", "rb");md.start_of_burst = false;md.end_of_burst = false;while( (!md.end_of_burst) && (!stop_signal_called) ){int read_length = 0;if( (read_length = fread(read_buff, sizeof(uint32_t), SAMPLE_PER_BUFF * 2, fp) ) == (SAMPLE_PER_BUFF * 2) ){//int index;//for(index = 0; index < SAMPLE_PER_BUFF * 2; index++)// printf("%0.2f ", read_buff[index]);//puts("");//md.start_of_burst = true;tx_stream->send(read_buff, SAMPLE_PER_BUFF, md);//md.start_of_burst = false;//sleep(1);}else if(read_length >= 0){md.end_of_burst = true;}}fclose(fp);}return 0;}

編譯

g++ 編譯時需要鏈接uhd庫,系統需提前安裝UHD驅動。具體過程參見之前博客。Ubuntu14.04 源碼安裝 UHD3.8.0

g++ tx.cpp -o tx -luhd

3. USRP接收數據

  啟動USRP,並使USRP一直接收數據。

源碼

#include <uhd/usrp/multi_usrp.hpp>#include <csignal>#define SAMPLE_PER_BUFF 2000int stop_signal_called = false;void sig_int_handle(){stop_signal_called = true;}int main(){std::string addr_args = " ";uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(addr_args);// set the clock source and clock ratestd::string ref = "internal";usrp->set_clock_source(ref);float clock_rate = 40e6;usrp->set_master_clock_rate(clock_rate);printf("set the clock rate %0.2f
", usrp->get_master_clock_rate() );// set the sample ratefloat samp_rate = 20e6;usrp->set_rx_rate(samp_rate);printf("set the tx sample rate to %0.2f
", usrp->get_rx_rate());// set the center frequencyfloat center_freq = 2.412e9;usrp->set_rx_freq(center_freq);printf("set the tx center freq to %0.2f
", usrp->get_rx_freq());// set the rf gainfloat rx_gain = 80;usrp->set_rx_gain(rx_gain);printf("set the tx gain to %0.2f
", usrp->get_rx_gain());std::string cpu_format = "fc32";std::string wire_format = "sc16";uhd::stream_args_t stream_args(cpu_format, wire_format);uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);uhd::rx_metadata_t md;//uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);stream_cmd.num_samps = SAMPLE_PER_BUFF;stream_cmd.stream_now = true;//stream_cmd.time_spec = uhd::time_spec_t();stream_cmd.time_spec = usrp->get_time_now();rx_stream->issue_stream_cmd(stream_cmd);uint32_t buff[SAMPLE_PER_BUFF*2] = {0};unsigned long long num_total_samps = 0;while(!stop_signal_called){//int num_rx_samps = rx_stream->recv(buff, SAMPLE_PER_BUFF, md);memset(buff, 0, SAMPLE_PER_BUFF * sizeof(uint32_t));int num_rx_samps = rx_stream->recv(buff, SAMPLE_PER_BUFF, md, 3.0, false);if(md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT){printf("Timeout while streaming......
");break;}if(md.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW){printf("Overflowing while stream......
");continue;}if(md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE){//printf("Receive error: %s
", md.strerror());continue;}//rintf("num_rx_samps = %d
",num_rx_samps);num_total_samps += num_rx_samps;}printf("num_total_samps = %d
", num_total_samps);stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS;rx_stream->issue_stream_cmd(stream_cmd);return 0;}

編譯

g++ 編譯時需要鏈接uhd庫,系統需提前安裝UHD驅動。具體過程參見之前博客。Ubuntu14.04 源碼安裝 UHD3.8.0

g++ rx.cpp -o rx -luhd

4. 結論

  以上代碼在Ubuntu上採用USRP B200測試通過。

  掌握UHD庫函數的使用、g++ 鏈接 UHD庫等是基於USRP開發軟體無線電項目的基礎。之後,我們可以進一步設計發送程序和接收程序,用USRP搭建一套SDR 收發系統。


推薦閱讀:

TAG:無線通信 | C編程語言 | 信號傳輸 |