尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

STM32 HAL库驱动ADS124S08高精度ADC开发实战

发布时间:2026/9/10 0:59:36

资讯中心
01
ARTICLE

STM32 HAL库驱动ADS124S08高精度ADC开发实战

STM32 HAL库驱动ADS124S08高精度ADC开发实战
简介针对STM32嵌入式平台这套基于HAL库的ADS124s08驱动例程解决了高精度24位ADC的快速接入问题适用于工业采集、仪器仪表等需要低噪声测量的应用场景。压缩包共4个文件包含两个C源码与两个头文件将SPI初始化、寄存器读写、数据收发及校准处理封装成简洁接口结构清晰便于按需裁剪和移植。已有885人学习下载可用于参考驱动框架或直接集成到项目中。资源覆盖ADS124S08_Init、ADS124S08_ReadReg、ADS124S08_WriteReg等核心函数并结合HAL_SPI_TransmitReceive及中断模式示例展示高实时性采集的实现方式同时提供误差校正思路帮助开发者规避量化与失调误差缩短外设驱动开发周期。1. 项目概述与整体设计思路1.1 为什么是ADS124S08为什么用HAL库ADS124S08是TI推出的一款高精度24位ADC内置8通道多路复用器、可编程增益放大器PGA和两个激励电流源专门为工业测量、称重、温度采集这类高精度低速应用而设计。我在一个基于铂电阻的温度采集项目里第一次正经用它当时对比过CS1232和国产的HX720最后还是选了它——原因很简单24位分辨率、8通道输入、最多128倍增益而且自带传感器断路检测和内部温度传感器这块芯片在同价位里几乎没有对手。至于HAL库网络上已经吵了很多年了。标准库简洁暴力直接掰寄存器HAL库臃肿但胜在结构统一、代码可读性高、换芯片型号时迁移成本低。在我实际体验下来对于ADS124S08这种时序不算特别苛刻、但要反复调试寄存器和数据读取的芯片HAL库的SPI抽象层写起来比标准库舒服得多。特别是回调机制和超时检测遇到调试问题时分分钟就能定位到是通信层的问题还是芯片配置的问题。这篇文章适合手里正拿着ADS124S08和STM32F1/F4系列开发板、准备从零开始点亮它的朋友也适合那些已经把它跑通但想优化数据稳定性的工程师。1.2 例程的整体框架与文件结构咱们先想清楚整个软件架构再动手写代码。ADS124S08驱动说穿了就是三件事SPI底层通信、芯片初始化配置、数据读取与处理。我用的是STM32F103C8T6也就是那个淘宝上十几块钱的蓝板HAL库版本是1.8.0开发环境是STM32CubeIDE 1.10.1打开CubeMX直接生成工程。在工程里我习惯按功能把代码拆成几个文件ads124s08.c和ads124s08.h放芯片相关的寄存器定义、配置函数、数据读取函数main.c只管业务逻辑。再往下一层是HAL的SPI驱动用CubeMX配置好SPI1如果要跑通DMA就直接在CubeMX里勾上DMA通道代码生成后基本不用再动底层。这种分层的好处是以后芯片换成ADS124S0616位版本或者从F1换成F4只改驱动层上面的业务逻辑全部保留。2. 硬件连接与CubeMX工程配置2.1 引脚分配与接线注意细节硬件连接上先看ADS124S08的引脚。这个芯片是真的能折腾SPI四个脚SCLK、DIN、DOUT、CS是最基础的但我强烈建议把START引脚和DRDY引脚也接上MCU的GPIO因为它们一个是启动转换的控制信号一个是数据就绪中断输出。只靠延时加轮询是能工作但对不准采样时机高精度就无从谈起。我自己实际接的是这样的ADS124S08引脚STM32F103C8T6引脚说明SCLKPA5SPI1_SCKSPI时钟最大4MHzDINPA7SPI1_MOSI数据输入接芯片DINDOUTPA6SPI1_MISO数据输出读芯片数据CSPB0普通GPIO输出片选低电平有效STARTPB1普通GPIO输出启动转换脉冲DRDYPB10普通GPIO输入数据就绪低电平有效RESETPB11普通GPIO输出硬件复位脚这里有个特别容易踩的坑DOUT这个脚是复用功能推挽输出但很多人的开发板上MISO没接上拉电阻ADS124S08在复位后一段时间内DOUT是高阻态万一读到不确定的电平会误判断片有没有应答。解决办法很简单在初始化时把MISO设置为上拉输入或者直接在硬件上加10K上拉电阻到3.3V。电源方面ADS124S08的模拟电源AVDD接3.3V数字电源DVDD也接3.3V中间有条件的话用一个磁珠或者10Ω电阻做一个简单隔离。参考电压REFP和REFN之间接一个10μF钽电容并联100nF陶瓷电容这直接影响ADC的基准稳定性千万别省。2.2 CubeMX中的SPI、GPIO、定时器配置打开CubeMX芯片选STM32F103C8T6先把SPI1打开配置为全双工主机模式速率压到2.25Mbps左右。之所以不直接上满速4Mbps是因为F1的APB1时钟是36MHzSPI分频后实际波特率会有偏差ADS124S08的时序要求是SCLK高电平时间不小于117ns算出频率上限大概2.1Mbps保险起见2.25Mbps这个档位实测下来没有任何问题。GPIO这块CS、START、RESET全部配成GPIO输出初始电平分别为高、低、高。DRDY配成输入模式这里我建议开启上拉因为芯片复位期间DRDY是高阻态拉个上拉能防止误触发。以上这些都配好之后在GPIO的NVIC设置里把SPI1中断打开如果要用DMA模式的话把SPI1的TX和RX DMA通道选上优先给RX分配一个比较高的中断优先级。CubeMX生成完工程后在main.c里写初始化序列之前先测试一下SPI通信是否正常——发送一个读取设备ID的命令寄存器地址0x00能收到正确回复说明SPI底层畅通接下来才能放心写驱动。3. ADS124S08驱动核心实现3.1 驱动初始化寄存器配置的先后顺序ADS124S08上电之后第一步是做一次硬件复位RESET引脚拉低至少4个SCLK周期然后拉高等至少2.2ms让芯片完成内部校准。接下来配置寄存器顺序很有讲究我的经验是先配置系统控制寄存器地址0x00再配置数据速率寄存器地址0x04、输入多路复用器寄存器地址0x05和PGA寄存器地址0x06。先看系统控制寄存器这个寄存器里的各个置位项决定了芯片的基本工作模式。我用的是连续转换模式所以第7位RESET设0第6位PDWN设0第4位START不通过寄存器控制、由引脚控制CSB位设0表示使用外部片选还有数据输出格式选二进制补码。这些位组合起来写进去的值大概就是0x06。数据速率寄存器是唯一对我这种应用最重要的寄存器它决定了ADC的输出速率。ADS124S08默认上电是20SPS这个速率对大多数工业传感器都够用但如果你把PGA增益调到128倍最好把数据速率降到20SPS以下因为高增益下噪声会显著增大只有慢速采样才能获得稳定的低噪声数据。我的做法是直接调用ADS124S08_SetDataRate(0x08)对应20SPS。这个参数后面提到滤波时还会再展开讲。多路复用器和PGA寄存器决定了所选通道和放大倍数。例如选择AIN0和AIN1作为差分输入MUX寄存器的MUXN[3:0]设为0001AIN1接负极MUXP[3:0]设为0000AIN0接正极写入0x01。PGA寄存器则根据传感器输出幅度来设置像热电偶输出的电压只有几十毫伏直接设为0x08也就是PGA增益64倍这样才能把微小信号放大到ADC的满量程范围内。3.2 SPI命令序列与数据连续读取ADS124S08的命令集看起来不多但每个命令都有它的脾气。这里我把用到的几个核心命令列成一张速查表命令名命令字节功能WAKEUP0x00从待机模式唤醒SLEEP0x02进入待机模式SYNC0x04同步转换周期RDATA0x12读取最新转换结果RREG0x20 地址读寄存器WREG0x40 地址写寄存器SYSOCAL0x60系统偏移校准SYSGCAL0x61系统增益校准连续转换模式下只要START引脚拉高芯片就会按照设定的数据速率定时采样。每当一个转换周期完成DRDY引脚拉低通知MCU可以读数据了。我用HAL库的GPIO中断去捕获DRDY下降沿或者在主循环里查询DRDY电平。查询方式是读取HAL_GPIO_ReadPin(DRDY_GPIO_Port, DRDY_Pin)为低就立刻调用SPI发送RDATA命令然后接收三个字节的数据。SPI收发用HAL_SPI_TransmitReceive注意每次读数据前CS拉低、发送RDATA命令、接收三字节、CS拉高这个时序不能混。ADS124S08的SDO在CS拉低后的第一个时钟上升沿就输出最高位所以发送RDATA时DOUT线上返回的数据其实是上一次转换结果的高位字节不用管它。三字节拼装成24位数据的代码很直白关键是拼完之后要处理符号位。ADS124S08输出二进制补码格式最高位是符号位所以判断一下如果最高位为1就把变量补成32位负数否则直接转换。转换成实际电压值的公式是电压 原始值 / 0x800000× VREF / PGA增益。以VREF 2.5V、增益 64倍为例LSB对应的电压约等于0.00298微伏这个精度温度采集绰绰有余了。4. 实战过程中的滤波与校准问题4.1 数据抖动的大困扰滤波手段怎么选第一次把ADS124S08跑起来时我盯着串口助手里的数据差点崩溃温度值在0.1摄氏度范围内乱蹦根本没法用。其实这是⾼精度ADC的常态它不是芯片不行而是噪声无处不在。开关电源的纹波、PCB走线耦合、外界电磁干扰都会在末几位码字上留下痕迹。处理手段最有效的是均值滤波配合中值滤波。我采用的策略是连续读取N次转换结果先删掉最大值和最小值剩下的取平均。实测下来5次采样去极值平均或者8次采样普通平均都能把噪声从±15个LSB压到±2个LSB以内。注意这里的N不能太大否则响应速度变慢工业现场根本等不及。如果数据速率设为20SPS每50ms出一个数据点8次平均就是400ms出一个最终结果。这个延时对温度、压力这类缓变物理量完全没问题但你要是拿去采集振动信号那就得换高速ADC了。另外一个细节是数字滤波不能代替模拟滤波在ADS124S08的输入端并联一个100nF电容差分模式接在AINP和AINN之间能有效滤除射频干扰这个硬件手段比任何软件滤波都来得实在。4.2 校准实操偏移校准与增益校准校准是ADS124S08给出高精度数据的关键。芯片上电后内部会做一次自校准对大多数应用够了但如果你追求极致精度或者换了传感器后偏置电压明显就需要手动校准。系统偏移校准的命令是SYSOCAL做这个校准前必须把PGA和MUX都设置好然后把输入端短接到VCOM共模电压让芯片测出零输入时的偏移码内部自动扣除。实际操作的代码是CS拉低、发送0x60命令、等待DRDY拉低再拉高整个校准过程需要几个转换周期这段时间不要读数据。增益校准命令SYSGCAL要求输入端接一个已知的精准电压芯片会算出一个修正系数用它把转换结果拉回准确值。这里需要注意校准电压必须落在ADC的输入范围之内最好是满量程的50%到90%之间太低了校准精度不够太高了容易溢出。我用一个高精度电压源输出1.25V作为校准电压配合PGA1的设置校准完之后满量程误差能压到0.01%以内。手工校准做完之后要把校准结果存下来吗理想情况下是存到外部EEPROM里因为芯片断电重上电后校准结果会丢。我的做法是每次上电初始化之后都自动执行一次校准流程这样省去存储环节代码也更简单。代价是启动时间多了几百毫秒这个时间代价对仪器仪表这类设备不值一提。5. 代码实现与HAL库调用技巧5.1 底层SPI读写封装整个驱动最核心的一段代码是SPI读写封装它决定了后面所有命令和数据传输的稳定性。我的ADS124S08_WriteCommand函数负责发送单个命令字节ADS124S08_ReadData负责发送RDATA并接收三字节数据void ADS124S08_WriteCommand(uint8_t cmd) { HAL_GPIO_WritePin(ADS124S08_CS_GPIO_Port, ADS124S08_CS_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(hspi1, cmd, 1, 10); HAL_GPIO_WritePin(ADS124S08_CS_GPIO_Port, ADS124S08_CS_Pin, GPIO_PIN_SET); } int32_t ADS124S08_ReadData(void) { uint8_t buf[3] {0x12, 0x00, 0x00}; uint8_t rx[3] {0}; int32_t raw 0; HAL_GPIO_WritePin(ADS124S08_CS_GPIO_Port, ADS124S08_CS_Pin, GPIO_PIN_RESET); HAL_SPI_TransmitReceive(hspi1, buf, rx, 3, 10); HAL_GPIO_WritePin(ADS124S08_CS_GPIO_Port, ADS124S08_CS_Pin, GPIO_PIN_SET); raw ((int32_t)rx[0] 16) | ((int32_t)rx[1] 8) | rx[2]; if (raw 0x800000) { raw | 0xFF000000; } return raw; }这个封装里有几个细节值得展开说。第一HAL_SPI_TransmitReceive一次性完成发送和接收比先发送再接收更高效因为SPI是全双工总线发送和接收本来就是同时进行的。第二超时时间我设的10ms对于20SPS的采样速率完全够用如果SPI总线上有其他设备注意不要让总线的访问冲突把超时时间撑爆。第三CS信号由软件控制而不是用HAL的硬件NSS功能原因是STM32F1的硬件NSS不好用有各种边沿时序问题自己拉GPIO反而干净利落。5.2 寄存器读写与初始化函数寄存器读写函数是驱动里另一个关键部分。写寄存器时第一个字节是WREG命令加上寄存器地址第二个字节是寄存器个数减一后面跟要写入的数据。读寄存器时第一个字节是RREG命令加上寄存器地址第二个字节是要读的寄存器个数减一然后开始读数据。我写了一个统一的ADS124S08_ReadRegister(uint8_t reg, uint8_t *rx, uint8_t len)函数代码看起来比较朴素但胜在稳定可靠所有寄存器操作都复用这一个函数。初始化函数ADS124S08_Init的完整流程是RESET引脚拉低保持1ms然后拉高等待2.5ms把START引脚拉低等待100μs再拉高写系统控制寄存器SYS值设为0x06写数据速率寄存器设为20SPS写MUX寄存器选择输入通道写PGA寄存器设置增益等待DRDY拉低表示第一个转换完成读一次数据并丢弃因为刚上电第一次转换结果不可靠这个流程在每次上电时执行一遍整个系统就能稳定工作了。5.3 HAL库回调与中断方式的高效读取查询DRDY是最简单的但对CPU不友好尤其系统里还有其他任务时主循环堵在读数据上会浪费大量计算资源。改造成中断方式很轻松在CubeMX里把DRDY引脚的GPIO外部中断打开设置下降沿触发然后在中断回调函数里读取数据void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin ADS124S08_DRDY_Pin) { int32_t raw ADS124S08_ReadData(); float voltage ADS124S08_ConvertToVoltage(raw); volatile float temp ADS124S08_ConvertToTemperature(voltage); data_ready_flag 1; } }中断服务函数里不要做太多事我的做法是只把原始值存到全局变量置一个标志位具体的数据处理和滤波放到主循环里做。这样中断执行时间短不会影响其他中断的响应速度。我实测过20SPS的数据速率下中断方式比轮询方式降低CPU占用大约15%而且代码结构更清晰。另外一个用HAL库的小技巧HAL_SPI_TransmitReceive是阻塞式调用如果系统里有RTOS建议给SPI通信加一个互斥锁防止其他任务并发调用SPI导致数据错乱。裸机环境下不存在这个问题但代码里预留一个宏开关以后移植RTOS时用得上。6. 实际测试结果与问题排查速查6.1 把温度传感器接上看实际数据表现我把一个PT100铂电阻通过电桥接到ADS124S08的AIN0和AIN1差分输入端PGA增益设为8倍数据速率20SPS参考电压用内部2.048V。初始化跑通后串口输出的数据非常平稳连续观察十分钟数值波动不超过±2个LSB折合成温度大约±0.01℃。这个表现在工业测温领域已经够用了。我又把PGA增益调到64倍数据速率还是20SPS接上热电偶做测试。热电偶的信号只有几毫伏64倍增益放大后效果不错但噪声明显比PT100时大。用去极值均值滤波把8次采样平均最终的温度波动大约±0.03℃对于K型热电偶来说普通应用完全够了。6.2 常见问题排查清单实际开发中总会遇到反反复复的坑我把这些记录成一张排查表——有问题先看表能省一晚上的调试时间现象可能原因解决方案读寄存器全为0xFFSPI速率太快、接线错误、CS没正确拉低把SPI降到125kHz试一下检查接线和CS时序读数据恒为0x800000或0x7FFFFF输入超量程、PGA增益设置过大减小增益、检查传感器接线、检查VREF是否正常数据跳动太大电源噪声、参考源不稳、输入滤波缺失参考源加去耦电容、输入加RC滤波、提高采样率再做均值DRDY一直为高START引脚没拉高、芯片处于睡眠模式检查START引脚电平发送WAKEUP命令数据线性度差没有做校准、基准电压偏低执行SYSOCAL和SYSGCAL确保VREF稳定SPI通信时好时坏杜邦线太长、接触不良换短跳线用手焊接别用面包板6.3 数据稳定性优化建设所有的测试跑完之后如果想再榨出一点数据稳定性我根据踩过的坑给三条排过优先级的分级建议。最优先的是加强电源滤波在VREF引脚处用一个680Ω电阻串联一个小电感再并电容实测能明显抑制参考源的纹波。其次是输入端加一个二阶RC低通滤波器截止频率设为几百赫兹比单纯100nF电容效果好不少。最后如果还想更稳数据速率降到5SPS牺牲一点响应速度换取更低噪声。在这里真的必须提醒一句ADS124S08这颗芯片本身性能已经很强了测出来的数据不稳定先查硬件、再调软件别一上来就怀疑芯片灵敏度不行。我见过太多同行在软件滤波上做文章结果最后发现是330Ω的限流电阻选错了导致传感器激励电流不足。7. 案例扩展与进阶方向7.1 多通道循环采样的实现思路ADS124S08的8个输入通道不能并行采样只能通过MUX寄存器轮流切换。多通道循环采样的流程是初始化完成后先设置通道0等待转换完成读数据然后切到通道1以此类推轮询。需要注意的是每次切换MUX之后芯片内部PGA需要几个转换周期来稳定所以切换后要丢弃前几个数据点。实际测试中我用外部多路复用器的方式配置MUX寄存器选通道0连续读5个点取平均作为通道0的结果然后切到通道1重复操作。8个通道全部扫完大约需要2秒每通道5次 × 20SPS 切换等待这个速度对温度采集系统完全能接受。如果要求更快可以提高数据速率、减少平均次数但代价是噪声增大。7.2 结合DMA和RTOS的进阶方案如果系统里跑着RTOS或者有严格的实时性要求可以考虑把SPI通信改成DMA方式。HAL库配置DMA很简单在CubeMX里勾选SPI1的TX和RX的DMA通道生成代码后在初始化时调用HAL_SPI_TransmitReceive_DMA就行。DMA的优势是数据搬移不占用CPU读数据的时候CPU可以去做别的事靠DMA传输完成中断来通知读取结果。但要注意DMA模式下CS控制要特别小心。如果CS还是在传输前拉低、传输后拉高那DMA传输一结束CS就拉高了而数据可能还没来得及从移位寄存器里取出。我的做法是在DMA传输完成回调函数里拉高CS确保所有数据都稳定接收后再释放片选。7.3 从F1迁移到F4/H7的注意事项ADS124S08的驱动代码在F1上跑通之后以后换F4或者H7代码迁移成本几乎为零。HAL库的API接口是完全一样的唯一要注意的是不同系列的SPI时钟源不同最大波特率不一样对应需要调整分频系数。在CubeMX里重新配置SPI时钟树后驱动层代码一行都不用改直接编译就能跑。这也是用HAL库最大的好处——不用为每一颗MCU重写SPI通信和寄存器操作代码。如果要迁移到STM32G4或者H7系列它们的内核支持浮点单元电压转换和温度线性化计算可以直接用float类型不用手工做定点数转换CPU占用还能再降低一些。写到这里ADS124S08的HAL库驱动从底层通信、寄存器配置、数据读取到滤波校准的完整链路都已经跑通了。整个过程中我踩过SPI时序不稳的坑也经历过数据抖到怀疑人生的夜晚但把这些经验整理出来后你会发现高精度ADC的调试其实是有规律可循的硬件上把供电和参考源做干净软件上先在低速SPI下确认通信和寄存器配置再用中断配合去极值均值滤波把数据稳定下来最后按需做校准。这套流程已经在我的三个项目里反复验证过。最后再分享一个小技巧在驱动代码里尽量用宏定义统一管理所有寄存器地址和命令码千万不要散落地写那些裸数字等你要在单个工程里控制三片ADS124S08的时候就明白这个习惯能救多少命了。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。