这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » TM32微控制器的ADC中断配置与结果处理的典型例程

共1条 1/1 1 跳转至

TM32微控制器的ADC中断配置与结果处理的典型例程

工程师
2025-10-14 04:29:55     打赏

以下是一个基于 STM32 微控制器的 ADC 中断配置与结果处理的典型例程示例。

该示例展示了如何通过中断方式触发 ADC 转换,并在中断服务函数(ISR)中获取并处理转换结果。

适用于大多数 STM32 系列芯片(如 STM32F1/F4)。


 核心步骤概览

1. 初始化 ADC 外设

2. 配置 ADC 中断

3. 编写中断服务函数 (IRQ Handler)

4. 启动首次转换

5. 在 ISR 中处理转换结果


所需头文件依赖

```c

#include "stm32f1xx.h"   // 根据实际使用的 MCU 系列替换

#include "stm32f1xx_hal.h" // HAL 库

```


1. ADC 初始化函数

```c

void ADC_Init(void) {

    __HAL_RCC_ADC1_CLK_ENABLE();       // 使能 ADC1 时钟

    

    // 初始化 ADC 句柄结构体

    ADC_HandleTypeDef hadc;

    hadc.Instance = ADC1;             // 使用 ADC1

    

    hadc.Init.ContinuousConvMode = DISABLE;      // 单次转换模式

    hadc.Init.DiscontinuousConvMode = DISABLE;   // 禁用非连续模式

    hadc.Init.ExternalTrigConvEdge = EXTI_RISING; // 外部触发边沿(可选)

    hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件启动转换

    hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;     // 右对齐

    hadc.Init.ScanConvMode = DISABLE;              // 单通道扫描

    hadc.Init.NbrOfConversion = 1;                 // 仅一个通道

    

    HAL_ADC_Init(&hadc);                          // 初始化 ADC

    

    // 配置通道映射到 PA0 (Channel 0)

    ADC_ChannelConfTypeDef sConfig = {0};

    sConfig.Channel = ADC_CHANNEL_0;               // PA0 -> ADC Channel 0

    sConfig.Rank = 1;                             // 排名靠前

    sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5; // 采样时间

    HAL_ADC_ConfigChannel(&hadc, &sConfig);        // 配置通道

    

    // 使能 ADC 中断

    HAL_ADC_StartIT(&hadc);                       // 启动中断模式

}

```


 2. ADC 中断服务函数 (IRQ Handler)

此函数会在每次 ADC 转换完成后自动调用。


```c

volatile uint32_t adcValue = 0; // 用于存储最新的 ADC 值


void ADC1_IRQHandler(void) {

    // 检查是否是 EOC(End Of Conversion)中断

    if (__HAL_ADC_GET_FLAG(&hadc, ADC_FLAG_EOC) != RESET) {

        adcValue = HAL_ADC_GetValue(&hadc);         // 获取当前 ADC 值

        __HAL_ADC_CLEAR_FLAG(&hadc, ADC_FLAG_EOC);  // 清除中断标志

        

        // TODO: 在这里添加你的数据处理逻辑

        // 例如:显示数值、控制 PWM 占空比、发送 UART 数据等

    }

}

```


注意:`hadc` 是在 `ADC_Init()` 中定义的局部变量,若要在 ISR 中使用,需将其声明为全局变量或将指针传入。


3. 主函数 main()

```c

int main(void) {

    HAL_Init();                                   // 初始化 HAL 库

    SystemClock_Config();                        // 系统时钟配置(可选)

    

    ADC_Init();                                  // 初始化 ADC

    

    while (1) {

        // 主循环可以做其他事情,ADC 会自动通过中断更新 adcValue

        // 如需手动启动下一次转换,可调用:

        // HAL_ADC_Start(&hadc);                  // 如果设置为单次模式且未启用自动重启

    }

}

```


关键注意事项

| 要点 | 说明 |

|------|------|

| 中断优先级 | 确保 ADC 中断优先级足够高,避免被其他低优先级中断阻塞。可通过 `HAL_NVIC_SetPriority()` 设置。 |

| 去抖动处理 | 如果连接的是传感器(如电位器),建议加入滤波算法(均值滤波、中值滤波)。 |

| 多通道支持 | 若需多通道采样,可将 `ScanConvMode` 设为 `ENABLE`,并按顺序配置多个通道。 |

| DMA 替代方案 | 对于大数据量采集,推荐使用 DMA + 双缓冲区,减少 CPU 负载。 |

| 电压范围匹配 | 确保输入电压不超过 Vref+,否则会导致读数饱和。 |


扩展建议

校准功能:调用 `HAL_ADCEx_CalibrationStart()` 提高精度。

温度补偿:结合内部温度传感器实现动态校正。

低功耗模式:在空闲时关闭 ADC 电源以节能。


完整示例整合版(简化版)

```c

#include "stm32f1xx.h"

#include "stm32f1xx_hal.h"


ADC_HandleTypeDef hadc;

volatile uint32_t adcValue = 0;


void ADC_Init(void) {

    __HAL_RCC_ADC1_CLK_ENABLE();

    

    hadc.Instance = ADC1;

    hadc.Init.ContinuousConvMode = DISABLE;

    hadc.Init.DiscontinuousConvMode = DISABLE;

    hadc.Init.ExternalTrigConvEdge = EXTI_RISING;

    hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;

    hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;

    hadc.Init.ScanConvMode = DISABLE;

    hadc.Init.NbrOfConversion = 1;

    HAL_ADC_Init(&hadc);

    

    ADC_ChannelConfTypeDef sConfig = {0};

    sConfig.Channel = ADC_CHANNEL_0;

    sConfig.Rank = 1;

    sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;

    HAL_ADC_ConfigChannel(&hadc, &sConfig);

    

    HAL_ADC_StartIT(&hadc); // 启动中断模式

}


void ADC1_IRQHandler(void) {

    if (__HAL_ADC_GET_FLAG(&hadc, ADC_FLAG_EOC)) {

        adcValue = HAL_ADC_GetValue(&hadc);

        __HAL_ADC_CLEAR_FLAG(&hadc, ADC_FLAG_EOC);

        // 此处可添加自定义处理逻辑

    }

}


int main(void) {

    HAL_Init();

    ADC_Init();

    

    while (1) {

        // 主循环可访问 adcValue 进行进一步处理

    }

}

```


提示

 如果使用的是其他 MCU(如 AVR、ESP32),原理类似,但寄存器名和 API 会有所不同。

 建议查阅对应芯片的数据手册和参考手册,了解具体的 ADC 模块特性。

 实际开发中建议使用 CubeMX 图形化工具生成初始代码框架,再在此基础上修改。



共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]