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的串口:

配置串口:

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

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

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

七、回调函数的原理

相关推荐
崇山峻岭之间28 分钟前
单片机步进电机实验
单片机·嵌入式硬件
xiangw@GZ2 小时前
802.11全系列标准调制编码与速率档对应关系
网络·单片机·嵌入式硬件·架构
希希之光2 小时前
Aurix Tc3xx Port&Dio模块总结
单片机·嵌入式硬件
日拱一卒的小田3 小时前
ZYNQ学习笔记2-ZYNQ的UART控制器1
单片机·嵌入式硬件
我想走路带风3 小时前
OPENWRT-Day01
stm32·单片机·嵌入式硬件
ACP广源盛139246256733 小时前
GSV2221@ACP#DP 1.4 MST 多屏转换芯片,物理 AI 多模态交互的视觉中枢
大数据·人工智能·嵌入式硬件·gpt·spark
云栖梦泽4 小时前
Linux内核与驱动:pinctl子系统和GPIO子系统
linux·单片机·嵌入式硬件
电气_空空5 小时前
基于 LabVIEW 的单片机串口通信设计
单片机·嵌入式硬件·毕业设计·labview
caimouse6 小时前
Reactos 第 9 章 设备驱动 — 9.10 磁盘的Miniport驱动模块
windows·嵌入式硬件
xiangw@GZ7 小时前
WiFi系统BCC与LDPC纠错编码技术性能对比
单片机·嵌入式硬件