16PSK调制在Matlab上的蒙特卡罗仿真

一、仿真原理

蒙特卡罗仿真通过大量随机试验统计通信系统性能指标(如误码率BER)。对于16PSK(16进制相移键控),核心是模拟“比特→符号映射→信道传输→符号判决→比特解映射”全流程,在高斯白噪声(AWGN)信道下统计误码率。

二、系统模型

  1. 调制:16PSK将4比特(log₂16=4)映射为一个复数符号,星座点均匀分布在单位圆上,相位间隔Δθ=2π/16=22.5°。
  2. 信道:AWGN信道,接收信号为发送符号叠加复高斯噪声(实部和虚部独立,方差σ²=N₀/2)。
  3. 解调:最大似然判决(MLD),计算接收信号与所有星座点的欧氏距离,选择最近点作为判决结果。
  4. 误码统计:对比原始比特与解调比特,计算误码率BER=错误比特数/总比特数。

三、关键参数与公式

四、Matlab实现步骤

1. 参数设置

clear; clc; close all;

% 仿真参数
M = 16;                  % 16PSK调制阶数
k = log2(M);             % 每符号比特数(4比特)
SNR_dB = 0:2:16;          % Eb/N0范围(dB)
Nmc = 1e4;               % 蒙特卡罗试验次数(每次试验含Ns符号)
Ns = 1e3;                % 每试验符号数(总比特数=k*Ns)
total_bits = k*Ns;       % 每试验总比特数

% 16PSK星座图(单位圆,格雷编码映射)
theta = (0:M-1)*2*pi/M;   % 相位:0°, 22.5°, ..., 337.5°
constellation = exp(1j*theta);  % 复数星座点(幅度=1)

2. 比特-符号映射(格雷编码)

采用格雷码映射(相邻星座点仅1比特差异),减少误码扩散:

% 生成格雷码映射表(4比特)
gray_map = [0 1 3 2 6 7 5 4 12 13 15 14 10 11 9 8];  % 十进制索引→格雷码值
bit_table = de2bi(gray_map, k, 'left-msb');  % 格雷码值→4位二进制(左高位)

映射函数(比特→符号):

function symbols = bits_to_symbols(bits, bit_table)
    % bits: 二进制矩阵(每行4比特)
    % bit_table: 4×16矩阵,每列对应1个符号的比特
    [~, idx] = ismember(bits, bit_table', 'rows');  % 查找比特对应的符号索引
    symbols = exp(1j*(idx-1)*2*pi/16);  % 映射到星座点(0~15对应0°~337.5°)
end

3. 加噪与解调

加噪:根据计算噪声方差,生成复高斯噪声:

function rx_signal = add_noise(tx_symbols, EbN0_linear, k)
    EsN0_linear = k * EbN0_linear;  % 符号信噪比
    noise_var = 1/(2*EsN0_linear);   % 噪声方差(实部/虚部方差)
    noise = sqrt(noise_var)*(randn(size(tx_symbols)) + 1j*randn(size(tx_symbols)));
    rx_signal = tx_symbols + noise;
end

解调(最大似然判决):计算接收信号与所有星座点的欧氏距离,选最近点:

function decoded_bits = symbols_to_bits(rx_signal, constellation, bit_table)
    [Ns, ~] = size(rx_signal);
    distances = abs(rx_signal - constellation.');  % 距离矩阵(Ns×16)
    [~, idx] = min(distances, [], 2);  % 每行最小距离索引(判决符号)
    decoded_bits = bit_table(:, idx);   % 符号索引→比特(4×Ns矩阵)
end

4. 蒙特卡罗仿真主循环

对每个,重复次试验,统计总误码数:

ber_sim = zeros(size(SNR_dB));  % 存储仿真BER

for snr_idx = 1:length(SNR_dB)
    EbN0_linear = 10^(SNR_dB(snr_idx)/10);  % Eb/N0线性值
    total_errors = 0;                       % 累计误码数
    
    for mc_idx = 1:Nmc
        % 1. 生成随机比特(Ns符号×4比特)
        bits_tx = randi([0,1], Ns, k);  % Ns×4矩阵(每行4比特)
        
        % 2. 比特→16PSK符号
        symbols_tx = bits_to_symbols(bits_tx, bit_table);
        
        % 3. 加AWGN噪声
        rx_signal = add_noise(symbols_tx, EbN0_linear, k);
        
        % 4. 解调:符号→比特
        bits_rx = symbols_to_bits(rx_signal, constellation, bit_table);
        
        % 5. 统计误码数(比特级)
        errors = sum(sum(bits_tx ~= bits_rx'));
        total_errors = total_errors + errors;
    end
    
    % 计算平均BER(总误码数/(总试验次数×每试验比特数))
    ber_sim(snr_idx) = total_errors / (Nmc * Ns * k);
end

5. 理论误码率对比

16PSK在AWGN信道下的理论误码率(近似):

其中

理论BER计算代码

ber_theory = zeros(size(SNR_dB));
for snr_idx = 1:length(SNR_dB)
    EbN0_linear = 10^(SNR_dB(snr_idx)/10);
    arg = sqrt(2*k*EbN0_linear*(sin(pi/M))^2);  % 根号内参数
    ber_theory(snr_idx) = (2/k) * 0.5*erfc(arg/sqrt(2));  % Q(x)=0.5*erfc(x/√2)
end

6. 结果可视化

绘制仿真BER与理论BER对比曲线:

figure;
semilogy(SNR_dB, ber_sim, 'bo-', 'LineWidth', 1.5); hold on;
semilogy(SNR_dB, ber_theory, 'r--', 'LineWidth', 1.5);
grid on; xlabel('E_b/N_0 (dB)'); ylabel('误码率 (BER)');
legend('蒙特卡罗仿真', '理论值'); title('16PSK在AWGN信道下的误码率性能');
axis([min(SNR_dB) max(SNR_dB) 1e-6 1]);

五、仿真结果与分析

参考代码 16PSK在matlab上的蒙特卡罗仿真 www.youwenfan.com/contentcnr/100780.html

六、优化与扩展

  1. 向量化加速:用矩阵运算替代循环(如批量生成噪声、距离计算),减少运行时间。

  2. 衰落信道:加入瑞利/莱斯衰落(修改add_noise函数,乘以衰落系数)。

  3. 工具箱简化:使用Matlab通信工具箱的pskmod/pskdemod函数:

    symbols_tx = pskmod(bits_tx, M, 0, 'gray');  % 16PSK调制(格雷编码)
    bits_rx = pskdemod(rx_signal, M, 0, 'gray');  % 解调
    

七、完整代码

整合上述模块,保存为psk16_monte_carlo.m,直接运行即可:

% 16PSK蒙特卡罗仿真(AWGN信道)
clear; clc; close all;

% 参数设置
M = 16; k = log2(M); SNR_dB = 0:2:16; Nmc = 1e3; Ns = 1e3; total_bits = k*Ns;
theta = (0:M-1)*2*pi/M; constellation = exp(1j*theta);  % 星座图

% 格雷码映射表(4比特)
gray_map = [0 1 3 2 6 7 5 4 12 13 15 14 10 11 9 8];
bit_table = de2bi(gray_map, k, 'left-msb');  % 4×16比特表

% 蒙特卡罗仿真
ber_sim = zeros(size(SNR_dB));
for snr_idx = 1:length(SNR_dB)
    EbN0_linear = 10^(SNR_dB(snr_idx)/10);
    total_errors = 0;
    for mc = 1:Nmc
        bits_tx = randi([0,1], Ns, k);  % 随机比特
        symbols_tx = exp(1j*(bi2de(bits_tx, 'left-msb', k)-1)*2*pi/M);  % 简化映射
        noise_var = 1/(2*k*EbN0_linear);  % 噪声方差
        noise = sqrt(noise_var)*(randn(Ns,1)+1j*randn(Ns,1));
        rx = symbols_tx + noise;  % 接收信号
        
        % 判决:计算距离
        [~, idx] = min(abs(repmat(rx,1,M) - repmat(conj(constitution), Ns,1)), [], 2);
        bits_rx = bit_table(:, idx)';
        total_errors = total_errors + sum(sum(bits_tx ~= bits_rx));
    end
    ber_sim(snr_idx) = total_errors/(Nmc*Ns*k);
end

% 理论BER
ber_theory = (2/k)*0.5*erfc(sqrt(2*k*10.^(SNR_dB/10))*(sin(pi/M)).^2);
ber_theory = arrayfun(@(x) (2/k)*qfunc(sqrt(2*k*x*(sin(pi/M))^2)), 10.^(SNR_dB/10));

% 绘图
figure; semilogy(SNR_dB, ber_sim, 'bo-', SNR_dB, ber_theory, 'r--');
grid on; xlabel('E_b/N_0 (dB)'); ylabel('BER'); legend('仿真', '理论');
title('16PSK AWGN信道误码率'); axis([0 16 1e-6 1]);

八、总结

通过蒙特卡罗仿真验证了16PSK在AWGN信道下的误码率性能,Matlab代码实现了从比特生成到误码统计的全流程。仿真结果表明,高阶PSK需更高信噪比保证可靠性,实际应用中需权衡频谱效率与抗噪性能。

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