简介:基于MATLAB的安捷伦信号源波形生成与回放工程方案,面向射频测试、通信系统验证与信号分析场景的工程师和科研人员。利用该方案可在MATLAB中生成自定义波形数据文件,下载到安捷伦信号源后,直接调用内置IQ调制功能完成回放,省去手动配置和底层编程。压缩包共21个文件,包括10个m格式脚本、7个p格式辅助函数,以及使用说明文档、帮助手册和动态库,整体体积仅98KB;目前已有137人学习,适合有MATLAB基础、希望掌握信号源波形下载与回放流程的中级用户。代码提供清晰的主函数与调用函数入口,替换数据或调整参数即可复现波形;配套说明文档详细讲解从文件加载、VISA连接配置到波形写入、IQ调制回放的完整步骤,并给出常见连接异常排查思路。该工具包可用于雷达信号生成、通信信号检测等方向,兼顾理论与工程实践。
1. 与其打开 Signal Studio 点半天,不如让 MATLAB 生成好波形直接推给安捷伦信号源
做射频测试时,信号源要不要用 Signal Studio 配置数字调制,很多人已经分成两派。我用安捷伦信号源做雷达波形和通信基带验证时,最烦的就是打开上位机软件手动点符号、滤波器和文件格式,参数一变就要重来一遍。这个资源其实是一套 MATLAB 侧的波形生成和下载方案:先用 MATLAB 写出基带 IQ 采样数据,再通过 agt_* 函数和 agt_sgIOmx.dll 建立 VISA 会话,把数据下载到信号源的 ARB 文件系统,最后打开 IQ 调制功能回放。核心入口是 my_test01.m,配合使用说明文档.md 和 Download_Assistant.chm。适合做基带算法预验证、自动测试脚本集成,以及不想在界面操作上反复浪费时间的人。
2. 压缩包里到底放了什么:agt_* 函数、.p 伪代码和 IO DLL 的配合方式
2.1 从文件列表反推工具链
解压后第一眼会看到三类东西:一堆 agt_ 开头的 .m 文件、同名 .p 文件、一个 agt_sgIOmx.dll,还有 my_test01.m 和说明文档。agt_ 前缀不是随便起的,它是安捷伦为 MATLAB 用户提供的仪器驱动函数族,命名风格和 VISA 的“建立连接、发送命令、查询、关闭”一一对应。看文件名就能猜出链路:agt_newconnection 负责建会话,agt_sendcommand 发 SCPI 指令,agt_query 发查询并收结果,agt_waveformload 把波形数据下载到信号源,agt_setVisaTimeout 设置超时,agt_closeAllSessions 清理会话。
这些函数在包里分成两份:同名 .m 和 .p。普通 .m 可以直接打开看实现,适合学习;.p 是加密过的伪代码,MATLAB 在调用时会优先加载 .p 文件。对使用者来说不需要去改它们,只要保证 .m 和 .p 在同一个路径下,或者让 MATLAB 的当前文件夹指向解压目录。一个容易踩的坑是:如果同时存在相同文件名的 .m 和 .p,MATLAB 会优先执行 .p,你改了 .m 却不生效,运行的还是旧代码。
下面是根据文件列表整理出来的角色分工:
| 文件 | 类型 | 在整个链路里的作用 |
|---|---|---|
| my_test01.m | 示例脚本 | 生成测试用 IQ 数据并调用下载函数,是上手最好的起点 |
| agt_newconnection.m / .p | 驱动函数 | 与信号源建立 VISA/TCPIP 会话,返回会话句柄 |
| agt_waveformload.m / .p | 驱动函数 | 把 I/Q 数据写入信号源的波形文件 |
| agt_sendcommand.m / .p | 驱动函数 | 向信号源发送 SCPI 指令 |
| agt_query.m / .p | 驱动函数 | 发送查询指令并读取返回值 |
| agt_setVisaTimeout.m / .p | 驱动函数 | 设置当前会话的 VISA 超时时间 |
| agt_sgIOmx.dll | 本地库 | 封装底层 VISA/IO 操作,供上述函数调用 |
| Download_Assistant.chm | 离线文档 | 提供波形下载辅助说明和命令参考 |
| 使用说明文档.md | 文本说明 | 操作步骤和常见问题速查 |
注意到这里没有单独的 main.m,资源说明里那句“主函数 main.m”是泛称,实际可执行入口是 my_test01.m。把它当作模板,把数据替换成自己的就行。
2.2 为什么需要 DLL:VISA 层的那点事
过去在 MATLAB 里控制信号源,常见做法是装 Instrument Control Toolbox,再手动指定 VISA 地址。这个包的方案是绕开那些通用命令,直接用 agt_sgIOmx.dll 封装好的 IO 通道。DLL 负责和底层 VISA 库或 socket 通信,.m/.p 函数再把它封装成更方便的 MATLAB 调用形式。好处是你不用关心 Windows 下 VISA 函数的具体签名,缺点是如果 DLL 和目标信号源型号协议对不上,所有调用都会报“加载失败”。
实际使用时要保持 DLL 在解压目录里原位置,不要单独挪走。我习惯先把整个压缩包解到独立目录,再用addpath('D:\work\agt_waveform')加进 MATLAB 路径,然后运行:
% 第一次验证 DLL 和函数库是否就绪 session = agt_newconnection('TCPIP0::192.168.1.100::inst0::INSTR'); idn = agt_query(session, '*IDN?'); agt_closeAllSessions(); disp(idn);这段代码做了最基本的三件事:连接、查询仪器 ID、关闭会话。能返回类似 “Agilent Technologies, E4438C” 的字符串,说明 DLL 加载成功且协议握手正常。如果在这里报错,后面做波形下载多半也会失败,所以不要跳过这步。
2.3 先看 my_test01.m 再动手
所谓“小白也能上手”的真正含义是 my_test01.m 已经把连接、造数据、下载、回放串了一遍。打开它,你会看到类似这样的流程:先设置采样率和符号率,生成一组复数基带信号,然后用 agt_newconnection 连接,再用 agt_waveformload 写入,最后用 agt_sendcommand 打开输出。第一次跑建议把脚本里信号源 IP 改成你自己的;如果手边没有实机,只跑造数据部分,画出星座图,也能验证 MATLAB 端没有问题。
看代码时重点看三个变量:采样率 Fs、波形文件名、射频中心频率。采样率要和后续信号源设置的 ARB 采样率对应,否则回放时间会差好几倍。波形文件名做好事小,后面 SCPI 选中文件时全靠它。射频中心频率不影响波形文件内容,但会影响频谱仪上看到的信号位置。把这几个参数放在脚本最前面,后续改起来会轻松很多。
3. 先造出合格的 IQ 数据,再谈下载到信号源
3.1 基带 IQ 数据的生成与归一化
信号源回放的是基带 IQ 波形,不是在 MATLAB 里算好中频再直接送射频。安捷伦信号源内部有正交调制器,你给它的是 I 路和 Q 路的基带采样序列。因此第一步是生成一组复基带信号,实部给 I,虚部给 Q。下面是一段生成 QPSK 波形的常见做法,可以直接替换 my_test01.m 里的数据段:
% 参数定义 Fs = 50e6; % 采样率 50 MHz,要和信号源 ARB 采样率对应 symRate = 5e6; % 符号率 5 MSps sps = Fs / symRate; % 每符号样点数,这里等于 10 numSym = 2000; % 符号个数 % QPSK 符号映射:00,01,11,10 对应四个相位 data = randi([0 3], 1, numSym); sym = exp(1j * (pi/4 + data * pi/2)); % 零阶保持内插:把每个符号重复成 sps 个点 iq = reshape(repmat(sym, sps, 1), 1, []); % 归一化到 0.8,给后面的滤波和 DAC 留峰值余量 iq = iq / max(abs(iq)) * 0.8; % 检查星座图 plot(real(iq(1:sps*16)), imag(iq(1:sps*16)), '.'); axis equal; grid on;这段代码做了三件关键的事:映射、内插、归一化。映射决定了调制格式,QPSK 只是最简单的一种,改成 16QAM 时需要把 data 先拆成 4 bit 一组再查表。内插用简单的重复方式,实际系统建议换成升余弦滤波器成型,否则频谱会有大量带外分量。归一化是我特别要强调的:agt_waveformload 本质上会把浮点数据转成信号源内部定点格式,如果幅度超过 1 会被截断,产生削波噪底;如果太小则浪费 DAC 动态范围。0.8 是一个稳妥起点,后续功率控制配合调整。
3.2 agt_newconnection 建立 VISA 会话
数据准备好了,接下来要连到信号源。接口用 TCPIP 还是 GPIB,取决于你的实际接线。安捷伦信号源一般支持后面板 LAN,我推荐 TCPIP,线材简单且下载速度远快于 GPIB。连接调用常见写法:
% 根据实际 IP 改写,常见是 inst0 或 inst1 addr = 'TCPIP0::192.168.1.100::inst0::INSTR'; session = agt_newconnection(addr); % 连接后立刻设置超时,防止波形下载一半卡住 agt_setVisaTimeout(session, 30000);agt_newconnection的返回值是一个会话句柄,后面的 agt_sendcommand、agt_waveformload、agt_query 都要带上它。如果你的仪器使用 GPIB,地址字符串要改成GPIB0::1::INSTR这类格式。这里有个细节:安捷伦的 TCPIP 地址后面经常带::inst0::INSTR而不是简单的 IP,直接写 IP 在某些型号上会连接成功但无法下发文件,因为驱动需要完整的 VISA 资源字符串。调试时可以用agt_query(session, '*IDN?')验证连接是否被识别,能返回仪器型号字符串就说明通道是通的。
如果 agt_newconnection 卡住不返回,先 ping 信号源 IP 看网络通不通,再看信号源前面板 Remote Interface 里 LAN 是否使能。很多情况下是电脑和仪器不在同一网段,导致 MATLAB 侧看不到设备。
3.3 agt_waveformload 的输入格式与点数限制
连接建立后,核心一步是把 I/Q 数据交给 agt_waveformload:
% 下载到信号源内部文件系统的指定名称 filename = 'myqpsk.wfm'; agt_waveformload(session, filename, real(iq), imag(iq));agt_waveformload一般接受四个参数:会话句柄、波形文件名、I 路数组、Q 路数组。数组长度必须一致,类型可以是 double 数组,函数内部会做定点转换。波形文件名会写到信号源的存储介质中,之后的 SCPI 指令要用同样的文件名引用。文件名不要含中文和空格,WFM 后缀最好保留,信号源靠它区分波形类型。
这里最常见的报错是长度问题。ESG/PSG 系列对 ARB 波形点数有上限,超过上限会返回错误或直接截断。我一般先算一下:采样率 50 MHz、回放 1 ms,那就是 5 万点,属于安全范围;如果跑几百毫秒的长包,点数上到千万级,就要提前确认当前选件支持的最大点数。其次,I/Q 数组里不能有 NaN 或 Inf,DLL 在做格式转换时碰到非有限值会直接失败,错误提示有时很抽象,只显示 “waveform load failed”。所以造完数据建议先跑检查:
assert(~any(isnan(iq)) && ~any(isinf(iq)), 'IQ 数据包含非有限值');另一个容易忽略的点是:agt_waveformload可能要求在下载前先关闭 ARB 调制,否则文件被占用。稳健的序列是先agt_sendcommand(session, ':RADio:ARB:STATe OFF'),再下载,下载完成后再打开。下面一章会讲到如何编排这些 SCPI 指令。
4. 下载不是结束,接着用 SCPI 把 IQ 调制打开
4.1 用 SCPI 选择已经下载的波形文件
agt_waveformload 只是把文件写到信号源的 ARB 文件系统里。要让它真正从射频口出来,还必须告诉信号源“当前需要回放哪个波形文件,并按什么频率、功率输出”。这组操作全部通过 SCPI 完成,而 agt_sendcommand 就是你在 MATLAB 里发 SCPI 的通道:
% 画信号通道,先用 ARB 的波形名 agt_sendcommand(session, ':RADio:ARB:WAVeform "WFM1:myqpsk.wfm"'); agt_sendcommand(session, ':RADio:ARB:STATe ON'); agt_sendcommand(session, ':OUTPut:STATe ON');:RADio:ARB:WAVeform的参数是信号源内部波形文件路径。不同型号前缀不一样,常见的有WFM1:、INT:、RAM:,具体看仪器的文件系统。如果省略前缀,信号源会根据当前选择的介质找。很多人在这一步会不小心写错文件名,一旦不匹配,信号源可能不报错,但 ARB 会静默关闭,输出没有载波,看起来像“没有信号”。建议在下载后立刻用查询指令把当前波形名读回来核对。
顺序也很重要:先选波形,后开 ARB。原因是一旦 ARB 处于 ON,信号源会立刻按当前配置开始生成,如果波形还指向旧文件,会出现短时间错误输出。先选好文件再开调制,可以把中间状态降到最少。
4.2 频率、功率和 IQ 调制开关的配合
信号源本质上是一个复杂的射频链路,ARB 产生基带,IQ 调制器把它搬移到载波上。IQ 调制功能一般在 ARB ON 时默认参与,但某些信号源需要额外确认:OUTPut:MODulation:STATe没有被设为 OFF。常用的射频参数设置:
% 2.4 GHz 载波,0 dBm 输出 agt_sendcommand(session, ':FREQuency:FIXed 2.4e9'); agt_sendcommand(session, ':POWer 0'); % 确保 IQ 调制打开 agt_sendcommand(session, ':OUTPut:MODulation:STATe ON'); % 确认输出 agt_query(session, '*OPC?');*OPC?是 IEEE 488 通用操作完成查询,返回 1 说明前面所有指令都已执行完成。在自动测试里,这个查询用来做同步,千万不要省略,否则你紧接着用频谱仪采集,可能采集到的还是功率稳定之前的瞬态。:POWer 0设置目标输出功率为 0 dBm,但实际输出还受 ALC 模式和波形峰均比影响,测量时以频谱仪读数为准。
常用 SCPI 指令和实际作用:
| SCPI | 作用 |
|---|---|
| :FREQuency:FIXed | 设置载波频率 |
| :POWer | 设置输出功率 |
| :RADio:ARB:WAVeform | 选择当前 ARB 波形 |
| :RADio:ARB:STATe | 打开/关闭 ARB 发生器 |
| :OUTPut:MODulation:STATe | 打开/关闭调制输出 |
| :OUTPut:STATe | 总射频开关 |
参数单位方面,频率可以写2.4e9也可以写2.4GHz,功率直接给 dBm 数值即可。信号源 SCPI 解析器对这些后缀的处理方式不完全一致,为了减少歧义,我通常全部使用十进制数。
4.3 用频谱仪或信号源屏幕验证回放
配置完之后不要急着关代码。先用 agt_query 读回参数,确认不是你刚才写错的符号:
freq = agt_query(session, ':FREQuency:FIXed?'); pwr = agt_query(session, ':POWer?');再看信号源前面板的 Modulation On/Off 指示灯,有些型号会显示 ARB 运行状态。最直接的办法是接一根射频线到频谱仪,观察频谱中心频率、带宽和功率。如果是 QPSK 波形且符号率 5 MSps,配上根升余弦滤波,频谱宽度大约 5 MHz 量级;如果你看到的是窄一根线,说明波形没有被真正调制,多半是 ARB 没有运行或 IQ 调制被关闭。
提示:功率回读如果显示 unleveled,说明 ALC 环没能锁定,常见原因是频率很高但电平校准表缺失,或者回波频谱超过了大功率限值。先降到 0 dBm 以下再观察。
5. 波形下载失败,先查这三个地方
5.1 超时不是越大越好
agt_setVisaTimeout 控制 VISA 读操作的等待时间。波形文件下载通常需要把几百 KB 到几 MB 数据分成多个块连续发送,如果 VISA 超时太短,MATLAB 会在传输中途抛错。对几十 MB 的大波形,我一般给 60 秒到 120 秒。但超时不是越大越好,它会把真正的问题掩盖住。如果你的网线或 DLL 加载本来就有故障,超时设置成 300 秒意味着你要等五分钟才看到错误。正确做法是先设 5 秒,跑通小数据,再针对大文件调大。
5.2 波形点数、文件格式与内存占用
信号源回放波形文件时,I/Q 数据在机器内部是定点数。我的实践是尽量让数据在 -1 到 1 之间,峰值控制在 0.8 附近。点数方面,不同型号和选件差别很大,老的 E4438C 可能只支持 1 M 点,新的型号带大内存选件可到几百 M 点。下载前可以用agt_query(session, ':RADio:ARB:WAVeform:POINts?')查一下当前选件支持的最大点数,如果指令不支持返回错误,这本身也是判断选件的方式。点数超限时,可以在 MATLAB 里降采样,或把长包拆成多个波形文件,用序列功能衔接。
5.3 用 Download_Assistant.chm 和查询指令对行为
包里有个 Download_Assistant.chm,这不是摆设。它通常包含波形加载辅助说明、错误码解释和 SCPI 命令清单。当 agt_waveformload 返回一个负数或错误码时,去 chm 里搜对应错误码,比盲改代码高效得多。另外,善用 agt_query 判断故障边界:连接后查*IDN?,下载后查波形是否存在,输出前查*STB?状态字节。这样三步定位下来,问题基本不会出在仪器层。
最后一个技巧:my_test01.m 里下载和回放代码通常混在一起,你可以把它拆成两个脚本,一个 build_iq.m 负责造数据并保存.mat,另一个 play_wave.m 负责连接和下载回放。开发阶段反复跑下载时不必重新生成数据,也方便把基带算法和仪器操作分开验证。
本文还有配套的精品资源,点击获取