简介:面向无线通信与信号处理领域工程师,针对在MATLAB中生成IQ波形数据文件、下载至安捷伦信号源并直接利用其IQ调制功能回放波形的常见需求,提供一套可直接运行的脚本与调用示例,适合实验室信号生成、教学演示与通信系统验证等场景。资源共19个文件,以10个m脚本为主,辅以7个p加密函数、1个dll动态库和1个chm帮助文档,压缩包仅94KB,结构紧凑、职责明确。已有572人学习下载。内容完整覆盖波形生成(涉及qammod、fskmod等调制函数及加噪处理)、数据二进制导出(fwrite/save)、基于GPIB/USB/以太网的设备连接与文件下发流程,并提供my_test01.m等调用样例及Agilent信号源辅助说明,可帮助读者快速掌握从MATLAB仿真到实际硬件回放的搭建与调试方法。
1. 用MATLAB生成波形文件,下载到安捷伦信号源,用IQ调制回放
实验室里经常出现这样的需求:需要给接收机灌一段自定义干扰,或者复现一个现场抓到的瞬态信号,但标准信号源没有这个调制模板。常见做法是在MATLAB里把复数基带样本算出来,量化成交错排列的I/Q整数数据,按安捷伦信号源认识的二进制格式写成一个波形文件,然后通过网络口送到信号源内部磁盘,再用信号源自带的ARB和IQ调制功能把波形搬到射频上。这套流程不需要另外买波形编辑软件,也不需要电脑和信号源之间接任何私有硬件。适合MXG、ESG、PSG这类带基带发生器和I/Q调制器的矢量信号源,普通只支持AM/FM的模拟信号源做不了。下面按我实际走通的顺序,把文件格式、MATLAB代码、下载命令和回放参数整体过一遍。
2. 波形文件格式先定住:IQ交织、16位整数和字节序
2.1 ARB模块只认样本,不认调制格式
信号源里的任意波形发生器,本质就是把一串数字样本按固定时钟送给DAC。I路样本和Q路样本分别被还原成模拟电平,再进入I/Q调制器,与本地振荡器信号混频后输出到射频口。所以信号源内部并不关心这串样本原来代表QPSK还是OFDM,它只关心一件事:每个样本时刻,I路和Q路各应该是多少伏。
这意味着波形文件里不需要存符号率、滤波器滚降系数、调制方式这些“元数据”。这些信息要么被MATLAB提前折算进样本里,要么在信号源回放时由你通过面板或SCPI命令另行指定。这一点被很多人忽略:明明波形文件是对的,回放时却因为ARB时钟设置和MATLAB里生成样本时用的采样率不一致,导致信号在频率轴上整体漂移或者带宽不对。
2.2 安捷伦不同型号的波形文件差异不小
我习惯先按“交织int16”这个最大公约数来写:I样本和Q样本交替排列,每个样本用16位整数存储,采用Intel小端字节序。这个规则在老一代ESG和后来的MXG上基本都能用。区别主要在文件名的磁盘路径、是否有文件头,以及SCPI命令的根路径上。
| 平台 | 常见后缀 | 数据组织 | 文件头 | 常用装载命令 |
|---|---|---|---|---|
| 老ESG/PSG | .bin | I/Q交错,int16 | 可选,通常不加 | :SOUR:DM:WAV "D:\WAVEFORM\xxx.bin" |
| MXG/EXG | .bin | I/Q交错,int16 | 一般不要 | :SOUR:RAD:ARB:WAV "D:\WAVEFORM\xxx.bin" |
| 新平台自家格式 | .wfm | 带节点头 | 必须 | :RAD:ARB:WAV "D:\WAVEFORM\xxx.wfm" |
一个可靠的办法:第一次使用某台具体型号时,先在仪器面板上生成一个内置演示波形,保存成.bin,再用十六进制编辑器打开看前几十个字节。如果开头有一串非零头部,说明该型号默认需要文件头;如果直接就是I/Q样本,说明裸交错数据就能用。把这一步记进实验记录本,后面写MATLAB脚本时就不用反复试。
2.3 一条最简的波形文件生成命令
为了验证链路通不通,我会先用单音而不是复杂调制信号。单音结果最容易判断:频谱仪上应当只在载频偏移的位置看到一根谱线。
Fs = 40e6; % 回放时的ARB采样率,文件本身不记录这个值 n = 8000; % 样本点数,回放时长 = n / Fs t = (0:n-1).' / Fs; f0 = 2e6; % 2 MHz 单音 iq = 0.8 * exp(1j * 2 * pi * f0 * t); lvl = 0.6; % 峰值余量系数 I = round(real(iq) * 32767 / max(abs(iq)) * lvl); Q = round(imag(iq) * 32767 / max(abs(iq)) * lvl); interleaved = zeros(1, 2*n); interleaved(1:2:end) = I; interleaved(2:2:end) = Q; fid = fopen('single_tone_2m.bin', 'wb'); fwrite(fid, interleaved, 'int16'); fclose(fid);这段代码先把复指数基带信号按峰值归一,再乘0.6的余量系数后转成int16。0.6是为了避免后面信号源内部做插值滤波时出现瞬时超量程;如果直接用到32767附近,波形虽然文件里没削波,但信号源DAC后级滤波时可能产生杂散。交错写入时,奇数位置放I路,偶数位置放Q路,这就是“IQ交织”四个字的含义。
提示:如果回放时发现单音频率不是2 MHz,而是跑到别处,先查信号源ARB采样率是否设成了40e6,不要急着怀疑文件格式。
3. 在MATLAB里构造IQ信号并量化成int16文件
3.1 用基带符号生成QPSK,sps决定回放带宽
单音验证通过后,就可以把代码换成真实调制信号。下面是QPSK基带生成的一段标准做法,尽可能减少对工具箱的依赖。
rng(1); numSym = 20000; bits = randi([0 1], 1, numSym*2); symIdx = 2 * reshape(bits, 2, []) .'; % 每两个bit对应一个星座点索引 symMap = [ 1+1i, -1+1i, -1-1i, 1-1i ] ./ sqrt(2); symbols = symMap(symIdx).'; sps = 16; % 每符号样本数 upsampled = zeros(1, numSym*sps); upsampled(1:sps:end) = symbols; % 成型滤波,避免频谱带外泄太大 h = rcosdesign(0.35, 8, sps, 'sqrt'); % 通信工具箱函数 tx = conv(upsampled, h, 'same');这里sps直接决定了回放带宽:符号速率等于ARB采样率除以sps。比如ARB采样率40 MHz、sps=16时,符号率为2.5 Msps,主瓣带宽约2.5 MHz,加上滚降后约占3.375 MHz。如果sps取得太小,比如sps=2,则在信号源内部重构滤波器带宽足够宽时,会看到更多频谱镜像。
rcosdesign属于通信工具箱。没有这个工具箱时,可以先用ones(1,sps)做零阶保持,也就是每个符号重复sps次。这样频谱会宽一些,但用来测试下载、回放和IQ调制链路没有任何问题。
3.2 峰值回退:把0.7的权重留给DAC
成型滤波之后,波形峰值会高于符号星座点的理论值。这是正常现象,成形滤波器本身会把能量向时间方向摊开,峰均比变高。如果直接把峰值映射到32767,那么大量样本会非常接近满码,后续信号源内部的插值滤波器稍微过冲就会削波。
我一般会预留2到3 dB峰值余量,对应线性系数0.6到0.8之间。
peak = max(abs(tx)); scaled = tx * (0.7 / peak); % 峰值约等于0.7倍满码 I = round(real(scaled) * 32767); Q = round(imag(scaled) * 32767); % 对超过int16范围的值再做一次防溢出保护 I(I > 32767) = 32767; I(I < -32768) = -32768; Q(Q > 32767) = 32767; Q(Q < -32768) = -32768;峰值余量不是越高越好。系数取0.3时虽然绝对不削波,但小信号区只用到int16的动态范围很小一部分,量化噪声占比上升,星座图点会明显变散。调试时先用0.7,再根据频谱仪观察到的杂散水平和星座图EVM做微调。
| 参数 | 推荐起始值 | 影响 |
|---|---|---|
| ARB采样率 Fs | 40 MHz | 决定信号带宽范围和回放时长 |
| sps | 16 | 决定符号率,带外镜像随sps降低而变差 |
| 峰值余量 | 0.7 | 余量越小动态越好,但削波风险越大 |
| 样本点数 | 符号数×sps | 回放时长等于点数除以Fs |
3.3 交织写入与回读验证
把I和Q交错写入文件,然后立刻用MATLAB读回来比对,这一步能提前拦截字节序和数组长度错误。
iqm = zeros(1, 2*numel(I)); iqm(1:2:end) = I; iqm(2:2:end) = Q; fid = fopen('qpsk_rrc_40m.bin', 'wb'); fwrite(fid, iqm, 'int16'); fclose(fid); % 回读比对 fid = fopen('qpsk_rrc_40m.bin', 'rb'); chk = fread(fid, inf, 'int16'); fclose(fid); I2 = chk(1:2:end); Q2 = chk(2:2:end); if isequal(I2, I(:)') && isequal(Q2, Q(:)') disp('文件写入和回读一致'); else error('I/Q数据回读不一致'); end如果这里已经不一致,通常是数组形状问题:I是行向量还是列向量,交错后长度有没有按元素数量计算。MATLAB的isequal在比较int16和double时不会自动判等,所以读取时需要直接按int16读入,再和写入前的I、Q做类型一致的比较。
提示:不要在写入文件前把
I和Q转换成double矩阵。fwrite按int16格式写入时,只取低16位,浮点小数部分会被截断,看起来没报错,但回放时波形幅度是错的。
4. 下载到安捷伦信号源:网络连接、FTP和SCPI
4.1 先用visadev把SCPI通道打开
信号源和电脑连到同一个网段,然后确认面板上的LAN服务已经启动。MATLAB从R2023b开始推荐用visadev替代旧的visa函数。R2023b之前仍然可以用tcpip直接连SCPI端口,但用visadev更省事。
v = visadev("TCPIP0::192.168.1.100::inst0::INSTR"); writeline(v, "*IDN?"); identity = readline(v); disp(identity);如果visadev执行后提示无法找到VISA驱动,检查是否安装了Instrument Control Toolbox,以及系统环境里是否有Keysight IO Libraries套件。只装NI-VISA也行,但路径名要写visadev("visa","ni","TCPIP0::..."),写法会繁琐一点。
4.2 FTP上传波形文件到信号源磁盘
安捷伦中高端信号源自带FTP服务,不需要额外开启。FTP的本质就是快速把整个文件完整送进仪器内部磁盘,而SCPI二进制块传输更适合小文件,FTP对大波形文件的稳定性和速度都更好。
f = ftp('192.168.1.100'); % 会提示输入用户名密码,一般留空或用anonymous cd(f, '/usr/waveform'); % 不同型号可能映射为 /internal 或 /D: mput(f, 'qpsk_rrc_40m.bin'); close(f);登录后先执行dir(f)看一下目录结构,找到包含waveform、wfm或者user的目录。有些老型号的磁盘路径显示为D:\WAVEFORM,在FTP里则显示成/usr/waveform。上传完成后可以用仪器的文件管理界面看到这个文件。
4.3 用SCPI把波形文件装载到ARB
文件上传只代表文件存在于磁盘上,还没进入ARB的播放列表。装载的SCPI命令因平台差异较大,但核心思路一致:先指定文件路径,再打开ARB状态。
writeline(v, ':SOUR:RAD:ARB:WAV "D:\\WAVEFORM\\qpsk_rrc_40m.bin"'); writeline(v, ':SOUR:RAD:ARB:STAT ON'); % 查询一路错误状态,确认命令被接受 err = writeread(v, ':SYST:ERR?'); disp(err);:SYST:ERR?返回的是错误队列里的最新一条。如果返回0,"No error",说明路径和语法都对了。如果返回路径相关错误,多半是FTP上传时目录放错,或者文件名里的反斜杠在SCPI字符串里没有转义。
4.4 触发模式:连续、单次和外部触发
ARB回放默认是连续循环,也就是文件里的样本反复输出。做长时间接收测试时这没问题,但如果要复现一次性的瞬态信号,需要把触发改成单次或外部触发。
% 连续循环回放 writeline(v, ':SOUR:RAD:ARB:TRIG:SOUR IMM'); % 外部触发回放 writeline(v, ':SOUR:RAD:ARB:TRIG:SOUR EXT'); % 总线触发,用 *TRG 命令启动一次回放 writeline(v, ':SOUR:RAD:ARB:TRIG:SOUR BUS'); writeline(v, '*TRG');外部触发信号一般从信号源后面板的Event 1或Trigger接口接入。触发沿极性、触发延迟也可以在SCPI里设置,但前期测试用默认配置就够。特别提醒:外部触发需要把触发源设置成EXT,否则即使后面板给信号也不会开始回放。
5. 打开信号源IQ调制回放:参数顺序与验证
5.1 IQ调制和ARB不是两个孤立选项
很多人误以为“IQ调制”是信号源里的一个独立开机选项,其实对ARB模式来说,基带I/Q样本送入I/Q调制器本身就是工作方式。面板上手机会看到类似I/Q Mod或ARB的独立按键,但底层是同一套链路:ARB存储器里的样本经过DAC,进入I/Q调制器,再经射频链路输出。
因此回放前要把几个参数设置成一组:载波频率、输出电平、ARB采样率、触发模式。载波频率和输出电平属于射频层,ARB采样率属于基带层。基带采样率决定了波形文件里的样本在时间轴上怎么被解释,这一步最容易被漏掉。
5.2 回放前的四类参数和最小SCPI脚本
实际用MATLAB一次把这些参数下发完成,顺序建议先频率后电平,再ARB采样率和波形文件,最后打开射频输出。
v = visadev("TCPIP0::192.168.1.100::inst0::INSTR"); writeline(v, "*RST"); % 恢复默认 writeline(v, ':FREQ 2.45e9'); % 射频载波 writeline(v, ':OUTP:STAT?'); % 默认输出为OFF writeline(v, ':POW -5'); % 输出功率,dBm writeline(v, ':SOUR:RAD:ARB:SCLO:RATE 40e6'); % ARB样本率 writeline(v, ':SOUR:RAD:ARB:WAV "D:\\WAVEFORM\\qpsk_rrc_40m.bin"'); writeline(v, ':SOUR:RAD:ARB:TRIG:SOUR IMM'); % 连续回放 writeline(v, ':SOUR:RAD:ARB:STAT ON'); % 打开ARB调制 writeline(v, ':OUTP ON'); % 打开射频载波输出这段脚本里,ARB采样率设为40 MHz,与MATLAB生成波形时的Fs一致。:SOUR:RAD:ARB:STAT ON会启动基带ARB引擎;:OUTP ON打开的是射频口总开关。顺序不能反过来,不然会出现射频口先输出纯净载波,等ARB启动后波形才滞后出现的情况。
| SCPI命令 | 用途 | 典型值 |
|---|---|---|
:FREQ | 设置射频载波频率 | 2.45e9 |
:POW | 设置输出功率 | -5 dBm |
:SOUR:RAD:ARB:SCLO:RATE | 设置ARB采样率 | 40e6 |
:SOUR:RAD:ARB:WAV | 选择波形文件 | D:\WAVEFORM\qpsk_rrc_40m.bin |
:SOUR:RAD:ARB:TRIG:SOUR | 设置触发源 | IMM/EXT/BUS |
:SOUR:RAD:ARB:STAT | 使能ARB | ON |
:OUTP | 射频输出总开关 | ON |
5.3 用频谱仪和星座图确认波形播对了
第一次回放建议先观察频谱。QPSK加根升余弦滤波后,频谱带宽大约等于符号率乘以(1+滚降系数)。按上面参数,符号率2.5 Msps、滚降0.35,主瓣宽度约3.25 MHz。如果频谱宽度和预设不符,优先怀疑ARB采样率设置。
第二层验证是功率。用频谱仪读取信道功率,和信号源面板显示输出功率做对照。如果差得比较多,检查波形文件峰值余量是否过小,ARB内部是否出现削波。
第三层验证是解调。手里有矢量信号分析仪时,把信号源输出的2.45 GHz信号接入分析仪,设置符号率2.5 Msps和QPSK解调类型,直接看星座图。星座点若出现明显扩散,除了量化噪声外,最常见的原因是信号源内部基带增益没有配合好,导致输出功率偏高,后级放大出现压缩。把POW往回减3到5 dB再观察。
5.4 几个典型异常和处理
| 现象 | 可能原因 | 处理方向 |
|---|---|---|
| 频谱带宽变成设定值的两倍 | ARB采样率实际为80 MHz,代码按40 MHz生成 | 查ARB时钟是否被外部参考源倍频 |
| 中心频率位置出现强载漏 | I/Q直流偏置不为零 | 波形数据里减去直流分量,或用仪器I/Q校准功能 |
| 星座点呈环状扩散 | 信号源驱动放大器饱和 | 降低输出功率,或减小波形峰值余量 |
| 单音回放变噪声底 | int16字节序反了 | 写入时改用big-endian,或检查下载流程是否被文本模式破坏 |
提示:如果信号源菜单里看到
I/Q Cal或I/Q Adjust,回放前先跑一遍内置校准,特别是长期没使用过的仪器。I/Q相位不平衡和镜频抑制会直接影响EVM。
6. 波形回放再省心的几个小技巧
6.1 波形长度与回放时钟对齐,避免跳变
ARB循环回放时,文件尾和文件头会首尾相接。如果波形不是整数个周期,切换瞬间会看到相位跳变,频谱仪上表现为最大保持谱线旁边多出一圈毛刺。生成单音或连续调制信号时,我习惯保证n * f0 / Fs是整数,其中f0是希望预置到射频偏移处的信号频率。
Fs = 40e6; f0 = 2.5e6; % 2.5 MHz偏置 periods = 100; % 整数周期 n = round(periods * Fs / f0); t = (0:n-1).' / Fs; iq = exp(1j * 2 * pi * f0 * t);这样循环回放时波形首尾相位相同,频谱干净。对QPSK这类调制信号,让总样本数是符号周期整数倍,同时符号数也是整数,就能避免末尾半个符号。
6.2 给波形尾部留静默样本
做触发回放时,接收端示波器或采集卡需要提前启动才能抓到完整波形。我会在文件末尾追加一段全零I/Q样本,长度相当于几个符号周期。这样外部触发启动后,先经过一段静默区,再进入真正的数据区,采集设备有足够时间锁定触发点,也不会把触发毛刺误当成信号起始点。
6.3 SCPI二进制块上传的适用场景
FTP适合几MB以上的大文件。但如果只是临时传一个几百KB的测试文件,也可以直接用SCPI二进制块,不用来回切FTP工具。注意visadev的write方法可直接发送uint8数组,避免文本通道把二进制中的NUL字节吃掉。
fid = fopen('qpsk_rrc_40m.bin', 'rb'); raw = fread(fid, inf, 'uint8')'; fclose(fid); n = numel(raw); header = sprintf(':MMEM:DATA "D:\\WAVEFORM\\qpsk_rrc_40m.bin", #%d%d', ... numel(num2str(n)), n); write(v, uint8([uint8(header), raw]));这条命令把文件内容作为SCPI二进制块直接写入信号源磁盘。命令头中的#后第一位数字表示长度占几位,第二段是实际长度,冒号后面是文件路径。执行后再用:SYST:ERR?确认没有错误,就可以按正常流程装载到ARB。
平时我把这三招固定进MATLAB生成脚本里:波形长度对齐周期、尾部留静默区、统一走FTP上传。这样每次生成完文件,后续下载和回放基本不需要再盯现场。
本文还有配套的精品资源,点击获取