ARTICLE DETAIL

资讯详情

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

用CD74HC4067模拟多路复用器将ADC扩展至16路:原理、电路与调试

用CD74HC4067模拟多路复用器将ADC扩展至16路:原理、电路与调试 裸板调ADC通道不够用这大概是做嵌入式采集绕不开的坎。最近一个项目里MCU自带ADC只有8个外部通道板子上偏偏要采16路模拟量既不想换大封装芯片也不想加一颗独立ADC芯片增加BOM成本。翻了翻库存正好有一片CD74HC406716通道模拟多路复用器几块钱的东西直接用它把ADC口扩展成16路效果还算理想。这块电路本身不复杂真正费时间的反而是两个看起来不起眼的调试坑。这篇笔记把方案思路、接线方法、驱动逻辑和排查过程都整理出来给后面要做类似扩展的朋友一个参考。1. 方案选型与整体设计思路1.1 为什么选择CD74HC4067而不是其他方案扩展ADC通道的方案其实不止一种常见的有三换大资源MCU、加外部独立ADC芯片、用模拟多路开关切换。前两种成本高或者周期长对于项目里只差几个通道的场景不划算。第三种方案里CD74HC4067属于非常经典的16选1模拟开关导通电阻典型值在70欧姆左右带宽40MHz以上开关切换时间在几十纳秒级别用来切低频模拟信号完全够用。和同为多路开关的CD40518通道相比CD74HC4067用两片才能凑够16路控制复杂度和PCB面积都上去了和带I2C接口的专用ADC扩展芯片比如ADS1115相比CD74HC4067是纯模拟开关不参与量化只要后级ADC性能不变整体采样精度就主要取决于开关的导通电阻和漏电流可控性更强。几毛钱到一两块钱一片的单价在量产项目里也有明显成本优势。选型时的另一个考量点是它支持双向传输输入输出可以互换使用除了扩展ADC输入还能用来复用GPIO、切换I2C或SPI总线等场景属于比较通用的基础器件。虽然我这次只用在模拟采集通道扩展上但后续如果项目里需要扩展其他接口这块板子还能继续复用。1.2 CD74HC4067的核心参数与引脚功能先过一遍这颗芯片的关键参数选型和排查问题时都用得上参数数值说明通道数量16通道16选1结构单端输入导通电阻RON典型70Ω随供电电压和温度变化5V供电时约40~80Ω漏电流ILEAK典型±100nA高温下会增大高阻源信号要注意工作电压VCC2V~6V常用3.3V或5V供电切换时间tON/tOFF典型20~40ns远快于ADC采样周期几乎不用考虑串扰CROSSTALK-50dB级别相邻通道在高频信号下会更明显封装SOIC-24 / TSSOP-24TSSOP焊接难度稍高引脚功能需要重点记几个S0到S3是通道选择地址线对应二进制0000到1111比如S3S2S1S00000时选通COM与CH01111时选通CH15。EN是使能脚低电平有效拉高时所有通道关闭输出呈高阻。COM是公共端接到MCU的ADC输入引脚16路输入信号分别接到CH0~CH15。VCC和GND为芯片供电另外还有VEE引脚如果信号有负电压才需要接负电源本项目只采单极性0~3.3V信号VEE直接接地即可。1.3 整体架构框图整个采集链路的结构线如下传感器/外部信号16路模拟电压→ CD74HC4067的CH0~CH15 → COM端输出选通信号 → MCU ADC引脚 → DMA搬运结果 → 软件组包上报MCU的3个普通GPIO如果加上EN就是4个分别接S0、S1、S2、S3通过软件查表方式控制通道切换。DMA模式下采集过程完全由定时器触发每次切换通道后启动一次采样全部16通道扫描一遍后再统一处理数据。当然不用DMA也行用软件轮询方式依次切换和读取逻辑更简单只是CPU占用高一些。后面会给出两种方式的对比。2. 硬件电路连接与PCB设计要点2.1 最小系统接线方案我这次用的是STM32F103系列MCU3.3V供电。连接方式如下VCC接3.3VGND接系统地VEE接地无负压信号S0、S1、S2、S3分别接MCU的四个GPIO任意引脚即可软件里用数组映射EN接MCU的另一个GPIO低电平使能CH0~CH15接16路待测信号信号幅度不超过VCC范围COM引脚接到MCU的ADC输入通道比如PC0对应ADC_IN10。硬件上要点不多但有几个容易忽略的细节值得提一下。2.2 输入信号阻抗匹配与缓冲问题CD74HC4067的导通电阻不是理想0欧姆后级ADC采样保持电容在采样瞬间会从信号源抽取电荷如果信号源内阻较高RON和信号源内阻串联分压会造成明显的采样误差。比如信号源内阻10k欧姆RON取70欧姆时影响还不太明显但如果信号源内阻到了100k甚至M欧姆级别误差就大了。处理办法有两个一是信号进CD74HC4067之前先用运放跟随器做阻抗变换低阻抗驱动开关再从COM端直接进ADC二是如果信号本身已经经过传感器调理电路输出内阻通常在几百欧姆以内可接受直接连接。我这次用的信号都是电压型传感器输出内阻约1k欧姆实测直接接没问题。另外一个容易被忽视的点是COM端到MCU ADC引脚之间的走线长度尽量短不要超过2厘米并做包地处理避免引入噪声。如果ADC引脚旁边还有其他高速数字信号线建议在布局时保持距离串扰会影响采样稳定性。2.3 供电滤波与参考电压稳定性模拟电路对电源纹波敏感CD74HC4067的供电VCC纹波会通过开关导通特性耦合到信号链路上。建议在VCC引脚就近放一个0.1uF陶瓷电容如果板子上有模拟电源和数字电源分区VCC接模拟电源域更好。我这里由于板子已经定型VCC和MCU的数字3.3V共用实测在ADC采样数据低位有1~2个字跳动后来在VCC处加了个磁珠隔离效果有所改善但不加也能接受。ADC参考电压的稳定性同样重要如果用MCU内部参考建议确保VREF引脚电容到位典型0.1uF1uF组合不要省。如果批量产品对精度有要求可以考虑外置基准如REF3033或TL431但这个取决于项目精度需求不是必须项。2.4 硬件焊接与常见连接错误检查焊接这类引脚间距1.27mm或0.65mm的芯片时焊接完毕务必用万用表蜂鸣档检查相邻引脚间有无锡连尤其S0到S3四条地址线和COM线之间桥接会导致通道错乱排查会非常费劲。第一次调试时最容易犯的错误是EN引脚悬空。悬空状态下EN内部可能受到干扰造成通道随机切换表现就是读出来的ADC值随机跳变。实测中遇到过这个问题把EN接低电平后症状消失。所以即使不需要控制使能也建议将EN直接接地别让它悬空。3. 软件驱动设计与采集流程3.1 四种GPIO组合控制16通道切换CD74HC4067通道选择的本质是4位二进制码。实现时直接用数组建立通道号到GPIO状态的映射避免每次切换都做位运算代码可读性更好。以一个伪代码示例说明#define CH0 0 #define CH1 1 // ... 以此类推到 CH15 const uint16_t mux_channel_table[16] { (0 12) | (0 8) | (0 4) | 0, // CH0: S30 S20 S10 S00 (0 12) | (0 8) | (0 4) | 1, // CH1: S30 S20 S10 S01 // ... 省略中间项 (1 12) | (1 8) | (1 4) | 1, // CH15: S31 S21 S11 S01 }; void mux_select_channel(uint8_t ch) { uint16_t val mux_channel_table[ch]; GPIO_WriteBit(MUX_S3_PORT, MUX_S3_PIN, (val 12) 0x01); GPIO_WriteBit(MUX_S2_PORT, MUX_S2_PIN, (val 8) 0x01); GPIO_WriteBit(MUX_S1_PORT, MUX_S1_PIN, (val 4) 0x01); GPIO_WriteBit(MUX_S0_PORT, MUX_S0_PIN, val 0x01); }工程上当然可以直接给GPIO的ODR寄存器赋值但为了代码可移植性使用标准库或HAL库的读写函数更稳妥。速度上每次通道切换不过几个微秒对采集周期没影响不必过度优化。3.2 轮询采集和DMA采集两种实现对比轮询方式适合采集频率不高、CPU资源充裕的场景。伪代码如下uint16_t adc_values[16]; void adc_scan_polling(void) { for (uint8_t i 0; i 16; i) { mux_select_channel(i); delay_us(50); // 等待通道稳定 adc_values[i] adc_read_single(); } }DMA方式适合需要连续后台采集、CPU不被采集流程占用的场景。结合定时器触发ADC转换每次转换完成通过DMA搬运到内存任务只对数组做后处理。这种方式的时序思路是开启定时器更新中断或ADC转换完成中断在中断服务函数里切换MUX通道号更新GPIO下一次定时器触发时ADC采样的是刚切换好的通道16次采样完成后软件置一个标志位主循环处理这批数据。这种方式要注意一点S0~S3的GPIO切换需要一点点时间定时器触发周期必须大于GPIO切换时间加上CD74HC4067开关建立时间实际取50微秒以上非常稳妥最大扫描周期就是16×50us800us即1kHz扫描频率对多数传感器采集场景足够。3.3 启动初始化流程细节初始化顺序建议先配置MUX控制GPIO为推挽输出拉高EN引脚再初始化ADC和DMA最后将EN拉低使能MUX。这样可以避免上电瞬间或初始化过程中意外选通通道导致ADC读到不确定电平。一个比较隐蔽的问题是MCU复位后GPIO默认状态不确定S0~S3可能处于任意组合此时COM端已经随机选通某一路。如果EN默认低电平使能外部待测信号会直接灌入ADC引脚轻则采到错误值重则影响ADC内部采样电容的初始状态。所以EN默认拉高、后使能这个顺序建议严格遵守。3.4 多通道数据排序与对齐DMA采集完成后内存里的数据是按一次触发一个值的顺序排列的但通道切换和ADC转换之间有固定延迟需要在软件里维护一个当前通道号变量每次DMA传输完成或转换完成中断时自增并回绕到0。数据排列顺序和通道映射表保持一致组包时直接按顺序填充即可。如果采集过程中还混入了其他中断或任务延迟通道号变量和实际采样值之间可能出现错位。排查方法是人为给某一通道加一个偏移电压比如CH5接3.0V看数据里对应位置是否稳定出现大值。这个方法在调试多通道时非常好用。4. 实操过程与关键验证记录4.1 我的实际电路搭建与测量数据我把CD74HC4067用在了一块基于STM32F103C8T6的采集板上电源3.3VVEE接地COM接PC0ADC_IN10S0~S3接PB0~PB3EN接PB4。16路输入信号分别用可调稳压源给不同电压范围从0.1V到3.2V。测量结果每路采样64次取平均通道设定电压(V)ADC原始值计算电压(V)误差(mV)CH00.1001320.1066CH10.5006210.497-3CH21.00012470.998-2CH31.60020051.6044CH42.20027462.197-3CH53.20040003.200012位ADC满量程电压按3.3V计算每位约0.806mV实测误差在±6mV以内折算约±7个LSB。这个结果对普通电压采集完全可用。4.2 通道切换稳定时间实测我专门用逻辑分析仪测过从GPIO切换信号发出到ADC引脚电平稳定的时间。实测在1k欧姆信号源内阻条件下通道切换后约10微秒左右电平稳定在最终值1LSB范围内。如果信号源内阻增大到100k欧姆稳定时间会超过50微秒此时50微秒的延时就不太够了建议加长到200微秒或者加运放缓冲。考虑到不同的信号源阻抗差异非常大建议在固件里保留一个可配置的稳定延时参数产品定型后根据实测标定。不要图省事直接把延时写死成最小值一旦换了传感器类型就要改固件不利于维护。4.3 长时间运行稳定性测试结果连续运行24小时采集中观察16路数据最大漂移约±12mV大部分通道在±8mV以内漂移来源主要是环境温度和参考电压的缓慢变化不影响系统功能。中间有段时间数据偶发出现单次大的跳变超过50mV后来定位为附近大功率设备启停导致的电源干扰加粗了地线并优化了滤波电容布局后明显改善。如果产品对长期漂移敏感建议在固件里加入周期性自校准逻辑在板子上留一路精准参考电压输入比如2.5V基准每次开机或定时采集这路并修正增益误差。5. 两个调试坑的完整排查过程5.1 坑一采样值随机跳变通道对不上现象是最开始调试时无论选择哪一路ADC读到的值都频繁在几个数值之间跳变而且切换通道后读到的数据像是混了前一通道的残余值感觉通道之间有串扰。排查过程第一步用万用表直接量CH0输入电压和COM引脚电压发现COM引脚电压确实等于CH0电压说明硬件链路是通的。第二步把S0~S3用杜邦线直接接地或接3.3V固定组合发现ADC读数稳定了说明问题出在GPIO切换过程。第三步示波器挂到S0引脚上观察切换瞬间波形发现GPIO从低到高跳变后S0引脚电平出现了一串明显振铃幅度接近1V持续约300纳秒。虽然CD74HC4067本身能容忍一定振铃但ADC触发采样的时刻如果正好落在振铃区间采集到的信号就不是稳定信号。根因找到了S0~S3的GPIO线走线过长且没有串接电阻走线电感和引脚电容形成LC振铃。解决办法是在每个控制引脚靠近MUX处串联33欧姆电阻并在S0~S3引脚与GND之间加10pF小电容把振铃抑制到200mV以内。实际改动后采样值变得稳定通道间串扰也基本消失。如果复现这类问题建议先去查控制信号波形不要一开始就怀疑ADC配置。ADC采到的数据只是结果的表象控制信号上的毛刺往往才是幕后元凶。5.2 坑二首采数据异常之后正常第二个问题更隐蔽通道切换后第一次采样值总是不对偏小或偏大几十个LSB但同一通道第二次、第三次采样就恢复了正常值。一开始以为是延时不够把延时从50微秒调到200微秒仍然只有第一次值异常。后来翻了MCU参考手册注意力落到ADC采样保持电容的充放电过程上。ADC在每次采样时内部采样电容需要从外部信号源抽取电荷如果外部信号源内阻较大采样电容无法在前一次转换结束后完全恢复到与当前输入信号一致的电平首次采样的结果就会实际偏小。多采几次后电容逐步逼近稳定值表现就是首采异常。解决办法也很直接通道切换后连续启动两次ADC转换第一次结果直接丢弃保留第二次结果。由于第二次采样时采样电容已经预充到接近当前通道电压结果就会准确。这个方法在STM32的多个型号上都适用实现成本几乎为零。5.3 现场调试其他小坑记录还有一个容易忽略的是S0~S3的线序反接问题。我们画PCB时S0、S1、S2、S3从MCU引出后在板子上交叉了一次导致通道选择表和实际选通的通道错位。排查时用固定电压逐通道扫描画出一张实际通道对应关系表反过来就定位了。这类问题原理上很简单但因为PCB丝印不明显往往会浪费不少时间。建议在硬件调试文档里专门建一个表格记录MCU GPIO、MUX S0~S3、通道号三者之间的实际映射关系后续写固件时直接照表填写。5.4 常见问题速查表现象可能原因解决措施某几个通道读值恒为0CH引脚漏焊、信号未接入检查硬件连接用万用表量CH引脚与信号源之间通断所有通道读数都偏大MUX导通电阻形成分压后级输入阻抗不匹配增加运放缓冲或减小信号源内阻通道切换后首采值异常ADC采样电容未预充到位连续采集两次丢弃第一次结果随机跳变不稳定控制信号振铃、电源纹波、信号源阻抗过高控制线串电阻、加滤波电容、检查地线某个通道偶尔串到相邻通道PCB布线间距过近、串扰调整布局走线增加屏蔽地线EN悬空导致行为随机EN输入浮空EN引脚接固定电平接地或拉高与逻辑分析仪共地异常地电位不一致确保共地必要时隔离供电6. 效果对比与扩展思路6.1 扩展前后采集性能对比方案改完后的整体数据16通道单轮扫描时间最快1.2ms含两次采样去首采逻辑换算扫描频率约830Hz每通道ADC值稳定跳变范围保持在±3LSB以内CPU占用率在DMA模式下几乎可以忽略。相比直接用MCU内置ADC通道这种方法用3个GPIO加一颗几块钱的芯片就拿到了16路模拟采集能力性能够用成本控制得很理想。如果后续需要更高精度可以考虑在COM端和MCU ADC之间加一级运放跟随器把MUX的RON影响彻底隔离掉。这样12位ADC采集的精度发挥会更充分。6.2 后续还可以扩展的方向CD74HC4067不止能做ADC扩展几个思路可以参考反向使用把COM当输入CH0~CH15当输出可以用少量GPIO控制多路模拟信号输出比如通过PWM滤波后的模拟电压数字信号扩展切换I2C总线上挂载的多颗同地址传感器轮询访问把多片CD74HC4067级联用EN控制不同芯片的使能理论上可以扩展到更多通道测试治具上用于自动化测试信号路由一个MCU控制所有开关切换不同的被测信号。我个人在实际操作中的一个体会模拟多路开关是那种看起来简单、用好了很省事、但细节决定成败的器件。整个调试过程下来真正让我印象深刻的不是芯片本身多难用而是排查采样抖动、首采异常这些现象时对MCU ADC采样原理和信号完整性的理解才是解决问题的关键。如果你正在做类似的扩展方案建议先把信号源内阻、延时设置、控制信号质量这些基础参数用示波器和万用表摸清楚再动手调软件能省掉非常多来回折腾的时间。
返回列表