STM32F103驱动AD7124:24位ADC完整方案与SPI驱动实现

发布时间:2026/10/16 10:16:48
STM32F103驱动AD7124:24位ADC完整方案与SPI驱动实现 简介基于STM32F103的AD7124高精度ADC驱动完整工程面向需要快速上手数据采集的嵌入式开发者代码已全部调通采用模拟串行外设接口方式通信省去硬件接口配置的麻烦。工程默认六通道、双极性、全功率采样并使用外部参考电压便于直接嵌入项目或作为学习模板压缩包共二百一十五个文件大小约六点一八兆字节以C语言源码与头文件为主体附带Keil集成开发环境工程配置及编译生成的中间文件保留了完整构建链方便二次开发与断点调试。目前已有六千二百一十二人浏览学习覆盖入门到进阶的STM32使用场景。作者免费分享调通经验并鼓励互助为新手打消代码可靠性疑虑同时预留硬件串行外设接口改造空间有兴趣者可自行扩展研究。读者可导入Keil5工程直接查看完整调用逻辑也可根据需求调整通道数、采样极性等关键参数。1. 认识 AD7124 驱动用 STM32F103 调通一颗 24 位 ADC 的完整方案最早做多路温度巡检的时候我用单片机内置 12 位 ADC 去采热电偶信号前端加了一堆运放和滤波最后出来的数据还是在一个范围内缓慢漂移怎么看都像在做布朗运动。后来换成外部高精度 ADC同样的前端噪声和温漂立刻降了一个量级。这颗 AD7124 驱动代码就是基于 STM32F103 的完整工程SPI 通信、寄存器配置、数据读取全调通了拿过来按自己的引脚改一下就能跑。它适合正在做测温、称重、应变、电流检测这类低速高精度采集的开发者也适合想从内置 ADC 跳到外部高精度 ADC、但对 Σ-Δ 型器件时序还不熟悉的人。这篇文章会把接口设计、驱动初始化、核心读取链路和调试踩坑一条线讲完。2. 硬件搭建与选型STM32F103 和 AD7124 之间怎么连接才稳2.1 引脚分配与最小连接AD7124 是标准 SPI 从机STM32F103 这边用 SPI1 是最顺手的接法引脚不冲突代码也最通用。核心信号就五根SCLK、DIN、DOUT、CS、DRDY另外建议把 RESET 引脚也接出来方便做软硬件复位切换。以我常用的接法为例STM32F103 引脚AD7124 引脚说明PA5SCLKSPI 时钟最大建议不超过 5 MHzPA7DIN主机 MOSI写给 AD7124 的数据PA6DOUT主机 MISOAD7124 返回的数据PA4CS片选低电平有效PA3DRDY数据就绪低电平有效建议接外部中断PA2RESET硬件复位低电平复位DRDY 这根线很多人会忽略它其实是整个驱动能不能读准的关键。AD7124 每次完成一次转换DRDY 会拉低表示数据寄存器已经更新这时候去读才能拿到完整有效的数据。我一般会把 DRDY 接到 STM32 的外部中断引脚上下降沿触发中断里只置一个标志位主循环看到标志再去读数据避免轮询时恰好撞上数据更新的边界。CS 用普通 GPIO 控制而不是硬件 NSS项目里几乎都是这么做的。硬件 NSS 在连续传输多个寄存器时容易出现片选状态不受控的问题用 GPIO 拉低拉高最直观也方便用逻辑分析仪抓时序。2.2 电源、基准电压和输入前端AD7124 的模拟电源 AVDD 和数字电源 DVDD 在大多数板子上用的是同一个 3.3 V但供电入口必须分开滤波。AVDD 引脚附近放一个 10 μF 钽电容并联 0.1 μF 陶瓷电容DVDD 至少放一个 0.1 μF这两个电源域之间再用一个磁珠或几欧姆电阻隔离能明显减少数字开关噪声串进模拟部分的概率。基准电压方面AD7124 内部有一个 1.17 V 基准源精度和温漂指标对一般工业测量够用省掉外部基准芯片板子面积和成本都能压下来。如果对温漂有硬性要求比如产品要过宽温标定建议还是用外部基准把 REFIN 引脚接上专用基准源配置寄存器里选择外部基准即可。输入前端这里有个常见做法模拟输入引脚对 AGND 各加一个 10 Ω 电阻串联、再并联 1 μF 电容到地构成一个简单 RC 滤波器。这个滤波器能抑制高频共模噪声也能削弱前级运放输出的毛刺。对热电偶这种内阻大的信号源电阻可以加到 100 Ω但要注意和 AD7124 内部 PGA 的输入偏置电流共同作用会产生直流误差电阻不是越大越好。2.3 SPI 方案硬件 SPI 还是 GPIO 模拟如果 STM32F103 的 SPI1 引脚刚好够用优先用硬件 SPI代码简单传输快。AD7124 的 SCLK 上限是 5 MHzSTM32F103 主频 72 MHzSPI 预分频 16 得到 4.5 MHz接近但没超过上限能用。板子布线差一点的话降到预分频 32 即 2.25 MHz稳定性会更好。我给出的驱动里默认用的是 GPIO 模拟 SPI原因有两个一是引脚可以随意映射方便 PCB 布线二是时序完全由代码控制遇到问题可以用逻辑分析仪直接看每个沿的位置排查起来比硬件 SPI 直观。模拟 SPI 在 72 MHz 主频下跑到 1 MHz 没有任何压力AD7124 这种低速高精度器件根本不需要很高的时钟频率。#define AD7124_SCK_PORT GPIOA #define AD7124_SCK_PIN GPIO_Pin_5 #define AD7124_MOSI_PORT GPIOA #define AD7124_MOSI_PIN GPIO_Pin_7 #define AD7124_MISO_PORT GPIOA #define AD7124_MISO_PIN GPIO_Pin_6 #define AD7124_CS_PORT GPIOA #define AD7124_CS_PIN GPIO_Pin_4 static void AD7124_DelayUs(uint32_t us) { for (volatile uint32_t i 0; i (us * 12); i) { __NOP(); } } uint8_t AD7124_SpiTransfer(uint8_t byte) { uint8_t recv 0; for (uint8_t i 0; i 8; i) { /* 先输出最高位 */ if (byte 0x80) { GPIO_SetBits(AD7124_MOSI_PORT, AD7124_MOSI_PIN); } else { GPIO_ResetBits(AD7124_MOSI_PORT, AD7124_MOSI_PIN); } /* SCLK 上升沿AD7124 锁存 DIN */ GPIO_SetBits(AD7124_SCK_PORT, AD7124_SCK_PIN); AD7124_DelayUs(1); /* 在 SCLK 下降沿之后采样 DOUT */ if (GPIO_ReadInputDataBit(AD7124_MISO_PORT, AD7124_MISO_PIN)) { recv (recv 1) | 0x01; } else { recv 1; } GPIO_ResetBits(AD7124_SCK_PORT, AD7124_SCK_PIN); AD7124_DelayUs(1); byte 1; } return recv; }这段模拟 SPI 的重点是时序的先后顺序先把 MOSI 数据摆好再拉高 SCLK然后等数据稳定后采样 MISO最后拉低 SCLK 完成一个时钟周期。AD7124_DelayUs里的延时值不需要很精确1 μs 左右的延时在 1 MHz 时钟下够用实际可以根据逻辑分析仪抓到的波形适当缩短能提高吞吐率。参数说明byte是本次要发送的一个字节函数返回值是同一个时钟周期内从 MISO 读到的字节。如果只用发送不看返回值直接忽略返回值即可。3. 驱动初始化复位、寄存器读写与配置写入3.1 软复位先把芯片从黑匣子状态唤醒AD7124 上电后处于什么状态不完全可控尤其是复位引脚悬空或者电源爬坡慢的时候芯片可能会停留在未知模式。最稳妥的方式是做一个软复位CS 拉低连续发送 64 个 0xFF然后 CS 拉高。void AD7124_SoftReset(void) { GPIO_ResetBits(AD7124_CS_PORT, AD7124_CS_PIN); for (uint8_t i 0; i 64; i) { AD7124_SpiTransfer(0xFF); } GPIO_SetBits(AD7124_CS_PORT, AD7124_CS_PIN); AD7124_DelayUs(100); }为什么是 64 个 0xFF因为 AD7124 的 SPI 接口在连续收到高电平脉冲时会触发复位序列0xFF 保证了每个时钟周期 DIN 都是高持续足够长就能让接口复位逻辑生效。这个操作必须在 CS 拉低期间完成中途不能把 CS 松开否则芯片会把前面的字节当成寄存器命令来解释。复位完成后不要立刻配置寄存器等 100 μs 左右让内部上电复位和基准源稳定。我见过有人在复位后马上写配置结果第一个寄存器写入被吞掉的案例多半就是没留这个稳定窗口。通信自检这一步很关键但很多驱动会跳过。做法很简单往某个可写寄存器写入一个已知值再读回来比对。一般我会拿 ADC 控制寄存器做测试因为它是 16 位且后面配置时反正要重写uint8_t testData[2] {0x00, 0x01}; AD7124_WriteRegister(AD7124_REG_ADC_CTRL, testData, 2); uint8_t readback[2] {0, 0}; AD7124_ReadRegister(AD7124_REG_ADC_CTRL, readback, 2); if ((readback[0] testData[0]) (readback[1] testData[1])) { /* SPI 通路正常 */ } else { /* 检查接线和时序 */ }这个自检能过滤掉一大半硬件问题尤其是 MISO 没接好、SCLK 极性反了这类低级错误。如果读回来全是 0xFF说明 DOUT 根本没被拉低先查接线。如果写不进去先查 CS 时序和数据手册上寄存器宽度的匹配。3.2 寄存器读写封装通信寄存器的地址约定AD7124 的 SPI 协议有一点和普通 SPI 器件不太一样每次读写寄存器之前都要先通过通信寄存器指定接下来要操作的目标地址和方向。通信寄存器本身也是寄存器地址是 0x00但它不能按普通寄存器的方式读。通信寄存器的字节格式是这样的bit6 是读写方向位1 表示读、0 表示写bit4 到位0 是目标寄存器地址。所以读一个寄存器的命令字节就是(寄存器地址 0x1F) | 0x40写一个寄存器的命令字节就是寄存器地址 0x1F。void AD7124_WriteRegister(uint8_t regAddr, uint8_t *data, uint8_t len) { GPIO_ResetBits(AD7124_CS_PORT, AD7124_CS_PIN); AD7124_SpiTransfer(regAddr 0x1F); for (uint8_t i 0; i len; i) { AD7124_SpiTransfer(data[i]); } GPIO_SetBits(AD7124_CS_PORT, AD7124_CS_PIN); } void AD7124_ReadRegister(uint8_t regAddr, uint8_t *data, uint8_t len) { GPIO_ResetBits(AD7124_CS_PORT, AD7124_CS_PIN); AD7124_SpiTransfer((regAddr 0x1F) | 0x40); for (uint8_t i 0; i len; i) { data[i] AD7124_SpiTransfer(0x00); } GPIO_SetBits(AD7124_CS_PORT, AD7124_CS_PIN); }需要注意寄存器宽度AD7124 的寄存器有的 8 位、有的 16 位、数据寄存器是 24 位。写配置寄存器 0 时 len 是 1写滤波器寄存器 0 时 len 是 2读数据寄存器时 len 是 3。如果 len 传错后续字节会跑到下一个寄存器去配置和读数据都会错位。CS 在整个读写过程中必须保持拉低通信寄存器命令、数据字节、结束状态都在同一个低电平窗口内完成。中途拉高 CS 会被 AD7124 视为一次异常结束当前操作作废。3.3 ADC 控制、通道与滤波器的配置顺序初始化配置通常分三步先设置 ADC 控制寄存器再设置通道对应的配置寄存器最后设置滤波器寄存器。顺序不能乱因为 AD7124 的通道选择是依赖 ADC 控制寄存器里的通道字段的配置寄存器和滤波器寄存器要先选好通道才会生效。连续转换模式是我在测量类项目里最常用的模式配置代码如下uint8_t adcCtrl[2] {0, 0}; AD7124_ReadRegister(AD7124_REG_ADC_CTRL, adcCtrl, 2); /* 清除模式位字段 */ adcCtrl[1] ~0x1C; /* 设置为连续转换模式模式值 0b010 左移 2 位 */ adcCtrl[1] | (0x02 2); AD7124_WriteRegister(AD7124_REG_ADC_CTRL, adcCtrl, 2);这段代码是读改写方式先把当前 ADC 控制寄存器的值读回来只动模式字段其它位保持不变。模式字段的具体位置在不同手册版本里可能有细节差异我这里的写法是按模式位占据低字节 bit4 到 bit2 处理的实际改代码时建议翻一下对应型号数据手册的寄存器位定义确认一遍。配置寄存器的设置uint8_t cfg0 0x00; /* PGA 增益 2对应增益字段 1 档 */ cfg0 | (0x01 4); /* 基准源选择内部 1.17V */ cfg0 | (0x02 2); /* 双极性模式 */ cfg0 | 0x02; AD7124_WriteRegister(AD7124_REG_CONFIG0, cfg0, 1);配置寄存器 0 的 PGA 增益字段在 bit7 到 bit4值 1 对应 2 倍增益值 0 是 1 倍。基准源字段在 bit3 到 bit2值 2 对应内部基准因为我这里用的就是内部 1.17 V。bit1 写 1 表示双极性模式单极性则保持 0。滤波器寄存器决定输出数据速率和有效分辨率。FS 字段越大输出速率越低但噪声越小、有效分辨率越高。这个没有通用的最优值取决于你的信号变化速度和对噪声的容忍度。静态测温场景我会把 FS 调大追求稳定动态称重场景 FS 要适当调小保证响应速度。uint8_t filter0[2] {0x00, 0x80}; /* FS 字段 128使用 Sinc3 滤波器 */ filter0[0] | 0x00; AD7124_WriteRegister(AD7124_REG_FILTER0, filter0, 2);FS 字段占滤波器寄存器低 11 位这里填 128 只是一个调试起点不代表任何特定输出速率具体数值要根据所用时钟频率从手册的速率表里换算。初始调试阶段建议从一个偏保守的配置开始比如 10 SPS 上下先把数据读稳定了再逐渐提速。4. 核心代码拆解一个转换数据从 DRDY 到应用层的完整链路4.1 DRDY 中断与读取时机数据读取的时机决定了你拿到的到底是一次完整转换还是一个中间态。最可靠的方式是利用 DRDY 引脚的中断下降沿代表数据寄存器已经更新完毕。STM32F103 的 EXTI 配置如下GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitStructure.GPIO_Pin GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource3); EXTI_InitStructure.EXTI_Line EXTI_Line3; EXTI_InitStructure.EXTI_Mode EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd ENABLE; EXTI_Init(EXTI_InitStructure); NVIC_InitStructure.NVIC_IRQChannel EXTI3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority 0; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure);中断服务函数里只做一件事把标志位置 1volatile uint8_t ad7124_drdy_flag 0; void EXTI3_IRQHandler(void) { if (EXTI_GetITStatus(EXTI_Line3) ! RESET) { ad7124_drdy_flag 1; EXTI_ClearITPendingBit(EXTI_Line3); } }置标志位而不是直接在中断里读数据是因为 SPI 传输要用延时函数放在中断里会拖长中断响应时间还可能和主循环里的其它 SPI 操作冲突。正确姿势是主循环里检查到标志后立刻读数据寄存器读完再清标志。4.2 24 位原始码读取与符号扩展读数据寄存器的过程分两步先发通信寄存器命令指定目标然后连续读三个字节。这三个字节是 MSB 在前组成一个 24 位的有符号补码。int32_t AD7124_ReadData(void) { uint8_t buf[3] {0, 0, 0}; int32_t raw 0; GPIO_ResetBits(AD7124_CS_PORT, AD7124_CS_PIN); /* 读数据寄存器地址 0x03bit6 1 表示读 */ AD7124_SpiTransfer((AD7124_REG_DATA 0x1F) | 0x40); buf[0] AD7124_SpiTransfer(0x00); buf[1] AD7124_SpiTransfer(0x00); buf[2] AD7124_SpiTransfer(0x00); GPIO_SetBits(AD7124_CS_PORT, AD7124_CS_PIN); /* 拼成 24 位有符号数 */ raw ((int32_t)buf[0] 16) | ((int32_t)buf[1] 8) | (int32_t)buf[2]; /* 24 位补码做符号扩展 */ if (raw 0x800000) { raw | ~0xFFFFFF; } return raw; }符号扩展这一步容易漏。24 位补码的最高位若是 1表示负值但int32_t里高 8 位还是 0直接当有符号数用会得到一个错误的正数。扩展后高 8 位全部置 1才是真正的负值。补码转电压值的公式是电压 原始码 / 满量程码 * 基准电压 / PGA 增益。24 位满量程码是 8388608双极性模式下这个满量程对应正负基准电压范围。4.3 连续转换模式与单次模式的选择连续转换模式下AD7124 转换完一次马上开始下一次DRDY 周期性拉低。这种模式适合持续监测的场景读数稳定后可以持续取均值。单次模式则是每次写命令触发一次转换转换完成进入待机模式。它适合通道切换后需要稳定时间的情形也可以避免连续模式在切换通道时混入上一通道残余数据。我一般会在多通道巡检时用单次模式每个通道切换后触发一次转换等 DRDY读一次再切下一个通道。差异点主要体现在功耗和通道切换效率上。电池供电的设备建议用单次模式转换间隔内芯片处于低功耗状态平均电流能降不少。4.4 用 DMA 批量读取连续数据如果系统里还有其它任务要跑连续模式下每次都用 CPU 做 SPI 传输会占用不少时间。可以考虑把 SPI 接收改成 DMA 方式数据寄存器每更新一次就触发一次 SPI 读取读到的数据直接进内存缓冲区。DMA 配置的核心是把 SPI1 的接收 DMA 通道打开每次 DRDY 中断到来时启动一次固定长度的 DMA 传输。这里要注意关闭 SPI 的硬件 NSS 管理DMA 传输期间 CS 要由 GPIO 手动保持拉低。缓冲区用环形缓冲管理主循环读取最新 N 次转换的平均值能进一步压低随机噪声。这个做法对单通道连续采集最有效多通道切换时 DMA 的启动时机和通道配置时序会变复杂性价比不高项目里建议只在单通道长期监测时启用。5. 避坑指南AD7124 调试时我踩过的 5 个坑5.1 读回全是 0xFF芯片像没在工作现象用自检函数读 ADC 控制寄存器返回数据全是 0xFF有时偶尔读到 0x00但配置写进去完全不生效。原因最彻底的可能是复位没成功芯片还停留在未定义状态。还有一个常见原因是 CS 电平不受控初始化 GPIO 时 CS 引脚默认是低电平导致芯片始终处于选中状态SPI 接口逻辑被一片乱流冲垮。解决复位函数里 CS 拉低之前先把 CS 引脚的 GPIO 初始化完成并且在空闲状态强制拉高。软复位那 64 个 0xFF 要一次性连续发完中间不能有 CS 抖动。复位后再加 100 μs 延时然后做寄存器回写自检。如果还是全 FF用逻辑分析仪抓 CS 和 SCLK确认时钟沿上的信号质量。5.2 数据抖动幅度超出数据手册承诺现象输入接一个稳定的 1.2 V 基准电压读出来的数据跳动幅度明显大于手册上该输出速率对应的有效噪声值。原因这类问题十有八九是模拟前端没处理好而不是芯片本身的问题。AVDD 和 DVDD 共用一个电源而没有做隔离滤波SPI 时钟和数字 IO 的开关噪声通过电源引脚耦合到模拟输入。另一个原因是输入 RC 滤波缺失高频噪声直接进入 Σ-Δ 调制器。解决检查 AVDD 和 DVDD 是否各自有完整的去耦电容模拟地 AGND 和数字地 DGND 是否在芯片下方做了单点汇接。输入引脚加 RC 滤波把带宽限制在信号实际频率的 5 到 10 倍。最后再用单次模式抓一拍数据连续读 100 次算标准差如果标准差明显下降说明连续模式下的数字串扰是抖动来源之一。5.3 切换通道后第一笔数据异常现象多通道巡检时切换通道后的第一个读取结果明显偏离真实值第二个数据才正常。原因AD7124 的模拟输入开关和 PGA 在通道切换后需要稳定时间滤波器的数字滤波器也需要几个转换周期才能收敛到新输入值。通道切换后立刻读数据拿到的是上一通道残留信号和当前通道混叠的过渡值。解决切换通道后不要立即读数据先丢弃当前滤波器输出。具体做法是切换后触发一次转换但不读或者连续触发两次转换只取第二次的结果。更稳的做法是切换到单次模式切换后发送一次转换命令等 DRDY 拉低后读数据这个数据是当前通道的完整转换结果不会混入历史残留。5.4 温度一变读数跟着缓慢漂移现象环境温度变化后同一输入信号的读数出现缓慢但持续的单向偏移校正一次后过一段时间又偏了。原因内部基准源的温度系数是主要来源。内部 1.17 V 基准虽然方便但温漂指标和外部精密基准相比有差距。如果模拟输入信号本身比较小PGA 增益又开得高基准的温漂会被等效放大到输出端肉眼看起来就是读数跟着温度走。解决对温漂有要求的项目换成外部基准源配置寄存器里的基准源选择从内部切到外部。如果基准源硬件已经无法更换退而求其次的做法是软件补偿在固件里内置一个温度传感器每隔一段时间读取温度查表修正增益误差但这种方式标定工作量很大属于事后救火能用外部基准解决就别用软件补。5.5 中断读取和轮询读取混用数据错位现象开始时用 DRDY 中断采集后来调试时又临时加了一段轮询 DRDY 引脚的代码结果数据偶发出现跳变且跳变值和上一次读到的值有某种对应关系。原因中断里已经置了标志位主循环的轮询逻辑也检测到 DRDY 低电平两边同时触发读数据操作一次转换数据被读了两遍把数据缓冲区的指针打乱后续数据整体错位。解决在一个工程里只保留一种读取触发方式。用中断标志位做主读取逻辑时轮询代码只用来做故障诊断诊断完毕就删除不要在正式采集路径里保留两套入口。另外DRDY 读数据寄存器后会自动拉高如果手动轮询时忽略了读操作对 DRDY 状态的复位会出现漏读或重复读这一点在代码注释里要写清楚防止后来接手的人又加一套轮询。6. 二次开发把它改造成多通道巡检仪的核心逻辑6.1 多通道配置表与轮询流程单通道驱动跑通后最常见的改造就是扩展成多通道巡检。AD7124 的每个模拟输入通道可以对应独立的配置寄存器和滤波器寄存器所以代码层面可以设计一张配置表把每个通道的增益、滤波器参数、基准源选择全部集中管理typedef struct { uint8_t cfgRegValue; uint16_t filterRegValue; } AD7124_ChannelConfig; static const AD7124_ChannelConfig channelTable[4] { {0x1A, 0x0080}, {0x1A, 0x0080}, {0x12, 0x0080}, {0x12, 0x0080}, };轮询主逻辑就是遍历配置表、加载配置、等待 DRDY、读数据、换算工程值for (uint8_t ch 0; ch 4; ch) { AD7124_LoadChannel(ch, channelTable[ch]); AD7124_TriggerSingleConversion(); while (ad7124_drdy_flag 0); ad7124_drdy_flag 0; int32_t raw AD7124_ReadData(); float eng AD7124_ConvertToEngineering(raw, channelTable[ch].cfgRegValue); saveResult(ch, eng); }AD7124_LoadChannel里做的是把对应通道的配置值写入 CONFIG 寄存器和 FILTER 寄存器同时在 ADC 控制寄存器里把当前通道字段切到目标通道。每个通道的增益不同时换算系数也不同所以AD7124_ConvertToEngineering要读取当前通道的配置再算满量程。6.2 两点校准把原始码换算成工程值原始码本身不代表物理量直接除以满量程再乘基准电压得到的是电压值。对于称重或压力传感器这类非线性要求高的应用建议做两点校准用标准源在低端和高端各校一次然后线性映射float AD7124_LinearCalib(float raw, float rawLo, float engLo, float rawHi, float engHi) { return (raw - rawLo) * (engHi - engLo) / (rawHi - rawLo) engLo; }调用时传入低端标准点的原始码和工程值、高端标准点的原始码和工程值函数返回当前实时工程值。校准参数保存在非易失存储里每次上电读出来覆盖默认值。从那以后我每次做带模拟前端的板子都会强制把自检函数留在出厂固件里复位后先跑一遍寄存器回写校验确认 SPI 通路没问题才进采集主循环。这个习惯帮我挡掉了不少硬件上面的低级问题节省的调试时间远比写自检函数花的多。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询