ARTICLE DETAIL

资讯详情

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

AD7606多通道同步采样ADC详解:从硬件设计到STM32驱动实践

AD7606多通道同步采样ADC详解:从硬件设计到STM32驱动实践 搞数据采集的人应该都遇到过这种尴尬事一个系统里要采的模拟量往往不止一路比如三相电机的U、V、W相电流加母线电压或者振动监测里的多路加速度信号。如果拿普通ADC一颗一颗轮询扫描每一路之间都存在时间差等把所有通道扫完前面的信号早就变了后面算相位、算功率、分析同步关系全都会出错。AD7606就是专门用来解决这个痛点的8路模拟输入、16位分辨率、200kSPS采样率所有通道在同一时刻完成采样并锁存之后主控想怎么读就怎么读。这篇文章我会从硬件引脚、电源与基准设计、并行和SPI接口时序、STM32下的驱动配置到实际调试中遇到的典型问题完整过一遍这颗芯片。无论你是第一次接触AD7606还是已经画完板子正在调固件都能在这里找到直接能用的内容。1. AD7606 到底是一颗什么样的芯片1.1 定位与解决的核心痛点AD7606是ADI推出的一款8通道同步采样ADC严格来说它并不是一颗裸ADC而是一个完整的模拟前端加转换器加数字接口的组合方案。芯片内部集成了输入钳位保护、一阶抗混叠滤波、放大器、16位逐次逼近型ADC、数字滤波器和参考源外部几乎不需要额外搭配运放和基准源接上电源和接口就能工作。它解决的核心问题有两个。第一是同步采样问题8个通道共用一个采样时钟所有输入在同一个时刻被“冻结”这样后续分析通道之间的相位关系才有意义。第二是简化了多通道采集系统设计传统的8通道同步方案往往要拼多颗ADC每颗ADC还要单独配基准、配运放、配参考电压板子面积和BOM成本都非常可观。AD7606把这些全部集成到一颗LQFP-64封装里外围器件数量大幅下降这对做产品的人非常友好。1.2 硬件规格速览我先给一张核心参数表方便你快速判断这颗芯片适不适合你的项目后面的内容再逐个展开。参数数值/范围备注通道数8路AD7606-4为4路、AD7606-6为6路全系列引脚兼容分辨率16位无失码采样率最高200kSPS8通道同步时单通道也是200kSPS模拟输入范围±5V / ±10V 可编程RANGE引脚控制也可寄存器配置模拟输入阻抗约1MΩ高阻输入无需额外驱动运放片内基准2.5V精度约±0.1%REFIN/REFOUT引脚引出可外部驱动数字接口并行16位/8位、SPI串行标准SPI和并行总线都支持工作电压AVcc 5VVDRIVE 2.3V~5.25V数字接口电平由VDRIVE决定过采样2x/4x/8x/16x/32x/64x可引脚或寄存器配置封装LQFP-64常规封装手工焊接难度不大这里有一个值得注意的点输入阻抗1MΩ是这款芯片的典型优势。很多传统ADC的输入阻抗只有几十千欧前端必须加运放做缓冲否则信号源一接上去电压就被拉低了。AD7606的输入端等效阻抗比较高大部分传感器、信号调理电路可以直接连接省掉一级运放的同时也降低了系统噪声和成本。1.3 与同类方案怎么选如果你正在纠结“到底该用AD7606还是用普通SAR ADC”我提供一个简单的决策思路。先说误区和对比维度。普通单通道SAR ADC例如AD7685、AD7091这类单颗成本确实比AD7606低但要做到8路同步你需要8颗芯片同时还得保证8颗的参考电压、时钟、采样触发完全一致这在工程上非常难。另一种做法是用多路复用器加一颗ADC比如用ADG706做扫描切换但这种方式本质上还是顺序采样通道间有时间差和“同步”两个字完全不沾边。只有对相位关系不敏感的场景比如电池电压巡检、温度采集、低频DC信号检测才适合用“MUX单ADC”这种低成本方案。如果你的系统涉及三相电参数测量、电机驱动电流波形分析、并网逆变器功率计算、振动模态测试这类强实时同步需求AD7606是性价比很高的选择。它省掉了多片ADC同步的硬件设计接口也简单用普通单片机就能驱动起来。至于具体选AD7606还是新款AD7606B主要看你的信号源阻抗和精度需求B版本在输入阻抗和直流精度上做了进一步优化如果对精度敏感可以优先考虑价格也略高一些。2. 硬件设计要点连接、供电与信号调理2.1 电源与基准最容易翻车的地方AD7606的供电分为两路模拟电源AVcc统一用5V数字接口电源VDRIVE接你的主控IO电压。很多人第一次画板子以为整块板子都是3.3V系统就把AVcc和VDRIVE全接到3.3V结果芯片完全不工作或者测量结果一塌糊涂。AVcc必须给5V这一点看数据手册第一页就会注意到但实际项目里还是经常有人踩。VDRIVE的作用是设置数字接口的电平标准。如果主控是3.3V的STM32VDRIVE就接3.3V这样并行总线和SPI信号的逻辑电平是3.3V兼容的不需要额外电平转换。如果主控是5V系统VDRIVE就接5V。理论上VDRIVE的范围是2.3V到5.25V灵活性比较大但它和AVcc之间没有内部关联各自独立供电即可。基准电压方面芯片内部集成了2.5V基准源默认情况下REFOUT引脚会输出2.5VREFIN/REFOUT引脚只需要按要求接一颗去耦电容。我实测下来这颗去耦电容的容值不能随便省太小会导致基准噪声变大影响ADC的DNL表现太大又会拖慢基准建立时间上电后如果很快启动采样前几百个点可能明显偏大或偏小。按照手册要求这里用10uF钽电容或22uF陶瓷电容并联0.1uF高频去耦电容是比较稳妥的做法。供电去耦我建议这样处理AVcc引脚附近放一颗10uF电容加一颗0.1uF电容靠近引脚放置VDRIVE附近至少放一颗0.1uF电容。模拟地和数字地采用单点连接ADC下方不要分割地平面。很多噪声问题并不是来自ADC本身而是来自地平面回流路径不干净这一点在布板时就要注意。2.2 模拟输入范围与前端电路AD7606的模拟输入范围由RANGE引脚决定高电平时为±10V低电平时为±5V。注意这个引脚不是纯数字电平内部有逻辑阈值但外部接法很简单直接接AVcc或GND即可。还有一个细节RANGE引脚的状态在上电复位后被锁存运行期间也可以通过寄存器重新配置量程两种方式选一种用就行不要混着来导致配置状态不确定。±5V和±10V怎么理解呢它的输入通道内部有缩放电阻网络把前端信号衰减到ADC核心的输入范围内。16位分辨率对应的最小量化步长可以算一下±5V量程时满量程是10V除以65536大约152.59uV±10V量程时满量程是20V除以65536大约305.18uV。这个数值决定了你能分辨的最小电压变化做高精度测量时需要根据信号幅值选择合适的量程尽量让信号接近满量程但又要留出一定的余量防止削波。前端电路有几个坑要重点提一下。第一个坑是输入滤波电容不能乱加我看到过不少设计直接在模拟输入端对地并联一颗0.1uF电容结果测量值偏低、建立时间变长。原因很简单AD7606的输入端等效模型是一个开关电容网络外部电容太大会和内部采样电容之间产生电荷分配导致建立误差。如果你想在外部加RC抗混叠滤波R和C的参数需要根据信号频率和采样率仔细计算并且把C控制在几百皮法到几纳法这个量级再用运放做缓冲会更加稳妥。第二个坑是输入保护。AD7606内部有钳位保护电路输入电压超过量程较多时会被钳位这能保护ADC不受损坏但不能无限承受高压。如果信号源可能产生几十伏甚至更高的电压尖峰一定要在输入端串联限流电阻电阻值一般选几千欧辅助内部钳位二极管泄放能量。我做过一个电机电流采集项目电流互感器输出在电机启停瞬间有比较大的过冲一开始没加限流电阻烧了两颗AD7606后来在每路输入串了2kΩ电阻问题就消失了。2.3 数字接口怎么接并行、串行与字节模式AD7606支持三种数字接口模式通过引脚配置选择。第一种是并行16位模式性能最好、速度最快适合需要连续高速采样的场景。第二种是并行字节模式数据总线只用8位分两次读出高字节和低字节适合8位单片机。第三种是SPI串行模式使用DOUT引脚逐位输出数据占用引脚最少速度比并行模式低但胜在接线简单。接口模式的选择也需要注意对应引脚的接法。并行模式下CS和RD信号共同控制数据输出CONVST引脚负责启动转换BUSY引脚反馈转换状态。串行模式下要用SCLK驱动时钟DOUT输出数据RD引脚要接高电平或者悬空处理。我自己的习惯是MCU引脚充足的项目优先用并行16位模式因为读取速度快、时序简单不容易出问题引脚紧张的项目才用SPI模式而且SPI模式下读取8个通道需要连续读128位对SPI外设的FIFO深度的要求会高一些用普通IO口模拟SPI也可以但速度会慢不少。还有一个容易被忽略的引脚是CONVST A和CONVST B。AD7606把8个通道分成两组通道1到4由CONVST A控制通道5到8由CONVST B控制。如果你需要所有通道严格同步启动转换务必将CONVST A和B短接在一起用同一个信号触发。如果两个信号存在时间差两组通道就会在不同时刻采样最终做出来的数据就不是真正同步的。这个细节在设计原理图时就要想清楚别等软件调完了才发现两组数据有固定的相位偏差。3. 驱动配置与数据采集实操3.1 并行模式 STM32F407 FSMC 读取在STM32F407这类带FSMC外设的单片机上接AD7606并行接口是一件非常舒服的事。FSMC可以把AD7606映射到内存地址空间读写外部模块就像读写普通变量一样简单不需要手动控制CS和RD波形。AD7606的数据总线和控制引脚直接接到FSMC对应的引脚把片选接到Bank1的NE1基地址就是0x60000000。FSMC的时序参数需要根据AD7606的读周期时间要求来配置。AD7606的典型读取时序要求CS拉低到RD拉低之间有最小建立时间RD有效宽度和RD撤销到数据失效之间也有约束。FSMC配置成异步模式A、16位数据宽度并用如下时序参数是比较稳妥的起始值RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE, ENABLE); RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE); // 省略GPIO复用配置注意将PE7~PE15、PD8~PD15等数据线设为AF12 FSMC_NORSRAMTimingInitTypeDef readTiming; readTiming.FSMC_AddressSetupTime 0x02; readTiming.FSMC_AddressHoldTime 0x00; readTiming.FSMC_DataSetupTime 0x0F; readTiming.FSMC_BusTurnAroundDuration 0x00; readTiming.FSMC_CLKDivision 0x00; readTiming.FSMC_DataLatency 0x00; readTiming.FSMC_AccessMode FSMC_AccessMode_A; FSMC_NORSRAMInitTypeDef fsmcInit; fsmcInit.FSMC_Bank FSMC_Bank1_NORSRAM1; fsmcInit.FSMC_DataAddressMux FSMC_DataAddressMux_Disable; fsmcInit.FSMC_MemoryType FSMC_MemoryType_SRAM; fsmcInit.FSMC_MemoryDataWidth FSMC_MemoryDataWidth_16b; fsmcInit.FSMC_BurstAccessMode FSMC_BurstAccessMode_Disable; fsmcInit.FSMC_AsynchronousWait FSMC_AsynchronousWait_Disable; fsmcInit.FSMC_WaitSignalPolarity FSMC_WaitSignalPolarity_Low; fsmcInit.FSMC_WrapMode FSMC_WrapMode_Disable; fsmcInit.FSMC_WaitSignalActive FSMC_WaitSignalActive_BeforeWaitState; fsmcInit.FSMC_WriteOperation FSMC_WriteOperation_Enable; fsmcInit.FSMC_WaitSignal FSMC_WaitSignal_Disable; fsmcInit.FSMC_ExtendedMode FSMC_ExtendedMode_Disable; fsmcInit.FSMC_WriteBurst FSMC_WriteBurst_Disable; fsmcInit.FSMC_ReadWriteTimingStruct readTiming; fsmcInit.FSMC_WriteTimingStruct readTiming; FSMC_NORSRAMInit(fsmcInit); FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);读取数据的流程就简单了先触发一次转换等待BUSY引脚释放再从基地址连续读取8次。每读一次FSMC会自动生成一个RD脉冲AD7606会顺序输出当前通道的数据。代码如下#define AD7606_BASE ((uint32_t)0x60000000) #define AD7606 (*(volatile uint16_t *)AD7606_BASE) // 触发一次同步转换CONVST默认低电平拉高产生上升沿 void AD7606_StartConvert(void) { HAL_GPIO_WritePin(CONVST_GPIO_Port, CONVST_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(CONVST_GPIO_Port, CONVST_Pin, GPIO_PIN_RESET); } // 等待BUSY拉高后拉低表示一次转换完成 void AD7606_WaitConvertDone(void) { while (HAL_GPIO_ReadPin(BUSY_GPIO_Port, BUSY_Pin) GPIO_PIN_RESET); while (HAL_GPIO_ReadPin(BUSY_GPIO_Port, BUSY_Pin) GPIO_PIN_SET); } // 读取8通道数据结果存入samples数组 void AD7606_ReadAllChannels(int16_t *samples) { AD7606_StartConvert(); AD7606_WaitConvertDone(); for (int i 0; i 8; i) { samples[i] (int16_t)AD7606; } }这个代码有两点需要解释。第一等待BUSY时我特意写了两个while循环先等它拉高再等它拉低这样能确保转换确实已经开始并且结束而不是因为之前的状态残留导致误判。第二连续读取同一地址8次FSMC产生的读时序是逐个有效的完全符合AD7606“CS保持低电平、RD连续拉低”的读取方式。实测下来用这套配置在168MHz主频下读取8个通道整体耗时极短跑满200kSPS没有任何压力。3.2 SPI 串行读取与寄存器配置如果你用的是SPI模式连接就清爽很多CS、SCLK、DOUT三根线加上CONVST和BUSY就能工作。AD7606在SPI模式下CS拉低后SCLK每个时钟沿从DOUT输出一位数据通道1的数据在前16个SCLK周期输出通道2接着是后16个周期以此类推8个通道总共需要128个SCLK周期。所以读取一次完整数据SPI的接收长度是16字节。SPI的时钟极性和相位建议设置为CPOL0、CPHA1数据手册的时序图里DOUT的数据是在SCLK下降沿之后变化的主机在上升沿处采样最稳妥。如果你用的MCU的SPI外设支持配置就用模式1如果不支持用GPIO模拟SPI时也要严格按照“下降沿移出、上升沿采样”的时序来做。寄存器配置也是通过SPI写入的。AD7606的片上寄存器可以配置过采样倍率、模拟输入范围、软复位等功能。使用寄存器配置前需要确保芯片没有在转换中按手册流程拉低CS后发送16位数据高字节是寄存器地址低字节是配置值。我在这里给一个通用的写寄存器函数框架具体寄存器地址和位定义一定要对照你自己芯片版本的数据手册void AD7606_WriteRegister(uint8_t reg, uint8_t value) { uint16_t cmd (uint16_t)((reg 8) | value); HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(hspi, (uint8_t *)cmd, 2, 1000); HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET); }使用SPI模式要特别注意引脚状态的默认电平。CS必须默认拉高SCLK默认低电平DOUT是输出模式。另外SPI模式下RD引脚建议接高电平或通过电阻上拉防止误触发并行读取操作。我之前在SPI模式下调不出数据排查了半天发现是RD引脚悬空噪声干扰导致芯片进入并行输出状态之后把它固定接高电平就正常了。3.3 过采样、量程切换与数据换算过采样是AD7606一个非常实用的功能。它的本质是让ADC内部以高于最终输出速率的速度多次采样同一输入信号然后通过数字滤波求平均从而换取更高的有效位数和更低的噪声。AD7606的过采样倍率由OS引脚组合决定也可以写成寄存器倍率和对应的最大输出速率如下表OS[2]OS[1]OS[0]过采样倍率最大输出速率000无过采样200kSPS0012x100kSPS0104x50kSPS0118x25kSPS10016x12.5kSPS10132x6.25kSPS11064x3.125kSPS我的使用经验是信号频率不高但对噪声敏感的场景比如称重、温度、直流电压测量开启16x或32x过采样能显著降低输出数据的波动高频信号采集场景则关闭过采样保证200kSPS的输出速率。过采样并不能替代外部抗混叠滤波它解决的是量化噪声和部分白噪声如果信号本身有带外强干扰还是要靠模拟滤波器来抑制。量程切换和信号换算也是一起要搞清楚的。如果你的RANGE引脚固定为±5V那么16位数据中0x7FFF对应大约5V0x8000对应-5V0x0000并不是0V。实际电压值建议这样计算// 以±5V量程为例 float voltage (float)raw / 32768.0f * 5.0f; // raw是int16_t类型用int16_t类型接收数据后正值范围是0到32767数据手册里满量程对应的码值会低于0x7FFF一点点但在绝大部分应用中按满量程计算已经足够。±10V量程时把5.0f换成10.0f即可。如果你要追求极致的精度需要根据手册的增益误差参数做校准补偿这是精密测量项目里另外一个话题这里先不展开。4. 常见问题与排查技巧实录4.1 读出来的数据全为 0 或全为 0xFFFF这个问题在并行接口上尤其常见数据全为0往往说明CS和RD的时序没有正确到达芯片主控读到的数据总线一直是某个固定状态。我建议先拿示波器同时观察CS、RD和某个数据位看系统跑起来后有没有正常的读脉冲出现。如果CS或RD信号根本没有动作大概率是FSMC或者GPIO配置有问题尤其是GPIO的模式没有改成复用推挽输出。数据全为0xFFFF时另一种可能是SPI模式下DOUT引脚被外部环境干扰或者VDRIVE电压不对IO电平不满足阈值要求。先检查VDRIVE电压是否在合理范围再确认DOUT引脚有没有上拉或者被其他信号占用。还有一个我踩过的坑芯片没有完成复位就开始读取数据。AD7606上电后需要一小段复位时间如果主控启动速度太快在芯片未就绪时就去触发转换BUSY信号根本不会正常产生读出来的数据自然不对。解决方法是初始化时先等待几十毫秒再拉一次RESET引脚确保芯片处于已知状态。4.2 数据跳变明显、噪声偏大这种问题九成出在电源或基准上而不是ADC本身。你可以做一个实验把所有模拟输入接到GND然后看采样值是否有大幅度的跳动。如果此时噪声还是比较大优先检查AVcc的电源质量AD7606的模拟电源最好由低噪声LDO供电不要直接用开关电源的输出。基准去耦电容也值得重新检查。REFIN/REFOUT的电容如果容量太小基准会抖动ADC的码值就会跟着跳。另外数字信号走线和模拟输入走线如果靠得太近数字开关噪声也会耦合到模拟输入上。布线时数字接口区域和模拟输入区域要分隔开最好在ADC下方铺设完整的模拟地平面。如果板子已经做完了可以尝试把过采样倍率开到16x牺牲一点输出速率来换取稳定性这是我是实测中比较有效的补救手段。4.3 多通道波形不同步或存在相位差这个问题特别迷惑人表面上看每个通道都能正常读到数据但把几个通道的波形画出来发现存在固定的时间偏移。如果你确认硬件上已经把CONVST A和CONVST B短接软件也是同一个信号触发那么瓶颈很可能在读取方式上。并行模式下AD7606在读取过程中会把当前通道的数据锁存但如果你在读取通道之前又额外触发了一次转换比如在for循环里调用了转换函数那么先读的通道和后读的通道实际不是同一次转换的结果自然就会出现时间上的错位。解决办法非常简单保证一次读8个通道的过程中不插入任何新的触发指令。另一个容易忽略的因素是BUSY信号的处理。如果软件没有等到BUSY释放就立刻读数据可能拿到的是上一次转换的残留值或者通道间数据错位。我建议在所有采集代码中都要显式地等待BUSY完全回到低电平再开始读取这个习惯能避免大量诡异问题。5. 个人经验几个容易被忽略的细节最后分享几个我在多个项目中反复踩过、后来形成固定习惯的细节希望能帮你少走弯路。第一原理图阶段就把CONVST A和CONVST B的短接画清楚。我看到不少板子把这两个引脚分别引到MCU的两个GPIO软件里又忘记同时触发导致通道1到4和通道5到8之间存在采样时刻差。如果你的项目必须同步硬件上就直接短接让它们永远不可能被软件分开控制。第二上电后将RESET引脚主动拉低再拉高一次。AD7606虽然标称内部有上电复位但在实际项目中尤其是电源上升沿比较缓慢的情况下不主动复位可能会出现启动异常。我在固件初始化里做的第一件事就是复位AD7606等复位完成后再配置量程和过采样用下来非常稳。第三调试时不要只盯数字输出偶尔看看BUSY信号的波形。BUSY是一个很好的“健康指示器”正常转换时它会拉高一段时间再拉低时间宽度与过采样配置相关。如果BUSY完全没有反应那基本可以断定模拟电源、外部时钟或触发信号有问题不用再浪费时间查数据总线。第四数据换算时统一用int16_t接收原始值而不要用uint16_t。AD7606输出的是二进制补码格式正负值都有用无符号类型接收会把负值变成很大的正数导致电压换算出现离谱结果。这个细节非常小但我在论坛上见过不少新手在这里困惑很久。AD7606这颗芯片的文档比较全面官方提供的数据手册里有非常详细的时序图和寄存器说明遇到问题先翻手册比我这里的经验更权威。用它的过程整体上是省心的真正花时间的往往是外围电路和软件配合这些细节希望这篇内容能让你直接避开我踩过的那些坑。
返回列表