ADC(Analog-to-Digital Converter)是嵌入式系统中连接模拟世界与数字世界的桥梁。在STM32微控制器中,ADC模块的性能直接影响着各类传感器数据采集、电源监测等关键应用的精度。以STM32F4系列为例,其内置的12位逐次逼近型(SAR)ADC最高采样率可达2.4MSPS,并支持多通道扫描模式。
实际工程中,ADC的配置误区常导致以下问题:
STM32的ADC输入引脚内部结构如图1所示。关键参数包括:
重要提示:当输入信号源阻抗超过10kΩ时,必须增加外部缓冲器或延长采样时间。我曾在一个光照传感器项目中,因忽略此问题导致采样值波动达5%。
ADC时钟由APB2分频得到,需满足:
code复制Tconv = (采样周期 + 12.5) / fADC
其中采样周期可通过SMPx[2:0]位配置(3-480个ADC周期)实测案例:测量50Hz交流电时,设置采样周期为84周期(对应3μs@28MHz),配合定时器触发可实现每周波采样128点。
| 寄存器 | 地址偏移 | 核心位域 | 配置要点 |
|---|---|---|---|
| CR1 | 0x00 | SCAN, JEOCIE | 扫描模式使能 |
| CR2 | 0x08 | ADON, CONT | 启动转换控制 |
| SQR1 | 0x2C | L[3:0] | 规则通道数设置 |
| SMPR2 | 0x10 | SMPx[2:0] | 通道采样时间 |
c复制// 初始化ADC1通道0/1/2,使用DMA传输
void ADC1_Init(void) {
// 1. 使能时钟
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
// 2. 配置CR1
ADC1->CR1 = ADC_CR1_SCAN; // 扫描模式
// 3. 配置CR2
ADC1->CR2 = ADC_CR2_CONT // 连续转换
| ADC_CR2_DMA // DMA使能
| ADC_CR2_ADON; // ADC上电
// 4. 设置采样时间(通道0/1/2设为56周期)
ADC1->SMPR2 = ADC_SMPR2_SMP0_0 | ADC_SMPR2_SMP0_1
| ADC_SMPR2_SMP1_0 | ADC_SMPR2_SMP1_1
| ADC_SMPR2_SMP2_0 | ADC_SMPR2_SMP2_1;
// 5. 配置规则序列(3个通道)
ADC1->SQR1 = (2 << 20); // L[3:0]=2表示3个转换
ADC1->SQR3 = (0 << 0) | (1 << 5) | (2 << 10);
}
实测数据表明,VDDA波动1%会导致ADC误差达8LSB。推荐方案:
校准代码示例:
c复制uint16_t Get_VREFINT_CAL(void) {
ADC1->CR2 &= ~ADC_CR2_ADON;
ADC1->SQR3 = 17 << 0; // VREFINT通道
ADC1->CR2 |= ADC_CR2_ADON;
while(!(ADC1->SR & ADC_SR_EOC));
return ADC1->DR;
}
| 算法类型 | 适用场景 | RAM占用 | 效果 |
|---|---|---|---|
| 滑动平均 | 平稳信号 | 低 | 抑制随机噪声 |
| 中值滤波 | 脉冲干扰 | 中 | 消除野值 |
| 卡尔曼 | 动态系统 | 高 | 最优估计 |
在电机电流采样中,我采用滑动平均+IIR的组合滤波:
c复制#define FILTER_DEPTH 8
uint16_t ADC_Filter(uint16_t new_val) {
static uint16_t buf[FILTER_DEPTH];
static uint8_t idx = 0;
uint32_t sum = 0;
buf[idx++] = new_val;
if(idx >= FILTER_DEPTH) idx = 0;
for(int i=0; i<FILTER_DEPTH; i++) {
sum += buf[i];
}
return (sum >> 3); // 除以8
}
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 采样值全0 | ADC未启动 | 检查CR2.ADON位 |
| 数据跳变 | 采样时间不足 | 增大SMPx值 |
| DMA传输中断 | 内存对齐错误 | 确保buf地址4字节对齐 |
| 值固定4095 | 输入超过VDDA | 检查前端分压电路 |
调试案例:在工业温度变送器项目中,发现ADC值周期性波动。通过频谱分析发现是24MHz晶体谐波干扰,最终在ADC输入端增加RC滤波器(R=100Ω, C=1nF)解决问题。
对于需要更高有效采样率的场景,STM32的双ADC模式可大幅提升性能:
c复制// ADC1+ADC2交替采样配置
void DualADC_Init(void) {
// 主机ADC1配置
ADC1->CR1 = ADC_CR1_SCAN;
ADC1->CR2 = ADC_CR2_CONT | ADC_CR2_ADON;
// 从机ADC2配置
ADC2->CR1 = ADC_CR1_SCAN;
ADC2->CR2 = ADC_CR2_CONT | ADC_CR2_ADON
| ADC_CR2_SWSTART;
// 设置交替触发
ADC1->CR2 |= ADC_CR2_DUAL_1; // 交替触发模式
ADC->CCR |= ADC_CCR_MULTI_2 | ADC_CCR_MULTI_0; // 双ADC模式
}
实测在72MHz系统时钟下,双ADC交替模式可实现5.33MSPS等效采样率(单ADC最高2.4MSPS)。但需注意: