通過Matlab設計OFDM收發信機及影象在該系統傳輸失真度分析
摘要
OFDM技術的思想是將指配的通道分成許多正交子通道,在每個子通道上進行窄帶調製和傳輸,訊號頻寬小於通道的相關頻寬。OFDM單個使用者的資訊流被串/並變換為多個低速率碼流(100Hz-50kHz),每個碼流用一條載波傳送。OFDM採用跳頻方式選用即便頻譜混疊也能保持正交的波形,所以OFDM既有調製技術,也有複用技術。OFDM增強了抗頻率選擇性衰落和抗窄帶干擾的能力。在單載波系統中,單個衰落或干擾會導致整條鏈路不可用,但在多載波系統中,只會有一小部分載波受影響。糾錯碼的應用可以恢復一些易錯載波上的資訊。 OFDM允許各載波間頻率互相混疊,採用基於載波頻率正交的FFT調製,由於各個載波的中心頻點處沒有其他載波的頻譜分量,所以能夠實現各個載波的正交。
OFDM設計流程
流程圖如上,這裡不做太多介紹。
通過OFDM模擬的大致步驟
1.序列資料產生
首先對影象檔案進行資料處理, 系統輸入資料訊號的長度是根據子載波的個數及每幀的符號的個數確定的,通過round()對產生的影象所生成的序列四捨五入取整。
imdata = imread('11.jpg'); BinSer=dec2bin(imdata,8); BinSer=BinSer'; FileName=[num2str(size(imdata,1)),'_',num2str(size(imdata,2)),'_',num2str(size(imdata,3)),'.txt']; fid=fopen(FileName,'w'); fprintf(fid,'%c',BinSer(:)); fclose(fid); FileName='256_256_3.txt'; %檔名為上述生成的檔名 mn1=sscanf(FileName,'%d_%d_%d'); fid=fopen(FileName,'r'); datainput=fscanf(fid,'%c'); fclose(fid); c=double(datainput); for i=1:length(datainput) c(i)=str2num(char(c(i))); end %-------------------------傳送端-------------------------------------% for g=1:SNRnum Signal=round(c);
2.串並\並串轉換
OFDM系統是多載波傳輸的一種特殊方式,而傳送端產生的資料為序列的,因此需要進行串並轉換。OFDM將高速輸入的序列資料位元流轉換成並行傳輸的低速資料流,而且串並轉換之後會提高系統的抗干擾能力。串並轉換的實現方法很多,在matlab裡reshape用來把指定的矩陣改變形狀,但是元素個數不變,在本程式中採用reshape函式來實現串並轉換。
同樣如果對訊號進行了串並轉換,那麼當傳送訊號和接收訊號時,也需對其進行並串轉換。在本程式中並串轉換也採用了reshape函式來實現。下面是實現串並及並串轉換的語句。
SubCarryNdata=reshape(encode,SubCarryN,SymbN*2) %串並轉換
ich4=reshape(ich3,1,(fftLen+GuardLen)*SymbN); %並串轉換
qch4=reshape(qch3,1,(fftLen+GuardLen)*SymbN);
3.卷積編碼與維特比譯碼
卷積編碼作為一種通道編碼,具有前向糾錯的功能。通過對訊號進行卷積編碼,對訊號增加冗餘。當訊號在通道傳輸時,會大大降低誤位元速率。卷積編碼的實現方法也很多,在matlab中有卷積編碼函式,本程式直接呼叫了convenc函式。實現卷積編碼如下:
trel=poly2trellis(9,[561 753]); %設定網格圖
encode=convenc(Signal,trel);
在卷積編碼前需要對卷積編碼設定網格圖,此約束長度為9,此網格圖設定可以實現卷積編碼後,訊號實現一進二岀。產生卷積編碼訊號如下圖。
可以看出原始序列通過卷積編碼後,產生一個其長度2倍的序列。
使用卷積編碼通常會使用維特比譯碼來進行譯碼。使用維特比譯碼是通常會定義譯碼深度、量化電平及量化等級,在matlab中維特比譯碼函式為vitdec。程式具體實現如下:
parti=0:.15:.9;
codebk=0:7;
[x,qcode]=quantiz(ReSig,parti,codebk);
decode= vitdec(qcode',trel,declen,'cont','soft',3);
維特比譯碼後的訊號圖如下:
4.QPSK調製與解調
訊號的調製方式有多種,可以通過改變發射的射頻訊號的幅度、相位和頻率來調製訊號。對於OFDM系統來說,只能採用前兩種方法,而不能採用頻率的調製方法。因為子載波是頻率正交,並且攜帶獨立的資訊調製子載波頻率會破壞這些子載波的正交特性。QPSK調製方案能等量調製,不會由於星座點的能量不等而為OFDM系統帶來PAPR較大的問題。 QPSK調製的方法有兩種:一種是數字方法,另一種是相位選擇法。本程式中選擇的是利用數字的方法來調製訊號。
QPSK調製程式如下:
function [iout,qout]=qpskmod(paradata,para,nd,ml)
m2=ml./2;
paradata1=paradata.*2-1;
count2=0;
for k=1:nd
isi = zeros(para,1);
isq = zeros(para,1);
for L = 1 : m2
isi = isi + 2.^ ( m2 - L ) .* paradata1((1:para),L+count2);
isq = isq + 2.^ ( m2 - L ) .* paradata1((1:para),m2+L+count2);
end
iout((1:para),k)=isi;
qout((1:para),k)=isq;
count2=count2+
在進行解調之前訊號要完成去掉保護間隔和進行FFT運算的任務。去掉保護間隔也就可以去掉符號間的干擾。解調程式如下:
function [data]=QPSKjietiao(idata,qdata,para,nd,ml)
data=zeros( para,ml*nd );
data((1:para),(1:ml:ml*nd-1))=idata((1:para),(1:nd))>=0;
data((1:para),(2:ml:ml*nd))=qdata((1:para),(1:nd))>=0;
保護間隔
在OFDM系統中,保護間隔是一種迴圈複製增加了符號的波形長度,在符號的資料部分每一個子載波內有一個整數倍的迴圈,此種符號的複製產生了一個迴圈的訊號,即將每個OFDM符號的後一段時間的樣點複製到OFDM符號的前面,形成字首。在交接點沒有任何的間斷。保護間隔的長度的大小是根據給定的系統的設計引數來確定的,為了最大限度的減小由於插入保護位元帶來的信噪比損失。在matlab裡採用一些特殊運算子號和矩陣的應用就可實現在訊號前新增保護間隔。實現程式如下:
ich3=[ich2(fftLen-GuardLen+1:fftLen,:);ich2];
qch3=[qch2(fftLen-GuardLen+1:fftLen,:);qch2];
系統誤位元速率分析
主要通過比較傳送端和接收端的訊號是否相同,用errbit來計算錯誤的個數,在沒有接到訊號的時候errbit設定為0,是通過傳送訊號的每一位和接收訊號的每一位進行比較,同errbit就加1。用錯誤的個數errbit和訊號的長度SignalLen的比值就是誤位元速率BER。具體實現為:
errbit=sum(abs(ReSig-encode)); %誤碼個數
encodenum=length(encode); %總共碼長
BER(g)=errbit/encodenum %誤位元速率
d(SNR(g))=BER(g);
decode2=decode1(declen+1:end);
Signal2=Signal(1:end-declen);
errbit1=sum(abs(decode2-Signal2));
BER1(g)=errbit1/SignalLen
e(SNR(g))=BER1(g);
未卷積前訊號的誤位元速率曲線如圖:
卷積後訊號的誤位元速率曲線如圖:
結果影象輸出:
結果可看出,該系統傳輸出的影象基本沒有失真,經卷積編碼後誤位元速率明顯降低,所以OFDM系統中卷積也是不可確少的。
原始碼如下:
主程式:
clear all;
close all;
clc;
%---------------------------------------------------------------------%
% OFDM收發信機的設計
% 說明:本程式為主程式,呼叫了QPSKtiaozhi和QPSKjietiao子函式
%---------------------------------------------------------------------%
%--------------------------引數設定-----------------------------------%
fftLen=512; %設定FFT長度
SymbN=64*3*16; %設定一個幀結構中OFDM訊號的個數
SubCarryN=512; %設定並行傳輸的子載波個數
GuardLen=32; %保護時隙的長度
SNR= 1:1:11; %信噪比
SNRnum=length(SNR); %信噪比數目
SignalLen=SubCarryN*SymbN; %傳送訊號長度
declen=40; %譯碼深度
%--------------------------------------------------------------------%
imdata = imread('11.jpg');
BinSer=dec2bin(imdata,8);
BinSer=BinSer';
FileName=[num2str(size(imdata,1)),'_',num2str(size(imdata,2)),'_',num2str(size(imdata,3)),'.txt'];
fid=fopen(FileName,'w');
fprintf(fid,'%c',BinSer(:));
fclose(fid);
FileName='256_256_3.txt'; %檔名為上述生成的檔名
mn1=sscanf(FileName,'%d_%d_%d');
fid=fopen(FileName,'r');
datainput=fscanf(fid,'%c');
fclose(fid);
c=double(datainput);
for i=1:length(datainput)
c(i)=str2num(char(c(i)));
end
%-------------------------傳送端-------------------------------------%
for g=1:SNRnum
%Signal=round(rand(1,SubCarryN*SymbN)); %產生隨機序列
Signal=round(c);
trel=poly2trellis(9,[561 753]); %設定網格圖
encode=convenc(Signal,trel); %卷積編碼
SubCarryNdata=reshape(encode,SubCarryN,SymbN*2); %串並轉換
[ich,qch]=QPSKtiaozhi(SubCarryNdata,SubCarryN,SymbN,2); %QPSK調製,呼叫子函式
kmod=1./sqrt(2);
ich1=ich.*kmod;
qch1=qch.*kmod;
qpskx=ich1+qch1.*sqrt(-1); %頻域資料變時域
fy=ifft(qpskx); %對訊號作IFFT
ich2=real(fy);
qch2=imag(fy);
%-----------------------------------------------------------------%
%---------------------插入保護間隔---------------------------------%
ich3=[ich2(fftLen-GuardLen+1:fftLen,:);ich2];
qch3=[qch2(fftLen-GuardLen+1:fftLen,:);qch2];
ich4=reshape(ich3,1,(fftLen+GuardLen)*SymbN); %並串轉換
qch4=reshape(qch3,1,(fftLen+GuardLen)*SymbN);
TrData=ich4+qch4.*sqrt(-1); %形成複數發射資料
%-----------------------------------------------------------------%
%----------------------加入高斯白噪聲------------------------------%
ReData=awgn(TrData,SNR(g),'measured');
%------------------------接收端 -----------------------------------%
%----------------------移去保護間隔--------------------------------%
idata=real(ReData);
qdata=imag(ReData);
idata1=reshape(idata,fftLen+GuardLen,SymbN);
qdata1=reshape(qdata,fftLen+GuardLen,SymbN);
idata2=idata1(GuardLen+1:GuardLen+fftLen,:);
qdata2=qdata1(GuardLen+1:GuardLen+fftLen,:);
Rex=idata2+qdata2.*sqrt(-1); % FFT
ry=fft(Rex);
ReIChan=real(ry);
ReQChan=imag(ry);
ReIchan=ReIChan/kmod;
ReQchan=ReQChan/kmod;
ReSubCarryN=QPSKjietiao(ReIchan,ReQchan,SubCarryN,SymbN,2); %QPSK解調 ,呼叫子函式
ReSig=reshape(ReSubCarryN,1,SubCarryN*SymbN*2); %接收端訊號
%-----------------------------------------------------------------%
%---------------------維特比譯碼-----------------------------------%
parti=0:.15:.9;
codebk=0:7;
[x,qcode]=quantiz(ReSig,parti,codebk);
decode= vitdec(qcode',trel,declen,'cont','soft',3);
decode1=reshape(decode,1,SignalLen);
%----------------------誤位元速率----------------------------------------%
errbit=sum(abs(ReSig-encode)); %誤碼個數
encodenum=length(encode); %總共碼長
BER(g)=errbit/encodenum %誤位元速率
d(SNR(g))=BER(g);
decode2=decode1(declen+1:end);
Signal2=Signal(1:end-declen);
errbit1=sum(abs(decode2-Signal2));
BER1(g)=errbit1/SignalLen
e(SNR(g))=BER1(g);
end
%----------------------------------------------------------------%
%-----------------------輸出結果---------------------------------%
%圖一輸入訊號與卷積後訊號
figure(1);
subplot(211);stem(Signal(1:40),'b'),grid;
title('輸入的訊號');
subplot(212),stem(encode(1:80),'b'),grid;
title('卷積編碼後的訊號');
%圖二QPSK星座對映
figure(2);
plot(ReIChan,ReQChan,'o'),grid;
ylabel('正交分量'),xlabel('同相分量');
title('接收端的QPSK星座對映');
%圖三接收訊號與維特比譯碼後的訊號
figure(3);
subplot(211);stem(Signal(1:40),'b'),grid;
title('接收到的訊號');
subplot(212),stem(decode(1:80),'b'),grid;
title('維特比譯碼後的訊號');
%圖四誤位元速率分析
figure(4);
semilogy(d,'bo-')
%hold on
%semilogy(e,'ro-')
xlabel('信噪比(dB)');
ylabel('誤位元速率');
title('誤位元速率曲線')
grid on
%卷積完誤位元速率曲線
figure(5);
semilogy(e,'r*-'),grid;
%axis([0,4])
ylabel('誤位元速率'),xlabel('信噪比');
title('卷積後誤位元速率曲線');
%--------------------------------------------------------------%
FileName=[num2str(64),'_',num2str(64),'_',num2str(3),'.txt'];
fid=fopen(FileName,'w');
%BinSer=dec2bin(imdata,8);
%BinSer=BinSer';
dataoutput=num2str(decode1);
datareal=strrep(dataoutput,' ','');
%fprintf(fid,'%c',BinSer(:));
fprintf(fid,'%c',datareal);
fclose(fid);
clear all
FileName='256_256_3.txt'; %檔名為上述生成的檔名
mn=sscanf(FileName,'%d_%d_%d');
M=mn(1);
N=mn(2);
K=mn(3);
fid=fopen(FileName,'r');
data=fscanf(fid,'%c');fclose(fid);
data1=reshape(data,8,length(data)/8);
data2=reshape(bin2dec(data1'),M,N,K);
figure(7);
imshow(uint8(data2));
子函式:
%-----------------------------------------------------------%
% QPSK調製前函式
%-----------------------------------------------------------%
function [iout,qout]=qpskmod(paradata,para,nd,ml)
m2=ml./2;
paradata1=paradata.*2-1;
count2=0;
for k=1:nd
isi = zeros(para,1);
isq = zeros(para,1);
for L = 1 : m2
isi = isi + 2.^ ( m2 - L ) .* paradata1((1:para),L+count2);
isq = isq + 2.^ ( m2 - L ) .* paradata1((1:para),m2+L+count2);
end
iout((1:para),k)=isi;
qout((1:para),k)=isq;
count2=count2+ml;
end
%----------------------------------------------------------------------%
% QPSK解調函式
%----------------------------------------------------------------------%
function [data]=QPSKjietiao(idata,qdata,para,nd,ml)
data=zeros( para,ml*nd );
data((1:para),(1:ml:ml*nd-1))=idata((1:para),(1:nd))>=0;
data((1:para),(2:ml:ml*nd))=qdata((1:para),(1:nd))>=0;