[算法] OFDM信号的调制与解调详解(完整仿真代码)_ofdm解调
OFDM信号的调制与解调详解
文章目录
-
-
- OFDM信号的调制与解调详解
-
- 一、数学原理
- 二、调制解调流程
-
- 调制过程(发送端):
- 信道传输:
- 解调过程(接收端):
- 完整流程图:
- 关键点说明:
- 三、完整Python仿真
-
- 1. 步骤详解
- 2. 关键参数说明
- 3. 仿真结果分析
-
一、数学原理
OFDM(正交频分复用)的核心思想是将高速数据流分割为多个低速子流,通过相互正交的子载波并行传输。其数学基础是离散傅里叶变换(DFT) 和奈奎斯特采样定理。
关键方程:
- 时域信号: s [ n ] = 1 N∑ k = 0 N − 1X [ k ] e j 2 π k n / N s[n] = \\frac{1}{N}\\sum_{k=0}^{N-1} X[k] e^{j2\\pi kn/N} s[n]=N1∑k=0N−1X[k]ej2πkn/N
- 频域信号: X [ k ] = ∑ n = 0 N − 1s [ n ] e − j 2 π k n / N X[k] = \\sum_{n=0}^{N-1} s[n] e^{-j2\\pi kn/N} X[k]=∑n=0N−1s[n]e−j2πkn/N
- 正交性: 1 N∑ n = 0 N − 1 e j 2 π ( k − m ) n / N= δ [ k − m ] \\frac{1}{N}\\sum_{n=0}^{N-1} e^{j2\\pi (k-m)n/N} = \\delta[k-m] N1∑n=0N−1ej2π(k−m)n/N=δ[k−m]
二、调制解调流程
调制过程(发送端):
-
数据映射:将输入的二进制比特流通过QAM调制映射为复数符号。例如在4-QAM中,每2个比特映射为一个复数符号(00→-1-j, 01→-1+j, 10→1-j, 11→1+j)
-
串并转换:将串行的符号流转换为N路并行数据,每个符号对应一个子载波
#mermaid-svg-eYyEaSiyvE3oVnZg {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-eYyEaSiyvE3oVnZg .error-icon{fill:#552222;}#mermaid-svg-eYyEaSiyvE3oVnZg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eYyEaSiyvE3oVnZg .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-eYyEaSiyvE3oVnZg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eYyEaSiyvE3oVnZg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eYyEaSiyvE3oVnZg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eYyEaSiyvE3oVnZg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eYyEaSiyvE3oVnZg .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eYyEaSiyvE3oVnZg .marker.cross{stroke:#333333;}#mermaid-svg-eYyEaSiyvE3oVnZg svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eYyEaSiyvE3oVnZg .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-eYyEaSiyvE3oVnZg .cluster-label text{fill:#333;}#mermaid-svg-eYyEaSiyvE3oVnZg .cluster-label span{color:#333;}#mermaid-svg-eYyEaSiyvE3oVnZg .label text,#mermaid-svg-eYyEaSiyvE3oVnZg span{fill:#333;color:#333;}#mermaid-svg-eYyEaSiyvE3oVnZg .node rect,#mermaid-svg-eYyEaSiyvE3oVnZg .node circle,#mermaid-svg-eYyEaSiyvE3oVnZg .node ellipse,#mermaid-svg-eYyEaSiyvE3oVnZg .node polygon,#mermaid-svg-eYyEaSiyvE3oVnZg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eYyEaSiyvE3oVnZg .node .label{text-align:center;}#mermaid-svg-eYyEaSiyvE3oVnZg .node.clickable{cursor:pointer;}#mermaid-svg-eYyEaSiyvE3oVnZg .arrowheadPath{fill:#333333;}#mermaid-svg-eYyEaSiyvE3oVnZg .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-eYyEaSiyvE3oVnZg .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-eYyEaSiyvE3oVnZg .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-eYyEaSiyvE3oVnZg .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-eYyEaSiyvE3oVnZg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eYyEaSiyvE3oVnZg .cluster text{fill:#333;}#mermaid-svg-eYyEaSiyvE3oVnZg .cluster span{color:#333;}#mermaid-svg-eYyEaSiyvE3oVnZg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-eYyEaSiyvE3oVnZg :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;} 符号1 子载波1 子载波2 符号2 子载波3 子载波4
-
IFFT变换:对并行的频域符号进行逆快速傅里叶变换,转换为时域信号
s [ n ] = 1 N ∑ k = 0 N − 1 X [ k ] e j 2 π k n / N s[n] = \\frac{1}{N}\\sum_{k=0}^{N-1}X[k]e^{j2\\pi kn/N} s[n]=N1k=0∑N−1X[k]ej2πkn/N -
加循环前缀:复制每个OFDM符号尾部的CP个采样点,添加到符号开头
#mermaid-svg-f3CkkFdZwSI9Hujn {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-f3CkkFdZwSI9Hujn .error-icon{fill:#552222;}#mermaid-svg-f3CkkFdZwSI9Hujn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-f3CkkFdZwSI9Hujn .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-f3CkkFdZwSI9Hujn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-f3CkkFdZwSI9Hujn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-f3CkkFdZwSI9Hujn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-f3CkkFdZwSI9Hujn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-f3CkkFdZwSI9Hujn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-f3CkkFdZwSI9Hujn .marker.cross{stroke:#333333;}#mermaid-svg-f3CkkFdZwSI9Hujn svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-f3CkkFdZwSI9Hujn .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-f3CkkFdZwSI9Hujn .cluster-label text{fill:#333;}#mermaid-svg-f3CkkFdZwSI9Hujn .cluster-label span{color:#333;}#mermaid-svg-f3CkkFdZwSI9Hujn .label text,#mermaid-svg-f3CkkFdZwSI9Hujn span{fill:#333;color:#333;}#mermaid-svg-f3CkkFdZwSI9Hujn .node rect,#mermaid-svg-f3CkkFdZwSI9Hujn .node circle,#mermaid-svg-f3CkkFdZwSI9Hujn .node ellipse,#mermaid-svg-f3CkkFdZwSI9Hujn .node polygon,#mermaid-svg-f3CkkFdZwSI9Hujn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-f3CkkFdZwSI9Hujn .node .label{text-align:center;}#mermaid-svg-f3CkkFdZwSI9Hujn .node.clickable{cursor:pointer;}#mermaid-svg-f3CkkFdZwSI9Hujn .arrowheadPath{fill:#333333;}#mermaid-svg-f3CkkFdZwSI9Hujn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-f3CkkFdZwSI9Hujn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-f3CkkFdZwSI9Hujn .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-f3CkkFdZwSI9Hujn .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-f3CkkFdZwSI9Hujn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-f3CkkFdZwSI9Hujn .cluster text{fill:#333;}#mermaid-svg-f3CkkFdZwSI9Hujn .cluster span{color:#333;}#mermaid-svg-f3CkkFdZwSI9Hujn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-f3CkkFdZwSI9Hujn :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;} 符号数据 尾部采样点 添加到头部
-
并串转换:将带循环前缀的并行符号转换为串行时域波形
#mermaid-svg-zVY8y54TV9DJKgVY {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-zVY8y54TV9DJKgVY .error-icon{fill:#552222;}#mermaid-svg-zVY8y54TV9DJKgVY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-zVY8y54TV9DJKgVY .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-zVY8y54TV9DJKgVY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-zVY8y54TV9DJKgVY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-zVY8y54TV9DJKgVY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-zVY8y54TV9DJKgVY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-zVY8y54TV9DJKgVY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-zVY8y54TV9DJKgVY .marker.cross{stroke:#333333;}#mermaid-svg-zVY8y54TV9DJKgVY svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-zVY8y54TV9DJKgVY .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-zVY8y54TV9DJKgVY .cluster-label text{fill:#333;}#mermaid-svg-zVY8y54TV9DJKgVY .cluster-label span{color:#333;}#mermaid-svg-zVY8y54TV9DJKgVY .label text,#mermaid-svg-zVY8y54TV9DJKgVY span{fill:#333;color:#333;}#mermaid-svg-zVY8y54TV9DJKgVY .node rect,#mermaid-svg-zVY8y54TV9DJKgVY .node circle,#mermaid-svg-zVY8y54TV9DJKgVY .node ellipse,#mermaid-svg-zVY8y54TV9DJKgVY .node polygon,#mermaid-svg-zVY8y54TV9DJKgVY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-zVY8y54TV9DJKgVY .node .label{text-align:center;}#mermaid-svg-zVY8y54TV9DJKgVY .node.clickable{cursor:pointer;}#mermaid-svg-zVY8y54TV9DJKgVY .arrowheadPath{fill:#333333;}#mermaid-svg-zVY8y54TV9DJKgVY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-zVY8y54TV9DJKgVY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-zVY8y54TV9DJKgVY .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-zVY8y54TV9DJKgVY .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-zVY8y54TV9DJKgVY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-zVY8y54TV9DJKgVY .cluster text{fill:#333;}#mermaid-svg-zVY8y54TV9DJKgVY .cluster span{color:#333;}#mermaid-svg-zVY8y54TV9DJKgVY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-zVY8y54TV9DJKgVY :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;} 符号1 合并 符号2 符号3 连续波形
信道传输:
- 信号发送:OFDM信号通过无线信道传输,仿真中模拟为加性高斯白噪声(AWGN)信道
r ( t ) = s ( t ) + n ( t ) r(t) = s(t) + n(t) r(t)=s(t)+n(t)
解调过程(接收端):
-
串并转换:将接收到的串行信号分割为独立的OFDM符号块
#mermaid-svg-cGzDU4BvaMn8Lxr1 {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .error-icon{fill:#552222;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .marker.cross{stroke:#333333;}#mermaid-svg-cGzDU4BvaMn8Lxr1 svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .cluster-label text{fill:#333;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .cluster-label span{color:#333;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .label text,#mermaid-svg-cGzDU4BvaMn8Lxr1 span{fill:#333;color:#333;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .node rect,#mermaid-svg-cGzDU4BvaMn8Lxr1 .node circle,#mermaid-svg-cGzDU4BvaMn8Lxr1 .node ellipse,#mermaid-svg-cGzDU4BvaMn8Lxr1 .node polygon,#mermaid-svg-cGzDU4BvaMn8Lxr1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .node .label{text-align:center;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .node.clickable{cursor:pointer;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .arrowheadPath{fill:#333333;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .cluster text{fill:#333;}#mermaid-svg-cGzDU4BvaMn8Lxr1 .cluster span{color:#333;}#mermaid-svg-cGzDU4BvaMn8Lxr1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cGzDU4BvaMn8Lxr1 :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;} 连续波形 分割 符号1 符号2 符号3
-
去循环前缀:移除每个符号块前端的CP个采样点
#mermaid-svg-qMwHrFlw7e4lSaBl {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-qMwHrFlw7e4lSaBl .error-icon{fill:#552222;}#mermaid-svg-qMwHrFlw7e4lSaBl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qMwHrFlw7e4lSaBl .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-qMwHrFlw7e4lSaBl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qMwHrFlw7e4lSaBl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qMwHrFlw7e4lSaBl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qMwHrFlw7e4lSaBl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qMwHrFlw7e4lSaBl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qMwHrFlw7e4lSaBl .marker.cross{stroke:#333333;}#mermaid-svg-qMwHrFlw7e4lSaBl svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qMwHrFlw7e4lSaBl .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qMwHrFlw7e4lSaBl .cluster-label text{fill:#333;}#mermaid-svg-qMwHrFlw7e4lSaBl .cluster-label span{color:#333;}#mermaid-svg-qMwHrFlw7e4lSaBl .label text,#mermaid-svg-qMwHrFlw7e4lSaBl span{fill:#333;color:#333;}#mermaid-svg-qMwHrFlw7e4lSaBl .node rect,#mermaid-svg-qMwHrFlw7e4lSaBl .node circle,#mermaid-svg-qMwHrFlw7e4lSaBl .node ellipse,#mermaid-svg-qMwHrFlw7e4lSaBl .node polygon,#mermaid-svg-qMwHrFlw7e4lSaBl .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qMwHrFlw7e4lSaBl .node .label{text-align:center;}#mermaid-svg-qMwHrFlw7e4lSaBl .node.clickable{cursor:pointer;}#mermaid-svg-qMwHrFlw7e4lSaBl .arrowheadPath{fill:#333333;}#mermaid-svg-qMwHrFlw7e4lSaBl .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qMwHrFlw7e4lSaBl .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qMwHrFlw7e4lSaBl .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-qMwHrFlw7e4lSaBl .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-qMwHrFlw7e4lSaBl .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qMwHrFlw7e4lSaBl .cluster text{fill:#333;}#mermaid-svg-qMwHrFlw7e4lSaBl .cluster span{color:#333;}#mermaid-svg-qMwHrFlw7e4lSaBl div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qMwHrFlw7e4lSaBl :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;} 带CP符号 移除头部CP 纯净符号
-
FFT变换:对时域信号进行快速傅里叶变换,恢复频域符号
X [ k ] = ∑ n = 0 N − 1 s [ n ] e − j 2 π k n / N X[k] = \\sum_{n=0}^{N-1}s[n]e^{-j2\\pi kn/N} X[k]=n=0∑N−1s[n]e−j2πkn/N -
信道均衡:补偿信道失真(仿真中未实现,实际系统必需)
-
QAM解映射:将复数符号解调为二进制比特流
#mermaid-svg-l6KNr3kPhPFn1G5e {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-l6KNr3kPhPFn1G5e .error-icon{fill:#552222;}#mermaid-svg-l6KNr3kPhPFn1G5e .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-l6KNr3kPhPFn1G5e .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-l6KNr3kPhPFn1G5e .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-l6KNr3kPhPFn1G5e .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-l6KNr3kPhPFn1G5e .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-l6KNr3kPhPFn1G5e .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-l6KNr3kPhPFn1G5e .marker{fill:#333333;stroke:#333333;}#mermaid-svg-l6KNr3kPhPFn1G5e .marker.cross{stroke:#333333;}#mermaid-svg-l6KNr3kPhPFn1G5e svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-l6KNr3kPhPFn1G5e .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-l6KNr3kPhPFn1G5e .cluster-label text{fill:#333;}#mermaid-svg-l6KNr3kPhPFn1G5e .cluster-label span{color:#333;}#mermaid-svg-l6KNr3kPhPFn1G5e .label text,#mermaid-svg-l6KNr3kPhPFn1G5e span{fill:#333;color:#333;}#mermaid-svg-l6KNr3kPhPFn1G5e .node rect,#mermaid-svg-l6KNr3kPhPFn1G5e .node circle,#mermaid-svg-l6KNr3kPhPFn1G5e .node ellipse,#mermaid-svg-l6KNr3kPhPFn1G5e .node polygon,#mermaid-svg-l6KNr3kPhPFn1G5e .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-l6KNr3kPhPFn1G5e .node .label{text-align:center;}#mermaid-svg-l6KNr3kPhPFn1G5e .node.clickable{cursor:pointer;}#mermaid-svg-l6KNr3kPhPFn1G5e .arrowheadPath{fill:#333333;}#mermaid-svg-l6KNr3kPhPFn1G5e .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-l6KNr3kPhPFn1G5e .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-l6KNr3kPhPFn1G5e .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-l6KNr3kPhPFn1G5e .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-l6KNr3kPhPFn1G5e .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-l6KNr3kPhPFn1G5e .cluster text{fill:#333;}#mermaid-svg-l6KNr3kPhPFn1G5e .cluster span{color:#333;}#mermaid-svg-l6KNr3kPhPFn1G5e div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-l6KNr3kPhPFn1G5e :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;} 复数符号 实部>0? 虚部>0? 比特1 比特2
完整流程图:
#mermaid-svg-tYqSUf6UtfkCI7Uq {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-tYqSUf6UtfkCI7Uq .error-icon{fill:#552222;}#mermaid-svg-tYqSUf6UtfkCI7Uq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tYqSUf6UtfkCI7Uq .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-tYqSUf6UtfkCI7Uq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tYqSUf6UtfkCI7Uq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tYqSUf6UtfkCI7Uq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tYqSUf6UtfkCI7Uq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tYqSUf6UtfkCI7Uq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tYqSUf6UtfkCI7Uq .marker.cross{stroke:#333333;}#mermaid-svg-tYqSUf6UtfkCI7Uq svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tYqSUf6UtfkCI7Uq .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-tYqSUf6UtfkCI7Uq .cluster-label text{fill:#333;}#mermaid-svg-tYqSUf6UtfkCI7Uq .cluster-label span{color:#333;}#mermaid-svg-tYqSUf6UtfkCI7Uq .label text,#mermaid-svg-tYqSUf6UtfkCI7Uq span{fill:#333;color:#333;}#mermaid-svg-tYqSUf6UtfkCI7Uq .node rect,#mermaid-svg-tYqSUf6UtfkCI7Uq .node circle,#mermaid-svg-tYqSUf6UtfkCI7Uq .node ellipse,#mermaid-svg-tYqSUf6UtfkCI7Uq .node polygon,#mermaid-svg-tYqSUf6UtfkCI7Uq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-tYqSUf6UtfkCI7Uq .node .label{text-align:center;}#mermaid-svg-tYqSUf6UtfkCI7Uq .node.clickable{cursor:pointer;}#mermaid-svg-tYqSUf6UtfkCI7Uq .arrowheadPath{fill:#333333;}#mermaid-svg-tYqSUf6UtfkCI7Uq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-tYqSUf6UtfkCI7Uq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-tYqSUf6UtfkCI7Uq .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-tYqSUf6UtfkCI7Uq .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-tYqSUf6UtfkCI7Uq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-tYqSUf6UtfkCI7Uq .cluster text{fill:#333;}#mermaid-svg-tYqSUf6UtfkCI7Uq .cluster span{color:#333;}#mermaid-svg-tYqSUf6UtfkCI7Uq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-tYqSUf6UtfkCI7Uq :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;} 解调器 调制器 星座映射 分配到N路子载波 时域转换 抗多径干扰 符号分割 移除保护间隔 频域恢复 符号到比特 去循环前缀 串并转换 FFT变换 QAM解映射 输出数据 串并转换 QAM映射 IFFT变换 加循环前缀 并串转换 二进制数据 发送信号 AWGN信道 接收信号
关键点说明:
-
正交性原理:子载波间距Δf=1/T,满足正交条件:
∫ 0 T e j 2 π ( m − n ) t / T d t = { T m = n 0 m ≠ n \\int_0^T e^{j2\\pi(m-n)t/T}dt = \\begin{cases} T & m=n \\\\ 0 & m≠n \\end{cases} ∫0Tej2π(m−n)t/Tdt={T0m=nm=n -
循环前缀作用:
- 消除符号间干扰(ISI)
- 将线性卷积转换为循环卷积
- 简化信道均衡过程
-
FFT/IFFT实现:利用快速傅里叶变换算法,将复杂度从O(N²)降低到O(NlogN)
-
频谱效率:虽然需要添加循环前缀(约20%开销),但通过子载波正交排列,仍比传统FDM节省50%带宽
-
抗多径能力:循环前缀长度需大于信道最大时延扩展,确保多径分量不会干扰下一个符号
此流程完整展示了OFDM系统从比特流到无线信号再到恢复比特流的全过程,Python代码实现了这一流程的端到端仿真。
三、完整Python仿真
import numpy as npimport matplotlib.pyplot as pltfrom scipy.fft import fft, ifft# ================== 参数设置 ==================N = 64 # 子载波数量CP = 16 # 循环前缀长度SNR_dB = 20 # 降低信噪比以展示噪声影响total_symbols = 10 # 总符号数mod_order = 4 # 4-QAM调制# ================== 调制过程 ==================def ofdm_modulator(data): # QAM映射(4-QAM) qam_symbols = 2 * data.reshape(-1, 2).astype(float) - 1 qam_symbols = qam_symbols[:, 0] + 1j * qam_symbols[:, 1] qam_symbols /= np.sqrt(2) # 能量归一化 # 串并转换 parallel_data = qam_symbols.reshape(total_symbols, N) # IFFT变换 time_domain = np.zeros_like(parallel_data, dtype=complex) for i in range(total_symbols): time_domain[i] = ifft(parallel_data[i], norm=\"ortho\") * np.sqrt(N) # 功率补偿 # 加循环前缀 cp = time_domain[:, -CP:] ofdm_symbols = np.hstack((cp, time_domain)) # 并串转换 tx_signal = ofdm_symbols.flatten() return tx_signal, qam_symbols# ================== 信道模拟 ==================def awgn_channel(signal, snr_db): snr = 10**(snr_db/10) signal_power = np.mean(np.abs(signal)**2) noise_power = signal_power / snr noise = np.sqrt(noise_power/2) * (np.random.randn(len(signal)) + 1j*np.random.randn(len(signal))) return signal + noise# ================== 解调过程 ==================def ofdm_demodulator(rx_signal): # 串并转换 rx_symbols = rx_signal.reshape(total_symbols, N + CP) # 去循环前缀 rx_no_cp = rx_symbols[:, CP:] # FFT变换 freq_domain = np.zeros((total_symbols, N), dtype=complex) for i in range(total_symbols): freq_domain[i] = fft(rx_no_cp[i], norm=\"ortho\") / np.sqrt(N) # 功率补偿 # QAM解映射 rx_symbols = freq_domain.flatten() rx_real = np.real(rx_symbols) * np.sqrt(2) rx_imag = np.imag(rx_symbols) * np.sqrt(2) rx_data = np.zeros(len(rx_symbols)*2) rx_data[0::2] = (rx_real > 0).astype(int) rx_data[1::2] = (rx_imag > 0).astype(int) return rx_data, freq_domain.flatten() # 返回解调比特和频域符号# ================== 主程序 ==================if __name__ == \"__main__\": # 生成随机二进制数据 tx_bits = np.random.randint(0, 2, total_symbols * N * 2) # 每个符号2比特 # OFDM调制 tx_signal, tx_symbols = ofdm_modulator(tx_bits) # 通过AWGN信道 rx_signal = awgn_channel(tx_signal, SNR_dB) # OFDM解调 rx_bits, rx_symbols = ofdm_demodulator(rx_signal) # 计算误码率 ber = np.mean(tx_bits != rx_bits) print(f\"误码率: {ber:.2e} (SNR={SNR_dB}dB)\") # 绘制时域信号 plt.figure(figsize=(12, 10)) plt.subplot(311) plt.plot(np.real(tx_signal[:200]), \'b\') plt.title(f\'发送信号实部 (前200个采样点, SNR={SNR_dB}dB)\') plt.grid(True) # 绘制频域信号 plt.subplot(312) plt.plot(np.abs(fft(tx_signal[:N*2])[:N], \'r\') plt.title(\'OFDM信号频谱 (首个符号)\') plt.grid(True) # 绘制星座图 plt.subplot(313) # 发送符号(理想位置) plt.scatter(np.real(tx_symbols), np.imag(tx_symbols), c=\'b\', marker=\'o\', alpha=0.5, label=\'Tx Symbols\') # 接收符号(实际位置) plt.scatter(np.real(rx_symbols), np.imag(rx_symbols), c=\'r\', marker=\'x\', alpha=0.5, label=\'Rx Symbols\') plt.title(f\'QAM星座图 (SNR={SNR_dB}dB)\') plt.xlabel(\'实部\'); plt.ylabel(\'虚部\') plt.grid(True); plt.legend() plt.axis(\'equal\') plt.tight_layout() plt.savefig(\'ofdm_simulation_corrected.png\', dpi=300) plt.show() # 绘制误差向量幅度(EVM) evm = np.sqrt(np.mean(np.abs(tx_symbols - rx_symbols)**2)) / np.sqrt(np.mean(np.abs(tx_symbols)**2)) print(f\"误差向量幅度(EVM): {evm*100:.2f}%\")
1. 步骤详解
调制过程:
- 数据映射:二进制数据→QAM符号(星座点映射)
- 串并转换:将串行符号流分配到N个并行子载波
- IFFT变换:将频域符号转换为时域波形(核心操作)
- 添加循环前缀:复制尾部CP长度数据添加到头部
- 消除符号间干扰(ISI)
- 对抗多径时延
- 并串转换:生成最终发送信号
解调过程:
- 串并转换:接收信号分割为OFDM符号
- 去除循环前缀:丢弃每个符号前CP长度的采样点
- FFT变换:将时域信号转换回频域符号
- 信道均衡(仿真中未体现):补偿信道失真
- QAM解映射:星座点→二进制数据
2. 关键参数说明
- 子载波数量(N):决定频谱效率和抗频偏能力
- 循环前缀长度(CP):需大于最大多径时延
- 调制阶数(mod_order):4-QAM(4种状态)/16-QAM(16种状态)
- SNR:衡量信道质量的关键指标
3. 仿真结果分析
- 时域波形:显示OFDM信号的幅度波动特性
- 频谱图:展示子载波的正交性和带限特性
- 星座图:
- 蓝色圆点:发送符号的理想位置
- 红色叉号:接收符号的实际位置
- 点集扩散程度反映噪声影响
误码率: 0.00e+00 (SNR=20dB)误差向量幅度(EVM): 9.96%
在理想信道(高SNR)下,误码率应接近0,可以通过修改仿真中的SNR参数,观察信噪比变化对误码率,EVM以及星座图的影响。实际无线通信中需增加信道估计、同步等模块。本仿真完整实现了OFDM核心处理流程,可作为更复杂系统设计的基础。
研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)