主頁 > 後端開發 > GNU Radio系列教程(七):初級篇之GNU Radio GRC PSK調制解調

GNU Radio系列教程(七):初級篇之GNU Radio GRC PSK調制解調

2020-09-13 07:34:31 後端開發

在本文中,我們將進行純仿真實驗,不使用任何硬體設備,但是,我們會考慮無線信號在實際信道傳輸程序中所面臨的一些諸如信道衰落、時鐘同步等影響信號傳輸的問題,我們會在信道仿真模塊中,通過設定引數來模擬這些問題,然后一步一步的解決它們,最終實作信號的正確解調解碼,

本文的實體只是實作PSK調制解調的一種方法,這里我們使用了GNU Radio自帶的PSK信號解調模塊,除了本文的方法之外,還有很多其他的PSK解調實作方法,這些不同方法的實作細節相差較大,

本文目標

(1)理解信號失真和信道對信號傳輸的影響作用

(2)了解信號還原操作所涉及的步驟,如時鐘恢復、多徑效應消除、相位和頻率糾正、符號解碼和位元排序重構,

需要具備的基礎知識:

(1)Suggested Reading list:https://wiki.gnuradio.org/index.php/SuggestedReading

"The ARRL Handbook." A kind of hodge-podge of stuff. If you already know what you're looking for, you might be able to find it here. http://www.arrl.org(第11.5節)

(2)GNU Radio系列教程(二):初級篇之GNU Radio介紹

(3)GNU Radio系列教程(六):初級篇之GNU Radio GRC 硬體使用實體之信號頻譜分析

目錄

一、發射一個信號

二、加上信道仿真

三、時鐘恢復Timing recovery

1、什么是碼間干擾?如何消除碼間干擾?

2、鎖相環時鐘同步模塊

3、使用Polyphase Clock Sync模塊

四、多徑效應

1、什么是多徑效應

2、CMA均衡器

3、LMS DD均衡器

五、相位矯正和頻率微調

六、解碼

七、有用鏈接和聯系方式


一、發射一個信號

本實驗的第一步是發射一個QPSK信號,首先,生成一串位元資料,然后將其調制成復數星座資料(這里更準確的說,最好別叫調制,叫映射更合適一些,即將位元資料映射到星座圖中的星座點,)為了實作這步操作,我們使用GNU Radio中的Constellation Modulator block模塊,該模塊通過Constellation Rect. Object和其他引數的設定來實作QPSK調制功能,

Constellation Rect. Object”引數可以用來決定符號的編碼方式,“Constellation Modulator”模塊可以基于“Constellation Rect. Object”引數來實作調制(或稱為映射),在“Constellation Modulator”模塊中可以設定是否采用差分編碼(即“Differential Encoding”引數設定為“Yes”或“No”),由于“Constellation Modulator”模塊需要的輸入資料是位元組型別的資料,因此,在本例子中,我們使用“Random Source”模塊生成取值空間為0-255的位元組流,

對于“Constellation Modulator”模塊中的“Sample per symbol”引數的取值,一般的取值原則是盡可能小,其最小值為2,通常來說,當確定了硬體設備的采樣率之后,這個“Sample per symbol”取值是可以和GRC流圖中的“samp_rate”取值一起幫助我們達到要得到的位元速率,由于我們在本文中只是做的純仿真實驗,沒有使用任何軟體無線電開發板,本例子中的“Sample per symbol”取值只要能滿足GRC流圖中的資料速率即可,例如,在這里,我們選定了“Sample per symbol”為4,這個取值比實際需要的取值要大,但是有利于在時域或頻域來觀察信號,

最后,我們需要設定“Constellation Modulator”模塊中的“Excess BW”(帶外帶寬)因子取值,即均方根升余弦脈沖成形濾波器中的roll-off因子“alpha”,下圖(mpsk_rrc_rolloff.grc)流圖中在五個“Constellation Modulator”中分別設定了五種不同的roll-off因子“alpha”取值,即0.1(100m)、0.22(220m)、0.35(350m)、0.5(500m)、1,

在下邊的圖形中,紅色曲線表示“alpha”取值為0.2,綠色曲線表示“alpha”取值為0.35,

mpsk_stage1.grc生成了QPSK信號,并同時繪制了發射信號(transmitted signal)和接收信號(received signal)的時域圖、頻域圖和星座圖,注意,這里還沒有加上信道模塊,“Throttle”模塊的輸出信號就看作是QPSK發射信號,“Decimating FIR Filter”模塊的輸出信號就看作是QPSK接收信號,

在星座圖中,我們可以直觀的看到過采樣(因為我們把Sample per symbol設定成了4,其實實際上我們并不需要這么大的sps,所以叫做過采樣)和濾波操作的作用,例如,過采樣的結果就是我們在一個符號中生成了4個采樣值,在本例子中,均方根升余弦濾波器帶來了自干擾,也就是符號間干擾或叫碼間干擾(inter-symbol interference, ISI),ISI對于信號接收和還原來說是一個不利因素,我們將在后續的時鐘恢復環節重點解決這個問題,

此刻,我們先觀察生成的QPSK信號,在頻域圖形中,一方面,濾波器可以使得頻域信號的帶外功率明顯降低;另一方面,“Throttle”模塊的輸出信號被看作是QPSK發射信號,圖形中的圖示是“Tx”(藍色曲線),“Decimating FIR Filter”模塊的輸出信號被看作是QPSK接收信號,圖形中的圖示是Rx(紅色曲線),通過對比發現,經過了“Decimating FIR Filter”模塊的作用,接收信號的帶外功率明顯減少了,即在有效帶寬之外,紅色曲線的帶外功率明顯要低于了藍色曲線的帶外功率,這主要是因為,兩個均方根升余弦濾波器形成了一個升余弦濾波器(奈奎斯特濾波器),實作了匹配濾波器的效果,

二、加上信道仿真

上述例子只是生成了一個QPSK信號,接下來我們會研究分析生成的QPSK信號在經過信道傳輸發射和接收程序中會發生什么樣的失真效果,首先第一步是在上述例子的基礎上,添加上GNU Radio GRC的信道模塊(“Channel Model”),

GNU Radio GRC的信道模塊(“Channel Model”)可以幫助我們來仿真信號在信道傳輸程序中遭受的一系列影響因素,接識訓面臨的第一個影響因素就是“噪聲”,接識訓中存在的熱噪聲(Thermal noise)一般為加性高斯白噪聲( Additive White Gaussian Noise (AWGN)),通常,我們在GRC中設定噪聲的大小,是通過設定噪聲的電壓,而不是設定噪聲的功率,原因在于,信道模塊并不知道輸入信號的任何資訊,但是在計算噪聲的功率時,我們是需要知道信號的帶寬之后才能計算得到功率的,因此,我們通常是基于仿真流圖程式的其他引數,來推算噪聲的電壓值,

另外,在發射端和接收端之間,一個重要問題就是二者的本地時鐘同步問題,如果二者時鐘不同步,則會導致信號的頻率發生偏差,例如,發射端本來是要在中心頻率fc(例如,450MHz)發射信號,但是由于時鐘精度問題,發射端的實際信號發射頻率是fc+f_delta_1,與此同時,接收端存在一個時鐘偏差f_delta_2,也就是接收端本來要在中心頻率fc(例如,450MHz)接收信號,結果實際上卻是在fc + f_delta_2處接收信號,這樣一來,接收端與發射端相比,存在著f_delta_1+f_delta_2的偏差,(f_delta_1、f_delta_2可以是正數或負數,)

與發射端和接收端時鐘相關的另一個問題,就是采樣點問題,由于在生成QPSK信號的時候,我們進行了過采樣和脈沖成形操作,那么在接收端的時候,我們就需要考慮如何確保在原始的采樣點出進行采樣,以此來盡可能降低碼間干擾的影響,盡可能提升接收的有用信號功率,理想情況下,類似于mpsk_stage1.grc中的匹配濾波情形,我們可以在過采樣后的4個采樣點中找到一個合適的原始采樣點,但是,當發射端和接收端的時鐘不同步的情況下,理想采樣點是很難找到的,

在下圖的GRC流圖程式中,我們針對加性噪聲、頻率偏移、時鐘偏移進行了仿真,在“Channel Model”中的引數設定中,“Noise Voltage”=0.2(200m)、“Frequency Offset”=0.025(25m)、時鐘偏移“Epslion”=1.0005,

上圖中,我們發現星座點已經亂成了一團,接下來我們分別解決這些加性噪聲、頻率偏移、時鐘偏移問題,

三、時鐘恢復Timing recovery

為了實作時鐘還原,我們將采用GNU Radio GRC中的鎖相環時鐘同步(Polyphase Clock Sync)模塊,該模塊具有幾個功能:(1)實作時鐘恢復;(2)在接收端提供一個匹配濾波器,消除碼間干擾ISI;(3)實作降采樣(降采樣是相對于過采樣來說的),將信號轉換為1 sps(sample per second),

在“Polyphase Clock Sync”模塊內部,采用的是一種“polyphase filterbank ”技術,

https://wiki.gnuradio.org/index.php/Polyphase_Clock_Sync

該技術的大致原理為,該演算法對輸入信號進行差分計算,并在一系列的濾波器中設定不同的時間,只要濾波器的數量足夠多,達到了時鐘恢復所需的數量,其中的一個濾波器就可以輸出正確的時間所對應的相位,

時鐘恢復的最主要效果就是,可以找到輸入信號的最佳采樣時間,并在最大化每個采樣的信噪比的同時,盡可能降低碼間干擾,

1、什么是碼間干擾?如何消除碼間干擾?

在正式進行時鐘恢復之前,我們先看看到底什么是碼間干擾ISI,我們可以通過symbol_sampling.grc流圖程式來觀察什么是碼間干擾,在symbol_sampling.grc流圖程式中,我們用“Vector Source”模塊生成了四組序列,每組都是100位0、1組成的序列,在該程式中,第一部分是通過使用“Interpolation FIR Filter”模塊實作sps倍過采樣(例如這里sps=4,Interpolation引數為4),并使用了一個均方根升余弦濾波器,第二部分是通過使用“Decimating FIR Filter”模塊與第一部分的“Interpolation FIR Filter”組合起來形成了一個奈奎斯特升余弦濾波器(匹配濾波器),下邊的程式輸出波形對比了均方根升余弦濾波器和升余弦濾波器的輸出信號,均方根升余弦濾波器的輸出信號圖形中,在每個符號的理想采樣點處,其他符號存在一些功率能量,這樣一來,所有這些符號累加起來,就會導致理想采樣點處的符號發生失真,然而,在奈奎斯特升余弦濾波器(匹配濾波器)的輸出信號圖形中,在每個符號的理想采樣點處,其他符號的功率都是0,這也就意味著,只要我們的采樣時刻把握準確,每個采樣點處的某個符號與其他符號之間沒有任何碼間干擾,這就展示了如何通過使用匹配濾波器來完全消除ISI,

上述程式(symbol_sampling.grc)中,我們可以隨便修改sps、帶外帶寬、濾波器的抽頭數等數值,并對比觀察這些數值對采樣點的影響,

接下來,我們將利用symbol_sampling_diff.grc流圖程式,分析發射端和接收端時鐘差異到底會給信號采樣帶來多大的影響,發射端和接收端的時鐘不可能做到百分之百的同步,這主要是因為:1)發射端和接收端的開始采樣時間不一樣;2)任何兩個設備的時鐘無法做到完全同步,為了模擬發射端和接收端之間的時鐘差異,我們采用了“Polyphase Arbitrary Resampler”模塊,并通過其引數“Resampling Rate”來調整了發射端和接收端的采樣時間,即設定“Resampling Rate”=1.125,這個1.125數值是為了明顯展示出時鐘的差異性,實際上現實系統中這個時鐘差異取值都在百萬分之一的量級,但是,值得注意的是,本例中,我們連理想的采樣周期也是不知道的,在這種情況下,即使是發射端和接收端的時鐘做到了同步,那么任何采樣操作仍然也是會帶來碼間干擾的,

在這里,我們接下來的主要任務就是如何在只知道接收信號采樣值的情況下,實作發射端和接收端的時鐘或采樣時間同步,這叫做時鐘恢復(或時間恢復),

2、鎖相環時鐘同步模塊

有許多中可以用來實作接收端時鐘同步的方法,這些方法幾乎都要用到一些反饋控制環的思想,一般來說,可以借助于前導碼來實作同步,我們將利用polyphase filterbank時鐘恢復技術來實作時鐘同步,

通過計算第一個到達接收端信號的差分值(這個差分值域時鐘偏差是相關的),鎖相環時鐘恢復模塊實作了三個功能:1)實作時鐘恢復;2)實作匹配濾波器,消除了ISI;3)降采樣,將采樣率調整為1sps,

我們使用symbol_differential_filter.grc流圖程式來觀察差分濾波是如何幫我們實作時鐘同步的,首先,我們將觀察當不存在發射端和接收端時鐘差異時的接收信號,需要將“Polyphase Arbitrary Resampler”模塊的“Resampling Rate”引數設定為“1”,觀察輸出的波形,發現“sym0”波形的最高點(拐點)出現在0.22ms處,表示我們需要的采樣點在0.22ms,“Decimating FIR Filter”模塊(抽頭設定成了[-1, 0, 1])生成的“Symbol0”的差分(求導值),觀察圖形發現,該濾波器輸出信號在0.22ms處的取值正好為0,這就表明,我們找到了最佳的采樣點,

那么,當存在時鐘偏移的時候,情況會是什么樣的呢?即在“symbol0”曲線到達峰值(拐點處)的時間點處,其差分值(d(symbol0)/dt)不等于0,

接下來,我們將在symbol_differential_filter_phases.grc流圖程式中,使用一些列的濾波器,濾波器有不同的相位,理論上,只要我們有足夠多的濾波器,那么這些濾波器中就必然有一個濾波器可以幫我們得到正確的采樣點時間,如下圖所示,程式中使用了5個濾波器,對應著5個不同的相位,可以理解成這5個濾波器把0到2pi的相位平均分成了5份,這里,我們使用“fractional resampler”模塊來實作從0到1之間的相位偏移,不過這樣操作后會產生延遲,因此,我們在“Fractional resampler”模塊的后邊追加上了“Delay”模塊,

在該程式輸出波形中,我們看到標記為“d(sym0)/dt+phi3”的波形,在“sym0”最高峰(拐點)所對應的時間點處的采樣值為0,這意味著,我們的理想采樣點處于這個相位偏差值,雖然這個程式的時間精度不是特別精確,但是基本也展示出來了不同濾波器不同相位偏差的差異性,

上述結果只是純仿真的結果,在實際發射接收程序中,所有濾波器的某時刻采樣點不可能同時出現在同一個時間點上,我們不得不通過采取過采樣來逼近這個效果,因為過采樣可以為我們接下來深入分析提供幫助,我們可以將不同濾波器看作是一個過采樣指數為M的復雜濾波器,例如本子中的M=5,在原始信號sym0的最高峰(拐點)對應的時刻,我們以5倍過采樣來查找到底哪個濾波器的輸出信號是0,這樣做的后果是,可能會帶來較大的計算開銷,而且計算開銷是與采樣率成正比的,但是,如果我們通過調整不同濾波器的對原始信號相位的修改,我們就可以避免產生過大的計算開銷,因此,在上述的例子中,我們將采樣率偏移了1.2倍,并通過5個濾波器的相位偏移,找到了最佳采樣點所對應的相位偏差,但是,我們僅僅有5個濾波器,如果在不同濾波器之間存在任何采樣偏差,仍然會帶來明顯的ISI,為了避免此種情況發生,我們將在接下來的例子中使用32個濾波器,以此來盡可能保證ISI噪聲低于16位元量化噪聲,如果我們有更高的要求,我們還可以使用更多個濾波器,

到這里,我們知道了,原來我們可以通過使用多個濾波器來找到其中一個能夠實作最佳采樣的濾波器,實作時鐘恢復,但是我們如果才能自動找到這個濾波器呢?為了解決這個問題,接下來我們將使用二階控制回路(2nd order control loop),差分濾波器的輸出信號是存在錯誤的信號,控制環路開始作業于其中一個濾波器,計算輸出信號作為錯誤信號(error signal),接下來控制環路根據錯誤信號,等比例的增加或減少濾波器,直到找到錯誤信號最接近于0的濾波器,這就是我們要找的最佳濾波器,【這句話暫時還不是理解,后續繼續琢磨,】

從github下載的GNU Radio原始碼中,在“gr-digital”檔案夾下的“examples”檔案夾下,找到“ example_timing.py”腳本,你可以運行該腳本,觀察“Polyphase Clock Sync recovery”的“收斂”特性,

3、使用Polyphase Clock Sync模塊

現在,我們將在仿真程式mpsk_stage3.grc中使用“Polyphase Clock Sync”模塊,該程式中“Channel Model”模塊的輸出信號輸入給“Polyphase Clock Sync”模塊,該模塊使用了32個濾波器,“Loop Bandwidth”為2pi/100,“Samples/Symbol”為4.004,這里,為什么要設定為4.004?只是我們為了將sps設定的與原本“Constellation Modulation”模塊的sps稍微不同而已,以此來表示發射端和接收端的時鐘偏差,在“Channel Model”模塊中,“Epsilion”的數值為“time_ offset”引數,該引數的默認值為1.0,

當運行mpsk_stage3.grc程式時,我們會看到左邊的星座圖是沒有實作時鐘恢復的(星座點雖然能大致看出來是QPSK,但是比較凌亂),右邊的星座圖是實作了時鐘恢復的(基本上算是一個可以接受的QPSK星座圖),但是由于在“Channel Model”模塊中設定了噪聲的電壓(即例如“Noise Voltage”=200m),所以即使是右邊實作了時鐘恢復的星座圖,從星座點也能看出來存在一定的噪聲,

我們可以調節“Timing Offset”的數值,在調節這個數值的程序中,你會發現,右邊實作了時鐘恢復的星座圖保持不動,這說明確實實作了時鐘恢復,不會受“Timing Offset”的影響,但是,當我們調節“Frequency Offset”數值時,會發現右邊實作了時鐘恢復的星座圖會變成一個圓圈,但是星座點固定是在一個圓上,這說明,雖然存在頻率偏移,但是星座圖仍然保持了正確的時鐘,但是由于mpsk_stage3.grc程式沒有解決頻率偏移的問題,所以我們需要在接下來的程式中,利用其它的模塊來抵抗頻率偏移問題,此外,“Channel Model”模塊中的“Taps”引數可以用來仿真傳輸信道的多徑效應,當增加了多徑效應仿真(例如將Taps由1修改為其他的復數取值),時鐘恢復操作對于多徑效應具有一定的魯棒性的,但是它無法完全消除多徑效應的作用,星座點變得沒有那么集中,這需要后續我們專門針對多徑效應,采取均衡器來完全消除多徑效應作用,

接下來,我們將先采用均衡器來解決多徑效應,然后再采用科斯塔斯環來解決頻率偏移問題,

四、多徑效應

1、什么是多徑效應

何為多徑效應?多徑效應(multipath effect)指電磁波經不同路徑傳播后,各分量場到達接收端時間不同,按各自相位相互疊加而造成干擾,使得原來的信號失真,或者產生錯誤,比如電磁波沿不同的兩條路徑傳播,而兩條路徑的長度正好相差半個波長,那么兩路信號到達終點時正好相互抵消了(波峰與波谷重合),【摘自百度百科-多徑效應】

在發射端和接收端之間,不僅僅存在一條傳輸路徑,在發射端和接收端之間存在的物體會成為信號傳輸的反射物,導致生成新的傳輸路徑,最終形成多條路徑傳播的效果,

多個路徑信號到到接收端疊加在一起的作用可能會導致信號失真,當兩個路徑信號達到接收端的時間差小于符號周期的話,那么失真發生在一個符號周期內部,叫做符號內多徑干擾,當兩個路徑信號達到接收端的時間差大于符號周期的話,信號失真作用與相鄰的不同符號,這叫做符號間干擾(也經常叫做碼間干擾),multipath_sim.grc(GRC v3.7和v3.8,這個程式有了較大的變化,以下截圖是v3.8的)程式給出了多徑效應的作用結果,我們將在后續的程式中,使用均衡器來解決多徑效應問題,類似于音響的立體均衡器,用于無線通信中的均衡器也是通過改變(加大或減小)特定頻率的信號增益,來使得到達接收端的信號變得均衡,

該程式建立了一個擁有五個均衡器控制的信道模型,其中四個是可以由用戶調節的,一個是固定不變的,用戶可以在0-1之間來調節,當取值為1時,均衡器將允許信號無損失的“通過”,當取值為0時,則均衡器將完全阻止信號“通過”,注意這里的通過是打雙引號的,

在實體multipath_sim.grc中,我們通過明確控制頻域的仿真方式,來實作對接收信號頻率回應的糾正和調節,最終目標是利用均衡器來對抗信道的衰落作用,使得接收信號在頻域上看起來變得平坦,但是,與在實體multipath_sim.grc中手動修改taps不同的是,一般我們都是通過選用合適的均衡器并設定好均衡器的引數,由均衡器演算法來自動實作均衡效果的,均衡器中的taps抽頭越多,效果會約好,但是也會帶來更多的計算開銷,

2、CMA均衡器

GNU Radio中有兩個經常用的均衡器,CMA均衡器和LMS DD均衡器,CMA(Constant Modulus Algorithm)均衡器是一種盲均衡器,只適用于信號幅度固定的場景,這也就意味著注入MPSK調制信號(幅度固定,相位變化)是非常適合用CMA均衡器的,

CMA演算法的輸入是均衡器的抽頭數量,這個數量是基于對信道質量的預測和信道的實際觀測值來決定的,我們需要在確保能夠滿足信道均衡要求的前提下,盡量讓抽頭數小一些,以此來避免產生過大的計算開銷,

在mpsk_stage4.grc程式中,CMA演算法使用了11個抽頭,運行該程式,觀察效果,

運行該程式后,我們會發現均衡器起到的作用,對比“CMA Equalizer”模塊的輸入和輸出信號,在經過均衡處理之前的信號在不同的頻率上,增益起伏變化較大,但是在經過了均衡處理后的信號則在不同頻率上變得非常平坦,

3、LMS DD均衡器

與CMA是一個盲均衡器不一樣,LMS DD均衡器是一個需要知道接收信號知識的均衡器,均衡器需要知道接收信號的星座點,以此來消除多徑效應,并且通過觀察均衡結果來動態更新抽頭的引數,LMS DD均衡器可以用于CMA均衡器無法滿足的場景,例如QAM調制信號場景(幅度是不固定的),

如果接收信號質量太差(SNR太差),則LMS DD均衡器的已知資訊則會誤導其后續的均衡操作,進而影響后續的解調解碼作業,當接收信號質量好的時候,則LMS DD均衡器則會發揮積極有效的作用,在實際系統中,一般是先用盲均衡器來得到足夠好的信號,然后再用非盲均衡器來繼續完成均衡操作,這里不再展示LMS DD均衡器,大家可以基于mpsk_stage4.grc來改造完成LMS DD均衡器程式,

五、相位矯正和頻率微調

在實作了信號均衡操作后,我們還需要解決相位和頻率偏移的問題,有兩件事請需要做:第一,使用一個二階環路來跟蹤相位和頻率(頻率其實就是相位的求導結果),第二,這里我們做的恢復是微調恢復,因此,我們必須確定已經確定了理想頻率,如果沒有確定的話,那么我們使用二階環路的結果也無法達到預期效果,接下來,我們將在mpsk_stage5.grc使用科斯塔斯環(Costas Loop),科斯塔斯環可以用于為BPSK、QPSK、8PSK實作相位和頻率同步,

在“Costas Loop”模塊中,需要確定兩個引數,第一,“Loop bandwidth”引數,第二,調制階數(例如BPSK是2,QPSK是4,8PSK是8),下邊左邊圖形表示經過“CMA Equalizer”處理的輸出的時鐘同步信號,但是由于存在噪聲、時鐘偏移、頻率偏移等影響因素,星座點雖然在一個圓圈上,但是不是正常的QPSK星座圖,下邊右邊圖形是經過“Costas Loop”模塊處理后的信號,已經變成了一個正常的QPSK星座圖(盡管由于存在噪聲,每個星座點不是一個點,而是一小簇),

六、解碼

到現在為止,前邊已經將比較難啃的骨頭都解決了,最后一步就是實作解碼了,我們在mpsk_stage6.grc程式中,添加一個Constellation Decoder模塊來實作解碼,并使用“Map”模塊來實作符號映射關系的轉換,使用“Unpack K Bits”模塊來分解bit,得到原始的bit流資料,

但是,我們如何才能判斷我們解碼的資料是否是正確的呢?由于我們是仿真程式,我們知道發送的原始bit資料,我們通過對比這兩份資料來查看解碼資料是否正確,但是由于前邊做各種同步和均衡等操作,引入了延遲,所以我們需要將發送的原始資料進行延遲后,再跟解碼后資料進行比對,

七、有用鏈接和聯系方式

https://wiki.gnuradio.org/index.php/Guided_Tutorial_PSK_Demodulation

淘寶店鋪、QQ技術交流群、CSDN聯系方式如下:

微信公眾號二維碼:

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/22024.html

標籤:java

上一篇:【方案搭建】如何使用RTSP協議網路攝像頭直播視頻平臺EasyNVR搭建智慧園區管理平臺?

下一篇:leetcode *216. 組合總和 III

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more