在工业自动化、环境监测和医疗设备中,微弱信号的精确采集始终是嵌入式系统设计的核心挑战。比如,一个称重传感器输出的差分电压可能仅有几毫伏甚至几百微伏,若使用普通MCU内置的12位ADC(如STM32F103自带的ADC),其理论最小分辨电压约为1.2mV(以3.3V参考电压计算),显然无法满足需求。更不用说,在实际应用中还存在噪声干扰、温漂、电源波动等问题,使得小信号测量更加困难。
正是在这种背景下,“外置高精度ADC + 通用MCU”的架构逐渐成为主流方案。TI推出的 ADS1220 作为一款集成了可编程增益放大器(PGA)、Σ-Δ调制器、数字滤波器和SPI接口的24位ADC芯片,恰好填补了这一空白。它不仅能将输入信号放大128倍,还能通过内部陷波滤波抑制工频干扰,非常适合用于RTD测温、称重模块、心电前置等对精度要求极高的场景。
而搭配 STM32F103 这类成本低、生态成熟、开发便捷的Cortex-M3控制器,则构成了一个兼顾性能与性价比的理想组合。这套系统不仅能在便携设备中实现亚微伏级分辨率的数据采集,还可通过UART上传数据、OLED显示结果或接入无线网络,具备良好的扩展性。
ADS1220本质上是一款面向精密模拟前端的Σ-Δ型ADC。它的核心优势不在于速度——最高仅支持1kSPS采样率,而在于“静”:极低的噪声、高度集成的信号调理功能以及出色的共模抑制能力。这使得它特别适合处理来自桥式电路、热电偶或应变片这类缓慢变化但极其敏感的信号源。
该芯片提供4个差分输入通道(或7个单端输入),用户可通过内部多路复用器灵活选择待测信号路径。更重要的是,其内置的PGA支持1~128倍增益调节。这意味着即使输入信号只有±16mV,也能被放大至接近满量程范围进行转换,从而大幅提升有效分辨率。例如,在使用2.5V外部参考电压且增益设为128时,每LSB对应的电压变化仅为约0.298μV,足以捕捉到细微的物理变化。
为了进一步提升抗干扰能力,ADS1220集成了同步50Hz/60Hz双陷波滤波器,能够有效抑制电力线耦合进来的交流噪声。这对于部署在工厂车间或电网附近的设备尤为重要。此外,它支持两种工作模式:连续转换和单次转换。后者允许系统在非采样期间关闭ADC以节省功耗,非常适合电池供电的应用。
通信方面,ADS1220采用标准四线SPI接口(SCLK、DIN、DOUT、CS),最高支持4MHz时钟频率,与STM32系列MCU天然兼容。所有配置均通过写入四个8位寄存器完成,包括通道选择、增益设置、输出速率、滤波模式等参数。整个过程无需额外驱动库,只需按照手册格式构造命令字即可完成控制。
下面是一段基于STM32 HAL库的SPI初始化代码:
void MX_SPI1_Init(void)
{
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.CLSPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
HAL_SPI_Init(&hspi1);
}
这里配置为SPI Mode 0(CPOL=0, CPHA=0),波特率预分频64,对应APB2总线72MHz下的SCLK约为1.125MHz,完全满足ADS1220的通信要求。NSS采用软件控制,便于精确管理片选时序,避免误触发。
接下来是对ADS1220寄存器的配置函数。关键在于理解每个bit的功能分布。例如,寄存器0(REG0)决定了输入通道和PGA状态:
void ADS1220_WriteRegister(uint8_t reg, uint8_t value)
{
uint8_t tx_data[2];
tx_data[0] = (reg << 2) | 0x02; // 写操作命令:[RegAddr<<2 | 0x02]
tx_data[1] = value;
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, tx_data, 2, 100);
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);
}
void ADS1220_Config(void)
{
ADS1220_WriteRegister(0, 0x20); // AIN0-AIN1差分输入,PGA=128,缓冲关闭
ADS1220_WriteRegister(1, 0x43); // 100SPS,单周期稳定,禁用斩波
ADS1220_WriteRegister(2, 0x14); // 启用50+60Hz滤波
ADS1220_WriteRegister(3, 0x00); // 默认设置
}
上述配置实现了最基本的高增益采集模式:选择AIN0与AIN1之间的差分电压作为输入,启用128倍放大,设定输出速率为100SPS,并开启工频抑制滤波。这种设置下,RMS噪声可低至700nV左右,信噪比显著优于大多数集成ADC。
读取转换结果的过程也需注意时序规范。ADS1220在每次转换完成后会拉低 DRDY 引脚,通知主控可以读数。虽然可以通过轮询方式处理,但更高效的做法是将其连接至STM32的外部中断引脚,实现事件驱动式采集。
以下是读取原始码值的实现:
int32_t ADS1220_ReadValue(void)
{
uint8_t tx_data[4] = {0x10, 0x00, 0x00, 0x00}; // 读数据命令
uint8_t rx_data[4] = {0};
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, tx_data, rx_data, 4, 100);
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);
int32_t result = ((int32_t)rx_data[1] << 16) |
((int32_t)rx_data[2] << 8) | rx_data[3];
if (result & 0x800000) {
result |= 0xFF000000; // 符号扩展
}
return result;
}
返回的是24位补码格式的有符号整数,正值表示AINP > AINN,负值则相反。要将其转换为实际电压,还需结合参考电压和增益系数:
float ADS1220_GetVoltage(float vref, uint8_t gain)
{
int32_t raw = ADS1220_ReadValue();
float voltage = (raw * vref) / (gain * 8388608.0f); // 2^23
return voltage;
}
假设使用REF3012提供的2.5V基准电压,增益为128,则每个LSB对应约0.298μV。也就是说,理论上系统可以检测到小于1μV的电压变化——这已经接近许多商用万用表的极限精度。
当然,理论分辨率并不等于实际可用精度。系统的稳定性受到多个因素影响,其中最关键是 参考电压的质量 。虽然ADS1220内置1.2V基准,但其负载能力和温漂表现不如专用外部基准源。因此在高精度场合,推荐使用REF3012、LM4040这类低温漂(<20ppm/℃)、低噪声的基准芯片,并通过独立LDO为其供电,避免受数字电源波动影响。
另一个常被忽视的问题是 PCB布局 。尽管原理图设计正确,但如果模拟走线靠近高频数字信号线(如SPI时钟、MCU晶振),很容易引入耦合噪声。建议采取以下措施:
- 模拟地与数字地分离,采用单点接地;
- 在AVDD引脚附近放置0.1μF陶瓷去耦电容,必要时再并联一个10μF钽电容;
- 输入端增加RC低通滤波(如10kΩ + 100nF),防止射频干扰进入前端;
- 使用磁珠隔离DVDD与AVDD电源路径。
软件层面也有优化空间。原始读数往往伴随随机跳动,尤其是当增益较高时。简单的滑动平均滤波就能大幅改善显示稳定性。例如,维护一个长度为16的环形缓冲区,每次更新后计算均值:
#define FILTER_SIZE 16
static float buffer[FILTER_SIZE];
static uint8_t index = 0;
float apply_moving_average(float new_value)
{
buffer[index] = new_value;
index = (index + 1) % FILTER_SIZE;
float sum = 0;
for (int i = 0; i < FILTER_SIZE; i++) {
sum += buffer[i];
}
return sum / FILTER_SIZE;
}
对于突发性尖峰干扰(如静电放电引起的毛刺),中值滤波更为有效。两者结合使用效果更佳。
此外,零点漂移是长期运行中的常见问题。解决方法是在系统启动时执行一次“空载校准”:短接输入端,读取当前偏移量并保存为offset,在后续测量中予以扣除。类似地,也可以施加已知标准电压进行增益校准,修正比例因子误差。
从整体架构来看,这个系统呈现出典型的“感知—处理—输出”链条:
+------------------+
| Sensor |
| (e.g., Load Cell)|
+--------+---------+
|
+-------v--------+ +------------------+
| ADS1220 |<--->| REF3012 |
| 24-bit ADC | | 1.2V Precision Ref|
+-------+----------+ +------------------+
| DRDY (INT)
| SCLK, DIN, DOUT, CS
v
+--------+----------+
| STM32F103 |
| ARM Cortex-M3 |
+--------+----------+
|
+--------v---------+
| UART / LCD / SD |
| 或无线模块(WiFi) |
+------------------+
STM32在这里扮演中枢角色:负责初始化外设、配置ADC、读取数据、执行滤波算法,并最终将结果可视化或上传云端。得益于Cortex-M3内核的硬件乘除单元和高效的中断响应机制,即便在72MHz主频下运行轻量RTOS(如FreeRTOS),也能轻松应对周期性采集任务。
值得一提的是,该系统的低功耗潜力尚未被充分挖掘。如果目标设备是野外部署的无线传感器节点,完全可以利用ADS1220的单次转换模式配合STM32的Stop模式来大幅延长续航。具体策略如下:
- 配置定时器或RTC周期唤醒MCU;
- 唤醒后使能ADS1220,启动一次转换;
- 等待DRDY中断到来,读取数据;
- 处理完毕后再次进入深度睡眠。
在此模式下,整个系统的平均电流可降至几十微安级别。
回顾整个方案的设计逻辑,它并非追求极致性能的技术堆砌,而是围绕“实用、可靠、易实现”展开的工程权衡。没有选用更高分辨率的32位ADC(如ADS1256),是因为24位已足够覆盖绝大多数应用场景;没有采用更高端的MCU,是因为STM32F103的成本和生态优势无可替代;甚至连SPI通信都没有启用DMA,因为数据量小,直接CPU搬运反而更简洁可控。
正是这种务实的态度,让“STM32 + ADS1220”组合在电子秤、温度巡检仪、pH计、生物电信号采集器等领域获得了广泛应用。它既避免了FPGA+高速ADC的复杂性,又突破了传统单片机ADC的精度瓶颈,为开发者提供了一条通往高精度测量的平滑路径。
未来,随着更多国产高精度ADC的崛起(如芯海科技CS1258),这一架构有望进一步降低成本门槛。但从系统设计的角度看,无论换用何种芯片,其背后的核心思想不会改变: 精准源于细节,稳定来自综合考量 。无论是电源完整性、参考电压选择,还是滤波算法与校准机制,每一个环节都值得深思熟虑。而这,也正是嵌入式工程师真正的价值所在。
————————————————
版权声明:本文为CSDN博主「vim8coder」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/vim8coder/article/details/154453210
|
|