从零开始USRP 03 实现一个USRP收发demo(hello world)
这里用的源码来自:
UHD C/C++ 编程实例 USRP发送、接收数据
我所使用的USRP型号是N210r4,因此默认地址的最后一位是4,使用Ubuntu 20.04运行(至于为什么之前配的是18.04,那是因为之前是在我的虚拟机上玩耍的,但是我的虚拟机配网络有点麻烦,因此我给学姐的学长借了一台Linux笔记本,用这台笔记本做的实验。)
我的N210照片如下:
编译命令:
g++ rx.cpp -o rx -luhd
tx同理。
实际上,Cmake和G++在我电脑上的虚拟机上都很好使,但是在师姐给的这台linux上都很不好使,版本有点低,比如需要uhdlib4.0.0.0这个问题,当然这种简单的版本问题不存在什么学会学不会,只存在知道不知道,直接问ChatGPT老师就可以了。与此同时我也出现了找不到hpp文件的问题,也是直接问gpt老师就可以了,一般它列出来的条例能够解决99%的问题。但即使这样,在师姐上重新编译我已经编译好的文件,也废了我不少功夫。
后来呢,Tx和Rx两个cpp都编译好了,开始发射。
Tx运行正常,Rx运行正常!
只是二者都有亿点点warning,无视就好了(坏习惯,但是跑个hello world,你不无视,你不无视,你不无视尼玛呢!!)
然而,二者只是单独运行正常,周一来了我同时开始跑两个程序,即首先打开接收程序,然后开始发射,然后呢?接收程序就崩溃了,报了一个错误:
随后,我开始解决,解决了一整天,硬是解决不了。这次,这个问题网上基本上没有人遇到类似的问题,
找到的唯一和我报错相同的帖子只有这个:https://github.com/EttusResearch/uhd/issues/121
但是人家做的事情和我在做的事情基本没啥关系,而且这个帖子的问题最终也没有得到解决……
当然了,研究了一整天,问了师兄问了师姐,师兄后来还开始了玄学调bug哈哈可爱捏,最后得出了问题的根源。我这么好的人,我当然要在那个没有解决问题的帖子下面回复一下辣:
对没错,我研究了一整天的问题,很有可能就是因为,一台USRP只能使用一个程序来调用。可能这对于这个领域的人来说这简直是吃饭睡觉一样的常识性问题,但是对于我,一个从来没有接触过硬件的小白来说,这真的问题很大好吧,一整天的时间全部浪费了。
此外,这种常识性的问题,ChatGPT老师知道吗?
我就是问过他之后,我才肯定的这一点。
可以写到一个程序中调用收发,但是线程又很有可能出大问题……因此,我不玩了,先这样吧,这个HelloWorld浪费的时间太多了。我还是喜欢两个程序,调用两台USRP去模拟。但是我来福州出差就带了一台USRP,等回到清华之后,我找两台USRP来测试一下,按理来说,下面粘好的两版代码应该是没有问题了。
源码:
发射数据:
#include <uhd/usrp/multi_usrp.hpp> #include <signal.h> #define SAMPLE_PER_BUFF 2000 int stop_signal_called = 0; void sig_int_handle(int) { stop_signal_called = 1; printf("stop tx.........\n"); exit(0); } int main() { std::string addr_args = "addr=192.168.10.4"; uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(addr_args); printf("Create a usrp......\n"); // set the ref and clock rate std::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 \n", usrp->get_master_clock_rate() ); // set the sample rate float samp_rate = 20e6; usrp->set_tx_rate(samp_rate); printf("set the tx sample rate to %0.2f \n", usrp->get_tx_rate()); // set the center frequency float center_freq = 2.412e9; usrp->set_tx_freq(center_freq); printf("set the tx center freq to %0.2f \n", usrp->get_tx_freq()); // set the rf gain float tx_gain = 90; usrp->set_tx_gain(tx_gain); printf("set the tx gain to %0.2f \n", usrp->get_tx_gain()); // create a tx stream std::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 signal signal(SIGINT, sig_int_handle); float read_buff[SAMPLE_PER_BUFF * 2] = {0}; while(!stop_signal_called) { FILE *fp = fopen("hello_world.txt", "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; }
接收数据:
#include <uhd/usrp/multi_usrp.hpp> #include <csignal> #define SAMPLE_PER_BUFF 2000 int stop_signal_called = false; void sig_int_handle() { stop_signal_called = true; } int main() { std::string addr_args = "addr=192.168.10.5"; uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(addr_args); // set the clock source and clock rate std::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 \n", usrp->get_master_clock_rate() ); // set the sample rate float samp_rate = 20e6; usrp->set_rx_rate(samp_rate); printf("set the tx sample rate to %0.2f \n", usrp->get_rx_rate()); // set the center frequency float center_freq = 2.412e9; usrp->set_rx_freq(center_freq); printf("set the tx center freq to %0.2f \n", usrp->get_rx_freq()); // set the rf gain float rx_gain = 80; usrp->set_rx_gain(rx_gain); printf("set the tx gain to %0.2f \n", 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......\n"); break; } if(md.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW) { printf("Overflowing while stream......\n"); continue; } if(md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) { //printf("Receive error: %s \n", md.strerror()); continue; } //printf("num_rx_samps = %d \n",num_rx_samps); num_total_samps += num_rx_samps; } printf("num_total_samps = %lld \n", num_total_samps); stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; rx_stream->issue_stream_cmd(stream_cmd); return 0; }