什么是ADC
本文是关于ADC(模数转换器)的基本概念、工作原理及基于STM32的驱动实现的详细讲解:
一、ADC核心原理与关键参数
1. ADC基本概念
ADC(Analog-to-Digital Converter)将连续的模拟信号(如电压、温度、声音)转换为离散的数字信号(二进制数值)。其核心步骤包括:
- 采样:在固定时间间隔内获取模拟信号的瞬时值(时间离散化)。
- 保持:在采样期间保持信号值不变,避免转换过程中信号变化。
- 量化:将采样值映射到有限的离散电平(幅值离散化)。
- 编码:将量化后的值转换为二进制数字(如二进制、格雷码)。
2. 关键参数
-
分辨率(Resolution)
ADC输出的二进制位数(如12位、16位),决定最小可分辨的电压变化(LSB,最低有效位)。
公式:分辨率 = 满量程电压 / (2^N),其中N为位数。
例如:12位ADC,Vref=3.3V时,LSB = 3.3V / 4096 ≈ 0.8mV。 -
采样率(Sampling Rate)
单位时间内完成的采样次数(SPS)。
关键公式:奈奎斯特定理要求采样率 ≥ 2×信号最高频率,否则会产生混叠(Aliasing)。 -
参考电压(Vref)
ADC的基准电压,决定转换范围。例如,若Vref=3.3V,则输入信号范围为0~3.3V。 -
输入通道(Channel)
ADC可连接的模拟信号输入引脚。STM32的ADC支持多通道切换,需配置通道映射。 -
采样时间(Sample Time)
每次采样过程中,ADC对输入信号稳定时间的设置。需根据信号频率和通道特性调整。
二、ADC驱动实现(以STM32为例)
1. ADC外设初始化流程
步骤:
-
时钟配置
- 使能ADC和GPIO时钟(如
RCC_APB2PeriphClockCmd)。 - 设置ADC时钟分频(如
ADC_ClockMode)。
- 使能ADC和GPIO时钟(如
-
分辨率与参考电压配置
- 设置分辨率(如12位):
ADC_Resolution_12b。 - 选择参考电压(内部或外部):
ADC_VoltageRegulat or_Enable启用内部Vref+。
- 设置分辨率(如12位):
-
通道配置
- 配置模拟输入引脚(如PA0)为模拟模式:
GPIO_Init。 - 设置通道参数(如通道号、采样时间):
ADC_RegularChannelConfig。
- 配置模拟输入引脚(如PA0)为模拟模式:
-
触发源配置
- 软件触发:
ADC_ExternalTrigConvEdge_None。 - 硬件触发(如定时器):
ADC_ExternalTrigConv_Tx_TRGO。
- 软件触发:
-
使能ADC
- 初始化ADC:
ADC_Init。 - 使能ADC:
ADC_Cmd(ADC1, ENABLE)。 - 校准ADC:
ADC_ResetCalibration→ADC_StartCalibration。
- 初始化ADC:
2. 启动转换与数据读取
三种方式对比:
| 方式 | 特点 | 适用场景 |
|---|---|---|
| 轮询(Polling) | 持续查询转换完成标志,简单直接。 | 低速、单通道采集。 |
| 中断(Interrupt) | 转换完成触发中断,降低CPU负载。 | 需实时响应的场景。 |
| DMA(Direct Memory Access) | 使用DMA自动传输数据到内存,高效。 | 高速、多通道或连续采集。 |
代码示例(轮询模式):
// 启动转换
ADC_StartConversion(ADC1);
// 轮询等待完成
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
// 读取结果
uint16_t adc_value = ADC_GetConversionValue(ADC1);
3. 多通道采样设计
- 配置通道序列:通过
ADC_RegularChannelConfig设置多个通道,形成转换序列。 - 数据管理:使用数组存储多通道数据,或通过DMA直接写入缓冲区。
// 配置通道1(PA0)和通道2(PA1)
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5);
// 启动连续转换
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 连续模式
ADC_Init(ADC1, &ADC_InitStructure);
4. 精度优化手段
-
硬件滤波:通过ADC的硬件去抖(如
ADC_OverrunMode)。 -
软件滤波:
- 滑动平均:对连续N次采样值求平均。
uint16_t sum = 0; for(int i=0; i<10; i++) { sum += ADC_GetConversionValue(ADC1); Delay_us(10); // 防止重复读取相同值 } uint16_t avg = sum / 10; - 中值滤波:取中间值抑制突变噪声。
- 滑动平均:对连续N次采样值求平均。
-
参考电压稳定性:使用低噪声LDO(如STM32的Vref+需外部去耦电容)。
5. HAL库与寄存器操作差异
| 方式 | 特点 | 适用场景 |
|---|---|---|
| HAL库 | 封装了底层寄存器操作,代码简洁。 | 快速开发,无需深入硬件细节。 |
| 寄存器操作 | 直接配置寄存器,灵活高效。 | 需自定义时序或优化性能时。 |
示例:寄存器配置ADC分辨率
// 使用寄存器设置12位分辨率
ADC1->CR1 &= ~ADC_CR1_RES; // 清除分辨率位
ADC1->CR1 |= ADC_CR1_RES_0; // 12位模式
三、典型代码模板(STM32 HAL库)
#include "stm32f1xx_hal.h"
ADC_HandleTypeDef hadc1;
uint16_t adc_value;
void ADC_Init(void) {
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
hadc1.Instance = ADC1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
HAL_ADC_Init(&hadc1);
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}
void ADC_Start(void) {
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 10);
adc_value = HAL_ADC_GetValue(&hadc1);
}
四、注意事项与应用场景
-
供电精度
- 参考电压(Vref+)需稳定,建议使用低噪声LDO并加去耦电容(如10μF+0.1μF)。
- 多通道切换时,避免不同通道间的串扰(如使用隔离电容)。
-
采样时序
- 高频信号需足够采样时间(如快速变化信号需短采样时间)。
- 多通道连续转换需确保转换速率与DMA吞吐率匹配。
-
典型应用
- 工业控制:温度、压力传感器(需高分辨率和抗干扰)。
- 消费电子:电池电压监测(低功耗模式)。
- 汽车电子:发动机参数采集(需高可靠性与EMC设计)。
五、流程图与思维导图
ADC初始化流程图
graph TD
A[启动] --> B{时钟配置}
B --> C[使能ADC时钟]
C --> D[配置GPIO为模拟模式]
D --> E[设置ADC分辨率]
E --> F[选择参考电压]
F --> G[配置通道参数]
G --> H[选择触发源]
H --> I[使能ADC并校准]
I --> J[完成初始化]
转换流程思维导图
graph TD
A[启动转换] --> B[等待完成(轮询/中断/DMA)]
B -->|轮询| C[主循环中读取]
B -->|中断| D[中断回调函数处理]
B -->|DMA| E[DMA缓冲区传输]
C --> F[读取数据]
D --> F
E --> F
F --> G{需要滤波?}
G -->|是| H[滑动平均或中值滤波]
H -->|否| I[直接使用数据]
通过以上步骤,您可以实现一个基础ADC驱动,并根据具体需求优化性能与精度。

浙公网安备 33010602011771号