2ASK调制解调实验
一,數字信號的鍵控調制
在數字調制技術中,由于數字信號具有離散值的特點,因此數字調制技術通常有兩種 方法:一是利用模擬調制的方法去實現數字調制,即把數字調制看成是模擬調制的一個特 例,把數字基帶信號當做模擬信號的特殊情況來處理;二是利用數字信號的離散取值特點 通過開關鍵控載波,從而實現數字調制。這種方法通常稱為鍵控法,比如對載波的振幅、 頻率和相位進行鍵控,便可以獲得振幅鍵控(Amplitude Shift Keying,ASK)、頻移鍵 控(Frequency Shift Keying,FSK)和相移鍵控(Phase Shift Keying,PSK)。 數字信息有二進制和多進制之分,因此數字調制可以分為二進制調制和多進制調制。 調制信號是二進制數字基帶信號時,這種調制稱為二進制數字調制。在二進制數字調制中, 載波的幅度、頻率和相位只有兩種變化狀態。相應的調制方式有二進制振幅鍵控(2ASK)、 二進制頻移鍵控(2FSK)和二進制相移鍵控(2PSK)
二,2ASK原理
2ASK又稱為二進制啟閉鍵控(On-Off Keying),它是以單極性不歸零碼來控制載波的開啟和關閉,而其頻率和初始相位保持不變,其調制方式出現得比模擬調制還早。雖然 2ASK 的抗干擾性能不如其他的調制方式,在無線通信中未得到實際應用,由于其實現簡單,在光纖通信中獲得廣泛應用。
2ASK 信號的產生原理圖:
假設二進制信源{b n }的序列取值為 1 或 0,發送濾波器的沖激相應為 g(t),則二進 制序列經過發送成形濾波器之后的基帶信號與載波相乘,即可得到 2ASK 信號,
其波形如圖所示?
?根據 2ASK 波形特點和鍵控調制法的基本原理,在本實驗中,我們的調制方式為:將 原始的二進制基帶信號與某一個載波信號(正弦波)相乘,即可得到 2ASK 已調信號。需 要注意的是,基帶碼元寬度要和載波周期相同,這就需要一些基帶碼元擴展手段。 和一般的解調方式一樣,2ASK也有相干解調和非相干解調兩種方法。在本實驗中, 采用類似于相干解調的方法,將兩路2ASK信號相乘取模,對于相乘后的信號,大于零的 信號則是原始基帶信號中的碼元‘1’,而為零的信號則是原始基帶信號中的碼元‘0’。 由此我們可以恢復出原始信號,即實現了2ASK信號的解調
三,代碼設計分析
1,發送端
%-----產生 I、Q 兩路載波信號,并量化-----% carrier_I=round(cos(2*pi/20*[0:19]).*30000); carrier_Q=round(sin(2*pi/20*[0:19]).*30000);?當產生隨機的二進制碼流之后,根據鍵控法的基本思想,每個碼元的寬度必須和 載波周期相同,以上分析可知,我們產生的載波一個周期為 20 個數據點,因此我們必須 將原始碼流的每一位擴展為 20 位,代碼如下:
%-----數據源數量-----% bit_Num = 500; %-----每個碼元占據 20 個采樣點,20M 采樣率下為 1M-----% bit_Width = 20; %-----產生隨機數據幀,length=500-----% bit_trans = randint(1,bit_Num); %-----數據擴展,每個碼元擴展為 20 位-----% tmp1 = repmat(bit_trans',1,bit_Width); data_trans = reshape(tmp1',1,length(tmp1).*bit_Width);?若產生 500bit 的原始流,經 20 倍擴展之后的數據量為 500*20=10000bit。 因此,我們也需要將載波擴展為 10000bit,代碼如下:
%-----載波擴展,長度和 data_trans 相等-----% carrier_I=repmat(carrier_I,1,bit_Num); carrier_Q=repmat(carrier_Q,1,bit_Num); carrier=carrier_I+1i*carrier_Q;至此,我們直接用鍵控法進行 2ASK 調制,即讓原始二進制碼元和載波直接相乘,即可得到 2ASK 已調信號。我們可以畫出調制好的信號 mod_dat
?發送數據時為 AD9361 實時循環發送,在接收端對數據進行解調的首 要任務就是進行幀數據到達檢測, 假設我們發送的數據幀長度為 500bit,那么在接收端 必須找到數據的起始位置,然后取出一幀數據(有效精準數據)進行解調處理。使用訓練序列進行幀同步,所用的算法為改進的 S&C 算法。在 mod_data 的前面插入一段特殊 的訓練序列,接收端進行窗口滑動數據到達相關性檢測,即可得到起始幀位置。關于此算 法的詳細原理,在 QAM 實驗部分有詳細講解,讀者可參考,在此不贅述。創建幀同步訓 練序列的函數調用為:[training]=creat_training();然后進行數據組幀。
%-----數據組幀-----% txdata=[training mod_data]; txdata 既是最終發送的數據。2,接收端
對于接收端,我們需要接收發送端的 2ASK 調制信號,因此 AD9361 的采樣率和頻點必 須與發送端一致,即: samp_hex=dec2hex(20e6,8); freq_hex=dec2hex(999e6,10); 接收到的信號應該是兩路正交的 IQ 正弦波信號,他們的頻率為 1MHZ(本實驗中為 a1 和 a2)。 接收端的首要任務就是進行幀同步,幀同步的函數調用為:
%-----起始幀同步-----% [frame_data,syn_symbol] = rx_frame_sync(a1+a2,a1,a2,mod_data);在幀同步函數中,通過調用 syn_time 函數求得幀同步相關性曲線,然后找到曲線最大值點的索引號,即 可得到起始幀位置:
syn_symbol=syn_time(frame_all); [s1,s2]=max(syn_symbol(1:length(syn_symbol)/2)); frame_begin=s2+576; frame_end=frame_begin+length(txdata_x); %------------找到幀位置后組成一幀數據----------------% frame_data_I=data_I(frame_begin:frame_end); frame_data_Q=data_Q(frame_begin:frame_end); frame=frame_data_I+1i*frame_data_Q; frame_data=frame(2:end);frame_data 既是發送端的有效數據幀,此幀數據已經丟棄了訓練序列,所以直接對它 進行解調處理即可。 解調端對數據進行解調的思路也比較簡單,由上述關于2ASK的解調原理可知,我們 可以將兩路調制信號相乘,結果中大于0的即判為碼元‘1’,小于等于 0 的即判為碼元 ‘0’。代碼如下:
%-----數據解調,采用幅度判決方法-----% receive_sig=abs(frame_data)>5000;由于信道噪聲影響,實際情況下,選取判別基準值為 5000,可以很好的恢復出原始 信號。 在發送端對信號進行調制時,我們進行了 20 倍的數據擴展,因此最后解調時,要進 行 20 倍的抽取,抽取之后的數據即是原始碼元信息。
%-----每隔 20 個點抽取一個點作為解調信號-----% dimod_data=receive_sig(4:20:end);?四,matlab代碼
1,運行發送端程序 tx_2ASK.m,當 matlab 命令行端顯示“data transfer done”時, 表明數據正常發送完畢
clc; clear all; close all; warning off; %****************ht7600*******************// %ref_hex 1=external ref;0=internal ref %vco_cal_hex 1=AUXDAC1;0=ADF4001 %fdd_tdd_hex 1=FDD 0=TDD %trx_sw_hex 1=TX 0=RX %****************ht7600*******************// rcount=dec2hex(10,4);%reference clock divide ncount=dec2hex(26,4);%internal vctcxo divide ref_hex=dec2hex(0,8);%1=external ref 0=internal ref vco_cal_hex=dec2hex(1,8);%1=auxdac 0=reference clock aux_dac1_hex=dec2hex(0,8); fdd_tdd_hex=dec2hex(1,8); trx_sw_hex=dec2hex(1,8);samp_hex=dec2hex(20e6,8); bw_hex=dec2hex(18e6,8); freq_hex=dec2hex(2140e6,10); %%for ad9361 tx_att1=dec2hex(30000,8); tx_att2=dec2hex(30000,8); tx_chan=1;%1=tx1;2=tx2;3=tx1&tx2 %=====以下為數據調制部分=====% %-----數據源數量-----% bit_Num = 500; %-----每個碼元占據20個采樣點,20M采樣率下為1M-----% bit_Width = 20; %-----產生隨機數據幀,length=500-----% bit_trans = randint(1,bit_Num); %-----數據擴展,每個碼元擴展為20位-----% tmp1 = repmat(bit_trans',1,bit_Width); data_trans = reshape(tmp1',1,length(tmp1).*bit_Width); %-----產生I、Q兩路載波信號,并量化-----% carrier_I=round(cos(2*pi/20*[0:19]).*30000); carrier_Q=round(sin(2*pi/20*[0:19]).*30000); %-----載波擴展,長度和data_trans相等-----% carrier_I=repmat(carrier_I,1,bit_Num); carrier_Q=repmat(carrier_Q,1,bit_Num); carrier=carrier_I+1i*carrier_Q; %-----鍵控2ASK信號調制-----% mod_data=data_trans.*carrier; %-----創建幀同步訓練序列-----% [training]=creat_training(); %-----數據組幀-----% txdata=[training mod_data]; %==========================================% %% copy to 2chanel if tx_chan==1 || tx_chan==2txdata2=txdata; elseif tx_chan==3txdata2=zeros(1,length(txdata)*2);txdata2(1:2:end)=txdata;txdata2(2:2:end)=txdata; end %% iq mux txdatas=zeros(1,length(txdata2)*2); txdatas(1:2:end)=real(txdata2); txdatas(2:2:end)=imag(txdata2); %% add pad rem=-1; i=0; while (rem<0)rem=1024*2^i-length(txdatas);i=i+1; end txdata1=[txdatas zeros(1,rem)]; txd1=(txdata1<0)*65536+txdata1; txd2=dec2hex(txd1,4); txd3=txd2(:,1:2); txd4=txd2(:,3:4); txd5=hex2dec(txd3); txd6=hex2dec(txd4); txd7=zeros(length(txd6)*2,1); txd7(1:2:end)=txd6; txd7(2:2:end)=txd5;%% open control port ctrl_link = udp('192.168.1.10', 5006); fopen(ctrl_link); %% open data port data_link = tcpip('192.168.1.10', 5005); set(data_link,'InputBufferSize',64*1024); set(data_link,'OutputBufferSize',64*1024); fopen(data_link); %% tx samp rate samp=[0 5 hex2dec('22') hex2dec('f0') hex2dec(samp_hex(7:8)) hex2dec(samp_hex(5:6)) hex2dec(samp_hex(3:4)) hex2dec(samp_hex(1:2))]; fwrite(ctrl_link,samp,'uint8'); %% tx bandwidth rate bw=[0 7 hex2dec('22') hex2dec('f0') hex2dec(bw_hex(7:8)) hex2dec(bw_hex(5:6)) hex2dec(bw_hex(3:4)) hex2dec(bw_hex(1:2))]; fwrite(ctrl_link,bw,'uint8'); %% send tx freq set cmd tx_freq=[hex2dec(freq_hex(1:2)) 3 hex2dec('22') hex2dec('f0') hex2dec(freq_hex(9:10)) hex2dec(freq_hex(7:8)) hex2dec(freq_hex(5:6)) hex2dec(freq_hex(3:4))]; fwrite(ctrl_link,tx_freq,'uint8'); %% send tx vga set cmd tx_vga=[0 9 hex2dec('22') hex2dec('f0') hex2dec(tx_att1(7:8)) hex2dec(tx_att1(5:6)) hex2dec(tx_att1(3:4)) hex2dec(tx_att1(1:2))]; %TX1 fwrite(ctrl_link,tx_vga,'uint8'); tx_vga=[0 11 hex2dec('22') hex2dec('f0') hex2dec(tx_att2(7:8)) hex2dec(tx_att2(5:6)) hex2dec(tx_att2(3:4)) hex2dec(tx_att2(1:2))]; %TX2 fwrite(ctrl_link,tx_vga,'uint8'); %% send tx channel set cmd channel=[tx_chan 0 hex2dec('20') hex2dec('f0') 0 0 0 0]; fwrite(ctrl_link,channel,'uint8'); %% custom rf control command % adf4001 config adf4001=[0 40 hex2dec('18') hex2dec('f0') hex2dec(ncount(3:4)) hex2dec(ncount(1:2)) hex2dec(rcount(3:4)) hex2dec(rcount(1:2))]; fwrite(ctrl_link,adf4001,'uint8'); % ref_select ref_select=[0 40 hex2dec('22') hex2dec('f0') hex2dec(ref_hex(7:8)) hex2dec(ref_hex(5:6)) hex2dec(ref_hex(3:4)) hex2dec(ref_hex(1:2))]; fwrite(ctrl_link,ref_select,'uint8'); % vco_cal_select vco_cal_select=[0 41 hex2dec('22') hex2dec('f0') hex2dec(vco_cal_hex(7:8)) hex2dec(vco_cal_hex(5:6)) hex2dec(vco_cal_hex(3:4)) hex2dec(vco_cal_hex(1:2))]; fwrite(ctrl_link,vco_cal_select,'uint8'); % fdd_tdd_select fdd_tdd_select=[0 42 hex2dec('22') hex2dec('f0') hex2dec(fdd_tdd_hex(7:8)) hex2dec(fdd_tdd_hex(5:6)) hex2dec(fdd_tdd_hex(3:4)) hex2dec(fdd_tdd_hex(1:2))]; fwrite(ctrl_link,fdd_tdd_select,'uint8'); % trx_sw trx_sw=[0 43 hex2dec('22') hex2dec('f0') hex2dec(trx_sw_hex(7:8)) hex2dec(trx_sw_hex(5:6)) hex2dec(trx_sw_hex(3:4)) hex2dec(trx_sw_hex(1:2))]; fwrite(ctrl_link,trx_sw,'uint8'); % aux_dac1 aux_dac1=[0 44 hex2dec('22') hex2dec('f0') hex2dec(aux_dac1_hex(7:8)) hex2dec(aux_dac1_hex(5:6)) hex2dec(aux_dac1_hex(3:4)) hex2dec(aux_dac1_hex(1:2))]; fwrite(ctrl_link,aux_dac1,'uint8'); %% send handshake cmd handshake=[2 0 hex2dec('16') hex2dec('f0') 0 0 0 0]; fwrite(ctrl_link ,handshake, 'uint8'); %% send handshake2 cmd data_length = dec2hex((2^(i-1)*2)*1024,8); handshake=[2 0 hex2dec('17') hex2dec('f0') hex2dec(data_length(7:8)) hex2dec(data_length(5:6)) hex2dec(data_length(3:4)) hex2dec(data_length(1:2))]; fwrite(ctrl_link ,handshake, 'uint8'); %% Write data to the zing and read from the host. fwrite(data_link,txd7,'uint8'); %% send handshake2 cmd to stop adc output %handshake=[hex2dec('ff') 0 hex2dec('17') hex2dec('f0') 0 0 0 0]; %fwrite(ctrl_link,handshake,'uint8'); %% close all link fclose(data_link); delete(data_link); clear data_link; fclose(ctrl_link); delete(ctrl_link); clear ctrl_link; disp('data tansfer done');2,運行接收端程序 rx_2ASK.m,程序會顯示接收到的2ASK調制信號和經過解調之后恢復出的原始基帶信號。
clc; %clear; %close all; warning off; buff_size=256; samp_hex=dec2hex(20e6,8); bw_hex=dec2hex(18e6,8); freq_hex=dec2hex(2140e6,10);%%for ad9361 rxgain1=5; rxgain2=5; rx_chan=3;%1=rx1;2=rx2;3=rx1&rx2 cyc=1; %% open control port ctrl_link = udp('192.168.1.10', 5006); fopen(ctrl_link); %% open data port data_link = tcpip('192.168.1.10', 5004); set(data_link,'InputBufferSize',256*1024); set(data_link,'OutputBufferSize',256*1024); fopen(data_link); %% rx samp rate samp=[0 17 hex2dec('22') hex2dec('f0') hex2dec(samp_hex(7:8)) hex2dec(samp_hex(5:6)) hex2dec(samp_hex(3:4)) hex2dec(samp_hex(1:2))]; fwrite(ctrl_link,samp,'uint8'); %% rx bandwidth rate bw=[0 19 hex2dec('22') hex2dec('f0') hex2dec(bw_hex(7:8)) hex2dec(bw_hex(5:6)) hex2dec(bw_hex(3:4)) hex2dec(bw_hex(1:2))]; fwrite(ctrl_link,bw,'uint8'); %% send rx freq rx_freq=[hex2dec(freq_hex(1:2)) 15 hex2dec('22') hex2dec('f0') hex2dec(freq_hex(9:10)) hex2dec(freq_hex(7:8)) hex2dec(freq_hex(5:6)) hex2dec(freq_hex(3:4))]; fwrite(ctrl_link,rx_freq,'uint8'); %% agc mode agc_mode=[0 21 hex2dec('22') hex2dec('f0') 0 0 0 0]; %定義RX1的增益控制模式 0-MGC 1-FGC 2-SGC fwrite(ctrl_link,agc_mode,'uint8'); agc_mode=[0 23 hex2dec('22') hex2dec('f0') 0 0 0 0]; fwrite(ctrl_link,agc_mode,'uint8'); %% send rx vga rx_vga=[0 25 hex2dec('22') hex2dec('f0') rxgain1 0 0 0]; fwrite(ctrl_link,rx_vga,'uint8'); rx_vga=[0 27 hex2dec('22') hex2dec('f0') rxgain2 0 0 0]; fwrite(ctrl_link,rx_vga,'uint8'); %% send rx channel set cmd channel=[rx_chan 0 hex2dec('21') hex2dec('f0') 0 0 0 0]; fwrite(ctrl_link,channel,'uint8'); %% send handshake cmd handshake=[2 1 hex2dec('16') hex2dec('f0') 0 0 0 0]; fwrite(ctrl_link,handshake,'uint8'); while (1)%% send handshake2 cmd to start adc threadsize_hex=dec2hex(buff_size*1024,8);handshake=[2 1 hex2dec('17') hex2dec('f0') hex2dec(size_hex(7:8)) hex2dec(size_hex(5:6)) hex2dec(size_hex(3:4)) hex2dec(size_hex(1:2))];fwrite(ctrl_link,handshake,'uint8');%% read 256*1024 bytes data from zingdata = fread(data_link,buff_size*1024,'uint8');%% receive % figure(2);clf;datah=data(2:2:end);datal=data(1:2:end);datah_hex=dec2hex(datah,2);datal_hex=dec2hex(datal,2);data_hex(:,1:2)=datah_hex;data_hex(:,3:4)=datal_hex;dataun=hex2dec(data_hex);datain=dataun-(dataun>32767)*65536; if rx_chan==1a1=datain(1:2:end);a2=datain(2:2:end);a3=zeros(1,length(a1));a4=zeros(1,length(a1));elseif rx_chan==2a3=datain(1:2:end);a4=datain(2:2:end);a1=zeros(1,length(a3));a2=zeros(1,length(a3));elseif rx_chan==3a1=datain(1:4:end);a2=datain(2:4:end);a3=datain(3:4:end);a4=datain(4:4:end);end%=====以下為數據解調部分=====%%-----起始幀同步-----%[frame_data,syn_symbol] = rx_frame_sync(a1+a2,a1,a2,mod_data); %-----數據解調,采用幅度判決方法-----%receive_sig=abs(frame_data)>5000;%-----每隔20個點抽取一個點作為解調信號-----%dimod_data=receive_sig(4:20:end);%-----計算誤碼率-----%bit_err=biterr(dimod_data',bit_trans);%===========================================================%-----畫圖顯示-----%h=figure(1);clf;set(h,'name','2ASK調制解調系統');subplot(221);plot(a1,'g');hold on;plot(a2,'r');ylim([-1e4 1e4]);axis square;title(['接收到的2ASK調制信號 cyc=',num2str(cyc)]);subplot(222);plot(bit_trans ,'b');ylim([-0.2 1.2]);title(['原始基帶信號序列 Total = ',num2str(length(bit_trans)),'bit']);subplot(223);plot(syn_symbol,'black');ylim([0 1.2]);axis square;title('幀同步相關性曲線');subplot(224);plot(dimod_data ,'m');ylim([-0.2 1.2]);title(['解調序列 Bit\_err = ',num2str(bit_err),';Demod\_times=',num2str(cyc)]);%-----接收次數變量值累加-----%cyc=cyc+1;%-----設置z鍵為停止鍵-----%if strcmpi(get(gcf,'CurrentCharacter'),'z')break;endpause(0.1); end%% send handshake2 cmd to stop adc thread handshake=[hex2dec('ff') 1 hex2dec('17') hex2dec('f0') 0 0 0 0]; fwrite(ctrl_link,handshake,'uint8'); %% close all link fclose(data_link); delete(data_link); clear data_link; fclose(ctrl_link); delete(ctrl_link); clear ctrl_link;?其中,cyc 顯示接收數據次數,下方畫出了幀同步曲線,原始基帶信號和長度也示于上面, 解調序列顯示誤碼率和解調次數,可以看到 bit_err 為 0,解調完全正確。
3,其它代碼
creat_training.m
function [training]=creat_training() Ns=128; N1=320; Nx=512; x1=randn(1,Ns); x2=randn(1,Ns);x3=x1+x2.*i;%生成隨機128點復數序列 y=x3(65:128);%x3的后64點用作循環前綴 y1=randn(1,N1); y2=randn(1,N1); y3=y1+y2.*i;%生成隨機320點復數序列用作數據符號 train1=[y3 y x3 x3 y3];%幀結構,共三個符號training=train1/sqrt(12); %數據量化為16bit index=30000./max([abs(real(training)),abs(imag(training))]); training=round(training.*index); endsys_time.m
function [C]=syn_time(data) Ns=128; N=length(data); N1=320;r=data; t1=zeros(1,N); t2=zeros(1,N);C=zeros(1,N);%原相關值對能量值歸一化 C1=zeros(1,N+4);%用循環前綴進一步歸一化tt=0; for timing=1:N-700for m=1:2*Nst1(timing)=t1(timing)+0.5*((abs(r(m+timing)))^2);%整個序列能量值,除了1/2end for m=1:Nst2(timing)=t2(timing)+conj(r(m+timing))*r(m+Ns+timing);%前半序列和后半序列相關值endC(1,timing)=(abs(t2(timing))^2)/(t1(timing)^2);%相關值對能量值歸一化end for timing=65:N-700 %利用訓練序列的循環前綴設定一個滑動運算窗口對序列進行歸一化for i=-64:0C1(1,timing)= C1(1,timing)+(1/65)*C(1,i+timing);end end [Y,I]=max(abs(C1)); timing_coarse=I-384; C=abs(C1);endrx_frame_sync.m
function [ frame_data,syn_symbol] = rx_frame_sync(receive_data,data_I,data_Q,txdata_x) % receive_data=receive_data'; [xx,PS]=mapminmax(receive_data); frame_all=xx'; syn_symbol=syn_time(frame_all); [s1,s2]=max(syn_symbol(1:length(syn_symbol)/2)); frame_begin=s2+576; frame_end=frame_begin+length(txdata_x); %------------找到幀位置后組成一幀數據------------------------------ frame_data_I=data_I(frame_begin:frame_end); frame_data_Q=data_Q(frame_begin:frame_end); frame=frame_data_I+1i*frame_data_Q; frame_data=frame(2:end); end總結
以上是生活随笔為你收集整理的2ASK调制解调实验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 单例模式中饿汉式
- 下一篇: Pagination(分页) 从前台到后