做高精度采集项目时,我第一次把LAT1545接到MCU的DFSDM外设上,就卡在输入模式配置这一关。DSD(数字Sigma-Delta)信号到底该走哪种输入路径、时钟怎么给、滤波器和抽取率怎么配合,手册里分散在好几个章节,不完整读一遍根本串不起来。这篇把LAT1545配合DFSDM的输入模式选择和配置过程完整拆开讲,适合正在调DSD采集链路、或者准备用DFSDM但还没理清输入模式的开发者参考。
1. LAT1545和DFSDM能组成什么样的采集链路
1.1 LAT1545在采集链路中的角色
LAT1545不是常规意义上的ADC芯片。它内部集成了Sigma-Delta调制器,把前端模拟信号转换成1-bit的数字流输出,而不是直接输出并行的二进制数据。这种架构跟传统的逐次逼近型ADC(SAR ADC)有本质区别:SAR ADC直接把模拟信号量化成N bit的并行数据推给MCU,而Sigma-Delta调制器输出的是一串01码流,码流中“1”的密度反映输入信号的幅值。要恢复出高分辨率的数字结果,必须由后级MCU或者DSP对这串码流做数字滤波和抽取。
DFSDM(Digital Filter for Sigma-Delta Modulators)就是STM32系列里专门干这个活的外设。它能产生调制器需要的时钟,也能接收调制器输出的1-bit数据流,内部通过可配置的Sinc滤波器、积分器、抽取器,把串行码流转换成24位或更高精度的并行数据,同时还能做平均值、极值等后处理。从整体链路看,LAT1545负责“模拟到1-bit数字流”的转换,DFSDM负责“1-bit数字流到高分辨率数字值”的还原,中间省掉了传统模拟放大器和独立ADC的麻烦,电路设计和PCB面积都能明显收缩。
1.2 为什么是DFSDM而不是软件模拟
有人会问,LAT1545输出的就是1-bit码流,用MCU的普通GPIO加上定时器中断,在软件里数脉冲密度不也能还原信号吗?理论上可行,但实际工程里几乎没人这么干。DFSDM的时钟可以做到几十MHz,而GPIO翻转加中断响应的开销通常在百纳秒级,CMOS输入阈值抖动、中断延迟抖动、电源噪声耦合进I/O缓冲,都会让采样的时间基准不干净。Sigma-Delta系统的核心优势恰恰在于“过采样+噪声整形”,如果采样时钟本身带抖动,噪声整形效果直接被破坏,最终的有效位数甚至不如普通12位SAR ADC。
DFSDM的优势在于硬件化、并行化。它内部有完整的数字滤波链,不占用CPU周期就能持续处理码流,多个通道可以同时跑,采集通道多、采样率要求高的场景优势更明显。我们项目里需要同时监视多路传感器信号,每路的采样率在几kHz到几十kHz级别,用DFSDM处理LAT1545的码流,CPU负载几乎可以忽略不计,这在软件解调方案里很难做到。
1.3 一个典型信号链路的全貌
实际项目中,完整的链路是:传感器输出的模拟小信号,先经过LAT1545内部的放大和调制,输出单bit码流DATA,同时由MCU通过DFSDM提供调制时钟CLK。DFSDM收到DATA后,按配置好的输入模式、时钟边沿、滤波类型、抽取率进行处理,结果存入数据寄存器,再通过DMA或者中断搬运到内存。应用层拿到的是已经还原好的24位数据,直接做工程量转换即可。
如果LAT1545还支持同步输出(SYNC)或者多个LAT1545级联,DFSDM的输入配置会更复杂一些。我在第一次调试时,只关注了DATA和CLK两条线,忽略了SYNC信号,导致多片LAT1545的采样时钟不同步,信号还原出来后相位有偏差。这个坑后面会详细讲。
2. DFSDM的四种输入模式,到底该怎么选
2.1 四种模式的原理和差异
STM32的DFSDM外设,标准型号通常支持四种输入模式:外部输入模式(External input)、外部串行输入模式(External serial input)、内部级联输入模式(Internal cascade input)、内部串行输入模式(Internal serial input)。手册上写得比较官方,实际选型时只要抓住一个核心问题:你的调制器数据流是被动由DFSDM驱动时钟,还是自己产生时钟并主动输出数据?
外部输入模式是最常用的,适合LAT1545这类需要DFSDM提供时钟的调制器。DFSDM的DATINx引脚接收LAT1545输出的串行数据流,CKOUT引脚输出时钟给LAT1545的CLK引脚。时钟的极性和频率都由DFSDM控制,数据流与时钟同步,可以在时钟上升沿或下降沿采样。
外部串行输入模式的区别在于,调制器自己有时钟,数据流和时钟都已经同步好,DFSDM只需要接收数据和时钟,不需要自己产生CKOUT。这种模式适合那些内部自带时钟源的Sigma-Delta调制器,或者前级已经有独立的时钟管理芯片的场景。缺点是DFSDM对输入时钟的质量要求较高,时钟抖动直接影响采样性能。
内部级联输入模式用于多个DFSDM滤波器级联,比如第一个滤波器输出的结果作为第二个滤波器的输入,用来实现更高阶的滤波或者更复杂的信号处理链。这种模式不接外部调制器,属于DFSDM内部数据流的再处理,日常单级采集基本用不到。
内部串行输入模式则是把内部数据总线的数据当作串行码流输入,通常用于测试或者处理来自其他外设的特殊数据流,工程上应用最少。
2.2 LAT1545适配哪种模式
根据LAT1545典型应用结构,滤波器时钟由外部提供,数据输出与时钟同步,且数据线上输出的就是调制器处理后的1-bit码流,最适合的输入模式是外部输入模式。此时DFSDM作为主控方提供时钟,LAT1545作为从属方接收时钟并输出数据,时序关系简单清晰,DFSDM采样时可以精确对齐时钟边沿。
选择外部输入模式还有一个实际好处:DFSDM的CKOUT频率可以通过配置寄存器精确控制,不依赖外部晶振或振荡器的频率精度。LAT1545的调制器对时钟频率有一定的容忍范围,只要DFSDM输出的时钟频率在LAT1545数据手册规定的工作范围内,就能保证调制器正常工作。我们实测下来,时钟频率在2.56MHz时效果最好,此时滤波后的有效位数最高。
2.3 选错模式会有什么现象
如果误选了外部串行输入模式,而LAT1545本身并没有独立的时钟输出,DFSDM就会一直等待外部时钟,数据寄存器永远不更新,DMA也拿不到数据。反过来,如果LAT1545有内部时钟,却被配置成了外部输入模式,DFSDM的CKOUT和LAT1545内部时钟会产生频率竞争,数据流时序错乱,滤波器输出的数据会周期性跳变,表现为采集结果的噪声异常大,甚至直接饱和。
我在第一次调试时,为了省事直接套用了其他项目的DFSDM配置,把输入模式设成了外部串行输入,结果LAT1545的码流一直在,但DFSDM的DFSDM_FLT0xISR寄存器里始终没有数据就绪标志。排查了很久才发现是输入模式不匹配,配置改成外部输入模式后数据立即正常了。这个坑值得记下来。
3. 输入模式与关键参数的完整配置步骤
3.1 CubeMX中的配置路径
推荐先用STM32CubeMX做图形化配置,生成基础工程后再按需修改。因为DFSDM的输入模式、时钟分频、滤波器参数之间存在关联,手工直接写寄存器容易漏配。
在CubeMX中,选择DFSDM外设后,首先是Channel标签页,每个DFSDM通道对应一组输入引脚。需要选择输入模式为External input,启用Channel,并确保引脚分配正确。然后是Filter标签页,每个滤波器绑定一个通道,滤波器的阶数、类型、抽取率等参数在这里设置。
关键配置项如下表所示,这些参数直接影响信号还原的精度和效率:
| 配置项目 | 可选值或范围 | 推荐值/说明 |
|---|---|---|
| 输入模式 | External input / External serial input / Internal cascade input / Internal serial input | 选择External input |
| 通道引脚 | DFSDM_DATINy / DFSDM_CKOUTy | 需分配实际引脚 |
| 时钟源 | 内部时钟 / 外部时钟 | 通常选内部时钟 |
| 时钟分频 | 1~256 | 根据LAT1545工作频率计算 |
| 滤波器类型 | Sinc x 1 / Sinc x 2 / Sinc x 3 | 一般选Sinc x 3 |
| 抽取率(FOSR) | 1~1024 | 根据目标输出数据率计算 |
| 积分器抽取率(IOSR) | 1~256 | 与FOSR配合 |
| 数据格式 | MSB对齐 / LSB对齐 | 一般选MSB对齐 |
3.2 时钟频率的计算逻辑
DFSDM的输入时钟一般来自芯片内部总线时钟,例如APB2时钟。假设APB2时钟为80MHz,DFSDM内部预分频为8,则实际进入DFSDM模块的时钟为10MHz。再经过CKOUTDIV分频,输出到LAT1545的时钟频率就是10MHz除以分频系数。
LAT1545的典型工作时钟范围是1MHz到3.2MHz,取2.56MHz比较适中。需要设置的分频系数就是10MHz除以2.56MHz,约等于3.9,实际取整数分频系数4,得到2.5MHz的调制时钟。这个频率略低于理想值,但Sigma-Delta调制器对时钟频率不敏感,性能影响可以忽略。如果时钟源是80MHz的HSE直接分频,可以先通过DFSDM的CLKIN选择器把时钟源切成PLL输出,再用CKOUTDIV分频。
调制时钟确定后,需要确定滤波器参数。DFSDM内部滤波链的第一级是Sinc滤波器,其抽取率由FOSR控制;第二级是积分器,抽取率由IOSR控制。最终的输出数据率等于调制时钟频率除以FOSR再除以IOSR。以2.5MHz调制时钟为目标输出500Hz数据率,则FOSR和IOSR的乘积需要达到5000,比如FOSR取50、IOSR取100,或者FOSR取100、IOSR取50。
这里要注意一个关键结论:Sinc滤波器的通带纹波和阻带衰减与FOSR相关,FOSR越大滤波效果越好,但输出数据率会降低。所以在满足输出率要求的前提下,尽量让FOSR大一些,IOSR小一些,这样信号带宽内的波动更小,信纳比更高。我们在项目里多次调节发现,FOSR=64、IOSR=39的组合,比FOSR=32、IOSR=78的组合在关键频段内信纳比高出约1.2dB,但FOSR不能无限大,否则输出延迟明显增加。
3.3 HAL库代码中映射的实际操作
CubeMX生成的工程里,核心初始化代码在mx_dfsdm1_init函数中。但CubeMX对DFSDM的部分高级配置支持不够灵活,比如Sinc滤波器的阶数选择、时钟边沿极性等,通常需要在用户代码里手动补充。
实际初始化流程大致如下:
/* 配置DFSDM1 Channel 0为外部输入模式 */ static void MX_DFSDM1_Init(void) { dfsdm1_channel_handler.Instance = DFSDM1_Channel0; dfsdm1_channel_handler.Init.OutputClock = DFSDM_CHANNEL_OUTPUT_CLOCK_ENABLE; dfsdm1_channel_handler.Init.InputMode = DFSDM_CHANNEL_INPUT_MODE_EXTERNAL; dfsdm1_channel_handler.Init.InputPolarity = DFSDM_CHANNEL_INPUT_POLARITY_RISING; dfsdm1_channel_handler.Init.TriggerMode = DFSDM_CHANNEL_TRIGGER_MODE_SW; HAL_DFSDM_ChannelInit(&dfsdm1_channel_handler); } /* 配置DFSDM1 Filter 0为Sinc x 3滤波器 */ static void MX_DFSDM1_Filter0_Init(void) { dfsdm1_filter_handler.Instance = DFSDM1_Filter0; dfsdm1_filter_handler.Init.RegularParam.Trigger = DFSDM_FILTER_SW_TRIGGER; dfsdm1_filter_handler.Init.FilterParam.Order = DFSDM_FILTER_SINC3; dfsdm1_filter_handler.Init.FilterParam.FOSR = 64; dfsdm1_filter_handler.Init.FilterParam.IOSR = 39; HAL_DFSDM_FilterInit(&dfsdm1_filter_handler); }这里特别注意Init.InputMode字段,取值必须是DFSDM_CHANNEL_INPUT_MODE_EXTERNAL,而不是默认的DFSDM_CHANNEL_INPUT_MODE_INTERNAL。很多从旧项目复制代码的朋友就是栽在这里。
此外,InputPolarity字段决定DFSDM在时钟的哪个边沿采样数据。LAT1545的数据在时钟上升沿输出、下降沿稳定,那么DFSDM就应该配置为下降沿采样,即DFSDM_CHANNEL_INPUT_POLARITY_FALLING。如果极性和LAT1545不匹配,接收到的码流虽然存在,但滤波器输出的数据噪声会明显增大,严重时信号完全失真。
3.4 DMA方式的数据搬运配置
高精度采集场景下,数据输出率一般不高,但需要连续采集,中断方式频繁进ISR会消耗CPU资源。推荐用DMA循环模式搬运数据,这样CPU几乎不参与数据搬运,只在应用层消费数据即可。
DMA配置需要注意数据宽度和方向。DFSDM的数据寄存器是32位的,DMA搬运方向为从外设到内存,外设地址固定,内存地址递增,数据宽度设为32位。DMA的循环模式开启后,缓冲区满了会自动回绕,保证数据持续写入缓冲区。
static void MX_DMA_Init(void) { hdma_dfsdm1_filter0.Instance = DMA1_Channel0; hdma_dfsdm1_filter0.Init.Request = DMA_REQUEST_DFSDM1_FILTER0; hdma_dfsdm1_filter0.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_dfsdm1_filter0.Init.PeriphInc = DMA_PINC_DISABLE; hdma_dfsdm1_filter0.Init.MemInc = DMA_MINC_ENABLE; hdma_dfsdm1_filter0.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; hdma_dfsdm1_filter0.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; hdma_dfsdm1_filter0.Init.Mode = DMA_CIRCULAR; HAL_DMA_Init(&hdma_dfsdm1_filter0); HAL_DMA_Start_IT(&hdma_dfsdm1_filter0, (uint32_t)&hdfsdm1_filter_handler.Instance->ISR, (uint32_t)dfsdm_buffer, BUFFER_SIZE); }DMA中断里只需要置一个标志位,表示新数据已经就位,主循环检测到标志后处理缓冲区即可。这种方式即使后续增加多路通道,也只是增加DMA通道和缓冲区,不会显著增加CPU负载。
4. 实测中的信号异常与完整排查链路
4.1 现象:数据恒为0或者偶尔跳变
LAT1545接入DFSDM后,最常见的问题就是滤波结果恒为0,或者数据偶尔跳一下然后回到0。这种问题从现象看很像LAT1545没有工作,但用示波器测量LAT1545的数据输出引脚,发现码流是正常的。此时问题大概率出在DFSDM的输入配置上,而不是信号源上。
排查链路建议按下面步骤走:
第一步,读取DFSDM通道的输入状态寄存器,确认码流是否真正到达DFSDM内部。DFSDM的通道状态寄存器里有时钟和数据引脚的实时电平状态,如果数据引脚电平跟示波器测量一致,说明引脚电平没有问题。
第二步,检查DFSDM的时钟输出是否正常。用示波器测量CKOUT引脚,确认频率和占空比符合预期。如果CKOUT没有波形,检查OutputClock使能位是否打开、时钟分频是否正确。
第三步,验证输入采样极性。在时钟极性配置错误时,DFSDM会在数据未稳定的边沿采样,导致采到的值几乎全是0。调整InputPolarity为相反边沿,观察数据是否恢复。
4.2 数据有值但噪声显著偏大
数据有值但噪声大,通常意味着系统正在拾取干扰,或者DFSDM的滤波配置无法有效抑制Sigma-Delta量化噪声。LAT1545的调制器把大部分量化噪声推向高频,DFSDM的Sinc滤波器必须恰好把这些高频噪声抑制掉,否则噪声会混叠到低频,表现就是数据方差大、有效位数低。
如果确认LAT1545的模拟输入已经短接或者接稳定的参考电压,但转换结果仍有较大的波动,最可能的原因是FOSR/IOSR配置不合理。Sinc3滤波器在FOSR较小时,阻带衰减不够,高频量化噪声泄漏到基带。解决办法就是增加FOSR,但同时要调整IOSR保持目标输出率不变。
此外,电源噪声也是一个常见的干扰源。DFSDM和LAT1545最好使用独立的LDO供电,中间加磁珠隔离,避免数字电源的高频噪声通过电源网络耦合进模拟前端。板卡上LAT1545的模拟电源引脚旁边必须加0.1uF和10uF去耦电容,且尽量靠近引脚放置。我们做过对比测试,把去耦电容从板卡边缘移到芯片引脚旁边后,低频噪声峰值降低了接近1/3。
4.3 数据率不对的排查
输出数据率的误差通常来自时钟分频和抽取率的组合计算。很多人忘记DFSDM内部还有一个可选的时钟分频预分频器,以为CKOUT输出的就是最终调制时钟。实际在有些型号上,DFSDM内核时钟和输出时钟之间还有一级分频。检查寄存器实际值而不是依赖CubeMX的可视化界面显示,是关键一步。
排查时直接读取DFSDM_CH0CFGR1的CKOUTDIV字段和DFSDM_FLT0FCR的FOSR、IOSR字段,手动计算当前配置下的输出数据率,再和实际观察到的DMA中断频率对比,就能定位是哪一个分频设置出了问题。
4.4 多片LAT1545级联时的同步问题
多片LAT1545同时采集时,不同通道的DFSDM各自输出CKOUT,即使配置完全一致,由于芯片间时钟起始相位不同,多通道数据之间会存在固定的相位偏移。对于只关心各通道独立幅值的应用,这种偏移问题不大。但如果要做多通道之间的相位差分析,或者用多个传感器信号做波束合成,就必须处理同步问题。
最简单的同步方案是让所有LAT1545共用一个时钟源,从其中一个DFSDM通道的CKOUT引出时钟信号,接到所有LAT1545的CLK引脚,同时把所有LAT1545的SYNC引脚连接在一起,由MCU的GPIO统一触发启动转换。这样每个通道的调制器在同一时钟沿工作,多通道数据的相位关系就保持一致了。
另一种方案是使用DFSDM内部的级联模式,但级联更多用于滤波器的串联,而不是多通道同步,所以实际项目里还是优先用外置硬件同步方案。
5. 从输入模式到信号质量的几个进阶细节
5.1 时钟极性和数据稳定时间的匹配
DFSDM对输入数据的采样边沿必须匹配LAT1545的数据输出时序。LAT1545的数据是在时钟上升沿之后延迟一段时间才稳定,因此DFSDM必须在时钟下降沿采样,才能保证采到的是稳定数据。如果配置成上升沿采样,DFSDM有可能采到数据跳变过程中的中间态,这在数字接口上虽然不常见,但实际会引入额外误差。
这个问题可以用示波器测量验证:把LAT1545的CLK和DATA两路信号同时接到示波器上,放大时间轴,观察数据信号相对时钟边沿的建立时间和保持时间。如果数据在时钟上升沿后约几十纳秒才稳定,那么DFSDM配置下降沿采样是安全的。实测中,把极性和LAT1545匹配好后,滤波输出的信纳比从约73dB提升到了接近85dB,效果非常明显。
5.2 Sinc滤波器阶数选择的权衡
DFSDM支持Sinc1、Sinc2、Sinc3三种滤波器阶数。Sinc1结构最简单,通带较宽,但阻带衰减慢;Sinc3阻带衰减快,对带外噪声抑制好,但通带边缘的跌落更明显。实际选择时,如果目标是宽频带信号的高线性度,Sinc1可能更合适;如果目标是最小化带内噪声、最大化有效位数,Sinc3是更稳妥的选择。
以2.5MHz调制时钟、FOSR=64为例,Sinc3的第一零点在2.5MHz/64,即约39kHz。也就是说,39kHz附近及以上的噪声会被极大衰减。如果信号本身带宽在1kHz以内,这个滤波性能完全够用;如果信号带宽要到10kHz以上,就需要适当降低FOSR并增加IOSR来拓宽通带,但这会增加带内量化噪声。取舍原则是:信号带宽越大,FOSR相对越小,有效位数相对越低。
5.3 失调校准与增益校准
DFSDM虽然内部没有硬件校准模块,但高精度应用里建议在应用层做软件校准。最简单的方法是两点校准:输入短接时采集零偏值,输入一个已知精密参考电压时采集满量程值,然后用线性映射修正输出。
实测中发现,DFSDM滤波器在上电初始阶段会有一段暂态过程,输出的前几十个点不是稳态信号,直接采集会污染平均值计算。解决方法是在DMA开始搬运后,先丢弃固定数量的样本,比如丢弃64个样本,再开始累计有效数据。这个方法在项目里帮我们省去了很多无效数据的烦恼。
5.4 抗混叠滤波的必要性
Sigma-Delta调制器本身有过采样和噪声整形,理论上不需要额外的模拟抗混叠滤波器,因为输入信号带宽远低于调制时钟频率。但在强电磁环境下,如果模拟输入端存在接近调制时钟整数倍的干扰信号,这些干扰会折叠到基带,Filter也无法完全消除。这种情况下,在LAT1545前端加一个简单的RC低通滤波器,截止频率设置在信号带宽的2至3倍,可以有效抑制高频干扰折叠。
我们项目里最开始没有加RC滤波,采集结果偶发突变,排查了很久才定位到是现场设备产生了与调制时钟接近的电磁干扰,频率约为2.5MHz的整数倍。增加RC低通后,突变消失,数据稳定性明显提升。RC的取值不需要特别精确,常见的是10kΩ电阻串联、1nF电容对地,截止频率约16kHz,满足大多数传感器信号带宽需求。
5.5 极低功耗场景下的DFSDM时钟策略
如果项目对功耗有严格要求,比如电池供电的传感器节点,DFSDM可以用较低频率的调制时钟来降低动态功耗。但Sigma-Delta系统的过采样比(OSR)与有效位数直接相关,降低调制时钟会降低过采样比,从而降低有效位数。这时需要在功耗和精度之间做取舍,一般不建议把调制时钟降低到1MHz以下,否则信纳比下降太快,24位分辨率形同虚设。
更合理的低功耗策略是间歇工作:高速采集一小段时间,然后把LAT1545和DFSDM全部关断,只在需要时重新启动。DFSDM重新启动后需要等待滤波器暂态结束,通常耗时在微秒级,对慢速传感器应用完全可以接受。
6. 扩展思路:把DFSDM用得更深
DFSDM不仅仅能接LAT1545这类单bit调制器,还可以接多bit的Sigma-Delta调制器,某些型号的DFSDM还支持曼彻斯特编码输入。曼彻斯特编码的优势是数据和时钟叠加在一根线上传输,节省引脚。如果后续项目里选了支持曼彻斯特编码的传感器,DFSDM输入模式的配置会变为Manchester模式,此时时钟重建和数据采样都由DFSDM内部完成,不再需要单独的CKOUT信号。这类模式对引脚时序更敏感,建议在拿到实物后先用低速时钟验证,确认无误再提高频率。
多路并行采集方面,DFSDM的多个通道可以独立配置,但滤波器资源是共享的,通道多了之后,每个滤波器同一时间只能处理一路信号,如果所有通道都要连续采集,需要合理分配滤波器与通道的绑定关系。低采样率的通道可以多个共用一个滤波器,通过时间片轮转或外部触发来分时复用,代价是每个通道的采样率会被摊薄。对于真正需要多路同步高速采集的场景,往往要选择滤波器资源更多的MCU型号,或者在PCB设计时把多个DFSDM外设分布在不同的时钟域,避免共同时钟产生的串扰。
如果要把数据通过串口或以太网实时上送,记得在DMA缓冲区和网络发送之间做双缓冲切换,避免在拷贝缓冲区时造成数据撕裂。这个技巧和DFSDM本身无关,但多通道高精度采集系统一旦跑起来,数据量大、位宽高,这个细节早晚会遇到。
我在实际项目中还有一个体会:第一次配置DFSDM时,别急着把滤波器阶数调到最高、抽取率拉到最大,先通过自测信号验证基本的数据通路。LAT1545的数据输出是否达到预期,DFSDM的滤波器和抽取器组合是否正常,这些基础功能确认无误后,再逐步优化性能和参数。否则一旦出现问题,排查范围会很大,很难确定是信号源、通道配置还是滤波参数的问题。DFSDM配起来不难,难的是理清输入模式、时钟、滤波器三者之间的关系。把外部输入模式、时钟分频、FOSR/IOSR这几个关键点一一确认,LAT1545的码流就能稳定变成干净的24位数据。后续再遇到其他Sigma-Delta调制器,只要按同样的思路走一遍,基本都能顺利跑通。