一、ADC 外设使用原理
1. ADC 基本特性
分辨率与数值范围:
STM32 的 ADC 为 12 位精度,满量程对应数值为 212=4096。输入电压与转换值的关系为:电压值=4096ADC 值×3.3V
例如,当 ADC 值为 4096 时,对应输入电压为 3.3V。
转换时间计算:
总转换时间 Tconv 由采样时间和固定周期组成:Tconv=采样时间+12.5个时钟周期
若 ADC 时钟频率为 14 MHz,采样时间设为 1.5 周期,则:Tconv=(1.5+12.5)×14MHz1=1μs采样时间与精度的权衡:采样时间越长,精度越高,但转换速率越低。
时钟配置:
ADC 时钟(ADCCLK)需通过 APB2 时钟分频得到,且最高不超过 14 MHz(否则精度下降)。例如,APB2 时钟为 72 MHz 时,可通过 6 分频(/6)得到 12 MHz 的 ADCCLK。
2. 数据存储与对齐方式
寄存器结构:ADC 转换结果存储在 16 位寄存器中,支持右对齐和左对齐:
右对齐:低 12 位为有效数据(D11~D0),高 4 位补 0,范围为 0~4095。左对齐:高 12 位为有效数据(D15~D4),低 4 位补 0,适用于需要移位运算的场景。
多通道采集:
规则组:常规转换通道,支持扫描模式(依次转换多个通道)。注入组:优先级高于规则组,用于紧急通道(如中断触发的转换)。
二、ADC 中断原理
1. 中断触发条件
转换完成事件(EOC):单个通道或规则组转换完成后触发中断。注入转换完成事件:注入组通道转换完成后触发。溢出事件:转换数据未及时读取导致溢出时触发。
2. 中断处理流程
使能中断功能:通过 HAL_ADC_Start_IT() 启动中断模式。注册回调函数:
HAL_ADC_ConvCpltCallback():转换完成时调用。HAL_ADC_ErrorCallback():错误发生时调用。
中断服务函数:STM32 自动调用 HAL_ADC_IRQHandler(),该函数会触发注册的回调函数。
3. 与 DMA 结合使用
DMA 中断:当 DMA 搬运完指定数量的数据时,触发 DMA 传输完成中断(如 DMA1_FLAG_TC1)。中断优化:在 DMA 中断中仅置位标志位(如 adc_complete_flag),主程序通过标志位处理数据,避免中断服务函数耗时过长。
三、ADC 使用方法总结
1. 初始化配置步骤
使能时钟:
使能 ADC 对应总线时钟(如 APB2 时钟)和 GPIO 时钟。示例:RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
GPIO 配置:
将输入引脚设为模拟输入模式(如 GPIO_Mode_AIN)。
ADC 基础配置:
设置分辨率(12 位)、数据对齐方式(右对齐为主)。配置转换模式:
单次转换:转换一次后停止,需软件重新触发。连续转换:持续循环转换,适用于实时采集。
启用扫描模式(多通道时),设置规则组通道数及采样时间。
时钟与预分频:
通过 ADC_Prescaler 配置分频系数,确保 ADCCLK ≤ 14 MHz。
中断 / DMA 配置(可选):
中断模式:启用 ADC 中断,注册回调函数。DMA 模式:配置 DMA 通道、传输方向(外设到内存)、数据长度等。
2. 数据采集方式
方式特点适用场景轮询(Polling)阻塞式等待转换完成,通过 HAL_ADC_PollForConversion() 查询状态。简单单通道采集,对实时性要求不高。中断(IT)非阻塞式,转换完成后触发中断,通过回调函数处理数据。多任务系统,需及时响应转换结果。DMA非阻塞式,自动搬运数据到内存,支持连续采集和环形缓冲区。高速多通道采集,大数据量场景。
3. 关键函数
启动转换:
轮询:HAL_ADC_Start(&hadc1);中断:HAL_ADC_Start_IT(&hadc1);DMA:HAL_ADC_Start_DMA(&hadc1, pData, Length);
读取数据:HAL_ADC_GetValue(&hadc1);(轮询 / 中断模式)。DMA 配置:设置外设地址(如 ADC1_DR_Address)和内存地址,启用连续传输模式。
四、应用示例
示例 1:单通道轮询采集(温度测量)
c
运行
// 声明变量
uint16_t AD_Value = 0;
float temperature = 0.0f;
// 主循环
while (1) {
HAL_ADC_Start(&hadc1); // 启动 ADC 转换
HAL_ADC_PollForConversion(&hadc1, 50); // 等待转换完成(超时 50ms)
if (HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC)) {
AD_Value = HAL_ADC_GetValue(&hadc1); // 读取转换值
// 温度计算(假设传感器公式:T = (1.43 - V)/0.0043 + 25)
temperature = (1.43f - (AD_Value * 3.3f / 4096)) / 0.0043f + 25.0f;
printf("Temperature: %.1f°C\r\n", temperature);
}
HAL_Delay(1000); // 延时 1s
}
示例 2:多通道 DMA 采集(规则组 2 通道,环形缓冲区)
初始化配置:
启用扫描模式,规则组通道数设为 2,DMA 配置为连续传输、环形模式。定义内存缓冲区:uint16_t ADC_Buffer[256][2] = {0};(256 组数据,每组 2 通道)。
DMA 启动代码:
c
运行
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC_Buffer, sizeof(ADC_Buffer)/sizeof(uint16_t));
DMA 中断处理:
c
运行
void DMA1_Channel1_IRQHandler(void) {
if (DMA_GetITStatus(DMA1_IT_TC1)) { // 传输完成中断
DMA_ClearITPendingBit(DMA1_IT_TC1);
adc_dma_complete = 1; // 置位标志位
}
}
主程序处理数据:
c
运行
while (1) {
if (adc_dma_complete) {
adc_dma_complete = 0;
// 处理 ADC_Buffer 中的数据(如滤波、计算平均值等)
}
}
五、注意事项
时钟频率限制:确保 ADCCLK ≤ 14 MHz,否则精度下降。采样时间设置:多通道采集时,每个通道需单独设置采样时间,长采样时间可提高精度。DMA 与中断协同:DMA 中断仅用于标志位通知,数据处理应在主循环中完成,避免中断阻塞。电源与滤波:模拟输入引脚需加滤波电容(如 0.1 μF),减少噪声干扰。
通过合理配置 ADC 时钟、采样时间及中断 / DMA 模式,可灵活适配不同采集需求,实现高精度、高效率的数据采集。
!