要进行QAM调制的仿真首先要了解QAM调制的基本原理。QAM调制是一种根据数字基带信号同时控制载波的幅度和相位的调制方式。也就是说对应不同的1和0的基带信号,载波的幅度和相位都可以发生变化。

根据这个调制方式可以得到QAM的带通信号的公式可以表示为

根据这个公式我们还不能进行仿真。我们还需要将这个公式做进一步的展开。

查看展开后的公式可以发现,一个QAM信号的码元波形,可以通过I路和Q路两路幅度调制的信号叠加而成。由于cost和sint是正交的,所以这是两路正交信号的叠加。

所以,如果我们想要的到一个QAM信号的码元波形,就要分别得到I路的幅度值,和Q路的幅度值。这里以16QAM为例进行说明。由于16QAM是16进制的,每4个比特为一组对应一个带通信号的码元波形。 对于给定的基带信号的比特流,就要每4个为一组,每一组绘制出对应的带通信号的码元波形。

基带信号的4个比特,有16种不同的比特组合。

要进行仿真就要给出这16种比特组合中,每种比特组合对应的带通信号的码元波形是多少。要想得到码元波形,就要知道I路和Q路的幅度值分别是多少。

接下来 就设定仿真中1和0的比特组合对应的I路和Q路的幅度值如下。将I路振幅对应前两个比特b0b1,Q路对应后两个比特b2b3。I路信号的四个振幅+3A +A -A -3A与比特b0b1的四个组合11 10 01 00相对应。Q路信号也采用相同的对应关系。

这样对于一个基带信号的比特组合,我们就可以对应到I路和Q路的不同幅度值。

例如基带信号中的1101。前面的两个比特11就对应I路幅度值+3A,后面两个比特01对应着Q路幅度值-A。这样基带信号1101对应的两路正交载波的振幅就可以得到了。

将I路载波乘以3进行振幅调制,Q路载波乘以-1进行振幅调制.再将两路正交载波经过振幅调制后的波形想加就得到了16QAM调制后的波形。可以发现1101对应的码元波形振幅为3.162A,相位为341.60 。需要注意的是16QAM带通信号码元宽度应该是基带信号码元宽度的4倍。

由于在仿真中每个码元信号的波形,要对应一个I路幅度值,一个Q路幅度值,还有码元本身的幅度值和相位。

这种复杂的对应关系可以保存在一个星座图中。

矩阵图中的一个点对应了一种比特组合,到原点的距离对应着带通信号的振幅,该点的相位对应这带通信号的相位。该点的横坐标对应I路振幅,纵坐标对应Q路振幅。这样就将比特组合对应带通信号直观的展现出来了。16QAM有16中比特组合,因此星座图中就有16个点。

接下来我们看一下如何进行16QAM星座和波形的Python仿真。

首先是星座图的绘制。

import  numpy as np
import matplotlib.pyplot as pltdigram = {'11':3,'10':1,'01':-1,'00':-3}#设置数字和幅度的对应关系
spots = {}#放置点plt.figure()
plt.xlabel('I',loc='right',labelpad = 0.5)
plt.ylabel('Q',loc='top',labelpad = 0.5)  # 设置坐标轴的文字标签ax = plt.gca()  # get current axis 获得坐标轴对象ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')  # 将右边 上边的两条边颜色设置为空 其实就相当于抹掉这两条边ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')  # 指定下边的边作为 x 轴 指定左边的边为 y 轴ax.spines['bottom'].set_position(('data', 0))  # 指定 data 设置的bottom(也就是指定的x轴)绑定到y轴的0这个点上
ax.spines['left'].set_position(('data', 0))plt.axis([-5,5,-5,5])#设置坐标的数字范围for i in ['0','1']:for j in ['0','1']:for k in ['0','1']:for p in ['0','1']:str = ''.join([i,j,k,p])#通过循环获得16个4位数的10组合str1 = ''.join([i,j])#前两个10组合a = digram[str1]#获取前两个10组合对应的幅值# a = int(a)str2 = ''.join([k,p])b = digram[str2]#获取后两个10组合对应的幅值# b = int(b)complexSpot = complex(a,b)#不能写为a+bj,因为编译不通过 生成坐标plt.scatter(a,b,c='black')#绘制点plt.text(a, b+0.3, str, fontsize=10, color = "black", weight = "light", verticalalignment='center', horizontalalignment='center', rotation=0)#绘制10组合tempspot = {str:complexSpot}#获得数字组合和点spots.update(tempspot)#存入点的集合plt.show()

首先将16QAM中比特与振幅的对应关系保存在Python的字典对象diagram中。然后通过for循环遍历出16种不同的比特组合放在变量str种。str中的前两个比特取出来放到str1变量中,查询字典可以得到I路幅值存到变量a中,str中的后两个比特取出来放到str2变量中,查询字典可以得到Q路幅值存到变量b中.有了I路的幅度值和Q路幅度值就可以定位比特组合对应的点的位置了。这里将I路幅度值a和Q路幅度值b保存在Python特有的数据类型一个复数变量complexSpot中。这样16中不同的比特组合就对应了16个不同的复数,每个复数就对应了一个坐标轴里的点的位置。16个比特组合和复数的对应关系作为字典类型保存在了spot中。运行以上程序就得到了16QAM波形图。

观察星座图可以发现16QAM共有三个不同的幅度,12个不同的相位。相邻比特需符合格雷码编码方式。

与16PSK星座图相比较,16QAM星座图中点和点之间的距离较远,这就表示16QAM符号间更加不容易产生相互干扰。通常进制数M增加,会引起误码率的增加。

因此在5G网络中,M<=8时采用MPSK;M>8时误码率就会继续增加,从而采用具有更好抗噪声性能的QAM。一般 16QAM是最低阶的QAM。在实际网络中,会根据信道条件相应调整调制方式,信道条件越好,就可以采用越高阶的调制方式。

通过星座图我们也可以详细的看到16种比特组合对应的16个码元波形。

有了16QAM星座图,就有了16种比特组合分别对应的I路和Q路幅度值。接下来就可以将需要进行调制的基带信号的比特流,每四个为一组进行带通信号码元的绘制。由于在绘制星座图的时候就已经保存了比特组合和I路和Q路幅度值的对应关系。因此对于基带信号,只需要每次绘制4个比特,先查询4个比特对应的I路和Q路幅度值,然后分别与两路载波相乘,然后相加就可以得到当前4个比特对应的码元波形了。最后将所有的码元波形都追加到一个列表中,进行图形绘制,就得到了基带信号比特流所对应的带通信号的波形图。

import numpy as np
import matplotlib.pyplot as pltbitsToAmp = {'11': 3, '10': 1, '01': -1, '00': -3}  # 设置数字和幅度的对应关系
spots = {}  # 放置点for i in ['0', '1']:for j in ['0', '1']:for k in ['0', '1']:for p in ['0', '1']:strs = ''.join([i, j, k, p])  # 通过循环获得16个4位数的10组合str1 = ''.join([i, j])  # 前两个10组合a = bitsToAmp[str1]  # 获取前两个10组合对应的幅值a = int(a)str2 = ''.join([k, p])b = bitsToAmp[str2]b = int(b)  # 获取后两个10组合对应的幅值complexSpot = complex(a, b)  # 不能写为a+bj,因为编译不通过 生成坐标tempSpot = {strs: complexSpot}  # 获得数字组合和点spots.update(tempSpot)  # 存入点的集合fig = plt.figure()
t = np.arange(0, 12.0, 0.5)  # 设置基带信号10的坐标轴,每隔0.5的距离绘制一个基带的二进制信号,一共16个比特# input
plt.subplot(2, 1, 1)
y1 = [0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1]
plt.plot(t, y1, drawstyle='steps-post')  # 将16个比特每隔0.5绘制到坐标系上
plt.xlim(0, 12)
plt.ylim(-0.5, 1.5)
plt.title('16QAM modulation')# 串并变换
l4 = int(len(y1) / 4)  # 获取比特流的长度除以4,4个比特为一组,则共有多少组
a = np.asarray(y1)  # 将基带信号转换为numpy格式
y2 = a.reshape(l4, 4)  # 将一维数组转置为二维数组,每一行中有4个比特的数据plt.subplot(2, 1, 2)
t = np.arange(0, 12., 0.01)  # 横坐标的数据列表,每个0.01绘制一个点
rectwav = []  # 用来存储纵坐标值的列表# i表示第i个线段,每个线段对应一个二进制的四位组合s0s1s2s3。每个线段的长度为2,是基带信号每个信号长度0.5的四倍
for i in range(l4):b = y2[i]  # 取出第i组四位数组合s0s1s2s3str4Bits = str(b).strip('[').strip(']').replace(' ', '')  # 将列表中的4个比特转换为字符串并且去掉[ ] 和空格complexWave = spots[str4Bits]  # 根据四个比特的字符串对应到字典中的复数,得到横坐标和纵坐标的幅度,I Q的幅度值xWave = complexWave.real  # 取出横坐标的值yWave = complexWave.imag  # 取出纵坐标的值# 在t数组中第i段横坐标的点数,此处每个段的波形长度应该是0.5的4倍,也就是2t_tmp = t[(i * 200):((i + 1) * 200)]xI_tmp = xWave * np.ones(200)  # 200个横坐标的幅度值yQ_tmp = yWave * np.ones(200)  # 200个纵坐标的幅度值# 将幅度分别与两个正交载波相乘求和wav_tmp = xI_tmp * np.cos(2 * np.pi * 5 * t_tmp) - yQ_tmp * np.sin(2 * np.pi * 5 * t_tmp)rectwav.append(wav_tmp)  # 将调制后的点加到总的波形列表中# 绘制调制后的波形
plt.plot(t, np.array(rectwav).flatten())
plt.xlim(0, 12)
plt.ylim(-5, 5)plt.tight_layout()
plt.show()

通过波形图可以观察到16QAM每个码元对应4个比特,不同比特组在振幅和相位上都有不同变化。

16QAM调制的仿真及其Python实现的代码(超级详细)相关推荐

  1. 16QAM调制解调仿真(matlab,详细介绍仿真方案的设计、结果及结论、完整代码及注释)

    16QAM调制解调仿真目录 一.仿真要求 二.仿真方案详细设计 三.仿真结果及结论 四.仿真代码 一.仿真要求 1.用基带等效的方式仿真16-QAM在AWGN信道下的误码率和误比特率性能,并与理论值相 ...

  2. import的用法python_Python导入模块,Python import用法(超级详细)

    Python导入模块,Python import用法(超级详细) 使用 Python 进行编程时,有些功能没必须自己实现,可以借助 Python 现有的标准库或者其他人提供的第三方库.比如说,在前面章 ...

  3. 通信算法之十一:QPSK/DQPSK/OQPSK/BPSK/DBPSK/16QAM调制解调仿真链路

    一. QPSK 正交相移键控 (Quadrature Phase Shift Keying)简称"QPSK",是一种数字调制方式.它分为绝对相移和相对相移两种.由于绝对相移方式存在 ...

  4. 慕课Python机器学习应用-代码实现(详细注释+数据集)

    课程链接:Python机器学习应用_北京理工大学_中国大学MOOC(慕课) 学习和实现的算法有Kmeans和DBSCAN,数据集是自己在网上搜集的,在我的资源区提供免费下载. Kmeans算法: 1. ...

  5. Python raise用法(超级详细,看了无师自通)

    当程序出现错误时,系统会自动引发异常.除此之外,Python 也允许程序自行引发异常,自行引发异常使用 raise 语句来完成. 异常是一种很"主观"的说法,以下雨为例,假设大家约 ...

  6. Python raise用法(超级详细,无师自通)

    问题: 是否可以在程序的指定位置手动抛出一个异常?答案是肯定的,Python 允许我们在程序中手动设置异常,使用 raise 语句即可. 你们可能会感到疑惑,即我们从来都是想方设法地让程序正常运行,为 ...

  7. 在python中、使用( )语句导入模块_Python导入模块,Python import用法(超级详细)...

    对于一个真实的 Python 程序,我们不可能自己完成所有的工作,通常都需要借助于第三方类库.此外,也不可能在一个源文件中编写整个程序的源代码,这些都需要以模块化的方式来组织项目的源代码. 使用 im ...

  8. qam已调信号matlab相干解调,16qam调制解调matlab

    (论文)题目 16QAM 的调制与解调 时间: 2012 年 12 月 19 日指导教师 主要研 究内容 基于 MatlabSimulink 的 16QAM 的调制与解调 研究方法 MatlabSim ...

  9. python字典去重合并_Python字典及基本操作(超级详细)

    Python字典及基本操作(超级详细) 收录于话题#Python入门27个 今天小张帮大家简单介绍下Python的一种数据结构: 字典,字典是 Python 提供的一种常用的数据结构,它用于存放具有映 ...

  10. python怎么运行代码-python如何运行代码

    python作为一种动态语言,其实是一个解释器软件包. 当Python运行脚本时,在代码开始进行处理之前,Python还会执行一些步骤.(推荐学习:Python视频教程) 第一步是编译成所谓的&quo ...

最新文章

  1. jquery实现截取pc图片_jquery实现图片裁剪思路及实现
  2. WorldWind源码剖析系列:可渲染对象类RenderableObject
  3. TransactionScope oracle不能用的问题(转载)
  4. 转:12种JavaScript MVC框架之比较
  5. python网络通信基础-udp+NetAssist(网络调试助手)
  6. 锐捷客户端显示无法连接认证服务器,锐捷客户端连接失败怎么办 锐捷连不上解决办法...
  7. 怎么换c语言程序窗口背景图,vc++如何给窗体添加背景图片
  8. SOLIDWORKS批量转化PDF图纸的方法
  9. JMeter-Ramp-up Period解释
  10. linux unzip 包括目录,Linux 命令(目录管理 - zip/unzip)
  11. ios 系统状态栏样式修改_iOS 导航栏颜色和状态栏颜色修改
  12. php.ini maxfileuploads,细说PHP高洛峰文件上传类源文件
  13. 什么是VOIP和SIP?
  14. wpf中图片资源引用问题
  15. c语言源码 文件绑捆,js捆绑TypeScript声明文件的方法教程
  16. python3之calendar日历模块
  17. 2022年系统架构师、案例分析、论文押题
  18. 毕业设计1-DFROBOT 风速计 调试记录(基于485协议+ STM32Cubemx + STM32F103C8T6)
  19. 全志平台lichee启动时间优化
  20. SATA 数据、电源 接口定义

热门文章

  1. .ani动态鼠标指针图像无法显示
  2. 华为数通HCIA笔记(OSI七层)
  3. 句柄详解,什么是句柄?句柄有什么用?
  4. Rainmeter雨滴天气-(永不过时版通过获取网页数据实现)
  5. 【RemoteJoy】PSP图像采集方案
  6. 透视特洛伊木马程序开发技术
  7. Java 正则表达式
  8. 思科2811路由器采购回来首次配置
  9. htc t528d解锁
  10. 前端html小技巧(css篇)—表单美化详解