Matlab示例-Examine 16-QAM Using MATLAB学习笔记
工作之余学习16-QAM
写在前面
网上看到许多示例,但一般都比较难以跑通。所以,还是老方法,先将matlab自带的例子研究下。
Examine 16-QAM Using MATLAB
Examine 16-QAM Using MATLAB
或者,在matlab中,键入:
openExample(‘comm/Examine16QAMUsingMATLABExample’)
会打开:
~\Document\MATLAB\Examples\R2022b\comm\Examine16QAMUsingMATLABExample
不得不感叹,WathWorks公司,依然在飞速的进步,其文档代码一体化能力,已经非常强了。
要注意有梯子之后,这个例子,可以直接在浏览器中运行和单步Trace.

不由得有些哀叹。软件这东西怎么说呢,越落后,就越落后。因为人家是在加速,我们则永远在零和搞一年就放弃归零的循环中。
我们能想象,如果MathWorks是中国公司,当你和老板说,我们也开发个网页版的调试器后,老板第一件事就问你这有用吗?这耽误我们挣钱吗?好吧,这玩意真的没什么用处,但真的是太cool了。
而且,下面就是有用的地方:
【注意】Matlab的示例,网页中的一般是最新的,而我们安装好的matlab所带的例子,往往,存在一些小的缺陷,并没有得到修正。
所以,当发生怀疑是不是哪里出错的时候,可以将被怀疑的代码段,与网页版的代码section 进行下比较。
比如当前的这个例子,的最后一段:
网页版是:
scatterplot(symgray,1,0,'b*');
for k = 1:Mtext(real(symgray(k)) - 0.0,imag(symgray(k)) + 0.3, ...dec2base(x(k),2,4),'Color',[0 1 0]);text(real(symgray(k)) - 0.5,imag(symgray(k)) + 0.3, ...num2str(x(k)),'Color',[0 1 0]);text(real(symbin(k)) - 0.0,imag(symbin(k)) - 0.3, ...dec2base(x(k),2,4),'Color',[1 0 0]);text(real(symbin(k)) - 0.5,imag(symbin(k)) - 0.3, ...num2str(x(k)),'Color',[1 0 0]);
end
title('16-QAM Symbol Mapping')
axis([-4 4 -4 4])
可是matlab中:
scatterplot(symgray,1,0,'b*');
for k = 1:Mtext(real(symgray(k)) - 0.0,imag(symgray(k)) + 0.3, ...dec2base(x(k),2,4));text(real(symgray(k)) - 0.5,imag(symgray(k)) + 0.3, ...num2str(x(k)));text(real(symbin(k)) - 0.0,imag(symbin(k)) - 0.3, ...dec2base(x(k),2,4),'Color',[1 0 0]);text(real(symbin(k)) - 0.5,imag(symbin(k)) - 0.3, ...num2str(x(k)),'Color',[1 0 0]);
end
title('16-QAM Symbol Mapping')
axis([-4 4 -4 4])
要注意,matlab中的代码,for循环中,少了一小段:
dec2base(x(k),2,4),‘Color’,[0 1 0]);
少了的这段Color,对我这样的学习的人,还是造成了一定的困扰。
初学者,在实操时,往往同时面对几个到十几个知识要学习,难以确定自己哪里是可以确认的。
正确的图像是这样的(在Web Cloud版跑出来的):

下面不对的是这样的:

所以,我很久都没有看懂——因为这张图。
看原图,很清楚是想让我们了解自然码与Gray Code的区别。
修改第一部分代码
这个示例的第一段是准备数据。
dataIn = randi([0 1],n,1); % Generate vector of binary data
但这一段,对于我来说,是不太喜欢的。因为作为初学者,要可控。
所以,我打算将数据进行变换,变换成为标准的0,1,2,3,…,15的样子。
所以,这是我第一步要做的。
在与ChatGPT进行了一番不对等的沟通之后,大致改好了,事实上,我花了不少时间。。。
clc;
clear all;
close all;M = 16; % Modulation order (alphabet size or number of points in signal constellation)
k = log2(M); % Number of bits per symbol
n = 256; % Number of bits to process
sps = 1; % Number of samples per symbol (oversampling factor)
上面的代码是将总binary长度,减为256
array_length=n/4% Create an array named input_data and fill it cyclically with numbers from 0 to 15
decimalArray = mod(0:array_length-1, 16);% Convert decimal array to binary array
binaryArray = dec2bin(decimalArray) - '0';
%swap columns
swappedBinaryArray = binaryArray(:, [4 3 2 1]);% Concatenate each line of binaryArray
%onerow_binaryArray = binaryArray_pose(:);
onerow_binaryArray = swappedBinaryArray(:);% Transpose the binary array to a column vector
%transposedBinaryArray = onerow_binaryArray.';dataIn = onerow_binaryArray;
这段花了不少时间,是因为这里面的矩阵的变换自己不是不熟,是完全不知道如何操作。。。
这一次是学明白了。
这段是为了得到可控的输出


然后我们直接到调制
Modulate Using 16-QAM
Use the qammod function to apply 16-QAM modulation to the dataSymbolsIn column vector for natural-encoded and Gray-encoded binary bit-to-symbol mappings.
dataMod = qammod(dataSymbolsIn,M,'bin'); % Binary coding with phase offset of zero
dataModG = qammod(dataSymbolsIn,M); % Gray coding with phase offset of zero
然后是开始Trace这个函数
在跟踪之前,不得不先学习格雷码。
关于格雷码(Gray Code),最好的文章是wikipedia的内容:https://en.wikipedia.org/wiki/Gray_code
还有一篇也不错:
QAM格雷码映射的规则(Gray Code Mapping in QAM)
自己biying
这句是得到自然码的调制后编码,
dataMod = qammod(dataSymbolsIn,M,‘bin’); % Binary coding with phase offset of zero
然后,下面这句是得到Gray的编码
dataModG = qammod(dataSymbolsIn,M); % Gray coding with phase offset of zero
汇总后见下图:

然后,进入matlab的qammod函数:
从这里
[y, const] = comm.internal.qam.modulate(x, M, symbolOrder, symbolOrderVector, ...bitInput, unitAveragePower, outputDataType);
function y = processIntInput(x, M, symbolOrder, symbolOrderVector, const)msg = processSymbols(x, M, symbolOrder, symbolOrderVector);y = lookupTable(const, msg);
end
function [y, const] = modulate(x, M, symbolOrderStr, ...symbolOrderVector, bitInput, unitAveragePower, outputDataType)y = processIntInput(x, Mnew, symbolOrderStr, symbolOrderVector, newConst);
end
重点是这句:
y = lookupTable(const, msg);
function y = lookupTable(table, x)y = coder.nullcopy(zeros(size(x),'like',table));y(:) = table(x + cast(1,'like',x));
end
重点是这句:
y(:) = table(x + cast(1,'like',x));
-
cast(1,'like',x): This part casts the value1to the same data type as the input variablex. This is necessary to ensure that the indexing operation doesn’t cause any type mismatches. -
x + cast(1,'like',x): This adds 1 to each element of the input vectorx. -
table(x + cast(1,'like',x)): This indexes thetablearray using the modified values ofx + cast(1,'like',x). It effectively looks up values in thetablecorresponding to the modified indices. -
y(:) = table(x + cast(1,'like',x));: This assigns the values obtained from the lookup to the entire vectory. The(:)syntax is used to linearizeyinto a column vector.
Let’s walk through an example:
- Original
xvalues: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] - Modified indices: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
- Values from the
tablecorresponding to the modified indices: [-3 + 1i, -3 - 1i, -3 - 3i, -1 + 3i, -1 + 1i, -1 - 1i, -1 - 3i, 1 + 3i, 1 + 1i, 1 - 1i, 1 - 3i, 3 + 3i, 3 + 1i, 3 - 1i, 3 - 3i]
So, the resulting y would be the values obtained from the table using the modified indices. The purpose seems to be to perform a table lookup operation using the input vector x to generate the output vector y.
解调的部分
注意,条件检查的部分,我省略了,实际我也是详细看了的,写得很精妙!
Demodulate 16-QAM
Use the qamdemod function to demodulate the received data and output integer-valued data symbols.
dataSymbolsOut = qamdemod(receivedSignal,M,'bin');
dataSymbolsOutG = qamdemod(receivedSignalG,M);function x = qamdemod(y, M, varargin) x = comm.internal.qam.demodulate(y, M, symbolOrderStr, symbolOrderVector, unitAveragePower, ...outputType, noiseVar);
end
function x = demodulate(y, M, symbolOrderStr, symbolOrderVector, ...unitAveragePower, outputType, noiseVar)intX = computeHardInt(y, Mnew);
这里是关键函数
function z = computeHardInt(y, M)if isa(y,'single')z = coder.nullcopy(zeros(size(y), 'single'));elsez = coder.nullcopy(zeros(size(y), 'double'));endif mod(log2(M), 2) % Cross constellation, including M=2const = comm.internal.qam.getSquareConstellation(M);z(:) = genqamdemod(y,const);else % Square constellation, starting with M=4% Precompute for later usesqrtM = sqrt(M);% Inphase/real rail% Move the real part of input signal; scale appropriately and round the% values to get index ideal constellation pointsrIdx = round( ((real(y) + (sqrtM-1)) ./ 2) );% clip values that are outside the valid rangerIdx(rIdx < 0) = 0;rIdx(rIdx > (sqrtM-1)) = sqrtM-1;% Quadrature/imaginary rail% Move the imaginary part of input signal; scale appropriately and round% the values to get index of ideal constellation pointsiIdx = round(((imag(y) + (sqrtM-1)) ./ 2));% clip values that are outside the valid rangeiIdx(iIdx < 0) = 0;iIdx(iIdx > (sqrtM-1)) = sqrtM-1;% compute output from indices of ideal constellation pointsz(:) = sqrtM-iIdx-1 + sqrtM*rIdx;end
end
computeHardInt中,这两句是重点
% Inphase/real rail% Move the real part of input signal; scale appropriately and round the% values to get index ideal constellation pointsrIdx = round( ((real(y) + (sqrtM-1)) ./ 2) );% Quadrature/imaginary rail% Move the imaginary part of input signal; scale appropriately and round% the values to get index of ideal constellation pointsiIdx = round(((imag(y) + (sqrtM-1)) ./ 2));
格雷码,并没有多大不同,调制是后处理,解调是前处理,将数据重新映射。
以上是所有的内容。
可惜这个例子只有基带的处理,没有信号的调制与解调。
是为遗憾。
希望再找个更全面的例子。
后记
写完才想起来这个例子,很前显有一个向导栏:

分别为:Use Pulse Shaping on 16-QAM Signal
和 Use Forward Error Correction on 16-QAM Signal(Step 3 of 3 in Compute BER for QAM System with AWGN Using MATLAB )
因为还没有看,所以不做评述。但是看来这个例子,应该是比较全面的。不仅仅是编解码。
相关文章:
Matlab示例-Examine 16-QAM Using MATLAB学习笔记
工作之余学习16-QAM 写在前面 网上看到许多示例,但一般都比较难以跑通。所以,还是老方法,先将matlab自带的例子研究下。 Examine 16-QAM Using MATLAB Examine 16-QAM Using MATLAB 或者,在matlab中,键入&#x…...
ArcGIS Pro SDK运行消息只提示一次
工具大部分都是异步执行,所以提示信息需要异步执行完再进行,所以注意async和await的使用。 相关async和await的文章请查看C# 彻底搞懂async/await_c# async await-CSDN博客 public async Task InformationPrompt() {string message String.Empty;await ArcGIS.De…...
通话状态监听-Android13
通话状态监听-Android13 1、Android Telephony 模块结构2、监听和广播获取通话状态2.1 注册2.2 通话状态通知2.3 通话状态 3、通知状态流程* 关键日志 frameworks/base/core/java/android/telephony/PhoneStateListener.java 1、Android Telephony 模块结构 Android Telephony…...
无懈可击的防泄密之旅:迅软DSE在民营银行的成功实践
客户简要介绍 某股份有限公司主体是中部地区的民营银行,由其母公司联合9家知名民营企业共同发起设立。正式开业于2016年,紧紧围绕目标产业生态圈和消费金融,着力打造产业银行、便捷银行、数字银行、财富管理银行为一体的BEST银行,…...
【送书活动】智能汽车、自动驾驶、车联网的发展趋势和关键技术
文章目录 前言01 《智能汽车》推荐语 02 《SoC底层软件低功耗系统设计与实现》推荐语 03 《SoC设计指南》推荐语 05 《智能汽车网络安全权威指南(上册)》推荐语 06 《智能汽车网络安全权威指南(下册)》推荐语 后记赠书活动 前言 …...
不同版本QT使用qmake时创建QML项目的区别
不同版本QT使用qmake时创建QML项目的区别 文章目录 不同版本QT使用qmake时创建QML项目的区别一、QT5新建QML项目1.1 目录结构1.2 .pro 文件内容1.3 main.cpp1.4 main.qml 二、QT6新建QML项目2.1 目录结构2.2 .pro文件内容2.3 main.cpp2.4 main.qml 三、两个版本使用资源文件的区…...
【PHP入门】1.1-PHP初步语法
-PHP语法初步- PHP是一种运行在服务器端的脚本语言,可以嵌入到HTML中。 1.1.1PHP代码标记 在PHP历史发展中,可以使用多种标记来区分PHP脚本 ASP标记: <% php代码 %>短标记: <? Php代码 ?>,以上两种…...
如何在jenkins容器中安装python+httprunner+pytest+git+allure(一)
背景: API接口自动化使用python语言实现,利用httprunner框架编写自动化用例场景(执行的时候还是依赖pytest),使用jenkins自动构建git上的源代码,并产生allure报告可视化展示API执行结果。 步骤 1.进入jenkins容器 注意使用roo…...
Android终端模拟器Termux上使用Ubuntu
Termux 上安装各种 Linux 系统是通过 proot-distro 工具来实现的,所以先安装一下 proot-distro 工具。 ~ $ pkg install proot-distro 查看Termux支持安装那些Linux ~ $ proot-distro listSupported distributions:* Alpine LinuxAlias: alpineInstalled: noComme…...
【神器】wakatime代码时间追踪工具
文章目录 wakatime简介支持的IDE安装步骤API文档插件费用写在最后 wakatime简介 wakatime就是一个IDE插件,一个代码时间追踪工具。可自动获取码编码时长和度量指标,以产生很多的coding图形报表。这些指标图形可以为开发者统计coding信息,比如…...
UML统一建模语言
一、建模语言的背景: 通俗地阐述就是:客户一开始不知道要什么,开发通过客户的阐述进行理解和分析,这个过程中间可能会产生一些误解。为了避免此类事件,所以需要建模。类似于要建造一栋楼,建筑设计师根据住…...
Linux命令行控制小米电源开关
飞灵科技产品 flyelf-tech.com,flyelf.taobao.com 最近有需求通过命令控制局域网内小米电源开关,以便于写脚本对产品进行反复上电的启动测试。参考了这篇文章:https://blog.csdn.net/2301_77209380/article/details/129797846 获取小米设备的…...
docker nginx 部署静态网站
1、dockerfile FROM nginx AS baseWORKDIR /appEXPOSE 80COPY . /app2、dockercompose.yaml version: 3 services:adminservice:container_name: adminwebbuild:context: ./dockerfile: Dockerfileports:- "5000:80"labels:description: adminwebrestart: always3、…...
uniapp之屏幕右侧出现滚动条去掉、隐藏、删除【好用!】
目录 问题解决大佬地址最后 问题 解决 在最外层view上加上class“content”;输入以下样式。注意:两个都必须存在在生效。 .content {/* 跟屏幕高度一样高,不管view中有没有内容,都撑开屏幕高的高度 */height: 100vh; overflow: auto; } .content::-webkit-scrollb…...
Linux 系统开机启动流程
可能没有完全理解,后期整理完Linux的内容,应该理解会深入一些,试着用更简洁的方式和图形来记录,以及一些概念的完善 2023-12-14 一、开机流程 BIOS MBR/GPT 加载 BIOS 的硬件信息与进行自检,并依据设定取得第一个可…...
vue2源码解析---watch和computed
监听属性watch 监听属性介绍 我们可以使用 watch 函数在每次响应式状态发生变化时触发回调函数wach 可以用于异步任务 监听属性的初始化 watch和computed都先走initSate判断传入选项 export function initState(vm) {const opts vm.$options; // 获取所有的选项if (opts.…...
【云原生】华为云踩坑日志(更新于2023.12.10)
1、华为云建议我们把sfs容量型升级到turbo版本,但是CCE产品storageclass sfs-turbo共享存储卷不支持动态绑定,官网文档可以实现动态创建子目录,建议大家直接选择这个,不要踩坑了 2、CCE 涉及到的产品,有的需要查看产品…...
计算机网络:自顶向下第八版学习指南笔记和课后实验--网络层(控制平面)
网络层:控制平面 记录一些学习计算机网络:自顶向下的学习笔记和心得 Github地址,欢迎star ⭐️⭐️⭐️⭐️⭐️ 控制平面作为一种网络范围的逻辑,不仅控制沿着从源主机到目的主机的端到端路径间的路由器如何转发数据报,而且控制…...
MFC 窗口创建过程与消息处理
目录 钩子简介 代码编写 窗口创建过程分析 消息处理 钩子简介 介绍几个钩子函数,因为它们与窗口创建工程有关 安装钩子函数 HHOOK SetWindowsHookExA([in] int idHook,[in] HOOKPROC lpfn,[in] HINSTANCE hmod,[in] DWORD dwThreadId ); 参数说明…...
基于JavaWeb+SSM+Vue微信小程序的移动学习平台系统的设计和实现
基于JavaWebSSMVue微信小程序的移动学习平台系统的设计和实现 源码获取入口Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 Lun文目录 第1章 绪论 1 1.1 课题背景 1 1.2 课题意义 1 1.3 研究内容 2 第2章 开发环…...
【OFDM通信】基于matlab室内NOMA-OFDM-VLC系统仿真【含Matlab源码 15240期】
💥💥💥💥💥💥💞💞💞💞💞💞💞💞欢迎来到海神之光博客之家💞💞💞Ὁ…...
51单片机之按键控制RGB灯
51单片机之按键控制RGB灯描述:利用KEIL5编程,使AT89C52通过按键输入控制RGB灯显示不同颜色。硬件:电路仿真图(未运行)电路仿真图(运行)程序:主要是按键消抖,机械按键按下…...
3步解锁B站Hi-Res音频:使用BilibiliDown开源工具轻松获取无损音乐
3步解锁B站Hi-Res音频:使用BilibiliDown开源工具轻松获取无损音乐 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/g…...
龙虾为啥越养越贵,越用越蠢?极客老王揭秘Agent落地真相
进入2026年3月,科技圈的舆论风向标发生了一次剧烈偏移。曾经被誉为开启“AI代驾”时代的超级智能体OpenClaw(俗称“龙虾”),在经历了一年的野蛮生长后,正陷入一场空前的信任危机。根据最新的行业调研数据显示ÿ…...
【风电功率预测】到了2026年,企业为什么总输在“最后一公里”?从气象到功率再到电力交易,少赚的钱到底丢在哪
2026年,风电行业已经进入一个非常现实的新阶段。过去,很多企业讨论风电功率预测,核心问题还是“预报准不准”。而到了今天,这个问题虽然仍然重要,却已经不是决定收益高低的唯一变量。真正拉开差距的,是企业…...
CAN FD通信中,如何用AUTOSAR配置搞定TDC和SSP?一个80% Offset的实战案例
CAN FD通信中AUTOSAR配置实战:TDC与SSP的80% Offset实现 在汽车电子领域,CAN FD(Controller Area Network Flexible Data-rate)正逐步取代传统CAN总线,成为车载网络的主流选择。随着数据传输速率提升至2Mbps甚至更高&a…...
小白也能玩转的AI语音合成:超级千问语音世界快速体验报告
小白也能玩转的AI语音合成:超级千问语音世界快速体验报告 1. 初识超级千问语音世界 第一次打开超级千问语音世界,我仿佛穿越回了童年玩红白机的时代。复古的像素风界面、跳跃的蘑菇按钮、会移动的小乌龟,这哪里是AI工具,分明是个…...
Downr1n iOS降级与越狱实战指南:从问题诊断到解决方案
Downr1n iOS降级与越狱实战指南:从问题诊断到解决方案 【免费下载链接】downr1n downgrade tethered checkm8 idevices ios 14, 15. 项目地址: https://gitcode.com/gh_mirrors/do/downr1n 一、决策指南:为什么选择Downr1n? 1.1 核心…...
Cadence Virtuoso仿真避坑指南:从网表生成到FFT分析的20个常见错误解决方案
Cadence Virtuoso仿真避坑指南:从网表生成到FFT分析的20个常见错误解决方案 在集成电路设计领域,Cadence Virtuoso作为行业标准工具链的核心组件,其仿真功能的正确使用直接关系到设计效率与结果可靠性。本文将系统梳理从网表生成到FFT分析全流…...
DeepSeek-Coder-V2技术深度解析:从Mixture-of-Experts架构到企业级部署
DeepSeek-Coder-V2技术深度解析:从Mixture-of-Experts架构到企业级部署 【免费下载链接】DeepSeek-Coder-V2 项目地址: https://gitcode.com/GitHub_Trending/de/DeepSeek-Coder-V2 在代码智能领域,开源模型长期面临着性能与闭源商业模型之间的巨…...
