16QAM调制与解调-MATLAB基带仿真

16QAM调制与解调-MATLAB基带仿真

---------------------------- 2020.05.14更新:----------------------------------
有几位小伙伴在评论区与私信想要高维M-QAM的代码,更新文章供大家参考:
高维M-QAM调制与解调-MATLAB基带仿真

仿真步骤

  1. 产生一定长度的值为0或1的随机序列 s ( t ) s(t) s(t)
  2. s ( t ) s(t) s(t)映射到16QAM星座图上的星座点。
  3. 产生高斯白噪声,将调制后的信号通过AWGN信道,得到输出信号 r ( t ) r(t) r(t)
  4. 利用最小距离判决准则实现检测,统计误比特数。
  5. 绘制仿真误符号率与理论误符号率曲线,进行对比分析。

16QAM发送端星座图:
16QAM调制与解调-MATLAB基带仿真_第1张图片
注意:
在仿真中,需要考虑发送信号能量的归一化。
这里提供一种思路

EbN0_dB = 0:14;                         % Eb/N0 dB形式
EbN0 = 10.^(EbN0_dB/10);                % 每比特能量/噪声
EsN0 = log2(M) * EbN0;                  % 每符号能量/噪声
send_set = [-3+3j,-1+3j,1+3j,3+3j,...
            -3+1j,-1+1j,1+1j,3+1j,...
            -3-1j,-1-1j,1-1j,3-1j,...
            -3-3j,-1-3j,1-3j,3-3j];     % 发射端星座点
Es_avg = sum(abs(send_set).^2) / length(send_set);
N0 = Es_avg ./ EsN0;

也就是这里面的Es_avg,计算了发送信号的平均能量。

16QAM相干解调

最小距离判决准则:

s ^ ( t ) = arg ⁡ min ⁡ 1 ≤ m ≤ M ∥ r ( t ) − s m ( t ) ∥ 2 2 \hat{s}(t)=\underset{1 \leq m \leq M}{\arg \min}{\|r(t)-s_m(t)\|_2^{2}} s^(t)=1mMargminr(t)sm(t)22

理论误符号率:

P e = 3 Q ( 4 5 E b N 0 ) [ 1 − 3 4 Q ( 4 5 E b N 0 ) ] P_e=3 Q(\sqrt{\frac{4}{5} \frac{\mathcal{E}_{\mathrm{b}}}{N_{0}}})\left[1-\frac{3}{4} Q(\sqrt{\frac{4}{5} \frac{\mathcal{E}_{\mathrm{b}}}{N_{0}}})\right] Pe=3Q(54N0Eb )[143Q(54N0Eb )]

仿真结果
16QAM调制与解调-MATLAB基带仿真_第2张图片
MATLAB基带仿真程序

clc
clear
close all
% Title:  16QAM调制与解调 %
% Data:   2020.01.22 %
% Author: K.X.Song % 
M = 16;                                 % 调制阶数
L_data = 1000000;                       % 数据长度
L_symbol = L_data/log2(M);              % 符号长度
data = round(rand(1,L_data));           % 原始数据
EbN0_dB = 0:14;                         % Eb/N0 dB形式
EbN0 = 10.^(EbN0_dB/10);                % 每比特能量/噪声
EsN0 = log2(M) * EbN0;                  % 每符号能量/噪声
error = zeros(1,length(EbN0_dB));       % 预置错误符号个数
ser = zeros(1,length(EbN0_dB));         % 预置仿真误符号率
tser_BPSK = zeros(1,length(EbN0_dB));   % 预置BPSK理论误符号率
tser_QPSK = zeros(1,length(EbN0_dB));   % 预置QPSK理论误符号率
tser_16QAM = zeros(1,length(EbN0_dB));  % 预置16QAM理论误符号率
% 16QAM调制
send = zeros(1,L_symbol);               % 预设发送信号
send_set = [-3+3j,-1+3j,1+3j,3+3j,...
            -3+1j,-1+1j,1+1j,3+1j,...
            -3-1j,-1-1j,1-1j,3-1j,...
            -3-3j,-1-3j,1-3j,3-3j];     % 发射端星座点
Es_avg = sum(abs(send_set).^2) / length(send_set);
N0 = Es_avg ./ EsN0;
for q = 1:L_symbol
    if (data(4*q-3:4*q) == [1,0,1,1])
        send(q) = send_set(1);          % 1001 => -3+3j
    elseif (data(4*q-3:4*q) == [1,0,0,1])
        send(q) = send_set(2);          % 1001 => -1+3j
    elseif (data(4*q-3:4*q) == [1,1,1,0])
        send(q) = send_set(3);          % 1110 => +1+3j
    elseif (data(4*q-3:4*q) == [1,1,1,1])
        send(q) = send_set(4);          % 1111 => +3+3j
    elseif (data(4*q-3:4*q) == [1,0,1,0])
        send(q) = send_set(5);          % 1010 => -3+1j
    elseif (data(4*q-3:4*q) == [1,0,0,0])
        send(q) = send_set(6);          % 1000 => -1+1j
    elseif (data(4*q-3:4*q) == [1,1,0,0])
        send(q) = send_set(7);          % 1100 => +1+1j
    elseif (data(4*q-3:4*q) == [1,1,0,1])
        send(q) = send_set(8);          % 1101 => +3+1j
    elseif (data(4*q-3:4*q) == [0,0,0,1])
        send(q) = send_set(9);          % 0001 => -3-1j
    elseif (data(4*q-3:4*q) == [0,0,0,0])
        send(q) = send_set(10);         % 0000 => -1-1j
    elseif (data(4*q-3:4*q) == [0,1,0,0])
        send(q) = send_set(11);         % 0100 => +1-1j
    elseif (data(4*q-3:4*q) == [0,1,1,0])
        send(q) = send_set(12);         % 0110 => +3-1j
    elseif (data(4*q-3:4*q) == [0,0,1,1])
        send(q) = send_set(13);         % 0011 => -3-3j
    elseif (data(4*q-3:4*q) == [0,0,1,0])
        send(q) = send_set(14);         % 0010 => -1-3j
    elseif (data(4*q-3:4*q) == [0,1,0,1])
        send(q) = send_set(15);         % 0101 => +1-3j
    else
        send(q) = send_set(16);         % 0111 => +3-3j
    end
end
for q = 1:length(EbN0_dB)
    noise = sqrt(N0(q)/2)*randn(1,L_symbol) + 1j*sqrt(N0(q)/2)*randn(1,L_symbol);   % AWGN
    receive = (send + noise);       % 接收信号
    detect = zeros(1,L_symbol);         % 预置检测信号
    distance = zeros(1,M);              % 解调:距离检测 
    for t = 1:L_symbol
        for w = 1:M
            distance(w) = norm(receive(t) - send_set(w))^2;     % 接收信号到所有星座点的距离
        end
        pos = find(distance == min(distance));      % 最小距离星座点的位置
        detect(t) = send_set(pos);                  % 解调后的符号
        if (detect(t) ~= send(t)) 
            error(q) = error(q) + 1;                % 统计错误符号数
        end
    end
    ser(q) = error(q)/L_symbol;                     % 16QAM仿真误符号率
    tser_BPSK(q) = qfunc(sqrt(2*EbN0(q)));          % BPSK理论误比特率
    tser_QPSK(q) = 2*qfunc(sqrt(2*EbN0(q)))*(1-qfunc(sqrt(2*EbN0(q)))/2);            % QPSK理论误符号率
    tser_16QAM(q) = 3*qfunc(sqrt(4/5*EbN0(q)))*(1-3/4*qfunc(sqrt(4/5*EbN0(q))));   % 16QAM理论误符号率
end
figure
semilogy(EbN0_dB,ser,'o',EbN0_dB,tser_BPSK,'k',EbN0_dB,tser_QPSK,'r',EbN0_dB,tser_16QAM,'b');     % 画图
grid on;                                        % 坐标轴开启
axis([0 14 10^-5 10^-1])                        % 限制作图范围
xlabel('Eb/N0 (dB)');                           % 横坐标
ylabel('SER');                                  % 纵坐标
legend('16QAM仿真误符号率','BPSK理论误符号率','QPSK理论误符号率','16QAM理论误符号率');   % 图例

你可能感兴趣的:(16QAM调制与解调-MATLAB基带仿真)