正交幅度调制(QAM)及解调matlab实验源代码【16QAM,32QAM,64QAM,256QAM】

写在前面:源代码下载请移步https://download.csdn.net/download/shizheng_Li/12629710

一、实验目的

(1) 掌握QAM及解调原理与特性。
(2) 了解星座图的原理及用途。

二、实验原理

在现代通信中,提高频谱利用率一直是人们关注的焦点之一。近年来,随着通信业务需求的迅速增长,寻找频谱利用率高的数字调制方式已成为数字通信系统设计、研究的主要目标之一。正交振幅调制(Quadrature Amplitude Modulation,QAM)就是一种频谱利用率很高的调制方式,其在中、大容量数字微波通信系统、有线电视网络高速数据传输、卫星通信系统等领域得到了广泛应用。在移动通信中,随着微蜂窝和微微蜂窝的出现,使得信道传输特性发生了很大变化。过去在传统蜂窝系统中不能应用的正交振幅调制也引起人们的重视。

1. MQAM原理

单独使用振幅或相位携带信息时,不能充分地利用信号平面,这可以由矢量图中信号矢量端点的分布直接观察到。多进制振幅调制时,矢量端点在一条轴上分布;多进制相位调制时,矢量端点在一个圆上分布。随着进制数M的增大,这些矢量端点之间的最小距离也随之减小。但如果我们可以充分利用整个平面,将矢量端点重新合理的分布,则有可能在不减小最小距离的情况下,增加信号矢量的端点数量。基于上述概念,我们可以引出振幅与相位结合的方式,这种方式常称为数字复合调制方式。一般的复合调制称为幅相键控(APK),两个正交载波幅相键控称为正交振幅调制(QAM)。

正交振幅调制是用两个独立的基带数字信号对两个相互正交的同频载波进行抑制载波的双边带调制,利用这种已调信号在同一带宽内频谱正交的性质来实现两路并行的数字信息传输。正交振幅调制信号的一般表示式为
在这里插入图片描述
式中,MQAM中的M表示调制进制数;An是基带信号幅度;g(t-nTs)是宽度为Ts的单个基带信号波形。上式还可以变换为正交表示形式:
在这里插入图片描述
令:
X n = A n c o s θ n , Y n = A n s i n θ n X_n=A_ncos\theta_n, Y_n=A_nsin\theta_n


S M Q A M ( t ) = n A n g ( t n T s ) c o s ( w c t + θ n ) = X ( t ) c o s w c t Y ( t ) s i n w c t S_{MQAM}(t)=\sum_{n}A_ng(t-nT_s)cos(w_ct+\theta_n)=X(t)cosw_ct-Y(t)sinw_ct

其中
X ( t ) = n X n g ( t n T s ) , Y ( t ) = n Y n g ( t n T s ) X(t)=\sum_{n}X_ng(t-nT_s),Y(t)=\sum_{n}Y_ng(t-nT_s)
QAM调制原理框图
在这里插入图片描述

2. MQAM的星座图

信号矢量端点的分布图称为星座图。通常,可以用星座图来描述QAM信号的信号空间分布状态。对于M = 16的16QAM来说,有多种分布形式的信号星座图。两种具有代表意义的信号星座图如图所示。
在这里插入图片描述
在图(a)中,信号点的分布呈方形,故称为方型16QAM星座,也称为标准型16QAM。在图(b)中,信号点的分布呈星形,故称为星型16QAM星座

若信号点之间的最小距离为2A,且所有信号点等概率出现,则平均发射信号功率为

在这里插入图片描述
对于方型16QAM,信号平均功率为
在这里插入图片描述

对于星型16QAM,信号平均功率为
在这里插入图片描述
两者功率相差1.4 dB。另外,两者的星座结构也有重要的差别。一是星型16QAM只有两个振幅值,而方型16QAM有3种振幅值;二是星型16QAM只有8种相位值,而方型16QAM有12种相位值。这两点使得在衰落信道中,星型16QAM比方型16QAM更具有吸引力。

M = 4,16,32,…,256时,MQAM信号的星座图如图所示。
在这里插入图片描述

若已调信号的最大幅度为1,则MPSK信号星座图上信号点间的最小距离为
 在这里插入图片描述

而MQAM信号矩形星座图上信号点间的最小距离为
在这里插入图片描述
式中,L为星座图上信号点在水平轴和垂直轴上投影的电平数,M = L 2 L^2

3.MQAM解调原理

MQAM信号可以采用正交相干解调方法,解调器输入信号与本地恢复的两个正交载波相乘后,经过低通滤波输出两路多电平基带信号X(t)和Y(t)。多电平判决器对多电平基带信号进行判决和检测,再经L电平到2电平转换和并/串变换器,最终输出二进制数据。
在这里插入图片描述

四、实验内容记录

本次实验主要练习星座图的映射。

1.16QAM源代码

这是常见的16QAM的星座映射图
在这里插入图片描述
图片来源:博客文章 “通信里 星座图 到底是什么”
本文采用另一种格雷码映射,如下图所示,本文的实验也是采用下图格式
在这里插入图片描述
16QAM映射表

格雷码 星座图坐标(x,y)
0000 (-3A,-3A)
0001 (-3A,-A)
0010 (-3A,3A)
0011 (-3A,A)
0100 (-A,-3A)
0101 (-A,-A)
0110 (-A,3A)
0111 (-A,A)
1000 (3A,-3A)
1001 (3A,-A)
1010 (3A,3A)
1011 (3A,A)
1100 (A,-3A)
1101 (A,-A)
1110 (A,3A)
1111 (A,A)

依据上表建立下列的映射表
同相分量2位+正交分量2位构成4位二进制数

 %建立16QAM同相分量映射表
mapping1=[-3,-3,-3,-3,-1,-1,-1,-1, 3, 3,3,3, 1, 1, 1,1]; 
 %建立16QAM正交分量映射表          
mapping2=[-3,-1, 3, 1,-3,-1, 3, 1,-3,-1,3,1,-3,-1,3,1];          

同时按照上表进行解映射(采用if else形式)

  %解映射
    if ([yc(N),ys(N)]==[-3,-3])
        bin(N,:)=[0,0,0,0];
    elseif([yc(N),ys(N)]==[-3,-1])
        bin(N,:)=[0,0,0,1];
    elseif([yc(N),ys(N)]==[-3,3])
        bin(N,:)=[0,0,1,0];    
    elseif([yc(N),ys(N)]==[-3,1])
        bin(N,:)=[0,0,1,1];    
    elseif([yc(N),ys(N)]==[-1,-3])
        bin(N,:)=[0,1,0,0];    
    elseif([yc(N),ys(N)]==[-1,-1])
        bin(N,:)=[0,1,0,1];    
    elseif([yc(N),ys(N)]==[-1,3]) 
        bin(N,:)=[0,1,1,0];    
    elseif([yc(N),ys(N)]==[-1,1])
        bin(N,:)=[0,1,1,1];    
    elseif([yc(N),ys(N)]==[3,-3])
        bin(N,:)=[1,0,0,0];    
    elseif([yc(N),ys(N)]==[3,-1])
        bin(N,:)=[1,0,0,1];    
    elseif([yc(N),ys(N)]==[3,3])
        bin(N,:)=[1,0,1,0];    
    elseif([yc(N),ys(N)]==[3,1])
        bin(N,:)=[1,0,1,1];    
    elseif([yc(N),ys(N)]==[1,-3])
        bin(N,:)=[1,1,0,0];    
    elseif([yc(N),ys(N)]==[1,-1])
        bin(N,:)=[1,1,0,1];    
    elseif([yc(N),ys(N)]==[1,3])
        bin(N,:)=[1,1,1,0];    
    elseif([yc(N),ys(N)]==[1,1])
        bin(N,:)=[1,1,1,1];    
    end

运行结果
在这里插入图片描述
横轴(in-phase)表示同相分量,纵轴(Quadrature)表示正交分量
在这里插入图片描述

源程序

将下列三个文件放在一起,运行QAM16.m即可
QAM16.m
Mapping_16QAM.m
Demapping_16QAM.m

QAM16.m


%description:16QAM主函数
%
% 
close all;clear all;
global num;%仿真的01比特数量
global inbits;%输入比特向量
global bin;%解调比特的矩阵(41行)
global ac;%同相分量
global as;%正交分量
global Eb_ratio_N0_indB;%分贝表示的信噪比
global result;%解映射之后比特向量,用result-inbits来求误码率
global i;%复数单位i
i=sqrt(-1);
pe=[];%误码率
num=20000;%仿真的01比特数量

 %---------------实际误码率部分----------------------------  
 %运行12,得到12个误码率,绘制误码率曲线 
for Eb_ratio_N0_indB=0:11
    Eb_ratio_N0_indB  %信噪比Eb/n0
    
    E=[];
    inbits=randi([0,1],1,num);              
    tx_bits_inv=reshape(inbits,4,num/4);
    tx_bits=tx_bits_inv';                   %由于matlab对矩阵按列访问,而方便阅读要将码元按行排列,所以事先进行转置处理
    tx_16QAM=Mapping_16QAM(tx_bits);        %100万比特进行格雷映射和调制,得到已调制复信号

    tx_16QAM_Energy=var(tx_16QAM);          %测量16QAM已调复信号的能量
    tx_16QAM_normalization=tx_16QAM/sqrt(var(tx_16QAM));    %16QAM已调复信号进行能量归一化
    rx_16QAM_normalization=awgn(tx_16QAM_normalization,Eb_ratio_N0_indB+6.0206);    %对归一化的16QAM已调复信号加复噪声AWGN
    rx_16QAM=rx_16QAM_normalization*sqrt(var(tx_16QAM));    %为了在解调时沿用已调复信号的判决、解映射规则,恢复已调复信号
    [result]=Demapping_16QAM(rx_16QAM);%判决子函数
    E=[E abs(inbits-result)];%得出出错的数量:1表示出现错误
    %mean(E)%计算平均值,就是误码率
    pe=[pe mean(E)];%12次误码率保存在pe向量中
end
 	 scatterplot(tx_16QAM);%绘制星座图

figure;
Eb_ratio_N0_indB=0:11;
semilogy(Eb_ratio_N0_indB,pe,'xr-');       %画格雷映射16QAM仿真的BER-EbN0离散点图
hold on

%---------------理论误码率部分----------------------------
BER=[];%理论误码率
for EbN0=0:11
	[ber,ser]=berawgn(EbN0,'qam',16) ;   %调用matlab的理论BER-EbN0离散点图,作为拟合度验证的参考
	BER=[BER ber];
end
%画理论BER-EbN0离散点图
%理论BER-EbN0离散点图上的12个离散点(EbN0=0:11):

hold on
EbN0=0:11
semilogy(EbN0,BER,'^-')
title("16QAM误码率");
legend('实际值','理论值');
xlabel("Eb/N0");ylabel("Pe");


主程序中部分解释

1)对于映射子函数的解释:

tx_16QAM=Mapping_16QAM(tx_bits);        %100万比特进行格雷映射和调制,得到已调制复信号

该句话的作用是得到要绘制星座图所需要的复数(实部对应同相分量,虚部对应正交分量),所以Mapping_16QAM是一个映射函数,将二进制比特转换成十进制数,然后查映射表,得到实部和虚部,合成为所需要的复数。

2)对于scatterplot函数的解释:
这是用来绘制星座图的函数

scatterplot(x) produces a scatter plot for the signal x. The interpretation of x depends on its shape and complexity:
If x is a complex vector, scatterplot interprets the real part as in-phase components and the imaginary part as quadrature components.、
如果x是一个复数的向量,这个函数将会把实部解释成同相分量,把虚部解释称正交分量

scatterplot(x,n) is the same as the first syntax, except that the function plots every nth value of the signal, starting from the first value. That is, the function decimates x by a factor of n before plotting.
每n个值绘制一次

3)对于随机数生成函数randi的解释

inbits=randi([0,1],1,num);

这个函数代替randint函数,用法如下,[0,1]表示生成的随机数在0和1之间,生成1行num列。
4)对于方差函数var的解释

var - Variance
This MATLAB function returns the variance of the elements of A along the first
array dimension whose size does not equal 1.
按照第一维返回方差

5)对于函数berawgn的解释
AWGN表示高斯白噪声信道,这个函数用于计算在AWGN条件下各种调制的理论误码率

[ber,ser]=berawgn(EbN0,'qam',16) ;   %调用matlab的理论BER-EbN0离散点图,作为拟合度验证的参考

其中ber和ser的解释如下
系统的误比特率(Bit Error Ratio, BER)以及误符号率(symbol error rate, SER).误比特率=误比特数/传输总比特数;误符号率=错误码元数/传输总码元数。在二进制中,两者相等。

help berawgn
berawgn - Bit error rate (BER) for uncoded AWGN channels
This MATLAB function returns the BER of uncoded PAM over an AWGN channel with coherent demodulation.
ber = berawgn(EbNo,‘pam’,M)
ber = berawgn(EbNo,‘qam’,M)
ber = berawgn(EbNo,‘psk’,M,dataenc)
ber = berawgn(EbNo,‘oqpsk’,dataenc)
ber = berawgn(EbNo,‘dpsk’,M)
ber = berawgn(EbNo,‘fsk’,M,coherence)
ber = berawgn(EbNo,‘fsk’,2,coherence,rho)
ber = berawgn(EbNo,‘msk’,precoding)
ber = berawgn(EbNo,‘msk’,precoding,coherence)
berlb = berawgn(EbNo,‘cpfsk’,M,modindex,kmin)
[BER,SER] = berawgn(EbNo, …)

解释:
The berawgn function returns the BER of various modulation schemes over an additive white Gaussian noise (AWGN) channel. The first input argument, EbNo, is the ratio of bit energy to noise power spectral density, in dB. If EbNo is a vector, the output ber is a vector of the same size, whose elements correspond to the different Eb/N0 levels. The supported modulation schemes, which correspond to the second input argument to the function, are in the following table.

在这里插入图片描述
来源于berawgn函数的参考页,matlab

6)对函数awgn的解释
这里先要对不同信噪比进行区别,
Eb/N0:比特信噪比,指的是每bit的能量与噪声功率谱密度之比,也是BER差错性能曲线的横轴;
SNR:每个采样点上的信噪比

awgn函数使用SNR,需要用Eb/N0进行转换,转换公式为:
计算信噪比的公式为SNR=10*log10(Eb./No)

调用子函数
Mapping_16QAM.m

function [tx_16QAM]=  Mapping_16QAM (tx_bits)

mapping1=[-3,-3,-3,-3,-1,-1,-1,-1,3,3,3,3,1,1,1,1];           %建立16QAM同相分量映射表
mapping2=[-3,-1,3,1,-3,-1,3,1,-3,-1,3,1,-3,-1,3,1];           %建立16QAM正交分量映射表
global ac;%同相分量
global as;%正交分量
global num;
global i;%i=-1,合成复信号时使用
Dec=zeros(num/4,1);               %初始化映射序号矩阵
ac=zeros(num/4,1);                %初始化同相分量矩阵
as=zeros(num/4,1);                %初始化正交分量矩阵
tx_16QAM=zeros(num/4,1);                %初始化复信号矩阵
for N=1:num/4
    Dec(N,:)=bi2de(tx_bits(N,:),'left-msb');  %将输入矩阵的每4个进行二十进制转换
    ac(N)=mapping1(Dec(N)+1);	%进行同相分量映射
    as(N)=mapping2(Dec(N)+1);	%进行正交分量映射
    tx_16QAM(N)=ac(N)+i*as(N);  %合成复信号
end



函数bi2de函数解释

  Dec(N,:)=bi2de(tx_bits(N,:),'left-msb');  %将输入矩阵的每4个(按行进行,这里每行4个比特)进行二十进制转换

bi2de - Convert binary vectors to decimal numbers
This MATLAB function converts a binary row vector b to a nonnegative decimal integer.
‘right-msb’ | ‘left-msb’:Character vector that determines whether the first column corresponds to the lowest-order or highest-order digit. If omitted, bi2de assumes ‘right-msb’.字符向量,用于确定第一列是对应于最低位还是最高位。 如果省略,bi2de将假定为“ right-msb”。
left-msb: Assign the most significant digit to the leftmost position,指定左边是最高位

tx_16QAM得到的合成复信号如下
在这里插入图片描述

加上高斯白噪声之后的复数信号
在这里插入图片描述
Demapping_16QAM.m

function[result] = Demapping_16QAM(rx_16QAM)
%判决子函数

global bin;
global num;

yc=[];
ys=[];
yc=real(rx_16QAM);%同相分量
ys=imag(rx_16QAM);%正交分量
bin=ones(num/4,4);
result=zeros(1,num);
for N=1:num/4
%最大似然门限判决
    if(yc(N)<-2)%对同相分量的判决
        yc(N)=-3;
    elseif(yc(N)>-2&&yc(N)<0)
        yc(N)=-1;
    elseif(yc(N)>0&&yc(N)<2)
        yc(N)=1;
    elseif(yc(N)>2)
        yc(N)=3;
    end

    if(ys(N)<-2)%对正交分量的判决
        ys(N)=-3;
    elseif(ys(N)>-2&&ys(N)<0)
        ys(N)=-1;
    elseif(ys(N)>0&&ys(N)<2)
        ys(N)=1;
    elseif(ys(N)>2)
        ys(N)=3;
    end

    %解映射(根据格雷码和星座图的关系)
    if ([yc(N),ys(N)]==[-3,-3])
        bin(N,:)=[0,0,0,0];
    elseif([yc(N),ys(N)]==[-3,-1])
        bin(N,:)=[0,0,0,1];
    elseif([yc(N),ys(N)]==[-3,3])
        bin(N,:)=[0,0,1,0];    
    elseif([yc(N),ys(N)]==[-3,1])
        bin(N,:)=[0,0,1,1];    
    elseif([yc(N),ys(N)]==[-1,-3])
        bin(N,:)=[0,1,0,0];    
    elseif([yc(N),ys(N)]==[-1,-1])
        bin(N,:)=[0,1,0,1];    
    elseif([yc(N),ys(N)]==[-1,3]) 
        bin(N,:)=[0,1,1,0];    
    elseif([yc(N),ys(N)]==[-1,1])
        bin(N,:)=[0,1,1,1];    
    elseif([yc(N),ys(N)]==[3,-3])
        bin(N,:)=[1,0,0,0];    
    elseif([yc(N),ys(N)]==[3,-1])
        bin(N,:)=[1,0,0,1];    
    elseif([yc(N),ys(N)]==[3,3])
        bin(N,:)=[1,0,1,0];    
    elseif([yc(N),ys(N)]==[3,1])
        bin(N,:)=[1,0,1,1];    
    elseif([yc(N),ys(N)]==[1,-3])
        bin(N,:)=[1,1,0,0];    
    elseif([yc(N),ys(N)]==[1,-1])
        bin(N,:)=[1,1,0,1];    
    elseif([yc(N),ys(N)]==[1,3])
        bin(N,:)=[1,1,1,0];    
    elseif([yc(N),ys(N)]==[1,1])
        bin(N,:)=[1,1,1,1];    
    end    
        result(4*N-3)=bin(N,1);%得到解映射result向量
        result(4*N-2)=bin(N,2);
        result(4*N-1)=bin(N,3);
        result(4*N)=bin(N,4);
 
end

2.32QAM源代码

星座图和二进制数对应关系
在这里插入图片描述
32QAM映射表
32QAMmapping1(横坐标)和mapping2(纵坐标)中各有32个数,对应位置构成星座图中的坐标,比如mapping(1)和mapping2(1)构成坐标(-3,-5)

%建立32QAM同相分量映射表      
mapping1=[-3 -1 -3 -1 -5 -5 -5 -5 -1 -1 -1 -1 -3 -3 -3 -3  3  1 3 1  5  5 5 5 1 1 1 1 3 3 3 3];   

%建立32QAM正交分量映射表
mapping2=[-5 -5 5  5  -3 -1 3   1 -3 -1 3   1 -3 -1  3  1 -5 -5 5 5 -3 -1 3 1 -3 -1 3 1 -3 -1 3 1];        
二进制数 星座图坐标(x,y)
00000 (-3A,-5A)
00001 (-A,-5A)
00010 (-3A,5A)
00011 (-A,5A)
00100 (-5A,-3A)
00101 (-5A,-A)
00110 (-5A,3A)
00111 (-5A,A)
01000 (-A,-3A)
01001 (-A,-A)
01010 (-A,3A)
01011 (-A,A)
01100 (-3A,-3A)
01101 (-3A,-A)
01110 (-3A,3A)
01111 (-3A,A)
10000 (3A,-5A)
10001 (A,-5A)
10010 (3A,5A)
10011 (A,5A)
10100 (5A,-3A)
10101 (5A,-A)
10110 (5A,3A)
10111 (5A,A)
11000 (A,-3A)
11001 (A,-A)
11010 (A,3A)
11011 (A,A)
11100 (3A,-3A)
11101 (3A,-A)
11110 (3A,3A)
11111 (3A,A)

运行结果
在这里插入图片描述

星座图
在这里插入图片描述
加上噪声之后的星座图
在这里插入图片描述

pe =
1 至 12 列
0.2109 0.1889 0.1612 0.1400 0.1149 0.0930 0.0705 0.0503 0.0341 0.0206 0.0119 0.0060

QAM32.m文件(主程序)
各参数的含义请参考16QAM的例程



close all;
clear all;
global num;
global inbits;
global ac;
global as;
global bin;
global Eb_ratio_N0_indB;
global result;
global i;
i=sqrt(-1);
pe=[];
num=200000;
for Eb_ratio_N0_indB=0:11
    Eb_ratio_N0_indB
    E=[];
    inbits=randi([0 1],1,num);
    tx_bits_inv=reshape(inbits,5,num/5);
    tx_bits=tx_bits_inv';
    tx_32QAM=Mapping_32QAM(tx_bits);        %100万比特进行格雷映射和调制,得到已调复信号
    tx_32QAM_Energy=var(tx_32QAM);          %测量32QAM已调复信号的能量
    tx_32QAM_normalization=tx_32QAM/sqrt(var(tx_32QAM));    %16QAM已调复信号进行能量归一化
    rx_32QAM_normalization=awgn(tx_32QAM_normalization,Eb_ratio_N0_indB+6.9897);    %对归一化的32QAM已调复信号加复噪声AWGN
    rx_32QAM=rx_32QAM_normalization*sqrt(var(tx_32QAM));    %为了在解调时沿用已调复信号的判决、解映射规则,恢复已调复信号
    [result]=Demapping_32QAM(rx_32QAM);
    E=[E abs(inbits-result)];
    pe=[pe mean(E)];
end
 
   scatterplot(tx_32QAM);grid on
   scatterplot(rx_32QAM);

pe
Eb_ratio_N0_indB=0:11;
figure;
semilogy(Eb_ratio_N0_indB,pe,'x-')       %画格雷映射32QAM仿真的BER-EbN0离散点图
hold on


    
BER=[];
for EbN0=0:11
    [ber,ser]=berawgn(EbN0,'qam',32);    %调用matlab的理论BER-EbN0离散点图,作为拟合度验证的参考
    BER=[BER ber];
end
%画理论BER-EbN0离散点图
hold on
EbN0=0:11;
semilogy(EbN0,BER,'^-')
title("32QAM误码率");
legend('实际值','理论值');
xlabel("Eb/N0");ylabel("Pe");

下面是两个子函数
Mapping_32QAM.m

function [tx_32QAM]=  Mapping_32QAM (tx_bits)

mapping1=[-3 -1 -3 -1 -5 -5 -5 -5 -1 -1 -1 -1 -3 -3 -3 -3 3 1 3 1 5 5 5 5 1 1 1 1 3 3 3 3];   %建立32QAM同相分量映射表      
mapping2=[-5 -5 5 5 -3 -1 3 1 -3 -1 3 1 -3 -1 3 1 -5 -5 5 5 -3 -1 3 1 -3 -1 3 1 -3 -1 3 1];  %建立32QAM正交分量映射表         
global ac;
global as;
global num;
global i;
Dec=zeros(num/5,1);
ac=zeros(num/5,1);
as=zeros(num/5,1);
tx_32QAM=zeros(num/5,1);                %初始化复信号矩阵
for N=1:num/5
    Dec(N,:)=bi2de(tx_bits(N,:),'left-msb');     %将输入矩阵的每5个进行二-十进制转换                                              
    ac(N)=mapping1(Dec(N)+1);	%进行同相分量映射
    as(N)=mapping2(Dec(N)+1);	%进行正交分量映射
    tx_32QAM(N)=ac(N)+i*as(N);  %合成复信号
end

Demapping_32QAM.m文件
(使用ifelse进行解映射)

function[result] = Demapping_32QAM(rx_32QAM)

global bin;
global num;
global result;
yc=[];
ys=[];
yc=real(rx_32QAM);
ys=imag(rx_32QAM);
bin=ones(num/5,5);
result=zeros(1,num);
%demapping=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31;
%    3-j,1+j*3,-3+j,-1-j*3,3+j*3,-3+j*3,-3-j*3,3-j*3,-1+j*3,-3-j,1-j*3,3+j,-5+j*3,-3-j*5,5-j*3,3+j*5,-5-j,1-j*5,5+j,-1+j*5,-1-j,1-j,1+j,-1+j,-1-j*5,5-j,1+j*5,-5+j,3-j*5,5+j*3,-3+j*5,-5-j*3];
for N=1:num/5

    %最大似然门限判决
    if(yc(N)<-4)
        yc(N)=-5;
    elseif(yc(N)>-4&&yc(N)<-2)
        yc(N)=-3;
    elseif(yc(N)>-2&&yc(N)<0)
        yc(N)=-1;
    elseif(yc(N)>0&&yc(N)<2)
        yc(N)=1;
    elseif(yc(N)>2&&yc(N)<4)
        yc(N)=3;
    elseif(yc(N)>4)
        yc(N)=5;
    end

    if(ys(N)<-4)
        ys(N)=-5;
    elseif(ys(N)>-4&&ys(N)<-2)
        ys(N)=-3;
    elseif(ys(N)>-2&&ys(N)<0)
        ys(N)=-1;
    elseif(ys(N)>0&&ys(N)<2)
        ys(N)=1;
    elseif(ys(N)>2&&ys(N)<4)
        ys(N)=3;
    elseif(ys(N)>4)
        ys(N)=5;
    end
    
    %使用ifelse进行解映射,这是老师源代码给的形式,当然这是一种费时费力的方式
    if ([yc(N),ys(N)]==[-3,-5])
        bin(N,:)=[0,0,0,0,0];
    elseif([yc(N),ys(N)]==[-1,-5])
        bin(N,:)=[0,0,0,0,1];
    elseif([yc(N),ys(N)]==[-3,5])
        bin(N,:)=[0,0,0,1,0];    
    elseif([yc(N),ys(N)]==[-1,5])
        bin(N,:)=[0,0,0,1,1];    
    elseif([yc(N),ys(N)]==[-5,-3])
        bin(N,:)=[0,0,1,0,0];    
    elseif([yc(N),ys(N)]==[-5,-1])
        bin(N,:)=[0,0,1,0,1];    
    elseif([yc(N),ys(N)]==[-5,3])
        bin(N,:)=[0,0,1,1,0];    
    elseif([yc(N),ys(N)]==[-5,1])
        bin(N,:)=[0,0,1,1,1];    
    elseif([yc(N),ys(N)]==[-1,-3])
        bin(N,:)=[0,1,0,0,0];    
    elseif([yc(N),ys(N)]==[-1,-1])
        bin(N,:)=[0,1,0,0,1];    
    elseif([yc(N),ys(N)]==[-1,3])
        bin(N,:)=[0,1,0,1,0];   
    elseif([yc(N),ys(N)]==[-1,1])
        bin(N,:)=[0,1,0,1,1];    
    elseif([yc(N),ys(N)]==[-3,-3])
        bin(N,:)=[0,1,1,0,0];    
    elseif([yc(N),ys(N)]==[-3,-1])
        bin(N,:)=[0,1,1,0,1];    
    elseif([yc(N),ys(N)]==[-3,3])
        bin(N,:)=[0,1,1,1,0];    
    elseif([yc(N),ys(N)]==[-3,1])
        bin(N,:)=[0,1,1,1,1];    
    elseif([yc(N),ys(N)]==[3,-5])
        bin(N,:)=[1,0,0,0,0];    
    elseif([yc(N),ys(N)]==[1,-5])
        bin(N,:)=[1,0,0,0,1];    
    elseif([yc(N),ys(N)]==[3,5])
        bin(N,:)=[1,0,0,1,0];    
    elseif([yc(N),ys(N)]==[1,5])
        bin(N,:)=[1,0,0,1,1];    
    elseif([yc(N),ys(N)]==[5,-3])
        bin(N,:)=[1,0,1,0,0];    
    elseif([yc(N),ys(N)]==[5,-1])
        bin(N,:)=[1,0,1,0,1];    
    elseif([yc(N),ys(N)]==[5,3])
        bin(N,:)=[1,0,1,1,0];    
    elseif([yc(N),ys(N)]==[5,1])
        bin(N,:)=[1,0,1,1,1];    
    elseif([yc(N),ys(N)]==[1,-3])
        bin(N,:)=[1,1,0,0,0];    
    elseif([yc(N),ys(N)]==[1,-1])
        bin(N,:)=[1,1,0,0,1];    
    elseif([yc(N),ys(N)]==[1,3])
        bin(N,:)=[1,1,0,1,0];    
    elseif([yc(N),ys(N)]==[1,1])
        bin(N,:)=[1,1,0,1,1];    
    elseif([yc(N),ys(N)]==[3,-3])
        bin(N,:)=[1,1,1,0,0];    
    elseif([yc(N),ys(N)]==[3,-1])
        bin(N,:)=[1,1,1,0,1];    
    elseif([yc(N),ys(N)]==[3,3])
        bin(N,:)=[1,1,1,1,0];    
    elseif([yc(N),ys(N)]==[3,1])
        bin(N,:)=[1,1,1,1,1];    
    end
    
    result(5*N-4)=bin(N,1);%5位二进制数按序放入result向量
    result(5*N-3)=bin(N,2);
    result(5*N-2)=bin(N,3);
    result(5*N-1)=bin(N,4);
    result(5*N)=bin(N,5);
 
end


关于32QAM的思考
在这里插入图片描述
通过绘制二进制数和星座图坐标,发现32QAM类圆形星座图并不能完全符合格雷码,上图中红色圆圈中有2位不同.32qam准圆形难以完全实现格雷规则,但长方形的误码性能还是不如准圆形好.一般来说,研究2的偶数次幂 进制的qam比较有代表性;2的奇数次幂 进制(32= 2 5 2^5 )的qam比较特殊,只能尽量保证格雷规则和码元幅度均匀化.

3.64QAM源代码

在这里插入图片描述

二进制数 星座图坐标(x,y) 二进制数 星座图坐标(x,y) 二进制数 星座图坐标(x,y) 二进制数 星座图坐标(x,y)
000 000 (-7,-7) 010 000 (-1,-7) 100 000 (7,-7) 110 000 (1,-7)
000 001 (-7,-5) 010 001 (-1,-5) 100 001 (7,-5) 110 001 (1,-5)
000010 (-7,-1) 010010 (-1,-1) 100010 (7,-1) 110010 (1,-1)
000011 (-7,-3) 010011 (-1,-3) 100011 (7,-3) 110011 (1,-3)
000100 (-7,7) 010100 (-1,7) 100100 (7,7) 110100 (1,7)
000101 (-7,5) 010101 (-1,5) 100101 (7,5) 110101 (1,5)
000110 (-7,1) 010110 (-1,1) 100110 (7,1) 110110 (1,1)
000111 (-7,3) 010111 (-1,3) 100111 (7,3) 110111 (1,3)
001000 (-5,-7) 011000 (-3,-7) 101000 (5,-7) 111000 (3,-7)
001001 (-5,-5) 011001 (-3,-5) 101001 (5,-5) 111001 (3,-5)
001010 (-5,-1) 011010 (-3,-1) 101010 (5,-1) 111010 (3,-1)
001011 (-5,-3) 011011 (-3,-3) 101011 (5,-3) 111011 (3,-3)
001100 (-5,7) 011100 (-3,7) 101100 (5,7) 111100 (3,7)
001101 (-5,5) 011101 (-3,5) 101101 (5,5) 111101 (3,5)
001110 (-5,1) 011110 (-3,1) 101110 (5,1) 111110 (3,1)
001111 (-5,3) 011111 (-3,3) 101111 (5,3) 111111 (3,3)

该方法对应的源代码

64qam程序运行
%下文包含1个QAM64.m文件,Mapping_64QAM.m和Demapping_64QAM.m各有两个,读者分别选择1个
构成下方的文件组合
QAM64.m
Mapping_64QAM.m
Demapping_64QAM.m

当上述3个文件放在同一路径时,运行QAM64.m即可

QAM64.m文件(主函数)


%description:64QAM主函数
%
% 
close all;clear all;
global num;%仿真的01比特数量
global inbits;%输入比特向量
  global bin;%解调比特的矩阵(41行)
global ac;%同相分量
global as;%正交分量
global Eb_ratio_N0_indB;%分贝表示的信噪比
global result;%解映射之后比特向量,用result-inbits来求误码率
global i;%复数单位i
i=sqrt(-1);
pe=[];%误码率
num=60000; 
   
    inbits=randi([0,1],1,num);
   tx_bits_inv=reshape(inbits,6,num/6);
   tx_bits=tx_bits_inv';
   tx_64QAM=Mapping_64QAM(tx_bits); 
  
   tx_64QAM_Energy=var(tx_64QAM);
   tx_64QAM_normalization=tx_64QAM/sqrt(var(tx_64QAM));    %64QAM已调复信号进行能量归一化
for Eb_ratio_N0_indB=0:11
      E=[];%误判向量
    rx_64QAM_normalization=awgn(tx_64QAM_normalization,Eb_ratio_N0_indB+10*log10(6));    %对归一化的64QAM已调复信号加复噪声AWGN
    rx_64QAM=rx_64QAM_normalization*sqrt(var(tx_64QAM));    %为了在解调时沿用已调复信号的判决、解映射规则,恢复已调复信号
   [result]=Demapping_64QAM(rx_64QAM);
   E=[E abs(inbits-result)];
   pe=[pe mean(E)];
end
pe
 scatterplot(tx_64QAM);grid on;
 scatterplot(rx_64QAM);grid on;
Eb_ratio_N0_indB=0:11;
figure,semilogy(Eb_ratio_N0_indB,pe,'^-r')       %画格雷映射64QAM仿真的BER-EbN0离散点图
hold on
 
BER=[];
for EbN0=0:11
[ber,ser]=berawgn(EbN0,'qam',64);    %调用matlab的理论BER-EbN0离散点图,作为拟合度验证的参考
BER=[BER ber];
end
BER;
hold on
EbN0=0:11;
semilogy(EbN0,BER,'x-b')
title("64QAM误码率");
legend('实际值','理论值');
xlabel("Eb/N0");ylabel("Pe");

调用两个子函数

映射函数有两种写法,关于映射子函数有2种写法,读者选择其一即可。
第一种

一种比较笨的映射方法,采用2个64位的map向量。
这是根据上面的二进制星座图坐标的关系得到的,每个map含有64个坐标分量,map1对应同相分量,map2对应正交分量,两者对应位置构成一个完整坐标,其与二进制数的映射关系通过数组下标完成,比如(map1(2),map2(2))得到的是(-7,-5),数组下标2对应的二进制数是000010

%同相分量:横坐标
map1=[-7,-7,-7,-7,-7,-7,-7,-7,-5,-5,-5,-5,-5,-5,-5,-5  -1,-1,-1,-1,-1,-1,-1,-1, -3   -3  -3  -3  -3  -3  -3  -3  7   7     7     7     7     7     7     7  5     5     5     5     5     5     5     5   1     1     1     1     1     1     1     1    3     3     3     3     3     3     3     3];

%正交分量:纵坐标
 map2=[-7 -5 -1 -3 7 5 1 3 -7 -5 -1 -3 7 5 1 3 -7 -5 -1 -3 7 5 1 3 -7 -5 -1 -3 7 5 1 3 -7 -5 -1 -3 7 5 1 3 -7 -5 -1 -3 7 5 1 3 -7 -5 -1 -3 7 5 1 3 -7 -5 -1 -3 7 5 1 3];

该Mapping_64QAM.m文件

function [tx_64QAM]=  Mapping_64QAM (tx_bits)
 
global ac;%同相分量
global as;%正交分量
global num;
global i;%复数单位,合成复信号时使用 
[m,n]=size(tx_bits);
num=m*n;

%同相分量:横坐标
map1=[-7,-7,-7,-7,-7,-7,-7,-7,-5,-5,-5,-5,-5,-5,-5,-5  -1,-1,-1,-1,-1,-1,-1,-1, -3   -3  -3  -3  -3  -3  -3  -3  7   7     7     7     7     7     7     7  5     5     5     5     5     5     5     5   1     1     1     1     1     1     1     1    3     3     3     3     3     3     3     3];

%正交分量:纵坐标
 map2=[-7 -5 -1 -3 7 5 1 3 -7 -5 -1 -3 7 5 1 3 -7 -5 -1 -3 7 5 1 3 -7 -5 -1 -3 7 5 1 3 -7 -5 -1 -3 7 5 1 3 -7 -5 -1 -3 7 5 1 3 -7 -5 -1 -3 7 5 1 3 -7 -5 -1 -3 7 5 1 3];


Dec_ac=zeros(num/6,1);
Dec_as=zeros(num/6,1);
 
ac=zeros(num/6,1);
as=zeros(num/6,1);
 
tx_64QAM=zeros(num/6,1);
 
for N=1:num/6
    Dec_ac(N,:)=bi2de(tx_bits(N,:),'left-msb');    
    Dec_as(N,:)=bi2de(tx_bits(N,:),'left-msb');  
    %同相分量ac
    ac(N)=map1(Dec_ac(N)+1);%MATLAB索引从1开始
    %正交分量as
    as(N)=map2(Dec_as(N)+1);%MATLAB索引从1开始  
    tx_64QAM(N,1)=ac(N)+i*as(N);
end
debug=1;

第二种
采用2两个8位的map向量

map1=[-7,-5,-1,-3,7,5,1,3]%同相分量
map2=[-7,-5,-1,-3,7,5,1,3]%正交分量

对应的映射函数
Mapping_64QAM.m文件

function [tx_64QAM]=  Mapping_64QAM (tx_bits)
 
global ac;%同相分量
global as;%正交分量
global num;
global i;%复数单位,合成复信号时使用 
[m,n]=size(tx_bits);
num=m*n;
 map1=[-7,-5,-1,-3,7,5,1,3]%同相分量
map2=[-7,-5,-1,-3,7,5,1,3]%正交分量

Dec_ac=zeros(num/6,1);
Dec_as=zeros(num/6,1);
 
ac=zeros(num/6,1);
as=zeros(num/6,1);
 
tx_64QAM=zeros(num/6,1);
 
for N=1:num/6
    Dec_ac(N,:)=bi2de(tx_bits(N,1:3),'left-msb');    %取出前三位
    Dec_as(N,:)=bi2de(tx_bits(N,4:6),'left-msb');  %取出后三位
    %同相分量ac
    ac(N)=map1(Dec_ac(N)+1);%MATLAB索引从1开始
    %正交分量as
    as(N)=map2(Dec_as(N)+1);%MATLAB索引从1开始  
    tx_64QAM(N,1)=ac(N)+i*as(N);
end
debug=1;

关于解映射子函数也有2种写法,读者选择其一即可。
第一种,采用ifelse解映射,这样需要写64个ifelse分支,如果是256QAM,需要写256个ifelse 分支,很明显这不是一个好的办法。
第二种,采用映射的方法。
1)ifelse解映射 的Demapping_64QAM.m文件

function [result] = Demapping_64QAM(rx_64QAM)
  
global bin;
global num;
yc=[];
ys=[];
yc=real(rx_64QAM);
ys=imag(rx_64QAM);
bin=ones(num/6,6);
result=zeros(1,num);
 
for N=1:num/6
%最大似然门限判决 

    if(yc(N)<=-6)
        yc(N)=-7;
        
    elseif(yc(N)>-6&&yc(N)<=-4)
        yc(N)=-5;
    
    elseif(yc(N)>-4&&yc(N)<=-2)
        yc(N)=-3;
     
    elseif(yc(N)>-2&&yc(N)<=0)
        yc(N)=-1;
      
    elseif(yc(N)>0&&yc(N)<=2)
        yc(N)=1;
     
    elseif(yc(N)>2&&yc(N)<=4)
        yc(N)=3;
    
    elseif(yc(N)>4&&yc(N)<=6)
        yc(N)=5;
   
    elseif(yc(N)>6)
        yc(N)=7;
 
    end
 
 
    if(ys(N)<=-6)
        ys(N)=-7;
     
    elseif(ys(N)>-6&&ys(N)<=-4)
        ys(N)=-5;
    
    elseif(ys(N)>-4&&ys(N)<=-2)
        ys(N)=-3;
   
    elseif(ys(N)>-2&&ys(N)<=0)
        ys(N)=-1;
  
    elseif(ys(N)>0&&ys(N)<=2)
        ys(N)=1;
  
    elseif(ys(N)>2&&ys(N)<=4)
        ys(N)=3;
   
    elseif(ys(N)>4&&ys(N)<=6)
        ys(N)=5;
   
    elseif(ys(N)>6)
        ys(N)=7;
    end
     
%     解映射
    %横坐标-7
     if ([yc(N),ys(N)]==[-7,-7])
        bin(N,:)=[0,0,0,0,0,0];
    elseif([yc(N),ys(N)]==[-7,-5])
        bin(N,:)=[0,0,0,0,0,1];
    elseif([yc(N),ys(N)]==[-7,-1])
        bin(N,:)=[0,0,0,0,1,0];    
    elseif([yc(N),ys(N)]==[-7,-3])
        bin(N,:)=[0,0,0,0,1,1];    
    elseif([yc(N),ys(N)]==[-7,7])
        bin(N,:)=[0,0,0,1,0,0];    
    elseif([yc(N),ys(N)]==[-7,5])
        bin(N,:)=[0,0,0,1,0,1];    
    elseif([yc(N),ys(N)]==[-7,1])
        bin(N,:)=[0,0,0,1,1,0];    
    elseif([yc(N),ys(N)]==[-7,3])
        bin(N,:)=[0,0,0,1,1,1];    
        
%     横坐标-5
    elseif([yc(N),ys(N)]==[-5,-7])
        bin(N,:)=[0,0,1,0,0,0];    
    elseif([yc(N),ys(N)]==[-5,-5])
        bin(N,:)=[0,0,1,0,0,1];    
    elseif([yc(N),ys(N)]==[-5,-1])
        bin(N,:)=[0,0,1,0,1,0];   
    elseif([yc(N),ys(N)]==[-5,-3])
        bin(N,:)=[0,0,1,0,1,1];    
    elseif([yc(N),ys(N)]==[-5,7])
        bin(N,:)=[0,0,1,1,0,0];    
    elseif([yc(N),ys(N)]==[-5,5])
        bin(N,:)=[0,0,1,1,0,1];    
    elseif([yc(N),ys(N)]==[-5,1])
        bin(N,:)=[0,0,1,1,1,0];    
    elseif([yc(N),ys(N)]==[-5,3])
        bin(N,:)=[0,0,1,1,1,1];  
        
%    横坐标-1     
    elseif([yc(N),ys(N)]==[-1,-7])
        bin(N,:)=[0,1,0,0,0,0];    
    elseif([yc(N),ys(N)]==[-1,-5])
        bin(N,:)=[0,1,0,0,0,1];    
    elseif([yc(N),ys(N)]==[-1,-1])
        bin(N,:)=[0,1,0,0,1,0];    
    elseif([yc(N),ys(N)]==[-1,-3])
        bin(N,:)=[0,1,0,0,1,1];    
    elseif([yc(N),ys(N)]==[-1,7])
        bin(N,:)=[0,1,0,1,0,0];    
    elseif([yc(N),ys(N)]==[-1,5])
        bin(N,:)=[0,1,0,1,0,1];    
    elseif([yc(N),ys(N)]==[-1,1])
        bin(N,:)=[0,1,0,1,1,0];    
    elseif([yc(N),ys(N)]==[-1,3])
        bin(N,:)=[0,1,0,1,1,1];    
%  横坐标-3       
        
    elseif([yc(N),ys(N)]==[-3,-7])
        bin(N,:)=[0,1,1,0,0,0];    
    elseif([yc(N),ys(N)]==[-3,-5])
        bin(N,:)=[0,1,1,0,0,1];    
    elseif([yc(N),ys(N)]==[-3,-1])
        bin(N,:)=[0,1,1,0,1,0];    
    elseif([yc(N),ys(N)]==[-3,-3])
        bin(N,:)=[0,1,1,0,1,1];    
    elseif([yc(N),ys(N)]==[-3,7])
        bin(N,:)=[0,1,1,1,0,0];    
    elseif([yc(N),ys(N)]==[-3,5])
        bin(N,:)=[0,1,1,1,0,1];    
    elseif([yc(N),ys(N)]==[-3,1])
        bin(N,:)=[0,1,1,1,1,0];    
    elseif([yc(N),ys(N)]==[-3,3])
        bin(N,:)=[0,1,1,1,1,1];    
        
        
%    横坐标7
     elseif ([yc(N),ys(N)]==[7,-7])
        bin(N,:)=[1,0,0,0,0,0];
    elseif([yc(N),ys(N)]==[7,-5])
        bin(N,:)=[1,0,0,0,0,1];
    elseif([yc(N),ys(N)]==[7,-1])
        bin(N,:)=[1,0,0,0,1,0];    
    elseif([yc(N),ys(N)]==[7,-3])
        bin(N,:)=[1,0,0,0,1,1];    
    elseif([yc(N),ys(N)]==[7,7])
        bin(N,:)=[1,0,0,1,0,0];    
    elseif([yc(N),ys(N)]==[7,5])
        bin(N,:)=[1,0,0,1,0,1];    
    elseif([yc(N),ys(N)]==[7,1])
        bin(N,:)=[1,0,0,1,1,0];    
    elseif([yc(N),ys(N)]==[7,3])
        bin(N,:)=[1,0,0,1,1,1];    
% 横坐标5        
    elseif([yc(N),ys(N)]==[5,-7])
        bin(N,:)=[1,0,1,0,0,0];    
    elseif([yc(N),ys(N)]==[5,-5])
        bin(N,:)=[1,0,1,0,0,1];    
    elseif([yc(N),ys(N)]==[5,-1])
        bin(N,:)=[1,0,1,0,1,0];   
    elseif([yc(N),ys(N)]==[5,-3])
        bin(N,:)=[1,0,1,0,1,1];    
    elseif([yc(N),ys(N)]==[5,7])
        bin(N,:)=[1,0,1,1,0,0];    
    elseif([yc(N),ys(N)]==[5,5])
        bin(N,:)=[1,0,1,1,0,1];    
    elseif([yc(N),ys(N)]==[5,1])
        bin(N,:)=[1,0,1,1,1,0];    
    elseif([yc(N),ys(N)]==[5,3])
        bin(N,:)=[1,0,1,1,1,1];  
        
%    横坐标1     
    elseif([yc(N),ys(N)]==[1,-7])
        bin(N,:)=[1,1,0,0,0,0];    
    elseif([yc(N),ys(N)]==[1,-5])
        bin(N,:)=[1,1,0,0,0,1];    
    elseif([yc(N),ys(N)]==[1,-1])
        bin(N,:)=[1,1,0,0,1,0];    
    elseif([yc(N),ys(N)]==[1,-3])
        bin(N,:)=[1,1,0,0,1,1];    
    elseif([yc(N),ys(N)]==[1,7])
        bin(N,:)=[1,1,0,1,0,0];    
    elseif([yc(N),ys(N)]==[1,5])
        bin(N,:)=[1,1,0,1,0,1];    
    elseif([yc(N),ys(N)]==[1,1])
        bin(N,:)=[1,1,0,1,1,0];    
    elseif([yc(N),ys(N)]==[1,3])
        bin(N,:)=[1,1,0,1,1,1];    
%  横坐标3       
        
    elseif([yc(N),ys(N)]==[3,-7])
        bin(N,:)=[1,1,1,0,0,0];    
    elseif([yc(N),ys(N)]==[3,-5])
        bin(N,:)=[1,1,1,0,0,1];    
    elseif([yc(N),ys(N)]==[3,-1])
        bin(N,:)=[1,1,1,0,1,0];    
    elseif([yc(N),ys(N)]==[3,-3])
        bin(N,:)=[1,1,1,0,1,1];    
    elseif([yc(N),ys(N)]==[3,7])
        bin(N,:)=[1,1,1,1,0,0];    
    elseif([yc(N),ys(N)]==[3,5])
        bin(N,:)=[1,1,1,1,0,1];    
    elseif([yc(N),ys(N)]==[3,1])
        bin(N,:)=[1,1,1,1,1,0];    
    elseif([yc(N),ys(N)]==[3,3])
        bin(N,:)=[1,1,1,1,1,1];  
     end
%矩阵降维成向量,用于和原inbits进行比较计算误码率
      result(6*N-5)=bin(N,1);
      result(6*N-4)=bin(N,2);
      result(6*N-3)=bin(N,3);
      result(6*N-2)=bin(N,4);
      result(6*N-1)=bin(N,5);
      result(6*N)=bin(N,6);   
      
end

Debug=1;%用于调试
    

2)矩阵映射的解映射Demapping_64QAM.m文件

function [result] = Demapping_64QAM(rx_64QAM)
  
global bin;
global num;
yc=[];
ys=[];
yc=real(rx_64QAM);
ys=imag(rx_64QAM);
bin=ones(num/6,6);

result=zeros(1,num);

index1=0;%索引
index2=0;
 map1=[-7,-5,-1,-3,7,5,1,3];
% 通过map1把坐标映射到demapping中的二进制数
demapping=[
    0 0 0;
    0 0 1;
    0 1 0;
    0 1 1;
    1 0 0;
    1 0 1;
    1 1 0;
    1 1 1];

 
for N=1:num/6
%最大似然门限判决 

    if(yc(N)<=-6)
        yc(N)=-7;
        
    elseif(yc(N)>-6&&yc(N)<=-4)
        yc(N)=-5;
    
    elseif(yc(N)>-4&&yc(N)<=-2)
        yc(N)=-3;
     
    elseif(yc(N)>-2&&yc(N)<=0)
        yc(N)=-1;
      
    elseif(yc(N)>0&&yc(N)<=2)
        yc(N)=1;
     
    elseif(yc(N)>2&&yc(N)<=4)
        yc(N)=3;
    
    elseif(yc(N)>4&&yc(N)<=6)
        yc(N)=5;
   
    elseif(yc(N)>6)
        yc(N)=7;
 
    end
 
 
    if(ys(N)<=-6)
        ys(N)=-7;
     
    elseif(ys(N)>-6&&ys(N)<=-4)
        ys(N)=-5;
    
    elseif(ys(N)>-4&&ys(N)<=-2)
        ys(N)=-3;
   
    elseif(ys(N)>-2&&ys(N)<=0)
        ys(N)=-1;
  
    elseif(ys(N)>0&&ys(N)<=2)
        ys(N)=1;
  
    elseif(ys(N)>2&&ys(N)<=4)
        ys(N)=3;
   
    elseif(ys(N)>4&&ys(N)<=6)
        ys(N)=5;
   
    elseif(ys(N)>6)
        ys(N)=7;
    end
     
%     解映射
     index1=find(map1==yc(N));
     index2=find(map1==ys(N));
     bin(N,:)=[demapping(index1,:),demapping(index2,:)];

      result(6*N-5)=bin(N,1);
      result(6*N-4)=bin(N,2);
      result(6*N-3)=bin(N,3);
      result(6*N-2)=bin(N,4);
      result(6*N-1)=bin(N,5);
      result(6*N)=bin(N,6);   
   
    
    
end
%  result=reshape(bin,1,num);
Debug=1;
    

运行结果
星座图
在这里插入图片描述
添加噪声之后的星座图
在这里插入图片描述

误码率曲线:仿真误码率曲线与理论误码率曲线对比,可以发现与理论值符合得很好
在这里插入图片描述
tx_bits变量中存储的是6位二进制数
在这里插入图片描述

添加噪声之后rx_64QAM:复数
在这里插入图片描述

踩坑记录
运行出来的误码率曲线总是高于理论值,错误仿真曲线如下图所示
在这里插入图片描述
找bug找了两天,第一天的重点放在映射和解映射的上面,可是我的映射和解映射一直都是对的,主函数中awgn也是采用SNR形式(Eb/N0),没有错误;然后老师说可能是解映射时候bin矩阵降维成向量result的映射可能错误,发现还是对的。然后竟然找bug找到判决门限,当然这种地方是不会出错的。
当排除完映射和解映射子函数的问题之后,如果有问题,问题一定出现在主函数,也就是for循环附近的问题。

bug所在地
在这里插入图片描述
应该E向量是和inbits向量、result向量是同型的,这是业务逻辑没清楚,用完之后没清空(类似于开内存没释放内存)
正确放置位置,应该是for循环中使用完1次就要清空
在这里插入图片描述

4.256QAM源代码

在这里插入图片描述
256QAM星座图根据格雷映射,每个点由4bit实部和4bit虚部组成,x轴由实部4bit控制,y轴由虚部4bit控制,分别从负到正以此为0000、0001、0011、0010、0110、0111、0101、0100、1100、1101、1111、1110、1010、1011、1001、1000(格雷码),这样每个相邻点均有4bit是相同的(在同一轴),而另外4bit是格雷编码的相邻点,因为按照格雷编码每相邻两个码组之间均差1个bit,所以在星座图中每相邻的点都是只差1个bit。
映射表

mapping1=[-15 -13 -9 -11 -1 -3 -7 -5 15 13 9 11 1 3 7 5];
mapping2=[-15 -13 -9 -11 -1 -3 -7 -5 15 13 9 11 1 3 7 5];

demapping的映射

demapping=[
    0 0 0 0;
    0 0 0 1;
    0 0 1 1;
    0 0 1 0;
    0 1 1 0;
    0 1 1 1;
    0 1 0 1;
    0 1 0 0;
    1 1 0 0;
    1 1 0 1;
    1 1 1 1;
    1 1 1 0;
    1 0 1 0;
    1 0 1 1;
    1 0 0 1;
    1 0 0 0];
 

demapping的过程

%将十进制数转换为在demapping对应的位置,并从demapping的相应位置取出4个bit,实部虚部合起来即8bit,即解码
bin(N,:)=[demapping((yc(N)+15)/2+1,:)  demapping((ys(N)+15)/2+1,:)];

其中yc为实部,ys为虚部

yc=real(rx_256QAM);%实部
ys=imag(rx_256QAM);%虚部

主函数
QAM256.m文件
下面各参数含义请参考上文中的注释。

close all;clear all;clc;
global num;
global inbits;
global Eb_ratio_N0_indB;
global result;
global i;
i=sqrt(-1);
pe=[];
num=80000;
  

for Eb_ratio_N0_indB=0:11 
    E=[];
    inbits=randi([0,1],1,num);
   tx_bits_inv=reshape(inbits,8,num/8);
   tx_bits=tx_bits_inv';
   tx_256QAM=Mapping_256QAM(tx_bits); 
 
   tx_256QAM_Energy=var(tx_256QAM);
   tx_256QAM_normalization=tx_256QAM/sqrt(var(tx_256QAM));    %256QAM已调复信号进行能量归一化
   rx_256QAM_normalization=awgn(tx_256QAM_normalization,Eb_ratio_N0_indB+10*log10(8));    %对归一化的256QAM已调复信号加复噪声AWGN
   rx_256QAM=rx_256QAM_normalization*sqrt(var(tx_256QAM));  %为了在解调时沿用已调复信号的判决、解映射规则,恢复已调复信号
   [result]=Demapping_256QAM(rx_256QAM);
   E=[E abs(inbits-result)];
   pe=[pe mean(E)];
end
pe
  scatterplot(tx_256QAM);  grid on;
  scatterplot(rx_256QAM);  grid on;
Eb_ratio_N0_indB=0:11;

figure,semilogy(Eb_ratio_N0_indB,pe,'^-r') 
hold on
 
BER=[];
for EbN0=0:11
[ber,ser]=berawgn(EbN0,'qam',256);    %调用matlab的理论BER-EbN0离散点图,作为拟合度验证的参考
BER=[BER ber];
end
BER;
hold on
EbN0=0:11;
semilogy(EbN0,BER,'x-b')
title("256QAM误码率");
legend('实际值','理论值');
xlabel("Eb/N0");ylabel("Pe");

调用2个子函数
Mapping_256QAM.m文件

function [tx_256QAM]=  Mapping_256QAM (tx_bits)
 
global i;
 
[m,n]=size(tx_bits);
num=m*n;

mapping1=[-15 -13 -9 -11 -1 -3 -7 -5 15 13 9 11 1 3 7 5];%同相分量
mapping2=[-15 -13 -9 -11 -1 -3 -7 -5 15 13 9 11 1 3 7 5];%正交分量
 
Dec_ac=zeros(num/8,1);
Dec_as=zeros(num/8,1);
 
ac=zeros(num/8,1);%同相分量映射
as=zeros(num/8,1);%正交分量映射
 
tx_256QAM=zeros(num/8,1);
 
for N=1:num/8
    Dec_ac(N,:)=bi2de(tx_bits(N,1:4),'left-msb');    
    Dec_as(N,:)=bi2de(tx_bits(N,5:8),'left-msb');    
    ac(N)=mapping1(Dec_ac(N,:)+1);%MATLAB索引从1开始
    as(N)=mapping2(Dec_as(N,:)+1);%MATLAB索引从1开始
    tx_256QAM(N,1)=ac(N)+i*as(N);
end

function [result] = Demapping_256QAM(rx_256QAM)
 
% global bin;
% global num;
 
[m,n]=size(rx_256QAM);
num=m*n;
 
yc=real(rx_256QAM);%实部
ys=imag(rx_256QAM);%虚部
 
bin=ones(num,8);
result=zeros(1,num*8);
 
demapping=[
    0 0 0 0;
    0 0 0 1;
    0 0 1 1;
    0 0 1 0;
    0 1 1 0;
    0 1 1 1;
    0 1 0 1;
    0 1 0 0;
    1 1 0 0;
    1 1 0 1;
    1 1 1 1;
    1 1 1 0;
    1 0 1 0;
    1 0 1 1;
    1 0 0 1;
    1 0 0 0];


 
for N=1:num
% 最大似然门限判决
    if(yc(N)<-14)
        yc(N)=-15;
    elseif(yc(N)>-14&&yc(N)<-12)
        yc(N)=-13;
    elseif(yc(N)>-12&&yc(N)<-10)
        yc(N)=-11;
    elseif(yc(N)>-10&&yc(N)<-8)
        yc(N)=-9;
    elseif(yc(N)>-8&&yc(N)<-6)
        yc(N)=-7;
    elseif(yc(N)>-6&&yc(N)<-4)
        yc(N)=-5;
    elseif(yc(N)>-4&&yc(N)<-2)
        yc(N)=-3;
    elseif(yc(N)>-2&&yc(N)<0)
        yc(N)=-1;
    elseif(yc(N)>0&&yc(N)<2)
        yc(N)=1;
    elseif(yc(N)>2&&yc(N)<4)
        yc(N)=3;
    elseif(yc(N)>4&&yc(N)<6)
        yc(N)=5;
    elseif(yc(N)>6&&yc(N)<8)
        yc(N)=7;
    elseif(yc(N)>8&&yc(N)<10)
        yc(N)=9;
    elseif(yc(N)>10&&yc(N)<12)
        yc(N)=11;
    elseif(yc(N)>12&&yc(N)<14)
        yc(N)=13;
    elseif(yc(N)>14)
        yc(N)=15;
    end
 
    if(ys(N)<-14)
        ys(N)=-15;
    elseif(ys(N)>-14&&ys(N)<-12)
        ys(N)=-13;
    elseif(ys(N)>-12&&ys(N)<-10)
        ys(N)=-11;
    elseif(ys(N)>-10&&ys(N)<-8)
        ys(N)=-9;
    elseif(ys(N)>-8&&ys(N)<-6)
        ys(N)=-7;
    elseif(ys(N)>-6&&ys(N)<-4)
        ys(N)=-5;
    elseif(ys(N)>-4&&ys(N)<-2)
        ys(N)=-3;
    elseif(ys(N)>-2&&ys(N)<0)
        ys(N)=-1;
    elseif(ys(N)>0&&ys(N)<2)
        ys(N)=1;
    elseif(ys(N)>2&&ys(N)<4)
        ys(N)=3;
    elseif(ys(N)>4&&ys(N)<6)
        ys(N)=5;
    elseif(ys(N)>6&&ys(N)<8)
        ys(N)=7;
    elseif(ys(N)>8&&ys(N)<10)
        ys(N)=9;
    elseif(ys(N)>10&&ys(N)<12)
        ys(N)=11;
    elseif(ys(N)>12&&ys(N)<14)
        ys(N)=13;
    elseif(ys(N)>14)
        ys(N)=15;
    end
%解映射
	bin(N,:)=[demapping((yc(N)+15)/2+1,:)  demapping((ys(N)+15)/2+1,:)];
	        
	result(8*N-7:8*N)=bin(N,:);  
end

运行结果
星座图
在这里插入图片描述
添加噪声之后的星座图

在这里插入图片描述
误码率曲线
在这里插入图片描述

至此,终于完成了16QAM,32QAM,64QAM,256QAM的仿真实验!

补充

5.各种QAM误码率对比

在这里插入图片描述
从图中可以看出,在相同的信噪比条件下,QAM的阶数越高,误码率越高。
源代码

BER=[];
BER32=[];
BER256=[];
BER128=[];
for EbN0=0:11
	[ber,ser]=berawgn(EbN0,'qam',64);    %调用matlab的理论BER-EbN0离散点图,作为拟合度验证的参考
	BER=[BER ber];
	[ber32,ser32]=berawgn(EbN0,'qam',32);    %调用matlab的理论BER-EbN0离散点图,作为拟合度验证的参考
	BER32=[BER32 ber32];
	[ber256,ser256]=berawgn(EbN0,'qam',256);    %调用matlab的理论BER-EbN0离散点图,作为拟合度验证的参考
	BER256=[BER256 ber256];

	[ber128,ser128]=berawgn(EbN0,'qam',128);    %调用matlab的理论BER-EbN0离散点图,作为拟合度验证的参考
	BER128=[BER128 ber128];
end
BER;
hold on
EbN0=0:11;
semilogy(EbN0,BER32,'--r')
semilogy(EbN0,BER,'-b');
semilogy(EbN0,BER128,'-k')
semilogy(EbN0,BER256,'-g')


title("64QAM误码率");
% legend('实际值','理论值');
title("各种QAM误码率性能对比");
legend("32QAM","64QAM","128QAM","256QAM");
xlabel("Eb/N0");ylabel("Pe");

五、参考博客

【1】16QAM调制解调仿真(matlab,详细介绍仿真方案的设计、结果及结论、完整代码及注释)
【2】通信里 星座图 到底是什么
【3】256QAM调制映射表

猜你喜欢

转载自blog.csdn.net/shizheng_Li/article/details/107315033