
简介面向嵌入式开发者的STM32驱动AD7175源码包聚焦高性能十六位数模转换器的SPI通信与数据采集实现适合工业控制、医疗仪器等需要低噪声高精度采集的场景。压缩包仅三KB共两个文件头文件包含寄存器定义与命令字源文件提供初始化、SPI总线配置、工作模式切换和转换结果读取等完整函数结构紧凑可直接移植。已有三千九百三十人学习下载代码演示了连续转换、单次转换等典型配置流程并给出基于官方开发环境的调试优化建议能帮助读者快速定位配置问题缩短驱动开发周期是学习高精度ADC驱动编写与调试的实用参考资料。 把STM32和AD7175凑到一块多半是在做称重、热电偶测温、应变式传感器采集这类对精度有硬性要求的活儿。AD7175是ADI的24位Sigma-Delta ADC自带PGA、数字滤波器、内部基准一片就能顶半个模拟前端而STM32负责控制、通信、数据处理属于最常见也最稳妥的主控选择。这篇笔记把我驱动AD7175的完整源码思路、SPI时序、寄存器配置顺序、数据读取机制和调试过程中踩过的坑一次讲透代码可以直接参考移植适合正在调这块芯片或者准备选型的朋友。我调这块板子前后花了将近两周真正卡住我的倒不是SPI读写本身而是芯片的状态机逻辑和滤波配置。很多细节数据手册上写得清楚但新手容易忽略等出了问题再翻手册就很被动了。下面按我实际项目的推进顺序来写尽量还原当时的思考过程。1. 为什么这年头还要自己写AD7175驱动1.1 这颗ADC到底强在哪AD7175系列在ADI产品线里的定位是快速建立、高精度转换器通俗讲就是既要分辨率高又不想牺牲速度。它最核心的几个指标24位无失码分辨率做微伏级信号采集绰绰有余最高输出数据速率250kSPS视具体型号和模式而定比同级别的ADS1256快不少内置PGA可编程增益放大器增益范围1到128直接接桥式传感器不用额外加仪表放大器多种数字滤波器可选Sinc3、Sinc4、Sinc5Sinc1等方便对工频干扰做针对性抑制内部集成2.5V基准源温漂指标很不错省掉一个外部基准芯片我做的是工业称重方案传感器输出灵敏度大约2mV/V加上5V激励后满量程也就10mV左右。这个量级的信号如果用普通24位ADC不加PGA分辨率根本不够看。AD7175的PGA能把信号放大到ADC满量程附近才真正发挥出24位的动态范围。1.2 和ADS1256比怎么选很多初学者上手第一颗高精度ADC都是TI的ADS1256网上教程多、资料全几乎是默认选择。但AD7175和ADS1256的差异其实挺大选型时要想清楚对比项ADS1256AD7175-2通道数8路单端/4路差分2路差分最高速率约30kSPS250kSPSPGA增益1-641-128滤波器固定Sinc多种Sinc组合内部基准温漂一般温漂指标更好价格相对便宜偏贵我的结论是如果只是做多通道低速数据采集ADS1256性价比更高但对精度、建立时间、抗干扰有硬需求AD7175贵得值。不过要特别提醒AD7175-2只有2个差分通道如果你要同时采集4路以上信号要么用AD7175-8要么多片并行。选型时务必先把通道数想清楚我就是没算够通道最后板子上被迫多加了一片。2. 驱动源码结构从一开始就别写成大泥球2.1 分层架构与文件组织很多初学者喜欢把SPI读写、寄存器配置、数据处理全堆在main.c里前期调试确实方便但一旦要换主控、加通道、改滤波策略后期改起来想骂人。AD7175的寄存器不少状态机也不算简单没有清晰分层的话出问题根本无从下手。我采用的源码结构是这种ad7175_driver/ ├── ad7175.h // 寄存器地址、数据结构定义 ├── ad7175.c // 驱动核心初始化、寄存器读写、数据读取 ├── ad7175_platform.c/h // 平台适配层SPI发送、CS控制、延时 └── app_measure.c // 应用层标定、软件滤波、数据上报这样分层的核心原则是驱动核心代码不直接调用HAL库的SPI接口而是通过platform层提供的HAL_SPI_WriteByte、HAL_SPI_ReadByte来操作硬件。这样以后从STM32F103换到F407或者从HAL库换成标准库、LL库只需要改platform层上层的寄存器配置和数据读取逻辑完全不用动。实测换平台只要半天。2.2 核心API与设计要点驱动对外暴露的接口我尽量收敛保持最少够用int32_t AD7175_Init(void); int32_t AD7175_Reset(void); int32_t AD7175_SetChannel(uint8_t ch); int32_t AD7175_SetODR(uint32_t odr); int32_t AD7175_StartContinuous(uint8_t ch); int32_t AD7175_ReadData(int32_t *value); int32_t AD7175_Calibrate(uint8_t ch);每个函数都保持幂等重复调用不会产生副作用。AD7175_Init内部先复位再按顺序配置寄存器最后做校准中途任何一个环节失败都会返回负的错误码方便定位问题。还有两个设计细节值得展开说。第一所有SPI读写都加了超时保护。嵌入式环境里SPI总线偶尔会挂住比如从机没响应、CS时序被中断打断如果不加超时机制整个系统就卡死在等待循环里看门狗也救不了。我在platform层的SPI传输函数里统一加了超时退出虽然正常情况不会触发但一旦总线异常至少能保证系统不锁死。第二寄存器操作尽可能用影子缓存。AD7175的寄存器配置值在初始化后基本不变但每次读取都要走一遍SPI总线既浪费时间又增加出错概率。我在ad7175.c里维护了一份寄存器影子值初始化时写入芯片读取时直接查影子把SPI通信量降到最低。3. 初始化那些事SPI时序和寄存器顺序3.1 SPI Mode 1的正确打开方式这个点必须单独拿出来说因为八成以上通信问题都出在这里。AD7175要求SPI工作在CPOL0、CPHA1也就是SPI Mode 1。很多人用STM32的HAL库默认配置SCLK空闲是低电平、数据在第一个边沿采样那是Mode 0和AD7175要求的时序完全对不上。表现就是写寄存器好像成功了读回来全是0xFF或者乱码折腾大半天找不到原因。正确的STM32 SPI配置核心代码SPI_InitTypeDef spi_cfg; spi_cfg.Mode SPI_MODE_MASTER; spi_cfg.Direction SPI_DIRECTION_2LINES; spi_cfg.DataSize SPI_DATASIZE_8BIT; spi_cfg.CLKPolarity SPI_POLARITY_LOW; // CPOL0 spi_cfg.CLKPhase SPI_PHASE_2EDGE; // CPHA1 spi_cfg.NSS SPI_NSS_SOFT; spi_cfg.BaudRatePrescaler SPI_BAUDRATEPRESCALER_16; spi_cfg.FirstBit SPI_FIRSTBIT_MSB;这里的两个关键点CPOL0表示SCLK空闲低电平CPHA1表示数据在第二个跳变沿采样。SCLK先拉低再拉高第二个边沿就是上升沿数据在上升沿被锁存这才是AD7175要的时序。波特率我建议从低开始。STM32F103主频72MHz先除64得到约1.125MHz。通信稳定之后再逐步提高不要一开始就顶到最高速率。PCB布线不好或者杜邦线连接的时候SPI跑太高经常会出现偶发错误。3.2 初始化流程与关键寄存器这是我实测稳定的初始化顺序每一步都有明确目的少了哪步都可能出怪问题。第一步复位。向寄存器地址0xFF写入任意数据实际效果是连续发送64个SCLK周期。复位后芯片回到默认状态所有寄存器恢复初值。第二步等待至少1ms。让内部LDO和基准源稳定下来。这一步别省否则后续配置经常莫名其妙失败尤其在上电快速初始化时特别明显。第三步配置ADC模式寄存器地址0x01。我设置成连续转换模式、使用内部晶振、使能内部基准。注意连续转换模式是默认的但从代码可读性考虑还是显式写清楚比较好。第四步配置接口模式寄存器地址0x02。这里设置SPI数据输出格式我选24位数据加状态字节的方案这样每次读取都能同时拿到通道编号和错误标志省去额外查询。第五步配置通道映射寄存器地址0x10~0x13。把通道0设置成AIN0/AIN1差分输入并关联到Setup 0。第六步配置设置寄存器地址0x20和滤波器配置寄存器地址0x24。设置PGA增益、滤波器类型、基准电压源。比如称重场景增益设128滤波器选Sinc5Sinc1兼顾建立时间和噪声性能。第七步配置输出数据速率寄存器地址0x07。根据需要的采样率计算FS值具体计算公式看数据手册我一般做称重选10~20SPS抗干扰和分辨率最均衡。第八步校准。这个单独在下一节讲。整个流程用表格总结一下步骤寄存器/操作作用备注10xFF写入复位芯片连续64个SCLK2无等待稳定至少1ms30x01设置ADC模式连续转换内部晶振40x02设置接口格式24位数据状态50x10配置通道映射AIN0/AIN160x20/0x24增益/滤波器按应用需求70x07设置输出速率计算公式见手册8校准减小零点/增益误差见下节3.3 校准流程不校准精度差一个量级AD7175内置了偏移校准和增益校准功能这是新手最容易忽略的一步。不校准直接用零点偏移和增益误差可能达到几百ppm甚至更高对于24位ADC来说完全不能接受。校准分两种内部校准和系统校准。内部校准是利用芯片内部机制自动校正偏移和增益误差简单可靠我默认走这个。系统校准需要外部提供标准信号源精度更高但工程上麻烦适合有精密源的环境。实际调用校准函数的时候注意校准期间不能读数据必须等DOUT/RDY引脚变低确认校准完成。这个过程通常需要几十毫秒到几百毫秒取决于滤波器配置。另外每次切换增益或者通道后建议重新做一次偏移校准因为不同增益档位下的失调电流不一样偷懒不复校的话小信号测量误差会明显变大。4. 数据连续采集轮询、中断还是DMA4.1 三种读取方案对比初始化完成之后就要持续读数据了。AD7175的DOUT/RDY引脚在数据准备好时拉低所以有几种方式获取数据。第一种轮询。主循环里不断读DOUT/RDY引脚电平变低了就发起SPI读取。优点是简单直观代码量少缺点是在高采样率下会占用大量主控时间做不了别的。第二种外部中断。把DOUT/RDY接到STM32的外部中断引脚下降沿触发在中断服务程序里发起SPI读取。效率比轮询高很多但要注意中断服务函数里别做太耗时的事读出来的数据放到缓冲区真正的业务处理交给主循环。第三种DMA加外部中断组合。DOUT/RDY触发中断后启动SPI DMA读取读完后产生DMA完成中断在完成中断里做数据解析。这是效率最高的方案适合10kSPS以上的高速场景。我实际项目里对这三种方案做过对比方式适合场景主控占用代码复杂度轮询100SPS高低外部中断中低速低中DMA中断10kSPS极低高4.2 数据稳定性的实战经验除了SPI读取方式数据稳定性还受几个因素影响这里一并说清楚。多通道切换时必须通过状态字节确认当前数据属于哪个通道。AD7175在连续转换模式下数据寄存器里始终是最新一次转换结果如果同时开启了多个通道不清除状态直接读数据很可能把通道0的数据记到通道1头上。我在驱动里解析状态字节后会把数据放入对应通道的缓冲区从源头杜绝错位。软件滤波不能省。虽然AD7175内置了Sinc滤波器但那主要用来抑制特定频率干扰工程上我还会叠加一层软件滤波。称重行业常用的是一阶低通简单有效// 一阶低通滤波右移4位对应平滑系数0.0625 filtered (raw - filtered) 4;这个式子实现了一个截止频率可调的一阶低通适合10~20SPS的称重场景。右移位数越大滤波越强但响应越慢实际调试时可以根据传感器变化速度调节。符号扩展是另一个容易忽略的坑。AD7175输出的24位数据是二进制补码格式而STM32的int32_t是32位直接赋值的话负数会变成正数数据完全乱掉。我在驱动里用了一行代码if (raw 0x800000) { raw | 0xFF000000; // 24位扩展到32位 }这行代码看起来不起眼漏掉它的话低温测温数据会跳得离谱排查半天还以为是传感器问题。5. 问题排查记录从读不出来到漂到怀疑人生5.1 SPI通信失败的几个典型原因调试过程中遇到的问题整理成一张排查表方便大家对照定位现象可能原因排查方向读ID寄存器返回0xFFSPI模式配置错误检查CPOL/CPHA读ID偶尔对偶尔错SPI速率太高/布线差降低波特率写寄存器后读回不对CS时序异常检查CS拉低/拉高时机读回全是0DOUT/RDY引脚接错确认引脚连接上电后完全无响应复位时间不足增加等待时间SPI模式出错是最常见的问题。我建议在初始化最后加一个ID校验步骤读0x06寄存器AD7175的ID值应该是0x0XD2不同型号略有差异以数据手册为准。如果读回来的值和预期不符直接打印错误信息就不用继续往下跑了。这个校验看起来多此一举但在批量生产或者换物料时能省大量排查时间。5.2 数据漂移和噪声问题定位通信通了之后数据漂移往往才是真正烧脑的问题。我遇到过两个印象深刻的案例。第一个是参考电压受热噪声干扰。我做热电阻测温常温下数据很稳一旦加热就开始缓慢漂移来回摆。排查了两天才发现是PCB布局的锅参考电压走线和加热电流回流路径挨得太近温度升高后参考电压被热噪声干扰了。参考电压是ADC的尺子参考不稳采集数据必然不稳。这个案例的教训是参考电压去耦要到位走线要远离大电流通道最好加一级LC滤波。第二个是数字电源和模拟电源共用LDO。AD7175的模拟电源和STM32数字电源共用了一颗LDO导致SCLK切换噪声耦合进模拟电源空采时噪声从50uV直接涨到200uV。后来把数字电源和模拟电源分开供电数据立刻安静了。高精度ADC的电源设计真的不能图省事一颗LDO省下的成本可能要用一整个调试周期来还。5.3 多通道串扰和地线处理的排查思路还有一个容易被忽略的问题是通道间串扰和地线处理。刚开始我以为多通道采集只要配置好寄存器就行结果发现相邻通道会互相影响。测量低电平信号时旁边通道如果悬空读数会有明显波动。这是因为悬空通道会耦合各种噪声通过芯片内部寄生电容串到正在测量的通道上。解决方法是不用的通道在软件里配置成接地或者硬件上直接接到AGND别让它们悬空。另外PCB布线时模拟地和数字地要单点连接别让数字信号回流穿越模拟区域。这些细节在低速场景下可能看不出差别但24位精度下就非常明显了。6. 源码的扩展方向和后续优化建议驱动调通只是第一步真正把AD7175用好后面还有不少扩展空间可以挖。一个方向是多片AD7175同步采集。有些项目需要同时采集多路高精度信号都用片内采样时钟的话片间会存在时间偏差。AD7175支持通过SYNC引脚实现多片同步采样我后来在做多通道温场测试时就用到这个功能代码上只需要把多片的SYNC引脚并联在统一时刻拉低再释放就能实现各通道同步启动转换。另一个方向是SPI速率优化。我前期调试用1MHz左右的速率通信稳定之后可以把速率往上提。实测在STM32F103上SPI跑到4.5MHz也没有问题。不过速率上去之后PCB走线质量的影响就凸显出来了建议用差分观测一下信号完整性别盲目追求高速。还有一个容易被忽略的点是看门狗策略。AD7175本身没有看门狗但SPI总线有可能挂住我最后在产品里加了一个通信超时检测如果超过1秒没有新的数据准备好信号就主动复位AD7175并重新初始化。这个机制看着简单但能显著提升长期运行的可靠性尤其对需要7x24小时工作的设备来说很重要。本文还有配套的精品资源点击获取