6.单片机回调函数

一、回调函数的本质

回调函数本质上是一个通过函数指针调用的函数

把一个函数的地址(指针)传递给另一个函数,当特定事件发生时,这个指针会被用来调用对应的函数。

这种机制允许底层驱动(如 HAL 库)在事件触发时,自动通知上层应用程序,而无需上层主动查询("轮询")。

二、回调函数的作用

在 STM32 开发中,回调函数主要用于处理异步事件(无法预测何时发生的事件),核心作用是:

解耦:底层驱动和上层应用分离,底层负责检测事件,上层负责处理事件。

高效:避免CPU持续轮询事件状态,提高资源利用率。

模块化:不同功能的处理逻辑可以独立封装在不同的回调函数中。

三、典型应用场景

1. GPIO 外部中断回调

场景:按键按下/松开、传感器电平变化等。

工作流程

    1. 配置 GPIO 为中断模式(上升沿/下降沿触发)。
    2. 当中断发生时,硬件自动跳转到中断服务程序(ISR)。
    3. HAL 库的 ISR 会调用回调函数 HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

示例

复制代码
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == KEY_PIN) // 判断是哪个引脚触发中断
    {
        LED_Toggle(); // 翻转 LED 状态
    }
}

2. 定时器中断回调

场景:定时执行任务(如每隔1秒采集一次数据)。

工作流程

    1. 配置定时器并使能更新中断。
    2. 当定时器计数达到设定值时,触发中断。
    3. HAL 库调用回调函数 HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

示例

复制代码
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM2) // 判断是哪个定时器触发
    {
        HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); // 翻转 LED
    }
}

3. UART 串口通信回调

场景:串口接收/发送数据完成后触发。

工作流程

    1. 配置 UART 并使能中断。
    2. 当串口接收/发送缓冲区满时,触发中断。
    3. HAL 库调用回调函数 HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
  • 示例

    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
    if (huart->Instance == USART1)
    {
    HAL_UART_Transmit(huart, &rx_data, 1, 1000); // 回显接收的数据
    HAL_UART_Receive_IT(huart, &rx_data, 1); // 重新开启接收中断
    }
    }


4. ADC 转换完成回调

场景:ADC 采集完成后处理数据。

工作流程

    1. 配置 ADC 并使能转换完成中断。
    2. 当 ADC 转换完成时,触发中断。
    3. HAL 库调用回调函数 HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

示例

复制代码
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    if (hadc->Instance == ADC1)
    {
        adc_value = HAL_ADC_GetValue(hadc); // 获取转换结果
    }
}

四、回调函数的执行时机

回调函数在中断上下文中执行,因此需要注意:

执行时间要短,避免阻塞其他中断。

不建议在回调函数中使用 printf 等耗时操作(可改用 DMA 或环形缓冲区)。

如果需要在回调函数中处理复杂逻辑,可通过信号量或消息队列通知任务处理。

五、回调函数的分类

函数调用分类:分为输出型和输入型两种类型(非标准分类)

输出型函数:

特点:调用者主导调用时机,明确知道何时需要调用

示例:C语言的sizeof()、memcpy()函数;单片机控制LED状态、继电器状态、LCD驱动等函数

输入型函数(响应式函数):

特点:响应外部事件,调用时机不可预知

示例:串口数据接收、按键检测、ADC采集等

实现方式:通过回调函数实现,在单片机领域应用广泛

六、回调函数的原理

实现机制:

函数指针:通过函数指针实现回调机制

固定名称:STM32库中预定义的中断回调函数名称(如外部中断0、定时器中断等)

执行流程:当特定事件发生时,程序自动跳转到对应的回调函数执行

实际应用:

数据传递:将硬件采集的数据传递给应用层

事件处理:处理异步事件,如中断服务

例如STM32的串口:

配置串口:

这里进行串口中断处理函数的指定:

也就是说,在串口发生中断时,会调用这个函数:

定义了虚函数,当用户没有编写回调函数时,编译工程也不会报错。

七、回调函数的原理

相关推荐
就是蠢啊2 小时前
单片机入门实验——点灯
单片机·嵌入式硬件
@曾记否2 小时前
瑞控FPVF405飞控开发板硬件功能整理
stm32·嵌入式硬件
oshan20123 小时前
小华HC32L136K8TA 单片机LED(三)
单片机·嵌入式硬件
小齐勇闯天涯3 小时前
STM32--PWM原理机制
stm32·单片机·嵌入式硬件
全球通史3 小时前
[特殊字符] RISC-V实战:从0到100+FPS!进迭时空(Spacemit)开发板YOLOv8部署终极指南
嵌入式硬件·yolo·risc-v
brave and determined7 小时前
可编程逻辑器件学习(day22):“让ARM穿上FPGA的马甲“:赛灵思Zynq的命名哲学与技术革命
arm开发·嵌入式硬件·fpga开发·zynq·fpga设计·嵌入式设计·fpga开发流程
余生皆假期-9 小时前
SPWM 与 SVPWM 电压利用率简谈
单片机·嵌入式
许商9 小时前
【stm32】【CDC】详解
stm32·单片机·嵌入式硬件
漂洋过海的鱼儿9 小时前
“中断方式”来读取串口
单片机·嵌入式硬件