1. 项目背景与核心需求
在工业测量和精密仪器领域,高精度模数转换器(ADC)是实现信号采集的关键部件。AD7175作为ADI公司推出的24位Σ-Δ型ADC,以其优异的噪声性能和灵活的接口配置,成为压力变送器、医疗设备等高精度应用的首选。而STM32系列MCU凭借丰富的外设资源和稳定的性能,常被选作其控制器。
这个项目要解决的核心问题是:如何基于STM32的硬件SPI接口,实现AD7175寄存器配置、数据采集和误差处理的完整驱动方案。不同于普通ADC的简单读取,AD7175需要处理复杂的寄存器映射、数据校验和噪声抑制,这对SPI时序控制和数据处理提出了更高要求。
2. 硬件设计与接口配置
2.1 硬件连接要点
AD7175与STM32的典型连接方式如下:
- SPI引脚:SCLK(PA5)、MISO(PA6)、MOSI(PA7)
- 控制引脚:CS(PA4自定义片选)、RDY(PA3中断输入)
- 参考电压:采用REF5025提供2.5V基准
- 模拟输入:差分模式接入AIN1+/AIN1-
关键提示:AD7175的SPI时序要求SCLK空闲时为高电平(CPOL=1),数据在第二个边沿采样(CPHA=1),这与STM32的SPI模式3完全对应。若配置错误会导致通信失败。
2.2 STM32 SPI外设初始化
以下是使用HAL库的初始化代码示例:
c复制SPI_HandleTypeDef hspi1;
void SPI_Init(void) {
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT; // 注意AD7175支持8/16/24位传输
hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH; // CPOL=1
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE; // CPHA=1
hspi1.Init.NSS = SPI_NSS_SOFT; // 软件控制片选
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; // 根据时钟树计算
HAL_SPI_Init(&hspi1);
}
3. AD7175寄存器配置详解
3.1 关键寄存器功能解析
AD7175采用寄存器映射式配置,主要寄存器包括:
- 通信寄存器(0x00):控制读写操作的目标寄存器
- 模式寄存器(0x01):设置转换模式、滤波器类型
- 接口模式寄存器(0x02):配置数据长度、CRC校验
- 通道寄存器(0x10~0x17):定义每个通道的输入配置
3.2 典型配置流程
以单通道连续转换模式为例,配置步骤如下:
- 复位操作:向通信寄存器写入0xFF五次实现软复位
- 设置接口模式:
c复制uint8_t if_mode[3] = {0x82, 0x00, 0x01}; // 使能CRC校验 AD7175_WriteReg(0x02, if_mode, 3); - 配置通道0:
c复制uint8_t chn_cfg[3] = {0x01, 0x80, 0x00}; // AIN1+/-差分输入 AD7175_WriteReg(0x10, chn_cfg, 3); - 设置采样率:
c复制uint8_t filter[3] = {0x00, 0x00, 0x05}; // 50SPS, SINC5滤波器 AD7175_WriteReg(0x01, filter, 3);
4. 数据采集与处理
4.1 数据读取机制
AD7175提供两种数据读取方式:
- 中断模式:利用RDY引脚下降沿触发中断
- 轮询模式:持续检查状态寄存器(0x00)的RDY位
推荐的中断服务例程实现:
c复制void EXTI3_IRQHandler(void) {
if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_3) != RESET) {
uint8_t data[3];
AD7175_ReadData(data); // 读取24位数据
int32_t raw_val = (data[0]<<16) | (data[1]<<8) | data[2];
float voltage = (raw_val * 2.5f) / 0x7FFFFF; // 转换为电压值
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_3);
}
}
4.2 数据校验与滤波
AD7175内置的CRC校验可显著提高数据可靠性。校验流程如下:
- 读取包含CRC的4字节数据
- 计算前3字节的CRC-8值(多项式0x07)
- 与接收的第4字节比较
示例校验函数:
c复制uint8_t Check_CRC(uint8_t* data) {
uint8_t crc = 0;
for(int i=0; i<3; i++) {
crc ^= data[i];
for(int j=0; j<8; j++)
crc = (crc & 0x80) ? (crc<<1)^0x07 : (crc<<1);
}
return (crc == data[3]);
}
5. 性能优化与问题排查
5.1 噪声抑制技巧
-
PCB布局:
- 将去耦电容(10μF钽电容+0.1μF陶瓷)尽量靠近AD7175电源引脚
- 模拟与数字地单点连接
- SPI走线长度不超过5cm
-
软件滤波:
c复制#define SAMPLE_NUM 5 float Get_Average_Voltage(void) { float sum = 0; for(int i=0; i<SAMPLE_NUM; i++) { sum += AD7175_ReadVoltage(); HAL_Delay(2); } return sum/SAMPLE_NUM; }
5.2 常见问题速查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| SPI无响应 | 1. 相位极性配置错误 2. 片选信号异常 |
1. 确认CPOL/CPHA=1/1 2. 用逻辑分析仪抓取CS信号 |
| 数据跳变大 | 1. 参考电压不稳 2. 输入阻抗不匹配 |
1. 检查REF5025输出 2. 前端添加缓冲运放 |
| CRC校验失败 | 1. 时钟速度过快 2. 信号干扰 |
1. 降低SPI波特率 2. 缩短走线增加屏蔽 |
6. 扩展应用实例
6.1 多通道切换采集
通过配置通道寄存器组实现4通道轮询采集:
c复制void MultiChannel_Init(void) {
uint8_t chn_cfg[3] = {0x01, 0x80, 0x00}; // 通道0: AIN1+/-
AD7175_WriteReg(0x10, chn_cfg, 3);
chn_cfg[1] = 0x90; // 通道1: AIN2+/-
AD7175_WriteReg(0x11, chn_cfg, 3);
// ...其他通道类似
}
float Read_Channel(uint8_t chn) {
uint8_t mode[3];
AD7175_ReadReg(0x01, mode, 3);
mode[0] = (mode[0] & 0xF0) | chn; // 设置当前通道
AD7175_WriteReg(0x01, mode, 3);
return AD7175_ReadVoltage();
}
6.2 自定义滤波器设置
AD7175允许灵活配置滤波器参数以适应不同场景:
c复制void Set_Custom_Filter(uint16_t fs, uint8_t type) {
uint8_t filter[3] = {0};
filter[0] = type & 0x0F; // 滤波器类型
filter[1] = (fs >> 8) & 0xFF; // 采样率高位
filter[2] = fs & 0xFF; // 采样率低位
AD7175_WriteReg(0x01, filter, 3);
}
// 示例:设置为SINC3滤波器,10SPS
Set_Custom_Filter(10, 0x03);
在实际项目中,我发现AD7175的校准寄存器(0x19~0x1B)对精度影响显著。建议上电后先执行内部零点校准(写0x01到模式寄存器bit6),并在环境温度变化超过5℃时重新校准。对于要求更高的场合,可以定期执行系统校准,通过外接精准参考源来修正增益误差。