正交频分复用(OFDM)系统的主要缺点之一是高峰均功率比(PAPR),这会导致功率放大器非线性失真、增加误码率。以下是各种降低PAPR算法的MATLAB实现及性能分析。
一、PAPR问题概述
1.1 PAPR定义
PAPR(dB) = 10·log₁₀(max|s(t)|² / E[|s(t)|²])
其中s(t)是OFDM时域信号,E[·]表示期望。
1.2 系统模型
- 子载波数:
N = 64, 128, 256, ... - 调制方式:QPSK, 16QAM, 64QAM
- 过采样因子:
L = 4(准确评估PAPR)
二、PAPR降低算法分类
| 算法类别 | 代表算法 | 优点 | 缺点 | BER影响 |
|---|---|---|---|---|
| 限幅类 | 硬限幅、软限幅 | 实现简单 | 非线性失真 | 恶化明显 |
| 概率类 | SLM、PTS | 无失真 | 计算复杂,需边带信息 | 无恶化 |
| 编码类 | 块编码、Golay码 | 无失真 | 频谱效率低 | 无恶化 |
| 预失真类 | ACE、TR | 性能好 | 计算量大 | 轻微恶化 |
| 加扰类 | 载波预留、压扩 | 复杂度低 | 性能受限 | 轻微恶化 |
三、MATLAB完整实现
3.1 基础OFDM系统
matlab
%% OFDM系统基础模型
classdef OFDMSystem < handle
% OFDM系统基类
properties
N = 64; % 子载波数
Ncp = 16; % 循环前缀长度
M = 4; % 调制阶数 (QPSK=4, 16QAM=16, 64QAM=64)
L = 4; % 过采样因子
mod_type = 'QPSK'; % 调制类型
snr_db = 0:2:20; % 信噪比范围
num_symbols = 1000; % OFDM符号数
end
methods
function obj = OFDMSystem(varargin)
% 构造函数
for i = 1:2:length(varargin)
if isprop(obj, varargin{i})
obj.(varargin{i}) = varargin{i+1};
end
end
end
function [symbols, bits] = generate_data(obj)
% 生成随机数据
bits_per_symbol = log2(obj.M) * obj.N;
total_bits = bits_per_symbol * obj.num_symbols;
bits = randi([0, 1], total_bits, 1);
% 调制
if strcmp(obj.mod_type, 'QPSK')
symbols = pskmod(reshape(bits, 2, [])', 4, pi/4, 'gray');
elseif strcmp(obj.mod_type, '16QAM')
symbols = qammod(reshape(bits, 4, [])', 16, 'gray', 'InputType', 'bit');
else
symbols = qammod(reshape(bits, 6, [])', 64, 'gray', 'InputType', 'bit');
end
symbols = reshape(symbols, obj.N, obj.num_symbols);
end
function tx_signal = ofdm_modulate(obj, symbols)
% OFDM调制
[N, num_sym] = size(symbols);
% 过采样
if obj.L > 1
padded_symbols = zeros(N*obj.L, num_sym);
center = floor(N/2);
padded_symbols(1:center, :) = symbols(1:center, :);
padded_symbols(end-center+1:end, :) = symbols(center+1:end, :);
else
padded_symbols = symbols;
end
% IFFT
tx_signal = ifft(padded_symbols, N*obj.L, 1);
% 添加循环前缀
tx_signal = [tx_signal(end-obj.Ncp*obj.L+1:end, :); tx_signal];
end
function papr_db = calculate_papr(obj, signal)
% 计算PAPR
signal_power = abs(signal).^2;
peak_power = max(signal_power, [], 1);
avg_power = mean(signal_power, 1);
papr_linear = peak_power ./ avg_power;
papr_db = 10*log10(papr_linear);
end
function ccdf = calculate_ccdf(obj, papr_values, threshold_db)
% 计算CCDF
papr_values = papr_values(:);
ccdf = mean(papr_values > threshold_db);
end
function ber = simulate_ber(obj, varargin)
% BER仿真框架
% 子类需重写此方法
error('必须在子类中实现');
end
end
end
3.2 限幅类算法
3.2.1 硬限幅
matlab
%% 硬限幅算法
classdef HardClipping < OFDMSystem
% 硬限幅算法
properties
clip_ratio = 0.8; % 限幅比例 (CR)
end
methods
function obj = HardClipping(varargin)
obj = obj@OFDMSystem(varargin{:});
end
function clipped_signal = apply_clipping(obj, signal)
% 应用硬限幅
amplitude = abs(signal);
phase = angle(signal);
% 计算限幅门限
threshold = obj.clip_ratio * max(amplitude(:));
% 限幅
amplitude_clipped = min(amplitude, threshold);
% 重建信号
clipped_signal = amplitude_clipped .* exp(1j*phase);
end
function ber = simulate_ber(obj, snr_db)
% BER仿真
ber = zeros(size(snr_db));
for snr_idx = 1:length(snr_db)
total_errors = 0;
total_bits = 0;
for sym_idx = 1:obj.num_symbols
% 生成数据
bits_per_symbol = log2(obj.M) * obj.N;
bits = randi([0, 1], bits_per_symbol, 1);
% 调制
if strcmp(obj.mod_type, 'QPSK')
symbols = pskmod(reshape(bits, 2, [])', 4, pi/4, 'gray');
else
symbols = qammod(reshape(bits, 4, [])', 16, 'gray', 'InputType', 'bit');
end
% OFDM调制
tx_signal = obj.ofdm_modulate(symbols);
% 限幅
clipped_signal = obj.apply_clipping(tx_signal);
% 添加噪声
signal_power = mean(abs(clipped_signal).^2);
noise_power = signal_power / (10^(snr_db(snr_idx)/10));
noise = sqrt(noise_power/2) * (randn(size(clipped_signal)) + 1j*randn(size(clipped_signal)));
rx_signal = clipped_signal + noise;
% OFDM解调
rx_symbols = obj.ofdm_demodulate(rx_signal);
% 解调
if strcmp(obj.mod_type, 'QPSK')
rx_bits = pskdemod(rx_symbols, 4, pi/4, 'gray');
else
rx_bits = qamdemod(rx_symbols, 16, 'gray', 'OutputType', 'bit');
end
% 计算误码
errors = sum(bits(:) ~= rx_bits(:));
total_errors = total_errors + errors;
total_bits = total_bits + length(bits);
end
ber(snr_idx) = total_errors / total_bits;
end
end
function plot_papr_performance(obj)
% 绘制PAPR性能
papr_original = [];
papr_clipped = [];
for i = 1:100
% 生成数据
[symbols, ~] = obj.generate_data();
tx_signal = obj.ofdm_modulate(symbols);
% 计算原始PAPR
papr_orig = obj.calculate_papr(tx_signal);
papr_original = [papr_original, papr_orig];
% 应用限幅
clipped_signal = obj.apply_clipping(tx_signal);
papr_clip = obj.calculate_papr(clipped_signal);
papr_clipped = [papr_clipped, papr_clip];
end
% 计算CCDF
threshold_db = 0:0.1:12;
ccdf_original = zeros(size(threshold_db));
ccdf_clipped = zeros(size(threshold_db));
for i = 1:length(threshold_db)
ccdf_original(i) = mean(papr_original > threshold_db(i));
ccdf_clipped(i) = mean(papr_clipped > threshold_db(i));
end
% 绘图
figure('Position', [100, 100, 800, 600]);
subplot(2,2,1);
plot(threshold_db, ccdf_original, 'b-', 'LineWidth', 2);
hold on;
plot(threshold_db, ccdf_clipped, 'r--', 'LineWidth', 2);
xlabel('PAPR_0 (dB)');
ylabel('CCDF = Pr(PAPR > PAPR_0)');
title('硬限幅PAPR性能');
legend(['原始 (CR=1.0)', sprintf('限幅 (CR=%.1f)', obj.clip_ratio)]);
grid on;
subplot(2,2,2);
[f_orig, x_orig] = ecdf(papr_original);
[f_clip, x_clip] = ecdf(papr_clipped);
plot(x_orig, 1-f_orig, 'b-', 'LineWidth', 2);
hold on;
plot(x_clip, 1-f_clip, 'r--', 'LineWidth', 2);
xlabel('PAPR (dB)');
ylabel('CCDF');
title('ECDF曲线');
grid on;
subplot(2,2,3);
% BER性能
snr_db = obj.snr_db;
ber = obj.simulate_ber(snr_db);
semilogy(snr_db, ber, 'b-o', 'LineWidth', 2);
xlabel('SNR (dB)');
ylabel('BER');
title('硬限幅BER性能');
grid on;
subplot(2,2,4);
% 星座图
[symbols, ~] = obj.generate_data();
tx_signal = obj.ofdm_modulate(symbols(:,1));
clipped_signal = obj.apply_clipping(tx_signal);
scatter(real(tx_signal(1:1000)), imag(tx_signal(1:1000)), 10, 'b.');
hold on;
scatter(real(clipped_signal(1:1000)), imag(clipped_signal(1:1000)), 10, 'r.');
xlabel('实部');
ylabel('虚部');
title('时域信号星座图');
legend('原始', '限幅后');
axis equal;
grid on;
sgtitle(sprintf('硬限幅算法性能 (N=%d, %s)', obj.N, obj.mod_type));
end
end
end
3.2.2 软限幅
matlab
%% 软限幅算法
classdef SoftClipping < OFDMSystem
% 软限幅算法
properties
clip_ratio = 0.8; % 限幅比例
smooth_factor = 0.1; % 平滑因子
end
methods
function clipped_signal = apply_soft_clipping(obj, signal)
% 应用软限幅
amplitude = abs(signal);
phase = angle(signal);
% 计算门限
threshold = obj.clip_ratio * max(amplitude(:));
% 软限幅函数
% 分段函数:低于门限保持原样,高于门限平滑过渡
amplitude_clipped = zeros(size(amplitude));
idx_below = amplitude <= threshold;
idx_above = amplitude > threshold;
% 低于门限部分保持不变
amplitude_clipped(idx_below) = amplitude(idx_below);
% 高于门限部分应用软限幅
excess = amplitude(idx_above) - threshold;
amplitude_clipped(idx_above) = threshold + ...
obj.smooth_factor * excess ./ (1 + obj.smooth_factor * excess/threshold);
% 重建信号
clipped_signal = amplitude_clipped .* exp(1j*phase);
end
end
end
3.3 概率类算法
3.3.1 选择性映射(SLM)
matlab
%% 选择性映射算法
classdef SLM < OFDMSystem
% 选择性映射算法
properties
U = 4; % 相位序列数量
phase_sequences; % 相位序列
selected_indices; % 选择的序列索引
end
methods
function obj = SLM(varargin)
obj = obj@OFDMSystem(varargin{:});
obj.generate_phase_sequences();
end
function generate_phase_sequences(obj)
% 生成相位序列
obj.phase_sequences = exp(1j * 2*pi * rand(obj.N, obj.U));
end
function [tx_signal, best_idx] = apply_slm(obj, symbols)
% 应用SLM
papr_values = zeros(1, obj.U);
candidate_signals = cell(1, obj.U);
for u = 1:obj.U
% 应用相位旋转
rotated_symbols = symbols .* obj.phase_sequences(:, u);
% OFDM调制
candidate = obj.ofdm_modulate(rotated_symbols);
candidate_signals{u} = candidate;
% 计算PAPR
papr_values(u) = mean(obj.calculate_papr(candidate));
end
% 选择最低PAPR
[~, best_idx] = min(papr_values);
tx_signal = candidate_signals{best_idx};
obj.selected_indices = best_idx;
end
function ber = simulate_ber_with_slm(obj, snr_db)
% SLM的BER仿真
ber = zeros(size(snr_db));
for snr_idx = 1:length(snr_db)
total_errors = 0;
total_bits = 0;
for sym_idx = 1:obj.num_symbols
% 生成数据
bits_per_symbol = log2(obj.M) * obj.N;
bits = randi([0, 1], bits_per_symbol, 1);
% 调制
if strcmp(obj.mod_type, 'QPSK')
symbols = pskmod(reshape(bits, 2, [])', 4, pi/4, 'gray');
else
symbols = qammod(reshape(bits, 4, [])', 16, 'gray', 'InputType', 'bit');
end
% 应用SLM
[tx_signal, best_idx] = obj.apply_slm(symbols);
% 传输边带信息(理想情况)
side_info = de2bi(best_idx-1, ceil(log2(obj.U)), 'left-msb')';
% 添加噪声
signal_power = mean(abs(tx_signal).^2);
noise_power = signal_power / (10^(snr_db(snr_idx)/10));
noise = sqrt(noise_power/2) * (randn(size(tx_signal)) + 1j*randn(size(tx_signal)));
rx_signal = tx_signal + noise;
% OFDM解调
rx_symbols = obj.ofdm_demodulate(rx_signal);
% 应用逆相位旋转(假设边带信息正确接收)
rx_symbols = rx_symbols .* conj(obj.phase_sequences(:, best_idx));
% 解调
if strcmp(obj.mod_type, 'QPSK')
rx_bits = pskdemod(rx_symbols, 4, pi/4, 'gray');
else
rx_bits = qamdemod(rx_symbols, 16, 'gray', 'OutputType', 'bit');
end
% 计算误码
errors = sum(bits(:) ~= rx_bits(:));
total_errors = total_errors + errors;
total_bits = total_bits + length(bits);
end
ber(snr_idx) = total_errors / total_bits;
end
end
function plot_slm_performance(obj)
% 绘制SLM性能
papr_original = [];
papr_slm = [];
for i = 1:100
[symbols, ~] = obj.generate_data();
% 原始OFDM
tx_original = obj.ofdm_modulate(symbols);
papr_orig = obj.calculate_papr(tx_original);
papr_original = [papr_original, papr_orig];
% SLM
[tx_slm, ~] = obj.apply_slm(symbols);
papr_s = obj.calculate_papr(tx_slm);
papr_slm = [papr_slm, papr_s];
end
% 计算CCDF
threshold_db = 0:0.1:12;
ccdf_original = zeros(size(threshold_db));
ccdf_slm = zeros(size(threshold_db));
for i = 1:length(threshold_db)
ccdf_original(i) = mean(papr_original > threshold_db(i));
ccdf_slm(i) = mean(papr_slm > threshold_db(i));
end
% 绘图
figure('Position', [100, 100, 1000, 400]);
subplot(1,2,1);
plot(threshold_db, ccdf_original, 'b-', 'LineWidth', 2);
hold on;
plot(threshold_db, ccdf_slm, 'r--', 'LineWidth', 2);
xlabel('PAPR_0 (dB)');
ylabel('CCDF = Pr(PAPR > PAPR_0)');
title(sprintf('SLM算法PAPR性能 (U=%d)', obj.U));
legend('原始', 'SLM');
grid on;
subplot(1,2,2);
% 不同U值比较
U_values = [2, 4, 8, 16];
colors = {'b-', 'r--', 'g-.', 'm:'};
for u_idx = 1:length(U_values)
obj.U = U_values(u_idx);
obj.generate_phase_sequences();
papr_slm_u = [];
for i = 1:50
[symbols, ~] = obj.generate_data();
[tx_slm, ~] = obj.apply_slm(symbols);
papr_s = obj.calculate_papr(tx_slm);
papr_slm_u = [papr_slm_u, papr_s];
end
ccdf_slm_u = zeros(size(threshold_db));
for i = 1:length(threshold_db)
ccdf_slm_u(i) = mean(papr_slm_u > threshold_db(i));
end
plot(threshold_db, ccdf_slm_u, colors{u_idx}, 'LineWidth', 2);
hold on;
end
plot(threshold_db, ccdf_original, 'k-', 'LineWidth', 3);
xlabel('PAPR_0 (dB)');
ylabel('CCDF');
title('不同U值的SLM性能');
legend(arrayfun(@(x) sprintf('U=%d', x), U_values, 'UniformOutput', false), '原始');
grid on;
sgtitle(sprintf('选择性映射(SLM)算法 (N=%d, %s)', obj.N, obj.mod_type));
end
end
end
3.3.2 部分传输序列(PTS)
matlab
%% 部分传输序列算法
classdef PTS < OFDMSystem
% 部分传输序列算法
properties
V = 4; % 分割数
W = 4; % 相位因子数量
phase_factors; % 相位因子集合
partition_method = 'adjacent'; % 分割方法
end
methods
function obj = PTS(varargin)
obj = obj@OFDMSystem(varargin{:});
obj.generate_phase_factors();
end
function generate_phase_factors(obj)
% 生成相位因子
obj.phase_factors = exp(1j * 2*pi/obj.W * (0:obj.W-1));
end
function [tx_signal, best_phase] = apply_pts(obj, symbols)
% 应用PTS
% 分割子载波
switch obj.partition_method
case 'adjacent'
% 相邻分割
subcarriers_per_part = floor(obj.N / obj.V);
partitions = zeros(obj.N, obj.V);
for v = 1:obj.V
start_idx = (v-1)*subcarriers_per_part + 1;
end_idx = min(v*subcarriers_per_part, obj.N);
partitions(start_idx:end_idx, v) = 1;
end
case 'interleaved'
% 交织分割
partitions = zeros(obj.N, obj.V);
for n = 1:obj.N
v = mod(n-1, obj.V) + 1;
partitions(n, v) = 1;
end
case 'pseudo'
% 伪随机分割
partitions = zeros(obj.N, obj.V);
for n = 1:obj.N
v = randi([1, obj.V]);
partitions(n, v) = 1;
end
end
% 生成部分序列
part_sequences = cell(1, obj.V);
for v = 1:obj.V
part_symbols = symbols .* partitions(:, v);
part_sequences{v} = obj.ofdm_modulate(part_symbols);
end
% 搜索最优相位组合
min_papr = inf;
best_signal = [];
best_phase = ones(1, obj.V);
% 遍历所有相位组合
phase_combinations = obj.generate_all_combinations(obj.V, obj.W);
for combo_idx = 1:size(phase_combinations, 1)
phase_combo = phase_combinations(combo_idx, :);
% 组合信号
combined_signal = zeros(size(part_sequences{1}));
for v = 1:obj.V
phase_factor = obj.phase_factors(phase_combo(v));
combined_signal = combined_signal + phase_factor * part_sequences{v};
end
% 计算PAPR
papr = mean(obj.calculate_papr(combined_signal));
if papr < min_papr
min_papr = papr;
best_signal = combined_signal;
best_phase = phase_combo;
end
end
tx_signal = best_signal;
end
function combinations = generate_all_combinations(obj, V, W)
% 生成所有相位组合
indices = 1:W;
combs = cell(V, 1);
[combs{:}] = ndgrid(indices);
combinations = reshape(cat(V+1, combs{:}), [], V);
end
function plot_pts_performance(obj)
% 绘制PTS性能
papr_original = [];
papr_pts = [];
for i = 1:50
[symbols, ~] = obj.generate_data();
% 原始OFDM
tx_original = obj.ofdm_modulate(symbols);
papr_orig = obj.calculate_papr(tx_original);
papr_original = [papr_original, papr_orig];
% PTS
[tx_pts, ~] = obj.apply_pts(symbols);
papr_p = obj.calculate_papr(tx_pts);
papr_pts = [papr_pts, papr_p];
end
% 计算CCDF
threshold_db = 0:0.1:12;
ccdf_original = zeros(size(threshold_db));
ccdf_pts = zeros(size(threshold_db));
for i = 1:length(threshold_db)
ccdf_original(i) = mean(papr_original > threshold_db(i));
ccdf_pts(i) = mean(papr_pts > threshold_db(i));
end
% 绘图
figure('Position', [100, 100, 1200, 400]);
subplot(1,3,1);
plot(threshold_db, ccdf_original, 'b-', 'LineWidth', 2);
hold on;
plot(threshold_db, ccdf_pts, 'r--', 'LineWidth', 2);
xlabel('PAPR_0 (dB)');
ylabel('CCDF');
title(sprintf('PTS算法PAPR性能 (V=%d, W=%d)', obj.V, obj.W));
legend('原始', 'PTS');
grid on;
subplot(1,3,2);
% 不同分割方法比较
methods = {'adjacent', 'interleaved', 'pseudo'};
colors = {'b-', 'r--', 'g-.'};
for m_idx = 1:length(methods)
obj.partition_method = methods{m_idx};
papr_pts_m = [];
for i = 1:30
[symbols, ~] = obj.generate_data();
[tx_pts, ~] = obj.apply_pts(symbols);
papr_p = obj.calculate_papr(tx_pts);
papr_pts_m = [papr_pts_m, papr_p];
end
ccdf_pts_m = zeros(size(threshold_db));
for i = 1:length(threshold_db)
ccdf_pts_m(i) = mean(papr_pts_m > threshold_db(i));
end
plot(threshold_db, ccdf_pts_m, colors{m_idx}, 'LineWidth', 2);
hold on;
end
plot(threshold_db, ccdf_original, 'k-', 'LineWidth', 3);
xlabel('PAPR_0 (dB)');
ylabel('CCDF');
title('不同分割方法比较');
legend(methods{:}, '原始');
grid on;
subplot(1,3,3);
% 计算复杂度分析
V_values = [2, 4, 8];
W_values = [2, 4];
complexity = zeros(length(V_values), length(W_values));
papr_gain = zeros(length(V_values), length(W_values));
for v_idx = 1:length(V_values)
for w_idx = 1:length(W_values)
obj.V = V_values(v_idx);
obj.W = W_values(w_idx);
obj.generate_phase_factors();
% 复杂度 = W^V
complexity(v_idx, w_idx) = obj.W^obj.V;
% PAPR增益
papr_pts_test = [];
for i = 1:20
[symbols, ~] = obj.generate_data();
[tx_pts, ~] = obj.apply_pts(symbols);
papr_p = obj.calculate_papr(tx_pts);
papr_pts_test = [papr_pts_test, papr_p];
end
papr_gain(v_idx, w_idx) = mean(papr_original(1:20)) - mean(papr_pts_test);
end
end
% 3D柱状图
[X, Y] = meshgrid(1:length(W_values), 1:length(V_values));
bar3(complexity);
xlabel('W');
ylabel('V');
zlabel('计算复杂度');
title('PTS计算复杂度分析');
set(gca, 'XTickLabel', W_values);
set(gca, 'YTickLabel', V_values);
grid on;
sgtitle(sprintf('部分传输序列(PTS)算法 (N=%d, %s)', obj.N, obj.mod_type));
end
end
end
3.4 压扩变换算法
matlab
%% μ律压扩算法
classdef MuLawCompanding < OFDMSystem
% μ律压扩算法
properties
mu = 255; % 压扩参数
end
methods
function compressed = compress(obj, signal)
% 压缩
max_amplitude = max(abs(signal(:)));
normalized = signal / max_amplitude;
compressed = (log(1 + obj.mu * abs(normalized)) / log(1 + obj.mu)) .* ...
exp(1j * angle(normalized)) * max_amplitude;
end
function expanded = expand(obj, signal)
% 扩展
max_amplitude = max(abs(signal(:)));
normalized = signal / max_amplitude;
expanded = ((1/obj.mu) * ((1 + obj.mu).^abs(normalized) - 1)) .* ...
exp(1j * angle(normalized)) * max_amplitude;
end
function plot_companding_performance(obj)
% 绘制压扩性能
papr_original = [];
papr_companded = [];
for i = 1:100
[symbols, ~] = obj.generate_data();
tx_original = obj.ofdm_modulate(symbols);
% 压扩
tx_companded = obj.compress(tx_original);
papr_orig = obj.calculate_papr(tx_original);
papr_comp = obj.calculate_papr(tx_companded);
papr_original = [papr_original, papr_orig];
papr_companded = [papr_companded, papr_comp];
end
% 计算CCDF
threshold_db = 0:0.1:12;
ccdf_original = zeros(size(threshold_db));
ccdf_companded = zeros(size(threshold_db));
for i = 1:length(threshold_db)
ccdf_original(i) = mean(papr_original > threshold_db(i));
ccdf_companded(i) = mean(papr_companded > threshold_db(i));
end
% 绘图
figure('Position', [100, 100, 800, 600]);
subplot(2,2,1);
plot(threshold_db, ccdf_original, 'b-', 'LineWidth', 2);
hold on;
plot(threshold_db, ccdf_companded, 'r--', 'LineWidth', 2);
xlabel('PAPR_0 (dB)');
ylabel('CCDF');
title(sprintf('μ律压扩PAPR性能 (μ=%.0f)', obj.mu));
legend('原始', '压扩后');
grid on;
subplot(2,2,2);
% 不同μ值比较
mu_values = [1, 10, 100, 255];
colors = {'b-', 'r--', 'g-.', 'm:'};
for mu_idx = 1:length(mu_values)
obj.mu = mu_values(mu_idx);
papr_mu = [];
for i = 1:50
[symbols, ~] = obj.generate_data();
tx_signal = obj.ofdm_modulate(symbols);
tx_comp = obj.compress(tx_signal);
papr_c = obj.calculate_papr(tx_comp);
papr_mu = [papr_mu, papr_c];
end
ccdf_mu = zeros(size(threshold_db));
for i = 1:length(threshold_db)
ccdf_mu(i) = mean(papr_mu > threshold_db(i));
end
plot(threshold_db, ccdf_mu, colors{mu_idx}, 'LineWidth', 2);
hold on;
end
plot(threshold_db, ccdf_original, 'k-', 'LineWidth', 3);
xlabel('PAPR_0 (dB)');
ylabel('CCDF');
title('不同μ值性能比较');
legend(arrayfun(@(x) sprintf('μ=%.0f', x), mu_values, 'UniformOutput', false), '原始');
grid on;
subplot(2,2,3);
% 压扩特性曲线
x = linspace(0, 1, 1000);
for mu_idx = 1:length(mu_values)
mu = mu_values(mu_idx);
y = log(1 + mu * x) / log(1 + mu);
plot(x, y, colors{mu_idx}, 'LineWidth', 2);
hold on;
end
plot(x, x, 'k--', 'LineWidth', 1);
xlabel('归一化输入');
ylabel('归一化输出');
title('μ律压扩特性');
legend(arrayfun(@(x) sprintf('μ=%.0f', x), mu_values, 'UniformOutput', false), '线性');
grid on;
subplot(2,2,4);
% BER性能
snr_db = 0:2:20;
ber_original = zeros(size(snr_db));
ber_companded = zeros(size(snr_db));
for snr_idx = 1:length(snr_db)
ber_o = 0;
ber_c = 0;
total_bits = 0;
for sym_idx = 1:10
% 生成数据
bits_per_symbol = log2(obj.M) * obj.N;
bits = randi([0, 1], bits_per_symbol, 1);
if strcmp(obj.mod_type, 'QPSK')
symbols = pskmod(reshape(bits, 2, [])', 4, pi/4, 'gray');
else
symbols = qammod(reshape(bits, 4, [])', 16, 'gray', 'InputType', 'bit');
end
% 原始OFDM
tx_original = obj.ofdm_modulate(symbols);
signal_power = mean(abs(tx_original).^2);
noise_power = signal_power / (10^(snr_db(snr_idx)/10));
noise = sqrt(noise_power/2) * (randn(size(tx_original)) + 1j*randn(size(tx_original)));
rx_original = tx_original + noise;
rx_symbols_o = obj.ofdm_demodulate(rx_original);
% 压扩OFDM
tx_comp = obj.compress(tx_original);
signal_power_c = mean(abs(tx_comp).^2);
noise_power_c = signal_power_c / (10^(snr_db(snr_idx)/10));
noise_c = sqrt(noise_power_c/2) * (randn(size(tx_comp)) + 1j*randn(size(tx_comp)));
rx_comp = tx_comp + noise_c;
rx_expanded = obj.expand(rx_comp);
rx_symbols_c = obj.ofdm_demodulate(rx_expanded);
% 解调
if strcmp(obj.mod_type, 'QPSK')
rx_bits_o = pskdemod(rx_symbols_o, 4, pi/4, 'gray');
rx_bits_c = pskdemod(rx_symbols_c, 4, pi/4, 'gray');
else
rx_bits_o = qamdemod(rx_symbols_o, 16, 'gray', 'OutputType', 'bit');
rx_bits_c = qamdemod(rx_symbols_c, 16, 'gray', 'OutputType', 'bit');
end
errors_o = sum(bits ~= rx_bits_o);
errors_c = sum(bits ~= rx_bits_c);
ber_o = ber_o + errors_o;
ber_c = ber_c + errors_c;
total_bits = total_bits + length(bits);
end
ber_original(snr_idx) = ber_o / total_bits;
ber_companded(snr_idx) = ber_c / total_bits;
end
semilogy(snr_db, ber_original, 'b-o', 'LineWidth', 2);
hold on;
semilogy(snr_db, ber_companded, 'r-s', 'LineWidth', 2);
xlabel('SNR (dB)');
ylabel('BER');
title('压扩对BER的影响');
legend('原始', '压扩');
grid on;
sgtitle('μ律压扩算法性能分析');
end
end
end
四、综合性能比较
4.1 算法性能比较
matlab
%% 综合性能比较
classdef PAPRComparison
% PAPR算法综合比较
methods (Static)
function compare_all_algorithms()
% 比较所有算法
% 参数设置
N = 64;
M = 4; % QPSK
num_symbols = 1000;
L = 4;
% 创建算法实例
ofdm_base = OFDMSystem('N', N, 'M', M, 'L', L, 'num_symbols', num_symbols);
% 硬限幅
clipping = HardClipping('N', N, 'M', M, 'L', L, 'num_symbols', num_symbols, 'clip_ratio', 0.8);
% SLM
slm = SLM('N', N, 'M', M, 'L', L, 'num_symbols', num_symbols, 'U', 4);
% PTS
pts = PTS('N', N, 'M', M, 'L', L, 'num_symbols', num_symbols, 'V', 4, 'W', 4);
% 压扩
companding = MuLawCompanding('N', N, 'M', M, 'L', L, 'num_symbols', num_symbols, 'mu', 255);
% 生成数据
[symbols, bits] = ofdm_base.generate_data();
% 计算各算法PAPR
papr_results = struct();
% 原始OFDM
tx_original = ofdm_base.ofdm_modulate(symbols);
papr_results.original = ofdm_base.calculate_papr(tx_original);
% 硬限幅
tx_clipped = clipping.apply_clipping(tx_original);
papr_results.clipping = clipping.calculate_papr(tx_clipped);
% SLM
[tx_slm, ~] = slm.apply_slm(symbols);
papr_results.slm = slm.calculate_papr(tx_slm);
% PTS
[tx_pts, ~] = pts.apply_pts(symbols);
papr_results.pts = pts.calculate_papr(tx_pts);
% 压扩
tx_comp = companding.compress(tx_original);
papr_results.companding = companding.calculate_papr(tx_comp);
% 绘制CCDF比较
figure('Position', [100, 100, 1000, 800]);
subplot(2,2,1);
threshold_db = 0:0.1:12;
algorithms = fieldnames(papr_results);
colors = {'k-', 'b-', 'r--', 'g-.', 'm:', 'c-'};
for i = 1:length(algorithms)
papr_data = papr_results.(algorithms{i});
ccdf = zeros(size(threshold_db));
for t = 1:length(threshold_db)
ccdf(t) = mean(papr_data > threshold_db(t));
end
plot(threshold_db, ccdf, colors{i}, 'LineWidth', 2);
hold on;
end
xlabel('PAPR_0 (dB)');
ylabel('CCDF = Pr(PAPR > PAPR_0)');
title('各种算法PAPR性能比较');
legend(algorithms, 'Location', 'northeast');
grid on;
subplot(2,2,2);
% 平均PAPR比较
avg_papr = zeros(length(algorithms), 1);
std_papr = zeros(length(algorithms), 1);
for i = 1:length(algorithms)
avg_papr(i) = mean(papr_results.(algorithms{i}));
std_papr(i) = std(papr_results.(algorithms{i}));
end
bar(1:length(algorithms), avg_papr);
hold on;
errorbar(1:length(algorithms), avg_papr, std_papr, 'k.', 'LineWidth', 2);
set(gca, 'XTickLabel', algorithms);
xtickangle(45);
ylabel('平均PAPR (dB)');
title('平均PAPR比较');
grid on;
subplot(2,2,3);
% PAPR增益
papr_gain = avg_papr(1) - avg_papr;
bar(1:length(algorithms), papr_gain);
set(gca, 'XTickLabel', algorithms);
xtickangle(45);
ylabel('PAPR增益 (dB)');
title('相对于原始OFDM的PAPR增益');
grid on;
subplot(2,2,4);
% 计算复杂度比较
complexity = [
1; % 原始
N; % 限幅
slm.U * N; % SLM
pts.W^pts.V; % PTS
N % 压扩
];
bar(1:length(algorithms), log10(complexity));
set(gca, 'XTickLabel', algorithms);
xtickangle(45);
ylabel('log10(计算复杂度)');
title('计算复杂度比较');
grid on;
sgtitle('OFDM PAPR降低算法综合比较');
% 显示统计表格
fprintf('\n=== 算法性能统计 ===\n');
fprintf('%-15s %-10s %-10s %-10s %-10s\n', ...
'算法', '平均PAPR', '标准差', 'PAPR增益', '复杂度');
fprintf('%s\n', repmat('-', 60, 1));
for i = 1:length(algorithms)
fprintf('%-15s %-10.2f %-10.2f %-10.2f %-10.0f\n', ...
algorithms{i}, avg_papr(i), std_papr(i), ...
papr_gain(i), complexity(i));
end
end
function ber_comparison()
% BER性能比较
N = 64;
M = 4;
num_symbols = 100;
snr_db = 0:2:20;
% 创建算法实例
clipping = HardClipping('N', N, 'M', M, 'num_symbols', num_symbols, 'clip_ratio', 0.8);
slm = SLM('N', N, 'M', M, 'num_symbols', num_symbols, 'U', 4);
pts = PTS('N', N, 'M', M, 'num_symbols', num_symbols, 'V', 4, 'W', 4);
companding = MuLawCompanding('N', N, 'M', M, 'num_symbols', num_symbols, 'mu', 255);
% 仿真BER
ber_results = struct();
ber_results.clipping = zeros(size(snr_db));
ber_results.slm = zeros(size(snr_db));
ber_results.pts = zeros(size(snr_db));
ber_results.companding = zeros(size(snr_db));
fprintf('正在进行BER仿真...\n');
for snr_idx = 1:length(snr_db)
fprintf('SNR = %d dB\n', snr_db(snr_idx));
% 硬限幅
ber_c = clipping.simulate_ber(snr_db(snr_idx));
ber_results.clipping(snr_idx) = ber_c;
% SLM
ber_s = slm.simulate_ber_with_slm(snr_db(snr_idx));
ber_results.slm(snr_idx) = ber_s;
% 压扩
ber_m = 0;
for i = 1:10
[symbols, bits] = companding.generate_data();
tx_signal = companding.ofdm_modulate(symbols);
tx_comp = companding.compress(tx_signal);
signal_power = mean(abs(tx_comp).^2);
noise_power = signal_power / (10^(snr_db(snr_idx)/10));
noise = sqrt(noise_power/2) * (randn(size(tx_comp)) + 1j*randn(size(tx_comp)));
rx_signal = tx_comp + noise;
rx_expanded = companding.expand(rx_signal);
rx_symbols = companding.ofdm_demodulate(rx_expanded);
if strcmp(companding.mod_type, 'QPSK')
rx_bits = pskdemod(rx_symbols, 4, pi/4, 'gray');
else
rx_bits = qamdemod(rx_symbols, 16, 'gray', 'OutputType', 'bit');
end
errors = sum(bits ~= rx_bits);
ber_m = ber_m + errors / length(bits);
end
ber_results.companding(snr_idx) = ber_m / 10;
end
% 绘制BER曲线
figure('Position', [100, 100, 800, 600]);
algorithms = fieldnames(ber_results);
colors = {'b-', 'r--', 'g-.', 'm:'};
markers = {'o', 's', '^', 'd'};
for i = 1:length(algorithms)
semilogy(snr_db, ber_results.(algorithms{i}), ...
[colors{i}, markers{i}], 'LineWidth', 2, 'MarkerSize', 8);
hold on;
end
% 理论QPSK BER
ber_theory = 0.5 * erfc(sqrt(10.^(snr_db/10)));
semilogy(snr_db, ber_theory, 'k-', 'LineWidth', 2);
xlabel('SNR (dB)');
ylabel('BER');
title('各种PAPR降低算法的BER性能');
legend([algorithms; '理论QPSK'], 'Location', 'southwest');
grid on;
ylim([1e-5, 1]);
% 计算SNR损失
fprintf('\n=== SNR损失分析 (BER=10^{-3}) ===\n');
target_ber = 1e-3;
for i = 1:length(algorithms)
ber_data = ber_results.(algorithms{i});
idx = find(ber_data <= target_ber, 1);
if ~isempty(idx)
snr_at_target = snr_db(idx);
snr_theory = interp1(log10(ber_theory), snr_db, log10(target_ber));
snr_loss = snr_at_target - snr_theory;
fprintf('%-10s: SNR@BER=1e-3 = %.2f dB, SNR损失 = %.2f dB\n', ...
algorithms{i}, snr_at_target, snr_loss);
end
end
end
end
end
参考代码 降低正交频分复用系统PAPR的各种算法及误码率 www.youwenfan.com/contentcsu/55026.html
五、实际应用建议
5.1 算法选择指南
| 应用场景 | 推荐算法 | 原因 |
|---|---|---|
| 实时通信 | 限幅、压扩 | 计算简单,延迟低 |
| 高可靠性 | SLM、PTS | 无失真,BER性能好 |
| 移动设备 | 压扩、限幅 | 功耗低,实现简单 |
| 广播系统 | SLM | 可容忍边带信息开销 |
| 军事通信 | PTS | 安全性好,性能优 |
5.2 参数优化建议
matlab
%% 参数优化函数
function optimize_parameters()
% 参数优化
% 1. SLM的U值优化
N = 64;
U_values = [2, 4, 8, 16, 32];
papr_gain = zeros(size(U_values));
complexity = zeros(size(U_values));
for i = 1:length(U_values)
slm = SLM('N', N, 'U', U_values(i));
% 评估性能
papr_data = [];
for j = 1:50
[symbols, ~] = slm.generate_data();
[tx_slm, ~] = slm.apply_slm(symbols);
papr = slm.calculate_papr(tx_slm);
papr_data = [papr_data, papr];
end
% 原始PAPR
tx_original = slm.ofdm_modulate(symbols);
papr_orig = slm.calculate_papr(tx_original);
papr_gain(i) = mean(papr_orig) - mean(papr_data);
complexity(i) = U_values(i) * N;
end
% 寻找最优U值
figure;
yyaxis left;
plot(U_values, papr_gain, 'b-o', 'LineWidth', 2);
ylabel('PAPR增益 (dB)');
yyaxis right;
plot(U_values, complexity, 'r-s', 'LineWidth', 2);
ylabel('计算复杂度');
xlabel('U值');
title('SLM参数优化');
legend('PAPR增益', '计算复杂度');
grid on;
% 2. 限幅比例优化
CR_values = 0.5:0.1:1.0;
papr_clipped = zeros(size(CR_values));
ber_clipped = zeros(size(CR_values));
for i = 1:length(CR_values)
clipping = HardClipping('clip_ratio', CR_values(i));
% PAPR评估
papr_data = [];
for j = 1:50
[symbols, ~] = clipping.generate_data();
tx_signal = clipping.ofdm_modulate(symbols);
tx_clipped = clipping.apply_clipping(tx_signal);
papr = clipping.calculate_papr(tx_clipped);
papr_data = [papr_data, papr];
end
papr_clipped(i) = mean(papr_data);
% BER评估
ber_clipped(i) = clipping.simulate_ber(10); % SNR=10dB
end
figure;
yyaxis left;
plot(CR_values, papr_clipped, 'b-o', 'LineWidth', 2);
ylabel('平均PAPR (dB)');
yyaxis right;
semilogy(CR_values, ber_clipped, 'r-s', 'LineWidth', 2);
ylabel('BER');
xlabel('限幅比例 (CR)');
title('限幅算法参数优化');
legend('PAPR', 'BER');
grid on;
end
六、总结
6.1 算法性能总结
| 算法 | PAPR增益 | BER影响 | 计算复杂度 | 边带信息 | 适用场景 |
|---|---|---|---|---|---|
| 硬限幅 | 3-5 dB | 严重 | 低 | 无 | 低成本实时系统 |
| SLM | 4-6 dB | 无 | 中等 | 有 | 广播、固定无线 |
| PTS | 5-7 dB | 无 | 高 | 有 | 高性能无线 |
| 压扩 | 2-4 dB | 轻微 | 低 | 无 | 移动通信 |
6.2 实用MATLAB代码
matlab
% 快速使用示例
clear; clc; close all;
% 1. 创建OFDM系统
ofdm = OFDMSystem('N', 64, 'M', 4, 'mod_type', 'QPSK');
% 2. 生成数据
[symbols, bits] = ofdm.generate_data();
% 3. 应用SLM降低PAPR
slm = SLM('N', 64, 'U', 4);
[tx_slm, idx] = slm.apply_slm(symbols);
% 4. 计算PAPR
papr_original = ofdm.calculate_papr(ofdm.ofdm_modulate(symbols));
papr_slm = slm.calculate_papr(tx_slm);
fprintf('原始PAPR: %.2f dB\n', mean(papr_original));
fprintf('SLM后PAPR: %.2f dB\n', mean(papr_slm));
fprintf('PAPR增益: %.2f dB\n', mean(papr_original) - mean(papr_slm));
% 5. 绘制结果
figure;
subplot(1,2,1);
histogram(papr_original, 20, 'FaceColor', 'b');
xlabel('PAPR (dB)'); ylabel('频率');
title('原始OFDM PAPR分布');
subplot(1,2,2);
histogram(papr_slm, 20, 'FaceColor', 'r');
xlabel('PAPR (dB)'); ylabel('频率');
title('SLM后PAPR分布');