OFDM 系统中 PAPR 降低

OFDM 系统中 PAPR 降低

从零搭一个离散 OFDM 发射链路 → 算 PAPR → 三种"非搜索"降低手段(限幅/压扩/预留子载波)


一、PAPR 的定义(时域)

对一个 OFDM 符号(N 个子载波,sampling pts = N·oversample 的过采样版本):

PAPR(线性尺度)

工程上常用 dB:


二、主干:OFDM 发射机 + PAPR 计算

2.1 主脚本(ofdm_papr_main.m

%% ofdm_papr_main.m
% OFDM PAPR 计算 & 降低(不限幅/压扩/预留子载波)
% 不依赖任何搜索/优化工具箱
clear; clc; close all;

rng(0);  % 可重复

%% ===== 1. 参数 =====
Nfft      = 128;           % FFT size(子载波数)
Ncp       = 16;            % 循环前缀长度
osf       = 4;             % 过采样倍数(测PAPR需≥4)
Nos       = Nfft * osf;    % 过采样点数(时域插值法)
Nsymb     = 200;           % 统计用的OFDM符号数(越多CCDF越稳)
Es         = 1;            % 平均符号能量归一化(QPSK)

% 子载波分配
% 最简单:直流(k=0)空,两边各用 Nused/2 个数据子载波
Nused     = 52;            % 实际数据子载波(示意)
k_data    = [(1:Nused/2)+1 , Nfft-(Nused/2)+1: Nfft]; % 避开 dc=1和Nyquist
k_reserve = [];            % 预留子载波索引(后面TR法用)

fprintf('=== OFDM PAPR 仿真 ===\n');
fprintf('Nfft=%d  Ncp=%d  osf=%d  Nsymb=%d\n',Nfft,Ncp,Nos,Nsymb);

%% ===== 2. 生成一批OFDM符号(原始) =====
tx_syms = cell(Nsymb,1);
time_sigs_orig = zeros(Nos, Nsymb);

for m = 1:Nsymb
    % QPSK符号(±1±j)/√2
    bits = randi([0 1], Nused, 2);
    sym  = (1-2*bits(:,1))/sqrt(2) + 1j*(1-2*bits(:,2))/sqrt(2);

    X = zeros(Nfft,1);
    X(k_data) = sym;

    % IFFT → 加CP → 过采样(补零插值 + 低通理想插值用 FFT过采样)
    x_base = ifft(X)*sqrt(Nfft);     % Nfft点
    x_cp    = [x_base(end-Ncp+1:end); x_base]; % (Nfft+Ncp)×1

    % 过采样:插0再低通 → 用fft技巧
    x_os = oversample_by_ifft(x_base, Nfft, osf);

    time_sigs_orig(:,m) = x_os;
end

%% ===== 3. PAPR & CCDF =====
[PAPR_orig, ccdf_orig] = papr_ccdf(time_sigs_orig, 0.5);

fprintf('\n原始信号:PAPR0(dB)  ~ %.2f dB\n', max(PAPR_orig));
fprintf('       P(PAPR>7dB) ~ %.4f\n', interp1(ccdf_orig.db, ccdf_orig.prob, 7));

%% ===== 4. 方法一:限幅(Clipping)=====
clip_gamma_dB = 6.5;   % 限幅门限(相对 RMS),可调
clip_gamma = 10^(clip_gamma_dB/20) * sqrt(mean(abs(time_sigs_orig(:)).^2));

time_clip = cellfun(@(x) clip_signal(x, clip_gamma), ...
                    num2cell(time_sigs_orig,1), 'UniformOutput',false);
time_clip = cell2mat(time_clip.');
[PAPR_clip, ccdf_clip] = papr_ccdf(time_clip, 0.5);

%% ===== 5. 方法二:μ-law 压扩(Companding)=====
mu = 10;  % μ参数,越大压得越狠
time_comp = zeros(size(time_sigs_orig));
for m = 1:Nsymb
    x = time_sigs_orig(:,m);
    r = abs(x);
    r_normed = r / sqrt(mean(r.^2)+eps);
    % μ-law 压缩
    r_comp = (log(1+mu*r_normed)/log(1+mu)) .* exp(1j*angle(x));
    % 恢复平均功率(可选:保证输出功率和输入一致)
    gain_corr = sqrt(mean(r.^2)+eps) / sqrt(mean(abs(r_comp).^2)+eps);
    time_comp(:,m) = r_comp * gain_corr;
end
[PAPR_comp, ccdf_comp] = papr_ccdf(time_comp, 0.5);

%% ===== 6. 方法三:预留子载波 TR(Tone Reservation)=====
% 思想:选一些子载波永远不送数据,只用来"反相"抵消时域峰值
% 不需要搜索:固定一组随机相位 / 或者解最小二乘(线性系统)→ 也不是搜索
Ntr = 8;  % 预留子载波个数
k_tr = randperm(Nfft-2, Ntr) + 1;  % 随机挑(避开dc),非搜索
k_tr(k_tr==1)=[]; if numel(k_tr)<Ntr, k_tr(end+1)=Nfft/2; end
k_tr = k_tr(1:Ntr);

time_tr = zeros(Nos, Nsymb);
for m = 1:Nsymb
    x_base = time_sigs_orig(1:osf:end, m);  % 关键:用基带Nfft点反演
    x_base = x_base(1:Nfft);  % 确保长度

    % 迭代抵消峰值(线性,非搜索)
    C = 1.5; iterTR = 5;
    for it = 1:iterTR
        peaks = find_peaks_for_cancel(x_base, C);
        if isempty(peaks), break; end
        % 构造 b = -x[peak] 的目标,A = F(:,k_tr) 的列为候选子载波时域基
        A = zeros(Nfft, Ntr);
        for t = 1:Ntr
            A(:,t) = sqrt(Nfft)*ifft(unit_impulse_at(Nfft, k_tr(t)));
        end
        % 最小二乘(解线性方程,不是搜索)
        c = A \ (-x_base(peaks));
        % 更新
        x_base(peaks) = x_base(peaks) + A(peaks,:)*c;
        % 裁剪极端(保底)
        x_base = min(abs(x_base),C)*exp(1j*angle(x_base));
    end
    time_tr(:,m) = oversample_by_ifft(x_base, Nfft, osf);
end
[PAPR_tr, ccdf_tr] = papr_ccdf(time_tr, 0.5);

%% ===== 7. 画图 =====
figure('Color','w','Position',[120 80 1100 420]);
subplot(1,3,1)
plot(ccdf_orig.db, ccdf_orig.prob,'k-','LineW',1.8); hold on
plot(ccdf_clip.db, ccdf_clip.prob,'r--','LineW',1.5)
plot(ccdf_comp.db, ccdf_comp.prob,'b-.','LineW',1.5)
plot(ccdf_tr.db,   ccdf_tr.prob,  'g:','LineW',1.8)
grid on; set(gca,'YScale','log')
xlabel('PAPR_0(dB)'); ylabel('CCDF = Prob(PAPR>γ)')
title('CCDF 对比')
legend('原始','限幅','μ压扩','TR预留子载波','Location','southwest')

subplot(1,3,2)
semilogy(ccdf_orig.db, ccdf_orig.prob,'k'); grid on; hold on
semilogy(ccdf_clip.db,ccdf_clip.prob,'r--')
xline(7,'k:'); yline(1e-2,'k:')
title('CCDF (log)')
xlabel('PAPR_0(dB)'); ylabel('Prob')

subplot(1,3,3)
% 抽一个符号看时域包络
x0 = time_sigs_orig(:,1); xc = time_clip(:,1); xt = time_tr(:,1);
plot(abs(x0),'k','LineW',1.2); hold on
plot(abs(xc),'r--','LineW',1.1)
plot(abs(xt),'g:','LineW',1.1)
plot([1 numel(x0)],[clip_gamma clip_gamma],'r:')
grid on; xlabel('样点 n'); ylabel('|x[n]|')
title('一个OFDM符号时域包络对比')
legend('原始','限幅','TR','ClipThr','Location','northwest')

sgtitle('OFDM PAPR 降低方法对比(无搜索工具箱)')

三、底层函数

3.1 过采样(IFFT补零插值)

function x_os = oversample_by_ifft(x_base, Nfft, osf)
% 时域过采样:把Nfft点x放到Nos点IFFT的低位 → 再做一次小IFFT
Nos = Nfft*osf;
X = fft(x_base);                 % Nfft点频域
X_up = zeros(Nos,1);
% 把正负频搬正确(假设 x_base 是 Nfft 点实对称结构)
% 最稳妥:直流+正频放前面,Nyquist放中间
mid   = floor(Nfft/2)+1;
X_up(1:mid) = X(1:mid);
X_up(end-(Nfft-mid)+1:end) = X(mid+1:end);
x_os = ifft(X_up)*sqrt(Nos);     % 注意幅度看你是否想保留sqrt(Nfft/Nos)因子
end

3.2 PAPR 计算 + CCDF

function [PAPR_vec, ccdf] = papr_ccdf(time_sigs, rms_ref)
% time_sigs : Nos × Nsymb
% 输出:PAPR_vec每个符号,ccdf结构(db, prob)

Ns = size(time_sigs,2);
PAPR_vec = zeros(Ns,1);

for m = 1:Ns
    x = time_sigs(:,m);
    p_inst = abs(x).^2;
    Pavg = mean(p_inst);
    PAPR_vec(m) = max(p_inst)/Pavg;
end

db = 0:0.1:12;
prob = zeros(size(db));
for k = 1:numel(db)
    prob(k) = mean(PAPR_vec > 10^(db(k)/10));
end
ccdf.db   = db;
ccdf.prob = prob;
end

3.3 限幅(硬限幅,最朴素)

function y = clip_signal(x, gamma)
% gamma = 限幅门限(幅度值,不是dB)
y = x;
mag = abs(x);
over = mag > gamma;
y(over) = gamma .* exp(1j*angle(x(over)));
end

3.4 TR法用到的两个小辅助

function idx = find_peaks_for_cancel(x, C)
% 简单找超过门限C的索引(非搜索优化,只是阈值检测)
idx = find(abs(x) > C);
end

function vec = unit_impulse_at(N,k)
% 频域冲激:第k个bin=1(k从1开始,MATLAB索引)
vec = zeros(N,1);
vec(k) = 1;
end

参考代码 ofdm码中papr的降低 www.youwenfan.com/contentcsv/101627.html

四、重点解释

方法 核心运算 为什么不是搜索
限幅 Clipping 逐点阈值判断 |x|>γ → 改幅度 纯代数/逻辑
μ-law 压扩 逐点非线性函数 y=f(|x|,∠x) 确定性映射
TR 预留子载波 每次检测到超门限位置后,解 Ax=b(最小二乘) 更新预留子载波权值 解线性方程组(\),不是搜索

 

专注于matlab/simulink,电子电路,编程