很多做嵌入式、通信以及FPGA开发的朋友,第一次接触“ADC、DAC、DDC、DUC、采样率、数据率”这一串名词时,基本都是懵的。ADC把模拟信号变成数字,DAC把数字变回模拟,这还好理解;但DDC和DUC夹在中间到底是干什么的?我明明设置了ADC采样率,数据率又是怎么算出来的?为什么同一颗ADC芯片,在不同人的板子上跑出来性能差一大截?
这篇文章就把这些概念放到一条真实的信号链路里去讲,从数字中频、软件无线电、单片机采集这几个常见场景出发,把ADC/DAC、DDC/DUC、采样率、数据率这些基础概念彻底理顺,再分享一些我在时钟、电源、PCB布局上踩过的坑。适合刚接触信号链的工程师,也适合做嵌入式或FPGA开发、想把这些概念系统搞明白的读者。
1. 先把ADC和DAC的角色放对位置
一条最简单的信号链路是这样:传感器或射频前端出来的模拟信号,经过ADC变成数字,交给处理器或FPGA处理;处理完的数字信号,经过DAC再变回模拟,去驱动功放、喇叭或者执行器。ADC/DAC就像模拟世界和数字世界之间的两扇门,这个位置关系如果你已经清楚,那接下来要聊的DDC/DUC就只是门后面多出来的两道工序,一点都不神秘。
真正让人头疼的是,很多人把“采样率”“数据率”“带宽”这几个词混在一起用,导致后面算接口速率、选FPGA资源、判断系统瓶颈的时候全乱套。所以第一步,先把这三个量彻底分清。
1.1 采样率、数据率、带宽:三个容易混淆的量
采样率说的是每秒采多少次样,也就是ADC或者DAC的工作频率,单位是SPS或者Hz。数据率说的是每秒实际产生或传输多少数据,单位是bps、MB/s这种。带宽指的是信号本身占用的频率范围,比如一段语音是300Hz到3.4kHz,一个LTE载波是20MHz带宽。
这三者的关系可以用相机来类比。采样率类似相机的拍照帧率,每秒拍多少张;数据率类似每张照片占多少存储空间,和像素位深以及帧率共同决定;带宽则类似画面内部色彩变化的丰富程度。拍照太快,存储卡不够写;位深太浅,画面质量差;带宽考虑不足,细节又采集不到。ADC/DAC系统里的设计取舍,本质上就是在这几个指标之间做平衡。
很多人有个错觉,觉得采样率越高越好。其实采样率一旦提高,数据率是成正比往上冲的。比如STM32的ADC,如果按1MSPS采样,12位分辨率,但一个样本读出来通常占16位寄存器,那数据率就是1M乘以2字节,大概是2MB/s。做一路采集还行,要是做三相电流、三路电压同时采样,数据率直接翻到6MB/s以上,单片机做实时FFT分析就开始吃力了。所以定采样率之前,先想清楚“我的信号带宽到底是多少”,这个思考顺序比选哪颗ADC更重要。
1.2 采样周期怎么算:从STM32的例子说起
“ADC采样周期”这个词在单片机里其实有两层意思。第一层是数据手册里的“采样时间”,特指采样开关闭合、给内部采样电容充电的时间;第二层是整体转换时间,等于采样时间加上转换时间。以STM32F103为例,ADC时钟最高14MHz,12位分辨率时转换阶段需要约12个ADC时钟周期,采样时间可以配置为1.5、7.5、13.5、28.5、41.5、55.5、71.5、239.5个周期。
如果采样时间配1.5个周期,那么单次转换总时间大概是1.5加12.5,约等于13.5个ADC时钟周期,除以14MHz,差不多0.96微秒一次,也就是约1MSPS的吞吐率。如果采样时间配到239.5个周期,总时间变成252个周期,约18微秒,采样率就掉到55kSPS左右。
这里有个很关键的工程直觉:采样时间越长,采样电容充电越充分,对高输出阻抗的信号源越友好。反过来,如果你信号源输出阻抗很高,又没有加缓冲,采样时间又很短,那采样电容来不及充满,转换结果就会偏小或者跳动。很多人在ADC前端不加运放,直接用电阻分压给ADC,然后发现数据非线性,大概率就是这个原因。
1.3 定时器触发采样:为什么工程上都这么干
如果不用定时器触发,直接在循环里启动ADC,转换开始时刻会受到代码执行时间影响,产生很大的采样抖动。举个例子,要测量一个开关电源的输出纹波,如果采样点刚好落在开关管开通或者关断的噪声边沿,和落在稳定区域,结果可能是天壤之别。
使用定时器触发ADC,就可以在一个稳定的时间窗口内固定采样。STM32里常用的做法是用高级定时器的PWM中心对齐模式,在计数器计数到0或更新事件时触发ADC,这样采样点正好落在PWM周期的中心,远离开关噪声边沿。F4系列里定时器6也可以作为DAC或者ADC的触发源。做DAC正弦波输出时,用定时器触发加DMA查表,每个定时器周期更新一次DAC,输出频率非常稳定,而且几乎不占用CPU。
在这个例子里,定时器的更新率就是DAC的“采样率”。你输出正弦波的频率上限,就受到这个更新率的限制,至少得满足奈奎斯特条件,实际工程中通常要保证一个周期有几十个点,波形才够平滑。
2. DDC和DUC:让数据率“听话”的两件套
DDC全称Digital Down Converter,数字下变频;DUC全称Digital Up Converter,数字上变频。这两个模块在软件无线电、雷达、通信基站、测试仪器里遍地都是,但很多刚接触的人不清楚它们到底解决了什么问题。
简单说,ADC采回来的数据如果频率很高、数据量很大,后端处理吃不消;DDC就是把ADC输出的高频数字信号搬到基带,同时降低数据率。DUC正好相反,DAC输出前,把基带数字信号搬到中频或者射频,同时提高数据率,让DAC输出的信号更好滤。它们都是做频率搬移和采样率变换的,一个往下搬,一个往上搬。
2.1 DDC结构和原理
设想一个场景:ADC直接采样中频信号,中频是70MHz,采样率100MSPS,12位输出。那ADC输出的数据率就是100M乘以2字节,约200MB/s,也就是1.6Gbps。这么大的数据率,即便FPGA接得住,你要在70MHz附近做解调、滤波,后端处理时钟的压力也很大。
DDC做的事情就是:先把ADC数据乘以一个本地振荡器产生的正弦和余弦,也就是NCO的输出,把70MHz的中频信号搬到零频附近,然后用低通滤波器滤掉高频分量,最后按整数倍抽取降低采样率,输出I/Q两路基带数据。
NCO全称数控振荡器,本质上是一个相位累加器加查找表或者坐标旋转算法。每来一个时钟,相位累加器加一个步进值,步进大小决定输出频率。频率分辨率等于时钟频率除以2的累加器位宽次方。比如200MHz时钟、32位累加器,频率分辨率大概是0.046Hz,这对绝大多数通信系统都够用了。
下变频后的滤波和抽取通常不是一级完成的,而是用多级滤波器级联。CIC滤波器不需要乘法器,适合大抽取率,但通带不够平坦;半带滤波器适合做2倍抽取;FIR滤波器灵活,阶数可以压得比较低。典型链路可能是CIC抽4、半带抽2、FIR再抽2,总抽取率8倍,最终数据率降到原来的八分之一。注意:抽取前必须先低通滤波,否则带外噪声或者干扰会折叠回带内,那才是真的灾难。
2.2 DUC结构和原理
DUC是DDC的逆过程。DAC输出前,数字基带I/Q信号要先内插提高采样率,再变频到中频或者射频。为什么要先内插?因为DAC输出的频谱会在整数倍采样频率处出现镜像,采样率越低,镜像离有用信号越近,后面的模拟重构滤波器就越难做。提高采样率之后,镜像被推到更远的地方,后面一级简单的LC低通就能滤得很干净。
DUC内部一般这样组织:基带I/Q信号先经过插值滤波器,在相邻两个点之间插入零值,再用FIR滤波器滤除镜像;然后通过NCO数字混频,把信号搬到中频或射频;最后送到DAC。多级结构也很常见,比如半带滤波器插2倍、FIR插2倍,最终采样率变成原来的4倍。
从系统角度看,DUC和DDC是成对出现的。发射链路要先DUC再DAC,接收链路要先ADC再DDC。两边的NCO频率如果设置成同一个值,整个系统就是标准的数字中频收发信机。
2.3 DDC/DUC放芯片里还是放FPGA里
现在很多高速ADC/DAC芯片已经内置了DDC/DUC,比如TI的ADC12DJ5200、ADI的AD9081,射频收发器AD9361、ADRV9002这些器件,芯片内部就集成了完整的数字下变频、上变频、抽取和内插。FPGA只通过JESD204B高速接口接收低速数据,接口压力小很多。
这种做法最大的好处是硬件简单,FPGA资源省。缺点是不够灵活,抽取率、滤波器带宽、NCO频率都靠寄存器配置,如果芯片内部的滤波器响应跟你需要的不完全匹配,还得在FPGA里再做一级补偿滤波。
反过来,在FPGA里自己写DDC/DUC,灵活性最高。NCO频率可以随时改,抽取率可以按算法需求调,还可以跟后续解调算法融合。缺点也很明显:NCO、CIC、半带、FIR、跨时钟域同步,工程量不小,调试起来也费时间。
我的建议是,项目初期或者验证阶段,优先用芯片内置的DDC/DUC,先把整条链路跑通,拿到参考数据。等真正理解了数字变频的细节,再在FPGA里自己做,这样至少有对照基准,出了问题也知道该查哪里。
2.4 一个DDC/DUC在系统里配合的实例
假设一个收发系统是这样的:发射时,基带I/Q数据率50Mbps,经过DUC内插4倍变成200MSPS,数字混频到70MHz中频,DAC以200MSPS更新输出。DAC后面接一个截止频率100MHz左右的低通滤波器,就能得到干净的中频模拟信号。接收时,ADC以200MSPS采样70MHz中频信号,FPGA里的DDC把信号搬到基带,抽取4倍后数据率回到50Mbps,交给解调模块。
这条链路的妙处在于:中间的数据率看起来很高,但只存在于DAC/ADC芯片内部或者紧邻的FPGA逻辑里,外部接口始终是低速的。这正好体现了DDC/DUC的核心价值,用数字处理换取系统的整体可实现性。
3. 采样率、数据率的设计计算与工程折中
前面讲了很多概念,这一章落到实际计算上。做信号链设计,躲不开采样率选多少、数据率多大、滤波器怎么设计这些具体问题。我把常用的计算方法和工程原则整理出来,可以直接照抄。
3.1 采样定理与工程裕量
奈奎斯特采样定理说,采样率至少要达到信号最高频率的两倍,才能无混叠恢复原信号。但实际工程里几乎没有人按2倍来设计,一般至少取2.5到3倍。原因很简单:抗混叠滤波器不是理想砖墙,需要过渡带。如果信号带宽10MHz,采样率只取20MHz,那抗混叠滤波器的截止频率必须压在10MHz,而且要在10MHz到20MHz之间迅速衰减到足够低,这种滤波器阶数非常高,实现代价大。把采样率提高到25到30MHz,过渡带就宽了很多,一个二阶或三阶低通就够用了。
过采样还有额外的好处。每过采样4倍,理论上量化噪声在信号带内降低约6dB,相当于多出1位有效分辨率。这也是Sigma-Delta ADC能实现高分辨率的原理:用很高的采样率加噪声整形,把带内噪声推走,再用数字滤波抽取。但要注意,过采样的收益不是无限的,到一定程度后会被时钟抖动、模拟前端噪声这些非理想因素压住,采样率再高也白搭。
实际中还有一种带通采样,也叫欠采样,用于直接采样中频信号。它不是按信号最高频率的两倍来采,而是让信号的频谱经过折叠后落在某个奈奎斯特区内,不发生混叠。举个例子,70MHz中频、10MHz带宽的信号,用100MSPS采样也能采回来,只要确保中频和采样率满足一定关系。但欠采样对前端带通滤波器和时钟抖动的要求非常高,带外信号一旦进来就会折到带内,所以工程上要特别谨慎。
3.2 几个典型算例,建立数量级直觉
做系统设计前,先对常见场景的数据率有个数量级概念,能少走很多弯路。我整理了一个表格:
| 场景 | 采样率 | 位宽 | 通道数 | 数据率 | 备注 |
|---|---|---|---|---|---|
| 音频CD | 44.1kHz | 16bit | 2 | 1.4112Mbps | 44.1k乘16乘2 |
| STM32单路ADC | 1MSPS | 12bit,按16bit存 | 1 | 2MB/s | DMA搬运典型 |
| LTE 20MHz载波 | 30.72MSPS | 16bit | I/Q两路 | 983.04Mbps | JESD204B常见 |
| 高速示波器前端 | 2.5GSPS | 10bit | 1 | 25Gbps | 不加抽取根本存不下 |
| 雷达中频采集 | 1.2GSPS | 12bit | 1 | 14.4Gbps | DDC抽取8倍后降到1.8Gbps |
这个表里最有意思的是LTE的例子。20MHz信号带宽,采样率30.72MSPS,I/Q两路各16bit,数据率计算方式是30.72M乘16bit乘2通道,约983Mbps。这个速率已经逼近千兆以太网了,所以做软件无线电的人经常头疼数据回传问题。如果自带DDC的芯片先把信号抽取到7.68MSPS,数据率就直接降到245Mbps,一张千兆网卡就能轻松传走。
3.3 抽取和内插:采样率变化后数据率怎么变
抽取R倍,输出采样率变成fs/R,数据率也跟着除以R。内插L倍,输出采样率变成L乘fs,数据率乘以L。这个看似简单,但很多人设计的时候会忘记一个关键点:抽取前必须低通滤波,内插后也必须低通滤波。
抽取前不滤波,带外信号会折叠回带内,换算公式是fa等于k乘fs加减fo这种关系。实际表现就是你的信号里突然多出一堆莫名其妙的杂散,怎么查都查不到源头。内插后不滤波,DAC输出频谱里会多出好几组镜像,后面的模拟滤波器压力山大。
多级抽取和内插比单级更高效。单级抽取16倍,需要一个阶数非常高的FIR,运算量大到FPGA可能跑不动。但把16倍分解成CIC抽4、半带抽2、FIR抽2,每级滤波器阶数都能大大降低,总运算量少一个数量级。这就是为什么DDC和DUC内部几乎都是多级级联结构。
3.4 动态参数SNR、SFDR、ENOB与采样的关系
选ADC或者DAC的时候,除了位宽和采样率,还有一组动态参数很重要:SNR、SFDR、ENOB。SNR是信号与噪声的比值,SFDR是信号与最大杂散的比值,ENOB是有效位数,换算关系是ENOB等于SNR减1.76后再除以6.02。
一颗标称12位的ADC,理论SNR上限是74dB,但实际能做到62dB已经不错,换算过来ENOB只有10位。也就是说,你花12位的价钱买到的动态范围,实际只有10位多点。所以做系统预算时,不要拿标称位宽算动态范围,要用ENOB。
ENOB和DDC/DUC的关系也很直接。如果ADC本身的SNR只有60dB,后端DDC做得再好,系统的信噪比上限也就60dB。反过来,如果ADC前端有很强的带外干扰,抽取滤波器带外抑制不好,干扰折叠进带内,有效SNR会迅速变差。所以DDC里每一级抽取前的抗混叠滤波,都是为保护ADC好不容易挣来的动态范围服务的。
4. 工程实战:时钟、电源、PCB与常见坑
概念讲清楚了,最终还是要落到板子上。我做过不少ADC/DAC相关的项目,最深的体会是:性能翻车往往不是选型问题,而是时钟、电源、PCB布局这三个环节出了问题。这一章我把经验集中写出来,尤其是那3个PCB布局要点,建议直接收藏。
4.1 时钟抖动为什么是高速ADC/DAC的“天敌”
时钟抖动对ADC的影响,等价于在模拟输入端叠加热噪声。采样时钟的边沿如果前后抖动,等效于采样点电压被错误地采到了。输入信号频率越高,同样的时间抖动造成的电压误差越大。
孔径抖动和SNR的理论关系大概是:SNR等于20倍log10(1除以2πf_in乘t_jitter)。代入一个例子:输入1GHz信号,时钟抖动1ps,算下来SNR上限只有44dB。这意味着一颗标称70dB的ADC,配了抖动很大的时钟后,实际动态范围只有44dB,完全浪费了。
所以高速ADC对参考时钟的要求几乎是苛刻的。工程上的经验做法是:时钟源优选低相位噪声的晶振或TCXO,锁相环的环路带宽和VCO相位噪声要匹配,时钟树里不要扇出太多路,每一路都最好用专门的时钟缓冲器。给ADC和DAC供同一个时钟时,尽量让它们共用一个低抖动时钟芯片,而不是各自从不同地方取时钟,否则两边的相位噪声叠加,还会影响系统相干性。
4.2 电源噪声是怎么混进ADC结果里的
电源噪声进入ADC结果有两个主要路径:一是通过模拟电源引脚,二是通过参考电压引脚。ADC内部的比较器、采样开关、放大器都依赖电源,电源上的纹波会被调制到输出码里。参考电压更是直接决定了每个LSB对应的模拟电压值,Vref上一丁点噪声,都会变成输出的直流漂移和杂散。
开关电源的纹波通常在几十kHz到几百kHz,还会叠加几MHz的开关噪声。这些噪声灌进模拟电源后,即使LDO抑制能力不错,高频段的PSRR也会迅速变差。所以工程上经常给模拟电源单独用一颗低噪声LDO,数字电源和模拟电源之间用电感或磁珠隔离。
参考电压的去耦也要特别注意。0.1uF高频去耦电容要尽量靠近Vref引脚,旁边再放一颗10uF的钽电容或MLCC做低频储能。很多ADC芯片的Vref引脚对外的输出阻抗不高,参考源驱动不了瞬态电流,去掉耦电容根本稳不住。
4.3 ADC/DAC电路设计中3个PCB布局要点
这块内容是我最想重点讲的。很多性能不错的ADC/DAC芯片,最后在全系统测试时达不到手册指标,大概率是PCB布局出了问题。
第一个要点,时钟和模拟输入必须严格分开。高速时钟走线要尽量短,尽量走内层且带完整地参考,关键部位包地处理。绝对不要让时钟走线和模拟输入走线平行长距离靠近,否则时钟的谐波会耦合到模拟输入上,产生很难排查的杂散。时钟走线下面如果被分割,回流路径会遭到破坏,共模噪声直接灌进ADC。
第二个要点,电源去耦电容的放置不是“放到附近”就行,而是要放到电源引脚旁边,过孔尽量靠近焊盘,让回流路径最短。0.1uF高频电容靠近引脚,还要搭配10uF以上大电容。模拟电源和数字电源之间用电感或磁珠隔离,但要关注磁珠的频率阻抗特性,选型要结合实际噪声频谱,不要盲目套用。
第三个要点,地平面不要随便分割。很多老资料喜欢把模拟地和数字地分开,再用一颗磁珠或者0欧电阻单点连接,这在低速电路里也许可行,但在高速ADC/DAC里往往适得其反。更推荐的做法是统一地平面,模拟器件和数字器件分区布局,让回流电流自然走最短路径。如果确实因为结构原因必须分割,那数字信号绝对禁止跨分割走线,否则回路面积变大,辐射和耦合问题都会冒出来。
4.4 常见问题与排查技巧速查
下面这个表是根据我自己的调试经历和一些常见的论坛问题整理的,直接对照排查会快很多。
| 现象 | 可能原因 | 处理建议 |
|---|---|---|
| ADC数据整体漂移 | 参考电压不稳、温度漂移、前端偏置电流 | 查Vref去耦,校准基准源,软件加滑动平均 |
| SNR差、码跳动大 | 时钟抖动大、采样时间不足、输入阻抗过高 | 换低抖动时钟,加大采样时间,前端加驱动 |
| 输出谐波大 | 输入信号过载、前端非线性、滤波不足 | 降低输入幅度,优化抗混叠滤波,检查驱动能力 |
| 注入通道读到旧值 | 读取时机不对,JEOC标志没等 | 等注入转换完成标志再读,确认触发源配置 |
| DAC输出波形变形 | 重构滤波截止不对、更新率不足、负载过重 | 检查滤波器设计,提高DAC更新率,加输出缓冲 |
| 数据偶发毛刺 | DMA触发出错、电源跌落 | 查触发源配置、DMA优先级、电源监测 |
| Sigma-Delta ADC数据跳变 | 前端RC设计不合理 | 减小R避免建立误差,增大C应对电荷反冲 |
关于注入通道再展开说一句。STM32的ADC有规则通道和注入通道之分,注入通道转换的时机经常由外部事件触发。很多人踩过坑,触发信号来了之后没有等JEOC标志就去读结果寄存器,读到的可能还是上一次存下来的旧值,甚至读到转换到一半的中间值。正确做法是触发后查询JEOC,置位了再读取。
另外,如果ADC输入来自室外长线缆或者有静电风险的环境,前端要加端口保护。常见做法是TVS管加限流电阻加钳位二极管,但必须注意TVS的寄生电容会影响采样建立时间,高速应用要选低电容TVS。RC滤波参数也要跟着调,不能直接照搬手册默认值。
4.5 别忘了软件滤波:从硬件到固件闭环
硬件处理得再好,软件滤波还是有必要。最常见的是三种:滑动平均、中值滤波、一阶低通。
滑动平均适合平稳信号的降噪,窗口越大越平滑,但延迟也越大。中值滤波适合剔除脉冲干扰,比如电源开关造成的毛刺,效果立竿见影。一阶低通的实现是y[n]等于y[n-1]加α乘以x[n]减y[n-1],α在0到1之间,越小越平滑,响应也越慢。
我的经验是先看信号特征再选滤波方式,不要一上来就套一大串处理。如果MCU支持硬件滤波,比如GD32H7系列ADC内置硬件滤波器,直接用硬件功能可以省下CPU时间,一边采一边滤,效果还不错。但要注意,任何滤波都会引入延迟和幅值衰减,做闭环控制的时候要把这部分延迟算进去,不然控制系统容易不稳定。
5. 最后分享一点我做项目的心得
做了这么多年信号链相关的项目,最大的体会是:采样率、数据率、SNR这些概念单独拿出来都很好懂,难的是放在一起做系统设计。我以前做过一块数据采集板,当时只盯着ADC型号和采样率,觉得12位100MSPS已经很牛了,结果测出来SNR和手册差了十万八千里。后来一步步排查,发现是时钟芯片相位噪声太大,加上模拟电源和数字电源没有隔离,Vref上全是开关噪声。重新画了布局、换了时钟源之后,性能完全不一样。
所以我后来养成了一个习惯:开工之前,先把整条信号链路的框图画出来,把每一级的采样率、数据率、SNR要求、滤波器设计挨个标上去,算清楚哪里是瓶颈。单片机开发可以先从定时器触发、DMA搬运、软件滤波这套组合练起,建立对采样和数据流的感觉。做通信和FPGA的同学,建议先找一颗自带DDC/DUC的芯片把链路跑通,再回头去写自己的数字变频,进步会快很多。
这些概念并不难,把它们放到具体的项目里,反复用几次,自然就通了。