ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

STM32 ADC通道不够用?用CD74HC4067扩展16路模拟采集实战

STM32 ADC通道不够用?用CD74HC4067扩展16路模拟采集实战 搞过嵌入式采集的朋友应该都有体会单片机自带的ADC通道永远不够用尤其是做多路模拟量采集的项目传感器一多就得想尽办法扩展。我这次项目里用的是STM32F103片上只有1个ADC模块、最多16个通道但实际要采集的模拟信号有12路还有几路需要预留光靠片上资源根本转不开。最开始想过直接换更大封装、更多引脚的型号但硬件方案已经定了板子也画完了换MCU不现实也考虑过用外部ADC芯片比如ADS1115这类I2C接口的但一颗只能接8路要上两颗才够电路复杂度和成本都上去了。最后选了CD74HC4067这个16通道模拟多路复用器一颗芯片加4个GPIO就能扩展出16路ADC输入成本不到两块钱电路也简单。方案定下来之后调试过程倒是没想象中顺利踩了两个特别典型的坑一个是采样数值偏低且不稳定另一个是切换通道后第一笔数据是脏数据。这篇文章就把整个扩展方案、硬件连接、代码实现和这两个坑的排查过程完整记录下来给正在做同类项目的朋友一个参考。1. 整体设计方案与选型思路1.1 为什么用CD74HC4067而不是直接换MCUCD74HC4067是TI生产的16通道模拟多路复用器/多路解复用器本质上就是一个由4位二进制信号控制的单刀16掷开关。S0到S3四个选择引脚的电平组合对应16个通道逻辑关系极其简单通道编号等于二进制数比如S3S2S1S0 0000选通道01010选通道10以此类推。选这颗芯片有几个现实理由。第一它支持双向传输既可以把16路模拟信号汇聚到1路ADC输入也可以反过来把1路信号分发到16个输出端项目里只用到了前者但以后如果要扩展DAC输出通道这颗芯片照样能用。第二导通电阻Ron典型值只有几十欧姆在低速模拟信号采集场景下影响相对可控。第三工作电压范围2V到12V3.3V和5V系统都能直接适配我用的是3.3V供电。还有一个很重要的点是控制逻辑兼容性。CD74HC4067的逻辑输入高电平阈值大约在0.7倍VCC左右3.3V供电时高电平阈值约为2.31VSTM32 GPIO输出高电平是3.3V直接驱动没有任何问题不需要额外的电平转换电路。这就是为什么我不选CD4051只有8通道也不选DG408这类老款芯片的原因CD74HC4067在通道数、逻辑兼容性和成本之间是平衡得最好的。1.2 硬件连接方式与信号链路设计硬件连接没有什么玄学成分按数据手册接就行。16路模拟输入连接到芯片的X0到X15引脚公共输出端数据手册里标为COM或X连接到STM32的ADC输入引脚。我这里用的是PA0对应ADC1的通道0因为PA0在芯片上单独引出不会和其他外设冲突。S0到S3分别连接到STM32的PB0、PB1、PB2、PB3这四个引脚全部配置为推挽输出。注意这里有个细节PB2在STM32F103上是BOOT1引脚如果板子上BOOT1有外部下拉电阻直接复用问题不大但如果BOOT1被拉高芯片会进入Bootloader模式程序跑不起来。我检查过自己板子的原理图BOOT1接了10k下拉电阻所以才放心用PB2。如果你的板子不确定BOOT1的状态最好换一个引脚。还有两个容易被忽略的引脚EN使能引脚和VEE引脚。EN是高电平有效还是低电平有效取决于具体型号CD74HC4067的EN是低电平有效必须接地或者由GPIO控制为低电平否则所有通道全部断开ADC什么都采不到。VEE在CD74HC4067这种单电源版本上是用来接负电源的如果信号都是0V以上直接接地就行。信号链路完整路径是这样的传感器输出信号经过调理电路进入CD74HC4067的某个输入引脚然后通过内部开关到达COM引脚再经过ADC引脚的输入阻抗进入STM32内部的采样保持电容最后由逐次逼近型ADC完成量化。这条链路里的每一个环节都会影响最终的采样精度后面要讲的两个坑就出在这条链路的前半段。2. 第一个坑采样数值整体偏低且波动2.1 现象描述与初步排查硬件焊好之后第一版固件的逻辑很简单循环切换通道每次切换后延时100微秒然后用HAL库的ADC单次转换模式读取数值通过串口打印出来。按理说这个流程应该没问题但实测结果让我有点懵。用信号发生器给通道0输入一个精确的2.0V直流电压串口打印出来的ADC值换算成电压只有1.83V左右偏低将近10%。而且数值不是稳定的在1.78V到1.88V之间来回跳。换通道1测试同样的2.0V输入读数变成了1.76V偏得更厉害。更奇怪的是直接把信号发生器接到PA0引脚上绕过CD74HC4067ADC读数完全正常2.0V输入采回来就是2.0V误差在0.01V以内。这说明问题一定出在CD74HC4067这条信号链路上。一开始我怀疑是芯片本身坏了换了颗新芯片现象依旧。后来检查接线确认所有引脚焊接都没有虚焊。又怀疑是不是EN引脚没拉低用万用表量了电平确实是0V。排查到这里问题还没定位到根因上。2.2 根因分析导通电阻与源阻抗的叠加效应之后认真翻了CD74HC4067的数据手册在电气特性表格里找到了关键线索。手册标注的导通电阻Ron典型值是70欧姆但这是在15V供电、信号电压5V、测试电流1mA的条件下测出来的。实际使用中Ron不是一个固定值而是随供电电压、输入信号电压和温度变化的。从手册的Ron vs Vin曲线图来看3.3V供电、信号电压2V时Ron大约在100到150欧姆之间温度升高还会继续增加。这个电阻本身看起来不大但它和信号源阻抗是串联关系。想象一个场景传感器的输出阻抗是10千欧经过CD74HC4067的150欧姆导通电阻再进入STM32的采样保持电路等效源阻抗就是10150欧姆。STM32F103的ADC采样保持电容大约是8皮法采样时间最短可以配置为1.5个ADC时钟周期在这个配置下采样电容充电时间常数约为10150欧姆乘以8皮法大约81纳秒一个时间常数内电容只能充到约63%的电压。实际采样转换中ADC内部会有采样开关闭合的固定时间如果源阻抗过高保持电容最终充到的电压就达不到输入信号的真实值转换结果自然偏低。为什么直接接PA0却不准因为STM32的ADC自带一个内部RC低通滤波器并且采样保持时间可以适当延长。HAL库默认配置的采样时间是55.5个ADC周期这个时间对低源阻抗信号足够用但CD74HC4067串联进来之后采样时间常数变大同样的采样时间就不够用了。2.3 解决方案延长采样时间与降低源阻抗定位到根因之后解决思路就清晰了。第一个办法是延长ADC的采样时间。把HAL_ADC_ConfigChannel里的SamplingTime从默认的ADC_SAMPLETIME_55CYCLES_5改成最长的ADC_SAMPLETIME_239CYCLES_5。STM32F103的ADC时钟设置为12MHz时239.5个采样周期的时间大约是19.9微秒瞬间把采样时间拉长了4倍多。实测同样的2.0V输入ADC读数恢复到1.98V左右误差从10%缩小到1%。第二个办法是降低源阻抗从硬件上做文章。我给每个传感器输出后都加了一级电压跟随器用LM358或者TL072这类运放在信号进入CD74HC4067之前做阻抗变换。运放的输出阻抗极低通常只有几欧姆加上CD74HC4067的导通电阻也不过百来欧姆远小于STM32的ADC要求的最大源阻抗数据手册推荐RAIN小于10千欧。这个方案的效果立竿见影但问题是运放的数量太多16路信号需要16个运放成本和面积都上去了。实际项目里我最终采用了折中方案保留运放跟随器但只在信号源阻抗本身较高的通道上添加。比如电流型传感器输出经过I/V转换后阻抗在千欧级别这类通道必须加跟随器而输出电压型传感器本身输出阻抗几十欧姆的就不加直接进CD74HC4067。同时把ADC采样时间统一配置成239.5个周期双管齐下16路通道的采样误差都控制在了0.5%以内。这里有个经验值得单独说判断是否需要加运放跟随器不能只看传感器标称输出阻抗还要把它和CD74HC4067的Ron、ADC要求的最大源阻抗放一起做加法。如果传感器输出阻抗加上Ron小于ADC要求的最大源阻抗的1/5不加运放问题不大如果接近甚至超过就必须加否则采样精度一定出问题。这个实践经验我写在团队硬件设计规范里了。3. 第二个坑切换通道后第一笔数据是脏数据3.1 现象描述通道切换瞬间的异常读数采样精度解决之后另一个问题很快浮现出来。程序逻辑是每个通道连续采10次取平均然后切换到下一个通道我通过串口打印每个通道的原始值和平均值发现一个规律每次切换通道之后该通道的第一个采样值总是异常的偏大或者偏小有时候甚至超出量程但第二个采样值开始恢复正常。以3.3V供电为例我给通道3输入一个稳定的1.2V电压通道4输入2.5V程序按通道号顺序扫描。打印结果里通道3的第一笔采样值测算下来是1.05V第二笔开始稳定为1.19V通道4的第一笔采样值是2.72V第二笔开始稳定为2.49V。不管切换顺序怎么变规律始终是切换后的第一笔数据不可信。这个现象最开始让我以为是ADC转换本身的问题怀疑是不是连续转换模式下第一次触发没有准备好但后来验证发现并非如此。我用固定通道连续采集100次第一笔数据是正常的只有切换通道的那一瞬间才会出现第一笔数据异常的情况。这就把问题范围缩小到了CD74HC4067的通道切换过程本身。3.2 根因分析导通电容电荷注入与信号建立时间再翻数据手册这次关注的是动态特性参数。CD74HC4067的通道切换时间turn-on/turn-off time标称值在纳秒级别非常快但同时手册里还有一组参数。电荷注入charge injection和通道间串扰crosstalk的说明这才是问题核心。模拟开关内部是由CMOS晶体管构成的栅极和源/漏极之间存在寄生电容。通道切换时控制信号加在栅极上通过寄生电容耦合到信号路径上产生一个短暂的电荷注入这个电荷会改变输出端电容上的电压导致信号建立需要额外的时间。具体到实际场景当S0到S3的电平被改变瞬间COM引脚上会叠加一个尖峰脉冲如果这个时候立即触发ADC采样采到的就是被污染的值。还有一个因素是采样保持电容的残存电荷。STM32的ADC采样电容在完成一次转换后会残留上一次采样的电压。直接切换到新通道后新通道的信号源阻抗需要把采样电容从旧电压充到新电压这又是一个建立时间。如果把建立时间估计得太短第一笔数据测出来的就是新旧电压的中间值。综合这两点切换通道后需要的稳定时间可以分为两个部分一是CD74HC4067输出端寄生电容的电荷注入恢复时间二是ADC采样保持电容从残留电压充到新信号电压的充电时间。前者通常在几百纳秒到几微秒量级后者取决于新通道的信号源阻抗和采样保持电容的乘积。我之前写的100微秒延时理论上应该足够但由于第一个坑里没有加运放跟随器的时候源阻抗太高第二部分的建立时间被大幅拉长了100微秒未必够用。3.3 解决方案软硬件组合拳解决这个问题最直接的办法就是加大切换后的延时时间。我把通道切换后的延时从100微秒改成了1毫秒第一笔数据的异常率从接近100%降到了大约20%。再加大到2毫秒异常率几乎降到了零。但单纯靠延时治标不治本不但拖慢了整体采样速率而且如果后续项目里有快速变化的信号需要高速轮询1到2毫秒的延时完全不可接受。所以我又做了两件事来彻底根除这个问题。第一在硬件上给COM引脚和GND之间加了一个10纳法的电容和STM32ADC输入引脚的内置采样电容并联。这个外部电容有两个作用一是吸收CD74HC4067切换瞬间的电荷注入抑制尖峰脉冲二是把COM引脚上的信号电压在切换后保持得更稳定相当于一个简易的采样保持器。加了电容之后即使延时时间缩短到200微秒第一笔数据的异常率也基本为零。第二在软件逻辑上做了一个取舍每次切换通道后连续采两次数据丢弃第一次只保留第二次。这个方案虽然损失了一半的采样吞吐率但换来的是干干净净的数据。因为第二次采样的时候无论是电荷注入的尖峰还是采样电容的残留电压影响都已经不存在了。最终实现的效果是切换延时配置为500微秒每次切换后采两笔取第二笔整个16通道的完整扫描周期大约8毫秒数据质量完全满足项目的需求。说句实话我当时一度纠结要不要用DMA方式以提高效率但最后发现DMA模式下丢弃首笔数据的实现稍微复杂需要额外构造一个数据缓冲区起始偏移量来丢弃第一个结果而且配合多路复用器切换时序很容易出错就放弃了。如果你需要高速轮询16路信号DMA方案也完全可以做但务必要把切换后延时的时序设计和DMA的触发时机对齐这个后面有机会再展开写。4. 完整代码实现与参数配置细节4.1 硬件配置GPIO与ADC初始化CD74HC4067的控制引脚使用普通GPIO即可不用复用功能所以初始化非常简单。四个控制引脚统一配置为推挽输出、最大翻转速度50MHz初始化时全部输出低电平默认选中通道0。ADC初始化部分我直接用STM32CubeMX生成的HAL库工程但有几处需要手动调整。ADC分辨率为12位数据对齐方式选择右对齐扫描模式关闭因为多路复用器的通道切换在外部ADC本身只需要单通道连续转换即可。ADC时钟分频系数选择6APB2时钟为72MHz时ADC时钟为12MHz这是STM32F103规格书保证最大精度下的最高频率。最关键的是采样时间必须设置为ADC_SAMPLETIME_239CYCLES_5这个参数直接决定采样精度。我用的是ADC单通道模式加软件触发没有上DMA。因为外部有16个通道要切换每一路都需要配置不同的控制引脚电平再用软件去读ADC的结果DMA在这种情况下反而增加复杂度。如果以后要扩展更大的通道数DMA是必须的但那是另一个话题了。4.2 核心扫描逻辑与代码注释完整的通道扫描代码贴在下面核心逻辑就是切换通道、延时、采样、丢弃首笔、再采样。代码里的冗余设计是为了明确展示每个步骤的意图方便初学者理解和修改。#define MUX_S0_PIN GPIO_PIN_0 #define MUX_S1_PIN GPIO_PIN_1 #define MUX_S2_PIN GPIO_PIN_2 #define MUX_S3_PIN GPIO_PIN_3 #define MUX_GPIO_PORT GPIOB #define MUX_CHANNEL_COUNT 16 #define MUX_SETTLE_DELAY 500 // 单位us static uint16_t adc_raw_values[MUX_CHANNEL_COUNT]; void MUX_SelectChannel(uint8_t channel) { if (channel MUX_CHANNEL_COUNT) { return; } // 通道编号的二进制位依次映射到S0-S3引脚 HAL_GPIO_WritePin(MUX_GPIO_PORT, MUX_S0_PIN, (channel 0x01) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(MUX_GPIO_PORT, MUX_S1_PIN, (channel 0x02) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(MUX_GPIO_PORT, MUX_S2_PIN, (channel 0x04) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(MUX_GPIO_PORT, MUX_S3_PIN, (channel 0x08) ? GPIO_PIN_SET : GPIO_PIN_RESET); // 关键延时1等待CD74HC4067内部开关稳定和外部电容充电建立 Delay_us(MUX_SETTLE_DELAY); } uint16_t MUX_ReadChannel(uint8_t channel) { MUX_SelectChannel(channel); // 关键延时2丢弃切换后首笔受电荷注入影响的数据 uint16_t dummy ReadADC(); (void)dummy; // 防止编译器告警 // 延时一段时间确保内部采样电容完成充电 Delay_us(100); // 第二笔数据已稳定作为有效采样结果 uint16_t value ReadADC(); return value; } void MUX_ScanAllChannels(void) { for (uint8_t ch 0; ch MUX_CHANNEL_COUNT; ch) { adc_raw_values[ch] MUX_ReadChannel(ch); } } uint16_t ReadADC(void) { HAL_ADC_Start(hadc1); HAL_ADC_PollForConversion(hadc1, 10); // 超时10ms return (uint16_t)HAL_ADC_GetValue(hadc1); }延时函数在实际工程中建议用定时器或者DWT实现我这里用的是HAL_Delay的微秒版本封装的Delay_us。注意HAL_Delay只提供毫秒级延时微秒延时如果是裸机工程用DWT计数器最方便如果是RTOS环境要注意延时不要影响任务调度。有一个容易忽视的点调用HAL_ADC_PollForConversion之前必须确保上一次转换已经结束否则HAL_ADC_Start会返回HAL_BUSY。我的代码里每次都是Start一次、读一次然后下次再Start流程是严格串行的。如果在中断或者多线程环境里调用需要对ADC加互斥保护。4.3 多通道滤波与均值处理16路原始AD值读回来之后如果直接在项目里用数据会显得比较毛糙因为CD74HC4067的导通电阻波动、外部干扰和电源噪声都会反映在采样值上。我项目的传感器信号大多是缓变信号比如温度、压力和液位这类信号的特点是低频、小幅波动适合用滑动平均滤波。最终采用的方法是每个通道连续采样10次去掉最大值和最小值剩下的8个值取平均。这个滤波算法虽然简单但在单片机上的执行效率很高纯整数运算不涉及浮点数也不会消耗大量内存。10次采样的开销在已经存在的扫描周期内可以接受。#define FILTER_SAMPLE_COUNT 10 uint16_t ADC_FilterRead(uint8_t channel) { uint16_t samples[FILTER_SAMPLE_COUNT]; for (uint8_t i 0; i FILTER_SAMPLE_COUNT; i) { samples[i] MUX_ReadChannel(channel); } // 冒泡排序去极值 for (uint8_t i 0; i FILTER_SAMPLE_COUNT - 1; i) { for (uint8_t j 0; j FILTER_SAMPLE_COUNT - 1 - i; j) { if (samples[j] samples[j 1]) { uint16_t tmp samples[j]; samples[j] samples[j 1]; samples[j 1] tmp; } } } uint32_t sum 0; for (uint8_t i 1; i FILTER_SAMPLE_COUNT - 1; i) { sum samples[i]; } return (uint16_t)(sum / (FILTER_SAMPLE_COUNT - 2)); }这个去极值平均滤波在这里的正确性依赖一个前提MUX_ReadChannel已经剔除了通道切换后的首笔脏数据所以进入滤波数组的每个样本本身是干净的。如果忽略这一点滤波算法会把那些异常值当作正常数据参与排序和平均结果中偶尔会出现特别离谱的尖刺而且不容易排查。5. 调试过程中的工具与方法总结5.1 用串口打印和实时曲线定位数据规律在调试这两个坑的过程中串口打印帮我省了很多时间。最开始我是把每个通道的单次采样值直接打印出来数据刷得太快根本看不出规律。后来改成每个通道打印10个原始值再打印平均值用串口助手的波形显示功能把数据画成曲线问题立刻就清晰了每次通道切换后都有一个明显的向下或者向上的毛刺后续数据逐渐收敛到真实值。这种数据呈现方式特别适合排查ADC这类采样型问题。你看着原始数据在串口助手里的波形比看一长串十六进制数字直观得多。市面上常见的串口调试助手基本都支持波形显示比如山外多功能调试助手或者VOFA把数据按通道用逗号分隔发出去就能在电脑上实时看到每个通道的曲线。如果波形出现周期性毛刺基本可以断定是切换瞬间的问题如果波形整体偏低或者偏高优先怀疑阻抗匹配或者参考电压。5.2 用万用表验证模拟开关导通状态为了排除CD74HC4067的引脚配置错误我还用万用表的通断档直接量了芯片引脚之间的导通情况。方法是把S0到S3全部置低选中通道0用万用表红表笔接COM引脚黑表笔依次碰X0到X15只有X0应该导通表笔会有短路报警其他引脚都应该开路。同理把S0置高、其余置低通道1导通其他开路。16个通道全部测一遍就能确认芯片本身没有问题也能验证GPIO控制逻辑是否正确。这个测试看似基础但在调试初期非常有用。可以快速区分问题是在硬件接线、芯片逻辑还是后端ADC读取环节。如果不做这个验证很容易像我一开始一样在ADC采样代码里瞎折腾了半天最后发现是控制引脚接错线或者芯片型号买错了市面上有些商家把CD74HC4051等8通道芯片当4067卖引脚定义完全不同。5.3 数据回溯法定位首笔脏数据处理第二个坑的时候我还用了一个比较通用的调试方法给同一通道连续设置两个不同的输入电压然后观察切换通道后的采样序列。比如通道5先给1.0V通道6先给3.0V程序从通道5切换到通道6之后打印通道6的第一笔到第十笔数据。如果第一笔数据明显偏向通道5的旧电压就说明是采样电容的残留电荷没有完成转换这时候增加延时或者外部电容都是有效的。如果第一笔数据偏向通道6的新电压但有一个尖峰说明是电荷注入干扰需要增加外部滤波电容。这种数据回溯的方法让我不用示波器也能大概判断出问题的性质对于没有示波器的调试场景很有用。当然有条件的话直接在COM引脚上用示波器量切换瞬间的波形是最直观的你能清楚看到尖峰脉冲的幅度和持续时间可以精确地确定最小延时时间而不是像我一样靠经验值一点点加延时去试。6. 常见问题速查表与避坑指南6.1 快速对照表为了方便后面项目复现我把这次调试中遇到的典型问题和对应解决方案整理成了表格可以直接对照排查。问题现象可能原因解决方案所有通道采样值整体偏低源阻抗过大采样时间不足增大ADC采样时间信号源加运放跟随器某个通道数值明显偏小该通道信号源阻抗高或有分压单独校准该通道检查该通道前端电路切换通道后第一笔数据异常电荷注入采样电容残留电荷切换后延时丢弃首笔采样COM引脚加电容所有通道读数为0EN引脚未拉低供电异常检查EN引脚电平测量VCC和GND通道选择混乱控制不精确S0-S3接线错误GPIO配置错误用万用表验证导通关系检查GPIO初始化采样值跳变剧烈波动大滤波不足电源纹波大增加去极值平均滤波在VCC加去耦电容高温下采样值漂移CD74HC4067导通电阻温度系数尽量选择低源阻抗必要时改用更高规格芯片6.2 容易被忽略的硬件细节CD74HC4067是CMOS器件对静电敏感焊接时最好使用防静电镊子不要用手直接拿芯片引脚。实验室环境如果不够规范芯片可能在焊接过程中就损坏了表现为特定通道不通或者读数异常这种情况下换一颗芯片往往就好了不用在电路设计上纠结太久。电源去耦不可省。CD74HC4067的VCC和GND之间要加0.1微法陶瓷电容尽量靠近芯片引脚放置。如果芯片供电是从STM32的3.3V引脚直接拉的而板上还有电机、继电器这类大电流负载建议另加一颗10微法钽电容或者电解电容做储能否则采样数据的噪声会明显增大。逻辑控制引脚的电平幅度也要注意。如果MCU是5V供电而CD74HC4067是3.3V供电GPIO高电平输出5V高于芯片的VCC这可能会导致芯片内部保护二极管导通或者逻辑异常最好加串阻或者分压处理。大多数现代MCU是3.3V系统CD74HC4067也是3.3V供电这个问题不太常见但还是值得留意。6.3 软件层面的避坑记录软件代码里最隐蔽的一个坑是ADC校准。STM32F103的ADC在初始化时最好调用HAL_ADCEx_Calibration_Start进行自校准如果漏掉了这一步ADC转换结果可能整体偏大或者偏小和CD74HC4067的导通电阻造成的偏差叠加在一起排查难度会增加很多。我这次一开始是用的CubeMX直接生成代码默认没有勾选校准功能后来发现数值不准把校准加上之后误差又缩小了一截。还有一个是采样时间参数的选择。很多人在CubeMX里配置ADC采样时间时看到默认值就觉得够用不会主动改成最大值。但如果你的信号链路上串联了模拟开关采样时间这个参数几乎可以肯定需要调整。具体的值可以通过计算得到也可以通过实验对比确认。我个人的习惯是在项目初期直接拉满把采样时间设为最大值先把功能跑通然后再根据实际需求优化速度。关于轮询扫描模式下整体采样周期的问题我也多说一句。每通道延时500微秒加两次ADC采样16个通道一圈下来大约8毫秒这个速度对于绝大多数传感器采集场景绰绰有余。如果你的系统需要1毫秒以内的响应速度可以考虑把延时缩短到200微秒、丢弃首笔采样的方案同时保留这样单圈扫描能压缩到3毫秒左右。如果还不够快就该换思路了比如把16路信号通过16个采样保持器同步锁存然后逐个读取或者直接用带更多ADC通道的高端MCU搭配DMA。7. 经验和心法总结CD74HC4067这颗芯片本身不复杂真正决定项目成败的往往是对数据手册里那些小参数的敏感度。导通电阻不是固定值、切换过程存在电荷注入、采样建立时间受到源阻抗影响这些在单纯的数字电路调试中完全不会碰到但一进入模拟量采集领域就成了必须面对的问题。我这次调试踩坑之后形成了几个固定习惯。第一所有模拟信号进入MCU之前先确认信号源阻抗是否满足ADC输入要求如果不满足优先加运放跟随器而不是盲目加大采样时间因为加大采样时间在高阻抗信号下也有极限而且会显著拖慢轮询周期。第二任何用到外部模拟开关的ADC采集程序通道切换后都必须有余量地等待信号建立最稳妥的方式就是丢弃切换后的首笔数据这个逻辑简单可靠性价比最高。第三硬件上的小型滤波电容往往能解决软件上很难处理的噪声问题个头虽小但效果出奇的好。如果你正准备在自己的项目里用CD74HC4067扩展ADC通道按照这个思路走应该能少绕一些弯路先把硬件信号链路里的源阻抗控制好再把采样时间参数拉满最后在软件上做好切换时序管理。这三个关卡都过了16路ADC采集就能稳定跑起来剩下的就是按实际需求做滤波和校准了。
返回列表