1. 项目背景与核心需求
在工业测量、医疗设备和环境监测等领域,我们经常需要将模拟信号(如温度、压力、光强等)转换为数字信号进行处理。ADS122U04作为TI公司的高精度24位Δ-Σ ADC,配合STM32F411RE的强劲处理能力,能够实现微伏级信号的精确采集。这个组合特别适合需要高精度、低功耗的便携式测量设备。
我最近在一个工业温度监测项目中采用了这个方案,需要测量多路热电偶信号,精度要求达到0.1℃。传统16位ADC无法满足要求,而ADS122U04的24位分辨率和内置PGA完美解决了这个问题。下面分享我的完整实现过程。
2. 硬件设计与关键器件选型
2.1 ADS122U04特性解析
这款ADC有几个突出优势:
- 24位无失码分辨率
- 内置可编程增益放大器(PGA),增益1~128
- 低噪声:50nV RMS(增益=128时)
- 支持2.7V-5.5V宽电压供电
- 集成温度传感器和电压基准
实际使用中发现,当测量微小信号时,启用内部低噪声PGA比外置放大电路效果更好,信噪比能提升20dB以上。
2.2 STM32F411RE的配置要点
我们主要利用其以下特性:
- 100MHz Cortex-M4内核
- 支持SPI时钟最高50MHz
- 1.7V-3.6V工作电压
- 低功耗模式与ADC唤醒配合良好
硬件连接示意图:
| ADS122U04引脚 | STM32F411RE连接 | 备注 |
|---|---|---|
| DRDY | PA0 | 数据就绪中断 |
| DIN | PA7 (MOSI) | SPI数据输入 |
| DOUT | PA6 (MISO) | SPI数据输出 |
| SCLK | PA5 (SCK) | SPI时钟 |
| CS | PA4 | 片选(软件控制) |
| AVDD | 3.3V | 模拟电源 |
| DVDD | 3.3V | 数字电源 |
3. 软件实现与寄存器配置
3.1 SPI通信初始化
void SPI1_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; SPI_HandleTypeDef hspi1 = {0}; __HAL_RCC_SPI1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); // SCK/MISO/MOSI引脚配置 GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 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; // ~3MHz hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; HAL_SPI_Init(&hspi1); }3.2 ADC寄存器配置示例
配置为连续转换模式,数据速率20SPS,增益128:
void ADS122U04_Config(void) { uint8_t config[4] = {0}; // 配置寄存器0: PGA启用,增益128,连续转换 config[0] = 0x01; // MUX0: AIN0和AIN1 config[1] = 0x62; // PGA=128, 20SPS config[2] = 0x10; // 内部2.048V基准 config[3] = 0x00; // 禁用IDAC HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, config, 4, 100); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); }4. 数据采集与处理优化
4.1 中断驱动数据读取
利用DRDY引脚触发中断,避免轮询:
// 中断回调函数 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == GPIO_PIN_0) { uint8_t rxData[3] = {0}; int32_t adcValue = 0; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); HAL_SPI_Receive(&hspi1, rxData, 3, 100); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); adcValue = (rxData[0] << 16) | (rxData[1] << 8) | rxData[2]; if(adcValue & 0x800000) { adcValue -= 0x1000000; // 补码转换 } float voltage = (adcValue * 2.048f) / (8388607.0f * 128); // 后续处理... } }4.2 噪声抑制实践技巧
- 电源处理:实测发现,给AVDD增加10μF钽电容+0.1μF陶瓷电容组合,噪声降低40%
- PCB布局:
- 将ADC放置在距离STM32至少5mm位置
- 模拟和数字地单点连接
- 敏感信号线走线长度不超过20mm
- 软件滤波:采用移动平均+中值滤波组合算法
#define FILTER_SIZE 5 typedef struct { float buffer[FILTER_SIZE]; uint8_t index; } Filter_t; float MedianFilter(Filter_t* filter, float newVal) { // 更新缓冲区 filter->buffer[filter->index] = newVal; filter->index = (filter->index + 1) % FILTER_SIZE; // 排序找中值 float temp[FILTER_SIZE]; memcpy(temp, filter->buffer, sizeof(temp)); for(int i=0; i<FILTER_SIZE-1; i++) { for(int j=i+1; j<FILTER_SIZE; j++) { if(temp[i] > temp[j]) { float swap = temp[i]; temp[i] = temp[j]; temp[j] = swap; } } } return temp[FILTER_SIZE/2]; }5. 校准与精度验证
5.1 两点校准法实现
在代码中增加校准参数存储:
typedef struct { float gain; float offset; uint32_t crc; // 校验值 } CalibrationParams; void PerformCalibration(float meas1, float actual1, float meas2, float actual2) { CalibrationParams cal; cal.gain = (actual2 - actual1) / (meas2 - meas1); cal.offset = actual1 - (meas1 * cal.gain); // 计算CRC并写入Flash cal.crc = CalculateCRC(&cal, sizeof(cal)-4); FLASH_Program(0x0801F000, (uint32_t*)&cal, sizeof(cal)); } float ApplyCalibration(float rawValue) { CalibrationParams cal; memcpy(&cal, (void*)0x0801F000, sizeof(cal)); if(CalculateCRC(&cal, sizeof(cal)-4) == cal.crc) { return (rawValue * cal.gain) + cal.offset; } return rawValue; // 校验失败返回原始值 }5.2 实测性能数据
使用6位半数字万用表34401A作为基准对比:
| 输入电压(mV) | 测量值(mV) | 误差(μV) |
|---|---|---|
| 10.000 | 10.003 | +3 |
| 50.000 | 49.998 | -2 |
| 100.000 | 100.005 | +5 |
| 500.000 | 499.997 | -3 |
在25℃环境下连续工作8小时,漂移小于2μV。这个性能完全满足热电偶测温的0.1℃分辨率要求。