OFDM系统仿真【matlab代码】

matlab源码链接: https://blog.csdn.net/qq_44394952/article/details/122508697.

一.仿真思路

为了便于计算把系统的仿真参数设置的较小。仿真参数为:子载波个数为 200,总符号数为100,IFFT/FFT 的长度为 512,调制方式选用16QAM调制,为了最大限度的减少插入保护间隔带来的信噪比损失,一般选择符号周期长度是保护间隔长度的5倍,所以保护间隔的长度为有效符号周期的1/4,故设循环前缀的长度为128,信噪比为20dB。
在这里插入图片描述

1.产生0-1随机序列

使用函数rand(),生成随机0-1串行序列,个数为:子载波个数总符号数4。

bit_length = carrier_count*symbol_count*bit_per_symbol;
bit_sequence = round(rand(1,bit_length))';

2.串并变换、并串转换

reshape()函数用来把指定的矩阵改变形状,但是元素个数不变,串并变换、并串转换均通过调用reshape()函数。OFDM将频带划分为多个子信道并行传输数据,将高速数据流分成多个并行的低速数据流,然后调制到每个信道的子载波上进行传输。

3.16QAM调制解调

信号的调制方式有多种,可以通过改变发射的射频信号的幅度、相位和频率
来调制信号。对于OFDM系统来说,只能采用前两种方法,而不能采用频率的调制方法,因为子载波是频率正交,并且携带独立的信息,调制子载波频率会破坏这些子载波的正交特性。本次仿真中我们采用16QAM调制的方式,由二进制变为四进制数字基带信号并进行格雷码映射,取值为-3,-1,1,3。格雷码的特点是邻近的两个信号,其标识仅有一位不同,这样当误符号率一定时,误比特率最小。仿真时直接调用qammod()函数实现。
16QAM调制:

carrier_position = 29:228;
conj_position = 485:-1:286;
bit_moded = qammod(bit_sequence,16,'InputType','bit');

16QAM解调:

bit_demod_sig = reshape(qamdemod(data_sig,16,'OutputType','bit'),[],1);
bit_demod_mut = reshape(qamdemod(data_mut,16,'OutputType','bit'),[],1);

4.IFFT和FFT

在IFFT实现OFDM中,发送端添加了IFFT模块、接收端添加了FFT模块。IFFT模块的功能相当于说:别麻烦发送N个子载波信号了,我直接算出你们在空中会叠加成啥样子吧;FFT模块的功能相当于说:别用老式的积分方法来去除其余的正交子载波了,我帮你一次把N个携带信号全算出来吧。IFFT实现OFDM的系统用数学的方法在发送端计算信号的叠加波形,在接收端去除正交子载波,从而大大简化了系统的复杂度。
I FFT:

ifft_position = zeros(ifft_length,symbol_count);
%将symbols_per_carrier*IFFT_bin_length矩阵赋0值,这里将20*512矩阵赋0值。这里512%IFFT的长度,也是OFDM符号子载波的个数。
bit_moded = reshape(bit_moded,carrier_count,symbol_count);\
ifft_position(carrier_position,:)=bit_moded(:,:);
ifft_position(conj_position,:)=conj(bit_moded(:,:));
signal_time = ifft(ifft_position,ifft_length);

%这段程序构造了512个子载波的OFDM符号,并且各个子载波上的数据是共轭对称的。这样做的目的是经过%IFFT后形成的OFDM符号均为实数。另外,在512个子载波中,仅有400个子载波为数据,其余为0值。相%当于补零,补零的目的是通常IFFT的长度应该为2的整数次幂。
FFT:

fft_sig = fft(Rx_data_sig);
fft_mut = fft(Rx_data_mut);

5.循环前缀和循环后缀

OFDM可以有效地对抗多径时延扩展,把输入数据流中并变换到N个并行的子信道中,使得每一个调制子载波的数据周期可以扩大为原始数据符号周期的N倍,因此时延扩展与符号周期的数值比也同样降低N倍。为了最大限度的消除符号间干扰,还可以在每个OFDM符号的起始位置插入保护间隔,而且该保护间隔长度一般要大于无线信道中的最大时延扩展,这样一个符号的多径分量就不会对下一个符号造成干扰。这种保护间隔是一种循环复制,增加了符号的波形长度,在符号的数据部分,将每个OFDM符号的后Tg时间中的样点复制到OFDM符号的前面,形成前缀,因此交接点没有任何的间断。

加入保护间隔的OFDM信号

加循环前缀和循环后缀:

signal_time_C = [signal_time(end-CP_length+1:end,:);signal_time];
signal_time_C = [signal_time_C; signal_time_C(1:CS_length,:)];

去循环前缀和循环后缀:

Rx_data_sig(1:CP_length,:) = [];
Rx_data_sig(end-CS_length+1:end,:) = [];
Rx_data_mut(1:CP_length,:) = [];
Rx_data_mut(end-CS_length+1:end,:) = [];

6.滤波器(加窗函数)

根据OFDM符号的功率谱密度,其带外衰减比较慢,为了加快带外衰减的速度我们需要使用加窗技术。通常采用升余弦类型的窗函数:

signal_window = zeros(size(signal_time_C));
signal_window =signal_time_C.*repmat(rcoswindow
(alpha,size(signal_time_C,1)),1,symbol_count);

7.信道

仿真中分析了两种情况:
1)高斯白噪声新道
2)多径信道+高斯白噪声信道
多径信道:

mult_path_am = [1 0.2 0.1]; %  多径幅度
mutt_path_time = [0 20 50]; % 多径时延
windowed_Tx = zeros(size(signal_Tx));
path2 = 0.2*[zeros(1,20) signal_Tx(1:end-20) ];
path3 = 0.1*[zeros(1,50) signal_Tx(1:end-50) ];
signal_Tx_mult = signal_Tx + path2 + path3; % 多径信号

高斯白噪声信道:

SNR_linear = 10^(SNR/10);
noise_power_mut = signal_power_mut/SNR_linear;
noise_power_sig = signal_power_sig/SNR_linear;
noise_sig = randn(size(signal_Tx))*sqrt(noise_power_sig);
noise_mut = randn(size(signal_Tx_mult))*sqrt(noise_power_mut);
Rx_data_sig = signal_Tx+noise_sig;
Rx_data_mut = signal_Tx_mult+noise_mut;
%在发送数据上加噪声,相当于OFDM信号经过加性高斯白噪声信道

8.计算误码率

误码率=错误的bit数/序列长度
分别计算单径和多径下的误码率。

error_bit_sig = sum(bit_demod_sig~=bit_sequence);
error_bit_mut = sum(bit_demod_mut~=bit_sequence);
error_rate_sig = error_bit_sig/bit_length;
error_rate_mut = error_bit_mut/bit_length;
rate = [rate; error_rate_sig error_rate_mut]

二.仿真结果

在这里插入图片描述
图3 16QAM调制后的星座图
16QAM调制的方式,由二进制数字基带信号变为四进制并进行格雷码映射,取值为-3,-1,1,3。
在这里插入图片描述
图4 IFFT变换后
在这里插入图片描述
图5 原始/加循环前缀后缀/加窗后的OFDM信号
在这里插入图片描述
图6 加窗后的信号频谱图
加窗后信号的频率不再分布于整个频域上,而是限定在一定范围内,便于后面在信道中的传输。
在这里插入图片描述
图7 单径/多径下的OFDM信号

在这里插入图片描述
图8 单径下接收信号的星座图
在这里插入图片描述
图9 多径下接收信号的星座图
对比图8图9单径和多径下接收信号的星座图,可以明显看出,相较于单径多径下信号混叠严重。
在这里插入图片描述上图所示分别为单径和多径下的误码率,单径下的误码率为0、多径下的误码率为0.0184,结合图8图9可以看出OFDM在单径下的误码率很低,在多径下的误码率略高于单径。

三.仿真结论

OFDM技术就正面直视并解决了这种载波相互干扰的问题,解决方法就是引入了正交的特性,从而可以在较少带宽中更快的发送信息。在本次OFDM仿真的过程中,引入了两个辅助技术,一是循环前缀和循环后缀,另一个则是加入余弦滚降窗函数。同时仿真过程采用了单径和多径两种信道,实验表明OFDM在单径下的误码率很低,在多径下的误码率略高于单径,可以很好的降低多径效应对于信号的不利影响。

matlab源码链接: https://blog.csdn.net/qq_44394952/article/details/122508697.

  • 70
    点赞
  • 603
    收藏
    觉得还不错? 一键收藏
  • 23
    评论
ESP8266是一款集成了WiFi模块的芯片,它可以通过串口与其他设备进行通信,并且可以使用AT指令进行WiFi模块的控制和通信。下面是ESP8266WiFi模块的教程: 1. 准备工作 首先,你需要准备一块ESP8266WiFi模块,一块Arduino开发板和一条USB数据线。 2. 连接ESP8266WiFi模块 将ESP8266WiFi模块与Arduino开发板通过杜邦线连接,连接方式如下: - ESP8266 VCC引脚连接Arduino 3.3V引脚 - ESP8266 GND引脚连接Arduino GND引脚 - ESP8266 RXD引脚连接Arduino TX引脚 - ESP8266 TXD引脚连接Arduino RX引脚 注意:连接时需将ESP8266模块的电源拔掉。 3. 编写程序 打开Arduino IDE,新建一个空白文件,然后将以下代码复制到文件中: ```c #include <SoftwareSerial.h> //导入串口库 SoftwareSerial wifiSerial(10, 11); //设置软串口 void setup() { Serial.begin(9600); //设置串口波特率 wifiSerial.begin(9600); //设置软串口波特率 wifiSerial.println("AT"); //发送AT指令 } void loop() { if (wifiSerial.available()) { //如果串口有数据 Serial.write(wifiSerial.read()); //将数据发送到串口 } if (Serial.available()) { //如果有串口数据 wifiSerial.write(Serial.read()); //将数据发送到ESP8266模块 } } ``` 这段代码的作用是通过Arduino开发板与ESP8266WiFi模块进行通信,并将ESP8266WiFi模块的响应数据输出到串口。将代码上传到Arduino开发板。 4. 测试ESP8266WiFi模块 在Arduino IDE的串口监视器中,将波特率设置为9600,并发送AT指令。如果ESP8266WiFi模块正常工作,应该会返回“OK”的响应。 现在,你已经成功使用ESP8266WiFi模块与Arduino开发板进行通信了。你可以使用AT指令控制ESP8266WiFi模块,实现WiFi通信等功能。
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值