1. 项目概述
在嵌入式系统开发中,模拟信号采集是一个永恒的话题。最近我在做一个需要高精度温度监测的项目时,遇到了模拟信号采集精度不足的问题。市面上的12位ADC模块已经不能满足我的需求,于是决定自己动手设计一个16位逐次逼近型模数转换电路。这个设计基于常见的STM32单片机,通过合理的电路设计和软件算法优化,最终实现了0.0015V的分辨率,完全满足了我的项目需求。
16位ADC在工业控制、医疗设备和精密测量等领域有着广泛的应用场景。相比常见的8位或12位ADC,它能提供更高的分辨率和更精确的测量结果。但高精度也意味着更高的设计难度,特别是在抗干扰和信号调理方面需要格外注意。下面我就把这个设计过程中的关键点和经验教训分享给大家。
2. 核心电路设计
2.1 逐次逼近ADC工作原理
逐次逼近型ADC(SAR ADC)是通过二分搜索的方式逐步逼近输入电压值的。它的核心是一个比较器、一个数模转换器(DAC)和一个逐次逼近寄存器(SAR)。工作时,SAR从最高位开始,依次将每一位设为1,通过DAC产生对应的电压与输入电压比较,根据比较结果决定该位保留1还是清零。
这种转换方式的速度和精度主要取决于DAC的性能和比较器的灵敏度。在16位设计中,我们需要特别关注以下几点:
- DAC的线性度和建立时间
- 比较器的输入失调电压和响应速度
- 参考电压的稳定性
2.2 关键元器件选型
主控芯片选择:
我选用了STM32F373系列单片机,它内部集成了16位Σ-Δ ADC,但为了更灵活地控制采样过程,还是决定使用外部ADC方案。这个系列的优势在于它有丰富的外设接口和足够的处理能力,价格也相对合理。
ADC芯片选型:
经过对比,最终选择了ADS1115这款16位ADC芯片。主要考虑因素包括:
- 采样率:860SPS(满足大多数应用)
- 输入范围:±6.144V(可编程)
- I2C接口(简化布线)
- 内置可编程增益放大器(PGA)
参考电压源:
使用REF5025精密电压基准源,它具有:
- 2.5V输出
- 3ppm/°C温漂
- 0.05%初始精度
信号调理电路:
包括一个OPA2188精密运放组成的电压跟随器,用于阻抗匹配和信号缓冲。
2.3 电路原理图设计
整个电路分为几个关键部分:
-
模拟输入部分:
- 采用RC低通滤波(10kΩ+100nF)滤除高频噪声
- TVS二极管保护防止过压
- 精密电阻分压网络用于量程调整
-
ADC核心电路:
- ADS1115的AIN0-AIN3四个差分输入通道
- 0.1μF去耦电容尽可能靠近电源引脚
- 10μF钽电容提供储能
-
参考电压电路:
- REF5025输出端接10μF+0.1μF电容组合
- 串联10Ω电阻抑制振荡
-
数字接口部分:
- I2C线上拉电阻(4.7kΩ)
- 信号线串联33Ω电阻抑制振铃
注意:模拟地和数字地的分割非常重要,建议在ADC下方使用磁珠单点连接。
3. PCB布局与布线技巧
3.1 层叠设计
对于这种混合信号电路,我采用了4层板设计:
- 顶层:信号层(主要是模拟信号)
- 内层1:完整地平面
- 内层2:电源层
- 底层:数字信号和部分模拟信号
这种结构可以提供良好的信号完整性和电源分布。
3.2 关键布局原则
-
ADC芯片布局:
- 尽可能靠近信号源
- 远离数字噪声源(如MCU、晶振)
- 参考电压源紧邻ADC
-
去耦电容布置:
- 每个电源引脚配置0.1μF陶瓷电容
- 电容接地引脚尽量短
- 使用多个过孔连接地平面
-
敏感走线处理:
- 模拟信号线尽量短
- 避免平行走长距离数字线
- 必要时使用保护环(Guard Ring)
3.3 布线注意事项
- 模拟信号线宽6-8mil,保持阻抗一致
- 数字信号线宽4-6mil,控制上升时间
- 电源线加宽到15-20mil,降低阻抗
- 关键信号线(如时钟)优先布线
经验分享:在布完线后,我习惯用3D视图检查是否有跨分割的情况,特别是高速信号线不要跨地平面分割区。
4. 软件设计与优化
4.1 驱动程序实现
ADS1115通过I2C接口通信,驱动程序需要实现以下功能:
c复制#define ADS1115_ADDR 0x48
void ADS1115_WriteReg(uint8_t reg, uint16_t value) {
I2C_Start();
I2C_WriteByte(ADS1115_ADDR << 1);
I2C_WriteByte(reg);
I2C_WriteByte(value >> 8);
I2C_WriteByte(value & 0xFF);
I2C_Stop();
}
uint16_t ADS1115_ReadReg(uint8_t reg) {
uint16_t value = 0;
I2C_Start();
I2C_WriteByte(ADS1115_ADDR << 1);
I2C_WriteByte(reg);
I2C_Start();
I2C_WriteByte((ADS1115_ADDR << 1) | 1);
value = I2C_ReadByte(1) << 8;
value |= I2C_ReadByte(0);
I2C_Stop();
return value;
}
4.2 采样配置优化
根据不同的应用场景,需要灵活配置ADS1115的工作参数:
-
数据速率设置:
- 8SPS:最高精度,适合静态测量
- 128SPS:平衡精度和速度
- 860SPS:高速采样,精度稍低
-
增益选择:
- ±6.144V:最小增益,最大量程
- ±0.256V:最大增益,最高分辨率
-
工作模式:
- 单次转换模式:节能
- 连续转换模式:实时性高
4.3 数字滤波算法
为了充分发挥16位ADC的性能,我实现了以下几种数字滤波算法:
- 移动平均滤波:
c复制#define FILTER_SIZE 16
uint16_t moving_avg_filter(uint16_t new_sample) {
static uint16_t buffer[FILTER_SIZE] = {0};
static uint8_t index = 0;
static uint32_t sum = 0;
sum -= buffer[index];
buffer[index] = new_sample;
sum += new_sample;
index = (index + 1) % FILTER_SIZE;
return sum / FILTER_SIZE;
}
- 中值滤波:
c复制uint16_t median_filter(uint16_t new_sample) {
static uint16_t buffer[5] = {0};
static uint8_t index = 0;
uint16_t temp[5];
buffer[index++] = new_sample;
if(index >= 5) index = 0;
memcpy(temp, buffer, sizeof(temp));
bubble_sort(temp, 5); // 实现简单的冒泡排序
return temp[2];
}
- 卡尔曼滤波:
对于动态信号测量,卡尔曼滤波能提供更好的效果,但计算量较大,需要根据MCU性能权衡。
5. 系统校准与测试
5.1 校准方法
高精度ADC系统必须进行校准,主要包括:
-
零点校准:
- 短接输入端
- 记录输出码值作为零点偏移
- 在软件中补偿
-
满量程校准:
- 输入精确的参考电压
- 调整增益系数使读数匹配
-
线性度测试:
- 使用精密电压源输入多个点
- 检查INL(积分非线性)和DNL(微分非线性)
5.2 测试结果
经过精心设计和调试,系统达到了以下性能指标:
| 测试项目 | 指标值 | 测试条件 |
|---|---|---|
| 分辨率 | 0.076mV | 输入±2.5V范围 |
| INL | ±2LSB | 全量程 |
| DNL | ±1LSB | 全量程 |
| 噪声 | 0.5LSB RMS | 10Hz带宽 |
| 温漂 | 3ppm/°C | 0-70°C |
5.3 常见问题排查
在实际调试中,我遇到了以下几个典型问题及解决方法:
-
读数不稳定:
- 现象:LSB位不断跳动
- 原因:电源噪声或接地不良
- 解决:加强电源滤波,优化地平面
-
增益误差大:
- 现象:满量程读数偏小
- 原因:参考电压负载能力不足
- 解决:增加参考电压缓冲器
-
转换结果错误:
- 现象:偶尔出现明显错误值
- 原因:I2C通信受干扰
- 解决:降低I2C速度,加强信号完整性
6. 应用实例与扩展
6.1 温度测量系统
将这个16位ADC应用于PT100温度测量,电路设计要点:
-
恒流源设计:
- 使用LM334提供1mA恒定电流
- 运放反馈稳定电流值
-
信号调理:
- 仪表放大器放大微小电压
- 二阶低通滤波抑制噪声
-
线性化处理:
- 查表法补偿PT100非线性
- 软件实现温度计算
6.2 电池监测系统
用于锂电池电压监测时的特殊考虑:
-
分压电路:
- 高精度电阻分压(0.1%精度)
- 低温度系数(<25ppm/°C)
-
隔离设计:
- 光耦隔离数字信号
- 隔离电源供电
-
安全保护:
- 过压保护电路
- 反接保护二极管
6.3 扩展可能性
这个设计可以进一步扩展:
-
多通道同步采样:
- 使用多个ADS1115
- 同步触发信号控制
-
更高精度方案:
- 24位Σ-Δ ADC
- 配合前置放大器
-
无线传输:
- 增加蓝牙/WiFi模块
- 实现远程监控
在实际项目中,我发现ADC的性能不仅取决于芯片本身,整个信号链的设计同样重要。从传感器到ADC输入端的每一个环节都会影响最终结果。特别是在高精度应用中,温度稳定性往往成为限制因素,必要时需要考虑温度补偿措施。