基于STM32与AD7606的多路模拟信号程控采集系统实战大家好最近在做一个工业传感器数据采集的项目需要同时处理多路微弱的电压信号而且信号大小差异很大有的几毫伏有的几伏。直接用单片机的ADC肯定不行精度和量程都跟不上。于是我设计并验证了一套以STM32为核心搭配专业ADC芯片AD7606和程控放大器AD8421的解决方案。今天我就把这个从原理图到代码调试的完整过程分享出来手把手教你搭建一个高精度、8档增益可调、带100kHz抗混叠滤波的多路数据采集系统。这套系统特别适合用在需要采集热电偶、压力传感器、应变片等微弱信号的场合。你可以通过程序或者外部按键灵活调整放大倍数来匹配不同强度的信号确保ADC始终工作在线性最佳区域。同时内置的滤波电路能有效滤除高频噪声让采集的数据更干净、更可靠。最后数据还能实时显示在OLED屏幕上非常直观。下面咱们就从硬件到软件一步步拆解这个系统的设计要点和实现方法。1. 系统整体方案与核心芯片选型做数据采集系统第一步永远是明确需求然后选择合适的“核心队员”。我这个项目的核心需求很明确多通道需要同时采集8到16路模拟信号。高精度与宽动态范围信号幅度从毫伏级到伏级ADC本身精度要高前端还需要可调增益的放大器来“适配”小信号。抗干扰工业现场噪声多必须有滤波电路。可控可显增益要能通过程序或按键调节结果要能实时显示。基于这些需求我选择了以下核心芯片搭建系统主控MCUSTM32系列。这个不用多说资源丰富、性价比高、生态完善是嵌入式项目的老朋友了。它负责控制整个采集流程、处理数据、驱动显示和响应按键。ADC芯片AD7606。这是本系统的数据采集核心。为什么选它真正的同步采样内部有8个独立的ADC可以同时锁存8路输入信号并转换对于需要分析多通道相位关系的应用比如电机控制、振动分析至关重要。高精度16位分辨率意味着它能将输入电压范围分成65536个等级精度很高。集成度高内部集成了输入缓冲、过压保护等简化了外围电路设计。程控放大器AD8421。这是一款低噪声、高精度的仪表放大器。它的增益由一个外部电阻Rg决定公式是 G 1 (9.9 kΩ / Rg)。我们通过模拟开关切换不同的Rg就能实现程控增益。本项目实现了8阶增益可调。模拟开关ADG708。这是一个8通道单刀单掷SPST模拟开关。我用它来切换连接到AD8421增益电阻引脚的不同电阻从而实现增益档位的数字控制。滤波与信号源采用运放如LM358搭建100kHz有源低通滤波器作为抗混叠滤波器。为了测试滤波器性能还用了DDS模块如AD9850来产生可调频率的纯净正弦波。整个系统的工作流程是这样的传感器弱信号 →AD8421程控放大增益由STM32通过ADG708设置→100kHz低通滤波滤除高频噪声→AD7606同步采样16位高精度数字化→STM32读取处理→OLED显示。如果采集值异常如超量程系统还会自动报警并降低增益起到保护作用。2. 硬件电路设计详解与踩坑心得原理图是硬件的灵魂设计不好后面调试会非常痛苦。我结合自己的板子把几个关键电路的设计要点和容易踩的坑给大家捋一捋。2.1 电源与接地稳定性的基石模拟电路最怕电源噪声和地线干扰。我的设计如下5V输入 —— 磁珠 —— 电解电容瓷片电容并联滤波 —— 模拟部分供电 | —— 0欧姆电阻 —— 数字部分供电 | —— 数字地DGND设计要点磁珠Ferrite Bead放在电源入口专门吸收高频噪声相当于一个高频滤波器。电容并联大容值电解电容如100uF应对低频波动小容值瓷片电容如0.1uF滤除高频噪声二者缺一不可。单点接地这是最关键的一点模拟地AGND和数字地DGND在电源入口处通过一个0欧姆电阻单点连接。这样能避免数字部分的开关噪声通过地线串扰到敏感的模拟电路尤其是放大器和ADC基准源。直接铺一块铜箔把模拟和数字地连在一起是常见错误。注意PCB布局时这个0欧姆电阻的位置要精心选择通常放在AD7606芯片下方或附近。模拟部分和数字部分的铺铜要尽量分开最后只在这一点汇合。2.2 程控放大与增益调节电路这是应对弱信号的核心。我用AD8421作为放大主角用ADG708模拟开关来切换增益电阻。AD8421放大电路图示AD8421典型应用电路Rg为增益设置电阻增益公式G 1 (9.9 kΩ / Rg)。你需要多大的增益就反算出需要多大的Rg。正负电源供电为了能放大正负双向的信号比如传感器桥式输出AD8421需要正负电源如±5V或±15V。这扩大了系统的输入电压动态范围。调零电路原理图中有一个电位器用于输出调零。但在实际测试中我发现如果放大器本身性能好、电阻精度高这个调零影响不大可以根据实际情况决定是否省略以简化电路。ADG708增益调节电路图示ADG708连接多个精密电阻电阻另一端连接到AD8421的Rg引脚工作原理ADG708有8个开关S1-S8每个开关串联一个精密电阻R1-R8所有电阻的另一端连在一起接到AD8421的Rg引脚。STM32通过3个地址线A0, A1, A2选择接通哪一个开关从而将对应的电阻接入电路改变增益。电阻选型一定要用低温漂、高精度的电阻比如0.1%精度的金属膜电阻。普通电阻的温漂会导致增益随温度变化影响系统精度。增益指示灯为了方便观察当前档位我设计了LED指示灯电路由STM32的GPIO直接驱动哪个档位有效对应的LED就亮起。2.3 滤波与信号调理在ADCAD7606之前必须放置一个抗混叠滤波器。它的作用是滤除信号中高于ADC采样频率一半奈奎斯特频率的高频成分防止这些高频信号混叠到有效频带内造成失真。我设计了一个截止频率为100kHz的有源低通滤波器通常用运放如LM358搭建巴特沃斯或切比雪夫滤波器。这意味着频率高于100kHz的噪声会被大幅衰减。这个频率值是根据我的信号最高频率和AD7606的采样率来确定的你需要根据自己项目的实际情况计算。提示为了验证这个滤波器的性能我专门用DDS信号源AD9850模块产生一个高于100kHz比如150kHz的正弦波输入滤波器。用示波器观察输出可以看到波形幅度被明显衰减证明滤波器工作正常。这个测试方法非常直观有效。3. 软件设计与STM32驱动实战硬件搭好了接下来就是让STM32“指挥”整个系统工作。软件部分主要分为系统初始化、AD7606驱动、增益控制、数据处理与显示。3.1 工程结构与初始化我的工程主要文件夹结构如下根据原文提示User/ ├── main.c // 主程序 ├── ad7606.c/.h // AD7606驱动 ├── adg708.c/.h // 增益控制驱动 ├── oled.c/.h // OLED显示驱动 ├── key.c/.h // 按键扫描 └── filter.c/.h // 软件滤波算法可选 Hardware/ // 底层硬件驱动 MDK-ARM/ // Keil工程文件系统上电后在main()函数中需要按顺序初始化各模块int main(void) { HAL_Init(); // 初始化HAL库 SystemClock_Config(); // 配置系统时钟 MX_GPIO_Init(); // 初始化GPIO MX_SPI1_Init(); // 初始化SPI用于AD7606或OLED MX_USART1_UART_Init(); // 初始化串口用于调试打印 OLED_Init(); // 初始化OLED显示屏 AD7606_Init(); // 初始化AD7606 ADG708_Init(); // 初始化增益控制开关 KEY_Init(); // 初始化按键 OLED_ShowString(0, 0, Data Acq System Ready); HAL_Delay(1000); OLED_Clear(); // 设置默认增益为1 ADG708_SetGain(GAIN_1); while (1) { // 1. 检查按键切换增益 Key_Process(); // 2. 启动一次AD转换并读取8通道数据 AD7606_ReadAllChannels(adc_values); // 3. 将原始ADC值转换为实际电压值需考虑当前增益 ConvertToVoltage(adc_values, voltage_values, current_gain); // 4. 判断是否过压报警 CheckOverVoltage(voltage_values); // 5. 在OLED上显示电压值和当前增益 Display_Voltage(voltage_values); // 6. 延时或等待下一次定时采集 HAL_Delay(100); } }3.2 AD7606驱动关键代码解析AD7606可以通过并行或串行SPI接口与STM32通信。为了节省IO口我选择了SPI模式。它的操作时序很关键。初始化AD7606void AD7606_Init(void) { // 1. 配置控制引脚RESET, CONVST, BUSY, CS, RD/SCLK GPIO_InitTypeDef GPIO_InitStruct {0}; // ... 将相关引脚配置为输出或输入 ... // 2. 复位AD7606 AD7606_RST_LOW(); HAL_Delay(1); AD7606_RST_HIGH(); HAL_Delay(1); // 3. 配置AD7606的SPI寄存器如设置输入范围、过采样等 // 通过SPI写入配置字具体寄存器地址和值需查阅AD7606数据手册 AD7606_WriteReg(REG_RANGE, 0x01); // 例如设置输入范围为±5V }读取8通道数据 这是最核心的操作。AD7606的转换由CONVST引脚启动转换完成后BUSY引脚变低然后才能读取数据。void AD7606_ReadAllChannels(int16_t *data) { // 1. 启动一次转换同时采样所有通道 AD7606_CONVST_LOW(); HAL_Delay(1); // 保持低电平至少25ns根据数据手册 AD7606_CONVST_HIGH(); // 2. 等待转换完成 while(AD7606_BUSY_READ() 1); // 等待BUSY引脚变低 // 3. 通过SPI连续读取8个通道的16位数据 AD7606_CS_LOW(); for(uint8_t i 0; i 8; i) { // 通过SPI接收两个字节组合成一个16位有符号数 data[i] AD7606_SPI_ReadWord(); } AD7606_CS_HIGH(); }3.3 增益控制与过压保护逻辑增益控制就是操作ADG708模拟开关。它非常简单只需要控制3个地址线A0, A1, A2来选择通道。// 定义增益档位对应的开关通道 #define GAIN_1 0 // 通道0电阻R1 #define GAIN_2 1 // 通道1电阻R2 // ... 以此类推直到 GAIN_8 对应通道7 void ADG708_SetGain(uint8_t gain_channel) { // 根据目标通道号设置A2, A1, A0三个GPIO的电平 HAL_GPIO_WritePin(GAIN_A2_GPIO_Port, GAIN_A2_Pin, (gain_channel 0x04) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(GAIN_A1_GPIO_Port, GAIN_A1_Pin, (gain_channel 0x02) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(GAIN_A0_GPIO_Port, GAIN_A0_Pin, (gain_channel 0x01) ? GPIO_PIN_SET : GPIO_PIN_RESET); // 更新当前增益档位状态并点亮对应的LED current_gain_index gain_channel; Update_Gain_LED(gain_channel); }过压保护是一个重要的安全功能。当STM32读取到某通道的电压值接近或超过ADC量程比如±5V系统下达到4.8V说明信号过强当前增益可能太高。void CheckOverVoltage(float *voltage) { for(int i 0; i 8; i) { if(fabs(voltage[i]) OVER_VOLTAGE_THRESHOLD) // 例如阈值设为4.5V { // 触发报警比如让蜂鸣器响或点亮报警灯 Trigger_Alarm(); // 自动将增益降低一档如果当前不是最低档 if(current_gain_index GAIN_1) { ADG708_SetGain(current_gain_index - 1); OLED_ShowString(0, 5, OVP! Gain Reduced); } break; // 一次只处理一个过压通道 } } }4. 系统测试与性能验证硬件焊接好程序烧录进去就到了最激动人心的测试环节。我主要做了以下几项测试静态精度测试在增益为1即放大倍数为1时用精密电压源给系统输入几个已知电压如1.000V 2.500V同时用高位数字万用表测量实际输入电压。对比OLED屏幕上显示的电压值。实测结果显示误差非常小通常在几个毫伏以内证明了ADC和前端通路的高精度。程控增益测试输入一个固定的弱信号如10mV。通过按键逐步增加增益。观察OLED显示的电压值是否按预期的倍数增加。例如增益从1切换到10倍显示电压应从10mV左右变为100mV左右。这个测试验证了ADG708和AD8421组成的程控放大电路工作正常。低通滤波器性能测试使用DDS信号源AD9850模块产生一个纯净的正弦波。先输入一个50kHz的信号观察示波器上滤波器输出波形幅度应基本无衰减。再将频率调到150kHz高于设计的100kHz截止频率观察输出波形幅度应明显减小。这个测试直观地验证了滤波器有效滤除了高频成分。多通道同步性测试用同一个信号源同时输入多路或给多路输入有固定相位差的信号通过STM32读取并记录AD7606各通道的数据。分析数据的时间戳或顺序可以验证AD7606的同步采样特性。实物调试心得电源一定要干净用示波器探头测量放大器和ADC的电源引脚如果看到明显的毛刺或噪声赶紧检查滤波电容和布局。地线环路要避免特别是模拟部分尽量采用星型单点接地。我第一版板子地线没处理好导致小信号放大时底噪很大。SPI通信速率刚开始SPI时钟设得太高导致AD7606数据读取错误。后来根据数据手册降低速率后问题解决。务必仔细看芯片数据手册的时序要求。增益电阻精度一开始用了普通5%精度的电阻测试发现不同增益档位的误差不一致。换成0.1%的精密电阻后线性度大大改善。这个项目从立项到完成测试花了相当一段时间但整个过程让我对高精度数据采集系统的每一个环节都有了更深刻的理解。希望这份详细的教程能帮你少走弯路。如果你在复现过程中遇到任何问题欢迎一起交流探讨。