STM32G070驱动CS5530高精度ADC:SPI时序、校准与噪声验证
简介STM32G070与CS5530联合开发资料包面向嵌入式开发者、电子爱好者及需要实现高精度数据采集的工程师。该资源整合了电路原理图与配套C语言驱动代码覆盖MCU初始化、SPI/I2C通信、数据处理等关键环节可帮助读者快速理解两款芯片的硬件连接方式与软件交互流程。压缩包共3个文件包含2个C源码文件和1份PDF说明文档整体仅105KB便于直接阅读和移植。目前已有787人学习下载适合正在做传感器采集、工业控制或低功耗物联网项目的开发者参考复用。资料价值在于将CS5530驱动代码与STM32G070集成示例相结合既给出了底层寄存器配置与读写函数也提供了原理图层面的引脚定义和信号连接说明能有效缩短从硬件搭建到固件调试的周期是嵌入式接口开发中难得的紧凑实例。1. STM32G070 接 CS5530先想清楚这一个问题很多从 HX711 转过来的工程师拿到 CS5530 的第一块板子往往读不出数。问题不在代码而在 CS5530 根本不像 HX711 那样上电就能用它要求外接 4.096MHz 晶振、要用命令字节启动校准、连 SPI 时序都要卡着时钟个数来读。STM32G070 做低成本工业采集板、称重仪表和压力变送器很常见和 CS5530 搭配是典型组合。这篇就顺着“G070 主控 CS5530 高精度 ADC”这条线把硬件接线、CubeMX 配置、最小驱动、校准顺序和噪声验证讲清楚适合正在画原理图或已经把板子点亮、正在调 SPI 的读者。2. CS5530 的 SPI 时序、寄存器与 STM32G070 的引脚分配2.1 CS5530 的时钟与电平要求先别急着写代码CS5530 内部没有振荡器XTAL1/XTAL2 必须挂一颗 4.096MHz 晶振。这是和 HX711 最不一样的地方很多第一版硬件死在这一步。晶振两端各接一个 10pF 到 20pF 的负载电容到地普通的 49S 晶振就能起振。判断晶振是否工作最直接的办法是量 DRDY如果上电后 DRDY 一直不动先查晶振再查 SPI。电源要注意 CS5530 的模拟电源 VA 和数字电源 VD 是分开的允许 VA 接 5V、VD 接 3.3V。G070 的 GPIO 只能承受 3.6V所以推荐 VA 用 5V 供电以提高模拟性能VD 接 3.3V这样 SDO/SDI/SCLK 的电平就跟着 3.3V 走可以直接连 G070不需要电平转换。模拟地和数字地在 CS5530 附近单点汇接开关噪声就不容易通过地回路进到模拟前端。2.2 命令字节、配置寄存器和 24 位转换结果的帧结构CS5530 的串行接口看起来像 SPI实际是“命令 移位”的混合时序。每次操作以 CS 拉低开始先送一个命令字节命令之后的 SCLK 个数由命令决定写配置寄存器命令后跟 32 位数据启动校准的命令后不需要额外数据读转换结果时先送一个空操作字节后续 24 个 SCLK 把数据从 SDO 推出。所有字节都是 MSB firstSPI 模式固定为 Mode 0CPOL0CPHA1Edge。常用命令如下这些是驱动里真正会用到的命令字行为后续数据0x01写配置寄存器4 字节共 32 位0x03自校准无完成后 DRDY 拉低0x15系统失调校准无输入应处于零点0x17系统增益校准无输入应加已知标准信号0x00NOP读结果时用来产生时钟配置寄存器共 32 位包含通道选择、增益、单/双极性、输入范围VRS、字速率等字段。对最小系统来说上电复位后的默认值就可以直接用通道 1、增益 1、双极性、输入范围 ±VREF。显式写一遍的作用是让后续改增益时有一个确定的基准所以初始化时写四个 0x00 已经足够跑通整个流程需要改增益时再查手册对应的位段不要靠猜。2.3 STM32G070 的 SPI1 引脚与接线G070 的 SPI1 可以映射到 PA5/PA6/PA7CS 用普通 GPIO 控制比硬件 NSS 更省心DRDY 接一个任意输入 GPIO。我一般把 CS 放在 PA4、DRDY 放在 PB1这样 CubeMX 里不需要配置 NSS 硬件功能。G070 引脚功能接 CS5530 引脚配置PA5SPI1_SCKSCLK复用推挽速率 HighPA6SPI1_MISOSDO复用输入PA7SPI1_MOSISDI复用推挽PA4GPIO 输出CS推挽初始拉高PB1GPIO 输入DRDY上拉输入或浮空输入3.3V电源VD与 G070 同源5V电源VA模拟电源可选 3.3VGND地AGND/DGND单点连接注意 SCLK 不要一开始就追求高速。CS5530 的串口时钟上限约 2.1MHz而 G070 的最高主频 64MHzAPB 分频后取 32 分频正好得到 2MHz。2MHz 对这个 ADC 完全够用7.5SPS 字速率下一帧才 133ms瓶颈根本不在 SPI。如果后续打算挂多个 SPI 器件2MHz 可能显得保守但 CS5530 的上限就在那里。G070 的 SPI 外设本身可以跑到 32MHz把它和一个限制 2MHz 的老 ADC 放在同一条总线上处理办法是给 CS5530 单独分一组 SCK 分频或者接受整体降到 2MHz。我一般建议 CS5530 独占 SPI1别的器件放到 SPI2省得为了它拖慢 Flash 或 DAC 的吞吐。3. 用 STM32G070 的硬件 SPI 驱动 CS5530最小驱动代码与配置步骤3.1 CubeMX 里 SPI1 的 4 个参数在 CubeMX 中把 SPI1 设为 Full-Duplex Master、8 位数据长度BaudRatePrescaler 选 /32Clock Polarity 和 Clock Phase 分别选 Low 和 1 Edge即 Mode 0。NSS 选 Disable因为 CS 用 PA4 软件控制。First Bit 保持 MSB First。对应到 HAL 初始化代码就是下面这段hspi1.Instance SPI1; hspi1.Init.Mode SPI_MODE_MASTER; hspi1.Init.Direction SPI_DIRECTION_2LINES; hspi1.Init.DataSize SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity SPI_POLARITY_LOW; hspi1.Init.CLKPhase SPI_PHASE_1EDGE; hspi1.Init.NSS SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler SPI_BAUDRATEPRESCALER_32; hspi1.Init.FirstBit SPI_FIRSTBIT_MSB; HAL_SPI_Init(hspi1);这里 32 分频在 64MHz 主频下是 2MHz刚好贴着 CS5530 的串口时钟上限。如果后续为了和别的器件共用 SPI 而把速率降下来/64 即 1MHz 也完全能跑低速只会让通信更稳不会损失转换精度。3.2 初始化、自校准与读取的三段代码驱动比一般 SPI 器件多两步写配置、自校准。先把底层字节操作写出来uint8_t cs5530_spi_byte(uint8_t val, uint8_t *rx) { HAL_SPI_TransmitReceive(hspi1, val, rx, 1, 10); return *rx; } void cs5530_write_cmd(uint8_t cmd) { uint8_t tmp; CS5530_CS_LOW(); cs5530_spi_byte(cmd, tmp); CS5530_CS_HIGH(); } void cs5530_write_config(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) { uint8_t tmp; CS5530_CS_LOW(); cs5530_spi_byte(0x01, tmp); // 写配置寄存器命令 cs5530_spi_byte(b0, tmp); cs5530_spi_byte(b1, tmp); cs5530_spi_byte(b2, tmp); cs5530_spi_byte(b3, tmp); CS5530_CS_HIGH(); }cs5530_spi_byte 用 HAL 的全双工接口发送命令字节的同时把 SDO 上的值收回来。CS 必须覆盖完整的命令加数据过程中间不能拉高否则 CS5530 会认为操作被中断。写配置命令 0x01 之后必须送满 32 位即使只改一个字段也要把四个字节补齐。初始化函数负责上电延时、写配置和自校准int cs5530_init(void) { uint32_t timeout 1000000; HAL_Delay(50); // 等待上电复位和晶振起振 cs5530_write_config(0x00, 0x00, 0x00, 0x00); // 默认配置 HAL_Delay(10); // 配置寄存器写入后留一点建立时间 cs5530_write_cmd(0x03); // 自校准 while (HAL_GPIO_ReadPin(DRDY_GPIO_Port, DRDY_Pin) GPIO_PIN_SET) { if (--timeout 0) return -1; // 校准超时 } return 0; }自校准是 CS5530 必做的一步它会用内部基准把失调和增益误差测出来并写到校准寄存器里。校准期间 DRDY 保持高校准完成后拉低所以等待 DRDY 变低是判断校准完成的可靠依据。超时不要设太短低字速率下自校准耗时可能达到几百毫秒。读取转换结果是一次 CS 低电平期间发 4 个字节int32_t cs5530_read_raw(void) { uint8_t tx[4] {0, 0, 0, 0}; uint8_t rx[4]; CS5530_CS_LOW(); HAL_SPI_TransmitReceive(hspi1, tx, rx, 4, 10); CS5530_CS_HIGH(); return ((int32_t)(int8_t)rx[1] 16) | ((uint32_t)rx[2] 8) | rx[3]; }第一个字节是 NOP用来对齐芯片的移位状态后面三个字节才是 24 位转换结果。rx[1] 是数据最高字节必须先转成 int8_t 再左移否则负数的符号位会被当成无符号数直接丢掉负的传感器读数会变成很大的正值。转换结果是二进制补码0x7FFFFF 对应正满量程减一个 LSB0x800000 对应负满量程。读结果时用 4 字节而不是 3 字节是为了让芯片先收到一个完整的 NOP 命令再在紧接着的 24 个 SCLK 里把数据移出来。有的驱动只用 3 字节也能工作那是利用了 CS 拉低后 SDO 立即输出第一个数据位的特性换个批次或温度可能就不一样不推荐。注意读结果和写配置的整个操作必须在一个 CS 拉低周期里完成CS 拉高就认为本次操作结束时钟数多一秒都不行。3.3 调用顺序与主循环的写法主循环不要每转一圈就去读一次寄存器CS5530 的转换完成由 DRDY 指示DRDY 没拉低时读到的还是上一帧数据。连续转换模式下芯片在读数结束、CS 拉高后自动开始下一次转换所以主循环最稳的写法是先等 DRDY 变低再执行读取读取后继续做滤波、标定和对外通信下一轮循环再等下一下降沿while (1) { while (HAL_GPIO_ReadPin(DRDY_GPIO_Port, DRDY_Pin) GPIO_PIN_SET) { } int32_t raw cs5530_read_raw(); // 滤波、标定、对外输出 }DRDY 是转换完成握手信号它从高变低说明新的 24 位数据已经锁存到输出寄存器。如果这一帧数据隔了很久才读读到的仍然是当前帧不会被覆盖只是实时性变差。想用中断方式就把 PB1 配成外部中断下降沿触发在中断服务函数里做读取并置标志位主循环处理滤波和协议这样即使高字速率下也不会漏帧。4. CS5530 的校准流程与 5 个容易把人绕进去的坑4.1 系统失调校准和系统增益校准什么时候用自校准只消除芯片内部的失调和增益误差不消除传感器和前端电路的误差。称重场景里传感器和放大器会引入零点偏移这时用系统失调校准更合适让称台保持空载发 0x15 命令芯片会以当前输入作为零点基准。做量程标定则发 0x17在输入端加一个已知标准信号后再校准。场景命令前置条件芯片上电首次使用0x03 自校准配置寄存器已设定传感器零点偏移0x15 系统失调校准称台空载、输入稳定满量程标定0x17 系统增益校准输入加标准信号顺序是先 0x15 后 0x17改完增益或字速率后必须重新校准。校准命令和写配置命令一样在 CS 拉低期间发一个字节等 DRDY 拉低表示完成。校准期间输入要稳定称重场景下不要在校准过程中碰传感器。4.2 DRDY 判空与转换速率的匹配CS5530 的字速率决定噪声水平速率越低噪声越小。7.5SPS 档的峰峰值噪声最小适合高精度平台秤需要快速响应的分选秤可以提到 240SPS 以上但无噪声位数会明显下降。DRDY 在高字速率下变低的时间窗口很短轮询读数据时如果主循环有长阻塞可能漏掉一次转换数据不会丢但时间戳会跳。稳妥做法是 DRDY 接外部中断读操作放到中断上下文或置位后立即执行。4.3 五个常见坑和排查顺序第一个坑是晶振。CS5530 没有内部时钟晶振没起振时 DRDY 完全不动。用示波器量 XTAL1 引脚10x 探头低输入电容档能看到 4.096MHz 正弦波就说明时钟活着看不到就先换晶振和负载电容。第二个坑是 SPI 模式。CS5530 是 Mode 0很多从别的 ADC 迁过来的人习惯性配成 Mode 3命令发出去全部错位。先确认 CPOL 和 CPHA 两个选项再查时钟频率G070 上 32 分频是上限别再往上加压。第三个坑是读数据时钟个数。读转换结果的这个过程必须在一个 CS 低电平周期里完成CS5530 对串口时钟是计数的多发一个字节或少发一个字节都会导致数据错位。用 HAL_SPI_TransmitReceive 一次传 4 字节不要拆成多次单字节传输。第四个坑是输入共模电压。CS5530 的 AIN、AIN- 差分输入各自对 AGND 有一个共模范围差不多是 AGND0.7V 到 VA−0.7V。传感器电桥供电后如果共模被拉出这个范围转换结果会顶在满偏附近像 0x7FFFFF 或 0x800000。第五个坑是 5V 和 3.3V 的电平。VA 可以接 5VVD 必须按逻辑电平接SDO、SDI、SCLK 的电平参考 VD。VD 接 5V 再连 G070 的 PA5/PA6/PA7长时间工作会损坏 G070 的引脚。判断电平是否正常的办法很简单量一下 CS5530 SDO 引脚在空闲时的高电平是不是接近 3.3V 而不是 5V。VA 5V、VD 3.3V 是最稳的组合。5. 做完最小系统后用峰峰值噪声验证 CS5530 的 24 位纯度5.1 把输入短接统计 100 个样本的峰峰值驱动跑通后别急着标定先验证板子的噪声水平。把 AIN 和 AIN- 用短跳线连到一起让输入为零采集 100 个样本统计最大值和最小值的差int32_t min 0x7FFFFFFF, max -0x7FFFFFFF; int32_t raw; for (int i 0; i 100; i) { while (HAL_GPIO_ReadPin(DRDY_GPIO_Port, DRDY_Pin) GPIO_PIN_SET) { } raw cs5530_read_raw(); if (raw min) min raw; if (raw max) max raw; } int32_t pp_lsb max - min;峰峰值 LSB 除以满量程就是无噪声分辨率。满量程是 ±VREF/增益LSB 大小等于 2×VREF/(增益×2^24)。VREF2.5V、增益1 时每个 LSB 约 0.298µV。峰峰值 30 个 LSB对应无噪声有效位数约 24−log2(30)≈19.1 位这是比较健康的结果。5.2 增益匹配和数字滤波的两个参数CS5530 的增益不是随便选的。传感器输出幅度较小且共模在范围内时用增益 64 可以降低对模拟放大的要求但输入范围同时缩小到 ±39mV 左右。无噪声位数的增益收益有一个拐点通常增益 32 或 64 的性价比最高具体以你的传感器满量程输出为准。数字滤波在 G070 上做一阶低通就够系数取 1/16 时收敛较快取 1/64 时更平滑static int32_t filtered 0; filtered filtered ((raw - filtered) 4); // 1/16约 0.4s 稳定称重场合采样率 7.5SPS 时1/16 系数下阶跃响应大概 0.4s 到稳态既能看清加载过程又不会把振动噪声全放进来。如果现场振动明显把右移 4 位改成右移 6 位。除了峰峰值标准差也能反映噪声分布采集 1000 个样本求标准差用 6 倍标准差估计 99.7% 的置信区间。峰峰值对偶发毛刺更敏感标准差更贴近长期稳定性两个都跑一遍再下结论。5.3 和 HX711 的边界在哪里HX711 在便携秤里仍然合适便宜、内置稳压、双线通信、PGA 到 128 倍。但需要系统级零点/增益校准、需要可编程字速率、需要和 PLC 或变送器做长距离稳定通信时CS5530 的寄存器访问模型和 7.5SPS 低噪声档位更合适。两者都是 24 位但 CS5530 的系统校准能抵消传感器和前端的大部分温漂HX711 只能靠外部补偿。把短接输入端测峰峰值这段代码留在工程里下一块板子回板后第一个跑的就是它。本文还有配套的精品资源点击获取