OFDM通信系统MATLAB仿真程序

目录

1 系统框图

2 程序

2.1 比特流产生

2.2 符号映射(16QAM)

2.3 串并转换

2.4 子载波映射

2.5 IFFT变换

2.6 并串转换

2.7 添加高斯复噪声 

2.8 并串转换

2.9 FFT 变换

2.10 子载波解映射

2.11 并串转换

2.12 解符号映射

2.13系统性能评估

1 系统框图

2 程序

2.1 比特流产生

bits_per_symbol=4;%每符号含比特数,16QAM调制
carrier_count=48;%使用子载波数
symbols_per_carrier=1;%每子载波含符号数
IFFT_bin_length=64;%FFT点数,OFDM子载波个数
bits_count=carrier_count * symbols_per_carrier * bits_per_symbol%比特流数量
BPS=80000000;%比特流速度80Mbps
SPS=BPS/4;%符号速度20Msps
t=0:1/BPS:(bits_count-1)/BPS;

%========产生待调制的基带二进制比特流==============
baseband_out_length = carrier_count * symbols_per_carrier * bits_per_symbol;%所输入的比特数目
rng( 1,'twister');%设置随机数发生器的状态,以确保每次运行代码时都生成相同的随机序列
baseband_out=round(rand(1,baseband_out_length));%输出待调制的二进制比特流

%将二进制数据存入mif文件
fid=fopen('F:\FPGA\ofdm\par\baseband_bits.mif','w'); % 打开T1.mif文件向里面写数据,如果还没有建立这个文件,会自动建立之后打开
fprintf(fid,'WIDTH=1;\n');          % 数据宽度为1位
fprintf(fid,'DEPTH=%d;\n\n',baseband_out_length);     % 数据的深度
fprintf(fid,'ADDRESS_RADIX=UNS;\n');% 地址数据为无符号数(unsigned)
fprintf(fid,'DATA_RADIX=UNS;\n\n'); % 数据也是无符号数
fprintf(fid,'CONTENT BEGIN\n');     
for x = 1:baseband_out_length                     % 数据数量
    fprintf(fid,'%d:%d;\n',x-1,baseband_out(x)); % 写入数据
end
fprintf(fid,'END;');                % 文件结束    
fclose(fid); 

% figure
figure(1);
subplot(2,1,1);
stairs(t,baseband_out,'b');
axis([0 1.5*bits_count/BPS -0.5 1.5]);
xlabel('t(/s)');
ylabel('Amplitude(/v)');
title('发送二进制比特流');
grid on;

subplot(2,1,2);
stem(baseband_out,'b');
xlabel('index');
ylabel('Amplitude(/v)');
axis([1 1.5*baseband_out_length -0.5 1.5]);
grid on;

关键点:rand函数,rng种子,数据存储文件,round函数,stairs,stem画图函数。

2.2 符号映射(16QAM)

%函数文件

function [qam_complex_data] = qam16(bitstream)
%   16qam modulation
%   Gray code
% 00 -3
% 01 -1
% 11 1
% 10 3
symbolstream=zeros(1,length(bitstream)/4);
for n=1:length(symbolstream)
pack=[bitstream(4*(n-1)+1) bitstream(4*(n-1)+2) bitstream(4*(n-1)+3) bitstream(4*(n-1)+4)];
    if pack==[0 0 0 0]
    symbolstream(n)=-3-3j;
    elseif pack==[0 0 1 0]
    symbolstream(n)=-3+3j;
    elseif pack==[0 0 1 1]
    symbolstream(n)=-3+1j;
    elseif pack==[0 0 0 1]
    symbolstream(n)=-3-1j;
    elseif pack==[0 1 0 1]
    symbolstream(n)=-1-1j;
    elseif pack==[0 1 0 0]
    symbolstream(n)=-1-3j;
    elseif pack==[0 1 1 1]
    symbolstream(n)=-1+1j;
    elseif pack==[0 1 1 0]
    symbolstream(n)=-1+3j;
    elseif pack==[1 1 1 0]
    symbolstream(n)=1+3j;
    elseif pack==[1 1 1 1]
    symbolstream(n)=1+1j;
    elseif pack==[1 1 0 1]
    symbolstream(n)=1-1j;
    elseif pack==[1 1 0 0]
    symbolstream(n)=1-3j;
    elseif pack==[1 0 0 0]
    symbolstream(n)=3-3j;
    elseif pack==[1 0 1 0]
    symbolstream(n)=3+3j;
    elseif pack==[1 0 0 1]
    symbolstream(n)=3-1j;
    else %pack==[1 0 1 1]
        symbolstream(n)=3+1j;
    end
end
qam_complex_data=symbolstream;
qam_complex_data=qam_complex_data/sqrt(10);%能量归一化

 qam16_complex_data=qam16(baseband_out);%行向量

subplot(2,2,3);
plot(qam16_complex_data,'*b');%16QAM调制后星座图
axis([-2 2 -2 2]);
title('16QAM调制后星座图');
grid on;

subplot(2,2,4);
polar(angle(qam16_complex_data),abs(qam16_complex_data),'b*');
title('16QAM调制后极坐标图');
grid on;

关键点:格雷码映射,能量归一化

2.3 串并转换

qam16_complex_data_p=reshape(qam16_complex_data.',carrier_count,symbols_per_carrier).';

2.4 子载波映射

%在64个子载波中,仅有48个子载波为数据,其余为0值,相当于补0,因为通常IFFT的长度应该为2的整数次幂
%子载波分配
carriers = (1:carrier_count) + 8;% 复数数据对应的IFFT点坐标,存放位置是9-56
subcarrier_map=zeros(symbols_per_carrier,IFFT_bin_length);%添0组成IFFT_bin_length点 IFFT 运算
subcarrier_map(:,carriers ) = qam16_complex_data_p; 

figure(2);
%第一个OFDM符号的各子载波数据的幅度
subplot(2,2,1);
% stem(0:IFFT_bin_length-1, abs(subcarrier_map(1,:)),'bo');
% hold on;
% stem(carriers-1, abs(subcarrier_map(1,carriers)),'g*');
% axis ([0 IFFT_bin_length -0.5 2.5]);
% xlabel('子载波 index');

% stem(0:1/SPS:(IFFT_bin_length-1)/SPS, abs(subcarrier_map(1,:)),'bo');
% hold on;
% stem((carriers-1)/SPS, abs(subcarrier_map(1,carriers)),'g*');
% xlabel('t(/s)');

stem(f_inteval:f_inteval:BW, abs(subcarrier_map(1,:)),'bo');
hold on;
stem((carriers)*f_inteval, abs(subcarrier_map(1,carriers)),'g*');
xlabel('f(/Hz)');

ylabel('Amplitude/v');
title('第一个OFDM符号的各子载波数据的幅度');
grid on;

%各子载波数据的相位
subplot(2,2,2);
% stem(0:IFFT_bin_length-1, (180/pi)*angle(subcarrier_map(1,:)),'ob');
% hold on;
% stem(carriers-1, (180/pi)*angle(subcarrier_map(1,carriers)),'g*');
% axis ([0 IFFT_bin_length -200 +200]);
% xlabel('子载波 index');

% stem(0:1/SPS:(IFFT_bin_length-1)/SPS,(180/pi)*angle(subcarrier_map(1,:)),'ob');
% hold on;
% stem((carriers-1)/SPS, (180/pi)*angle(subcarrier_map(1,carriers)),'g*');
% xlabel('t(/s)');

stem(f_inteval:f_inteval:BW, (180/pi)*angle(subcarrier_map(1,:)),'bo');
hold on;
stem((carriers)*f_inteval, (180/pi)*angle(subcarrier_map(1,carriers)),'g*');
xlabel('f(/Hz)');

ylabel('Phase (degrees/°)');
title('第一个OFDM符号的各子载波数据的相位');
grid on;
 

 

关键点:子载波映射方法

2.5 IFFT变换

signal_after_IFFT=ifft(subcarrier_map,IFFT_bin_length,2);%IFFT变换

subplot(2,2,3);
plot(0:tx_inteval:ofdm_period-tx_inteval,real(signal_after_IFFT(1,:)),'-');
ylabel('Amplitude (/v)');
xlabel('t(/s)');
title('第一个OFDM符号周期的时域同相分量波形');
grid on;

subplot(2,2,4);
plot(0:tx_inteval:ofdm_period-tx_inteval,imag(signal_after_IFFT(1,:)),'-');
ylabel('Amplitude (/v)');
xlabel('t(/s)');
title('第一个OFDM符号周期的时域正交分量波形');
grid on;

2.6 并串转换

 tx_count = (symbols_per_carrier)*(IFFT_bin_length);%发送总位数
ifft_tx_s=reshape(signal_after_IFFT.',1,tx_count);

% 在计算功率谱密度时,乘以适当的归一化因子可以将其单位调整为功率/Hz,
% 乘以采样频率的倒数和信号长度的目的是确保总的能量在频域上正确归一化,以便得到平均功率。
% 这个归一化因子保证了在频率范围内对所有功率谱密度进行积分时,结果是信号的总功率。
%频域求解平均功率
% PSD = (1/(BW*64)) * abs(subcarrier_map).^2; % 计算功率谱密度,64个点总能量归一化/64  纵W/Hz,横Hz
% awerage_power=sum(PSD)*(BW/64);%所有能量 除以采样点数。
Power=abs(subcarrier_map).^2/64; %功率谱,每个频率点上功率。纵W,横Hz。/64归一化。
awerage_power=sum(Power)/64; 

2.7 添加高斯复噪声 

Tx_signal_power_real = mean(real(ifft_tx_s).^2);%发送信号平均功率=瞬时功率的均值
Tx_signal_power_imag = mean(imag(ifft_tx_s).^2);
Tx_signal_power=Tx_signal_power_real+Tx_signal_power_imag;%0.0107
linear_SNR=10^(SNR/10);%线性信噪比
noise_sigma_real=Tx_signal_power_real/linear_SNR;
noise_sigma_imag=Tx_signal_power_imag/linear_SNR;
noise_scale_factor_real = sqrt(noise_sigma_real);%标准差sigma
noise_scale_factor_imag = sqrt(noise_sigma_imag);%标准差sigma

noise_real=randn(1,symbols_per_carrier*IFFT_bin_length).*noise_scale_factor_real;%产生正态分布(高斯分布)噪声序列
noise_imag=randn(1,symbols_per_carrier*IFFT_bin_length).*noise_scale_factor_imag;%产生正态分布(高斯分布)噪声序列

noised_fixed_real=fi(noise_real,1,16,14);
noised_fixed_imag=fi(noise_imag,1,16,14);
noised_fixed_decimal_value_real=zeros(1,IFFT_bin_length);
noised_fixed_decimal_value_imag=zeros(1,IFFT_bin_length);
%实部噪声
for i = 1:length(noised_fixed_real)
    noise_binary_representation = bin(noised_fixed_real(i)); % 使用 bin 方法将定点数转换为二进制字符串,注意是字符串
    % 确定符号位和数值部分
    sign_bit = noise_binary_representation(1); % 符号位
    value_bits = noise_binary_representation(2:16); % 数值部分
    % 将数值部分转换为十进制数
    decimal_value = bin2dec(value_bits);
    % 如果符号位为1,则为负数,需要取补码
    if sign_bit == '1'
        decimal_value = decimal_value - 2^(length(value_bits));
    end
    noised_fixed_decimal_value_real(i)=decimal_value;
%     disp(['index: ',num2str(i-1),', noised_fixed Value: ', num2str(noised_fixed_real(i)), ', noise real Binary representation: ', noise_binary_representation,', Decimal Value:', num2str(decimal_value)]);
end
%将二进制数据存入mif文件
noise_fixed_real=fopen('F:\FPGA\ofdm\par\noise_real_fixed.mif','w'); % 打开noise_real_fixed.mif文件向里面写数据,如果还没有建立这个文件,会自动建立之后打开
fprintf(noise_fixed_real,'WIDTH=16;\n');          % 数据宽度为16位
fprintf(noise_fixed_real,'DEPTH=%d;\n\n',IFFT_bin_length);     % 数据的深度
fprintf(noise_fixed_real,'ADDRESS_RADIX=UNS;\n');% 地址数据为无符号数(unsigned)
fprintf(noise_fixed_real,'DATA_RADIX=DEC;\n\n'); % 数据也是无符号数
fprintf(noise_fixed_real,'CONTENT BEGIN\n');
for x=1:IFFT_bin_length
        fprintf(noise_fixed_real,'%d:%d;\n',x-1,noised_fixed_decimal_value_real(x)); % 写入数据
end
fprintf(noise_fixed_real,'END;');                % 文件结束    
fclose(noise_fixed_real); 
%虚部噪声
for i = 1:length(noised_fixed_imag)
    noise_binary_representation = bin(noised_fixed_imag(i)); % 使用 bin 方法将定点数转换为二进制字符串,注意是字符串
    % 确定符号位和数值部分
    sign_bit = noise_binary_representation(1); % 符号位
    value_bits = noise_binary_representation(2:16); % 数值部分
    % 将数值部分转换为十进制数
    decimal_value = bin2dec(value_bits);
    % 如果符号位为1,则为负数,需要取补码
    if sign_bit == '1'
        decimal_value = decimal_value - 2^(length(value_bits));
    end
    noised_fixed_decimal_value_imag(i)=decimal_value;
%     disp(['index: ',num2str(i-1),', noised_fixed Value: ', num2str(noised_fixed(i)), ', noise imag Binary representation: ', noise_binary_representation,', Decimal Value:', num2str(decimal_value)]);
end
%将二进制数据存入mif文件
noise_fixed_imag=fopen('F:\FPGA\ofdm\par\noise_imag_fixed.mif','w'); % 打开noise_fixed.mif文件向里面写数据,如果还没有建立这个文件,会自动建立之后打开
fprintf(noise_fixed_imag,'WIDTH=16;\n');          % 数据宽度为16位
fprintf(noise_fixed_imag,'DEPTH=%d;\n\n',IFFT_bin_length);     % 数据的深度
fprintf(noise_fixed_imag,'ADDRESS_RADIX=UNS;\n');% 地址数据为无符号数(unsigned)
fprintf(noise_fixed_imag,'DATA_RADIX=DEC;\n\n'); % 数据是十进制数
fprintf(noise_fixed_imag,'CONTENT BEGIN\n');
for x=1:IFFT_bin_length
        fprintf(noise_fixed_imag,'%d:%d;\n',x-1,noised_fixed_decimal_value_imag(x)); % 写入数据
end
fprintf(noise_fixed_imag,'END;');                % 文件结束    
fclose(noise_fixed_imag); 


%接收到的信号加噪声
Rx_data_real=real(ifft_tx_s) +noise_real;
Rx_data_imag=imag(ifft_tx_s) +noise_imag;
Rx_data=complex(Rx_data_real,Rx_data_imag);
 

figure(3);
subplot(2,1,1);
plot(0:tx_inteval:ofdm_period-tx_inteval,real(signal_after_IFFT(1,:)),'-');
hold on;
plot(0:tx_inteval:ofdm_period-tx_inteval,Rx_data_real(1,:),'-');
ylabel('Amplitude (/v)');
xlabel('t(/s)');
legend('without noise','add noise');
title('添加高斯噪声后第一个OFDM符号的时域同相分量波形');
grid on;

subplot(2,1,2);
plot(0:tx_inteval:ofdm_period-tx_inteval,imag(signal_after_IFFT(1,:)),'-');
hold on;
plot(0:tx_inteval:ofdm_period-tx_inteval,Rx_data_imag(1,:),'-');
ylabel('Amplitude (/v)');
xlabel('t(/s)');
legend('without noise','add noise');
title('添加高斯噪声后第一个OFDM符号的时域正交分量波形');
grid on;

关键点:rand产生均匀随机数,randn产生正态随机数。信号平均功率的求法。(时域,频域),功率谱,功率谱密度

2.8 并串转换

Rx_data_p=reshape(Rx_data.',IFFT_bin_length,symbols_per_carrier).';

2.9 FFT 变换

signal_after_fft=fft(Rx_data_p,IFFT_bin_length,2);%即FFT变换

 

2.10 子载波解映射

Rx_carriers=signal_after_fft(:,carriers);%除去IFFT/FFT变换添加的0,选出映射的子载波

2.11 并串转换

Rx_serial_complex_symbols = reshape(Rx_carriers.',size(Rx_carriers, 1)*size(Rx_carriers,2),1).';

2.12 解符号映射

%输入为行向量
function [demod_complex_symbol]=symbol_judge(Rx_serial_complex_symbols)

decode_symbol_real=zeros(1,length(Rx_serial_complex_symbols));
decode_symbol_imag=zeros(1,length(Rx_serial_complex_symbols));

for i=1:length(Rx_serial_complex_symbols)
    %实部
    if real(Rx_serial_complex_symbols(1,i))<0               %<0
        if real(Rx_serial_complex_symbols(1,i))>-2/sqrt(10) %能量归一化 -1
            decode_symbol_real(1,i)=-1/sqrt(10);
        else 
            decode_symbol_real(1,i)=-3/sqrt(10); %-3
        end
    else                                                    %>0
        if real(Rx_serial_complex_symbols(1,i))<2/sqrt(10) %能量归一化 1
            decode_symbol_real(1,i)=1/sqrt(10);
        else 
            decode_symbol_real(1,i)=3/sqrt(10); %3
        end
    end
    %虚部
    if imag(Rx_serial_complex_symbols(1,i))<0               %<0
        if imag(Rx_serial_complex_symbols(1,i))>-2/sqrt(10) %能量归一化 -1
            decode_symbol_imag(1,i)=-1/sqrt(10);
        else 
            decode_symbol_imag(1,i)=-3/sqrt(10); %-3
        end
    else                                                    %>0
        if imag(Rx_serial_complex_symbols(1,i))<2/sqrt(10) %能量归一化 1
            decode_symbol_imag(1,i)=1/sqrt(10);
        else 
            decode_symbol_imag(1,i)=3/sqrt(10); %3
        end
    end   
end
demod_complex_symbol=complex(decode_symbol_real,decode_symbol_imag);

 function [bits_demod]=qam16_demod(rx_complex_symbol_s)
%   16qam modulation
%   Gray code
% 00 -3
% 01 -1
% 11 1
% 10 3
symbol_stream=rx_complex_symbol_s*sqrt(10);%去除归一化
bits_rx=zeros(length(symbol_stream),4);
for n=1:length(symbol_stream)
    if  symbol_stream(n)==-3-3j
        bits_rx(n,:)=[0 0 0 0];
    elseif symbol_stream(n)==-3+3j
        bits_rx(n,:)=[0 0 1 0];
    elseif symbol_stream(n)==-3+1j
        bits_rx(n,:)=[0 0 1 1];
    elseif symbol_stream(n)==-3-1j
        bits_rx(n,:)=[0 0 0 1];
    elseif symbol_stream(n)==-1-1j
        bits_rx(n,:)=[0 1 0 1];
    elseif symbol_stream(n)==-1-3j
        bits_rx(n,:)=[0 1 0 0];
    elseif symbol_stream(n)==-1+1j
        bits_rx(n,:)=[0 1 1 1];
    elseif symbol_stream(n)==-1+3j
        bits_rx(n,:)=[0 1 1 0];
    elseif symbol_stream(n)==1+3j
        bits_rx(n,:)=[1 1 1 0];
    elseif symbol_stream(n)==1+1j
        bits_rx(n,:)=[1 1 1 1];
    elseif symbol_stream(n)==1-1j
        bits_rx(n,:)=[1 1 0 1];
    elseif symbol_stream(n)==1-3j
        bits_rx(n,:)=[1 1 0 0];
    elseif symbol_stream(n)==3-3j
        bits_rx(n,:)=[1 0 0 0];
    elseif symbol_stream(n)==3+3j
        bits_rx(n,:)=[1 0 1 0];
    elseif symbol_stream(n)==3-1j
        bits_rx(n,:)=[1 0 0 1];
    else    % symbol_stream(n)==3+1j
        bits_rx(n,:)=[1 0 1 1];
    end
end
bits_demod=reshape(bits_rx.',1,length(symbol_stream)*4);

 rx_symbol_judge=symbol_judge(Rx_serial_complex_symbols);%硬判决
bit_rx=qam16_demod(rx_symbol_judge);%解符号映射

 

2.13系统性能评估

  • 19
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值