【STM32G431实战】模拟SPI轮询ADS1118四通道电压采集的时序优化与抗干扰设计
1. 工业噪声环境下的电压采集挑战在工业自动化、电力监测等场景中电压采集常常面临复杂的电磁干扰环境。我最近用STM32G431和ADS1118搭建的四通道采集系统就遇到了这样的问题——当附近电机启动时采集数据会出现明显的跳变。这种干扰主要来自三个方面电源线上的高频噪声、信号传输过程中的耦合干扰以及通道切换时的瞬态响应。ADS1118作为TI的16位精密ADC本身具备较强的抗干扰能力。但在实际项目中发现当采用模拟SPI通信时若时序控制不当SCLK边沿的抖动会导致数据采样错误。特别是在128SPS速率下CS信号下降沿到第一个SCLK上升沿的间隔t_CSSCLK若小于200ns误码率会显著上升。有次调试时我把延时从150ns调整到300ns通道错位问题立刻减少了80%。另一个常见陷阱是通道切换后的稳定时间不足。手册建议等待1/DR时间128SPS时为8ms但实测在存在工频干扰时这个时间需要延长到15-20ms。我曾用示波器捕捉到AIN0切换到AIN1后信号需要约12ms才完全稳定。如果此时提前启动转换前3-4个采样点会包含上个通道的残留电压。2. 模拟SPI的时序优化实战2.1 关键时序参数校准用GPIO模拟SPI最头疼的就是时序控制。根据ADS1118的SPI Mode1CPOL0, CPHA1要求我总结出三个必须精确控制的时序点CS建立时间CS拉低后至少等待200ns再发SCLK。在STM32G431上用HAL库直接操作寄存器能实现更精确的控制#define CS_L GPIOA-BSRR GPIO_BSRR_BR_4 // 原子操作拉低 #define CS_H GPIOA-BSRR GPIO_BSRR_BS_4 // 原子操作拉高 void delay_300ns(void) { DWT-CYCCNT 0; while(DWT-CYCCNT SystemCoreClock/1000000*0.3); }SCLK脉冲宽度每个时钟周期要保证高/低电平各维持至少400ns。我的做法是用定时器生成精确延时void SPI_WriteBit(uint8_t bit) { if(bit) MOSI_H; else MOSI_L; SCLK_H; delay_500ns(); // 使用DWT计数器实现 SCLK_L; delay_500ns(); }数据保持时间在SCLK下降沿后MOSI数据需要保持至少50ns。实测发现若用HAL_GPIO_WritePin函数由于函数调用开销这个时间自然满足。2.2 通道切换的防错设计多通道轮询时最容易出现通道数据错位。根本原因是ADS1118的转换流水线特性——本次读取的是上次配置的转换结果。我摸索出两种可靠方案方案一双次读取法float ReadChannel(uint8_t ch) { uint16_t config 0xC58B | (ch 12); // 设置目标通道 Write_ADS1118(config, 1); // 丢弃第一次结果 int16_t raw Write_ADS1118(config, 0); // 读取本次配置结果 return raw * 0.125f; // 4.096V量程时的LSB }方案二DRDY引脚判断法// 硬件连接ADS1118的DRDY引脚接STM32的EXTI void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin DRDY_Pin) { ready_flag 1; } } float ReadChannelSafe(uint8_t ch) { ready_flag 0; Write_ADS1118(0xC58B | (ch 12), 1); while(!ready_flag); // 等待转换完成 return Write_ADS1118(0xC58B, 0) * 0.125f; }实测发现方案二可靠性更高但需要占用额外IO口。在EMC测试中方案二的误码率比方案一低两个数量级。3. 硬件抗干扰设计要点3.1 电源滤波方案ADS1118的VDD引脚噪声会直接影响转换精度。推荐采用π型滤波电路3.3V ──[10Ω]──┬──[0.1μF]── GND │ [4.7μF] │ VDD我在一个变频器项目中对比过不同滤波方案的效果无滤波噪声峰峰值达120mV单电容滤波降至45mVπ型滤波仅8mV3.2 信号输入保护工业现场常有过压风险建议每个AINx通道增加保护电路AINx ──[1kΩ]──┬──[100Ω]── ADS1118 │ [TVS二极管] │ GNDTVS二极管选型要注意钳位电压不超过ADS1118的极限值VDD0.3V响应时间快于5ns建议使用SMF3.3系列4. 软件层面的优化技巧4.1 数字滤波算法对于工频干扰采用滑动平均滤波配合50Hz陷波效果显著#define FILTER_DEPTH 8 float moving_filter(float new_val) { static float buf[FILTER_DEPTH]; static uint8_t idx 0; buf[idx] new_val; if(idx FILTER_DEPTH) idx 0; float sum 0; for(int i0; iFILTER_DEPTH; i) { sum buf[i]; } return sum / FILTER_DEPTH; }4.2 异常值处理机制工业环境常有瞬时干扰建议增加合理性判断#define VALID_RANGE 4.2 // 超过量程10% float safe_read(uint8_t ch) { float val ReadChannel(ch); if(fabs(val) VALID_RANGE) { val ReadChannel(ch); // 重试一次 if(fabs(val) VALID_RANGE) return NAN; } return val; }4.3 温度补偿实现ADS1118内置温度传感器可用于冷端补偿float read_temperature(void) { uint16_t config 0x8000 | ADS1118_CONFIG_TS_MODE_TEMP; Write_ADS1118(config, 1); HAL_Delay(10); // 温度转换需要更长时间 int16_t raw Write_ADS1118(config, 0); return (raw 4) * 0.03125 - 50; }在热电偶测量应用中配合此功能可将测温误差从±5℃降低到±1℃以内。