在STM32中,中断服务函数的命名有什么要求?

在STM32中,中断服务函数(ISR)的命名和使用有特定的规则要求,下面详细说明:

一、中断服务函数命名要求

1. 官方命名规则(必须遵守)

中断服务函数的名字在启动文件(如startup_stm32fxxx.s)中已经预定义,必须使用完全相同的名字

常见命名格式:

cs 复制代码
// 外设中断
void USART1_IRQHandler(void)    // USART1中断
void TIM2_IRQHandler(void)      // TIM2中断
void EXTI0_IRQHandler(void)     // EXTI线0中断
void EXTI15_10_IRQHandler(void) // EXTI线10-15中断

// 系统中断
void SysTick_Handler(void)      // 系统滴答定时器中断
void PendSV_Handler(void)       // PendSV中断
void SVC_Handler(void)          // SVC调用中断

2. 命名查找方法

在启动文件中查找:

cs 复制代码
; startup_stm32f103xe.s 示例
g_pfnVectors:
  .word  _estack
  .word  Reset_Handler
  .word  NMI_Handler
  .word  HardFault_Handler
  .word  MemManage_Handler
  .word  BusFault_Handler
  .word  UsageFault_Handler
  .word  0
  .word  0
  .word  0
  .word  0
  .word  SVC_Handler
  .word  DebugMon_Handler
  .word  0
  .word  PendSV_Handler
  .word  SysTick_Handler
  .word  WWDG_IRQHandler        ; 窗口看门狗
  .word  PVD_IRQHandler         ; PVD通过EXTI检测
  .word  TAMPER_IRQHandler      ; 篡改中断
  ; ... 更多中断向量

二、中断服务函数的使用步骤

1. 步骤1:编写中断服务函数

cs 复制代码
// 在.c文件中定义中断服务函数
void TIM2_IRQHandler(void)
{
    // 1. 检查中断标志位
    if (TIM2->SR & TIM_SR_UIF)  // 更新中断标志
    {
        // 2. 清除中断标志(非常重要!)
        TIM2->SR &= ~TIM_SR_UIF;
        
        // 3. 执行中断处理逻辑
        GPIOA->ODR ^= GPIO_ODR_ODR5;  // 翻转LED
        
        // 4. 其他处理...
    }
}

2. 步骤2:配置NVIC(嵌套向量中断控制器)

cs 复制代码
// 配置TIM2中断优先级并使能
void TIM2_IRQ_Config(void)
{
    // 设置中断优先级分组
    NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
    
    // 配置TIM2中断优先级
    NVIC_SetPriority(TIM2_IRQn, 2);  // 抢占优先级2,子优先级0
    
    // 使能TIM2中断
    NVIC_EnableIRQ(TIM2_IRQn);
}

3. 步骤3:配置外设中断

cs 复制代码
void TIM2_Config(void)
{
    // 1. 使能TIM2时钟
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
    
    // 2. 配置TIM2
    TIM2->PSC = 7200 - 1;      // 预分频
    TIM2->ARR = 10000 - 1;     // 自动重载值
    TIM2->EGR |= TIM_EGR_UG;   // 生成更新事件
    
    // 3. 使能更新中断
    TIM2->DIER |= TIM_DIER_UIE;
    
    // 4. 启动定时器
    TIM2->CR1 |= TIM_CR1_CEN;
}

4. 步骤4:完整示例(以TIM2中断为例)

cs 复制代码
#include "stm32f1xx.h"

// 中断服务函数
void TIM2_IRQHandler(void)
{
    static uint32_t counter = 0;
    
    if (TIM2->SR & TIM_SR_UIF)
    {
        TIM2->SR &= ~TIM_SR_UIF;  // 清除标志
        
        counter++;
        if (counter >= 1000)
        {
            GPIOA->ODR ^= GPIO_ODR_ODR5;  // 每秒翻转LED
            counter = 0;
        }
    }
}

// 初始化函数
void TIM2_Init(void)
{
    // 启用GPIOA和TIM2时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
    
    // 配置PA5为推挽输出(LED)
    GPIOA->CRL &= ~GPIO_CRL_MODE5;
    GPIOA->CRL |= GPIO_CRL_MODE5_0;
    GPIOA->CRL &= ~GPIO_CRL_CNF5;
    
    // 配置TIM2
    TIM2->PSC = 7200 - 1;       // 72MHz/7200 = 10kHz
    TIM2->ARR = 10000 - 1;      // 10kHz/10000 = 1Hz中断
    
    // 使能更新中断
    TIM2->DIER |= TIM_DIER_UIE;
    
    // 生成更新事件
    TIM2->EGR |= TIM_EGR_UG;
    
    // 启动定时器
    TIM2->CR1 |= TIM_CR1_CEN;
    
    // 配置NVIC
    NVIC_SetPriority(TIM2_IRQn, 2);
    NVIC_EnableIRQ(TIM2_IRQn);
}

int main(void)
{
    TIM2_Init();
    
    while(1)
    {
        // 主循环
    }
}

三、使用HAL库的中断处理

1. HAL库中断服务函数

cs 复制代码
// 使用HAL库的回调机制
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM2)
    {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    }
}

// 仍然需要弱定义的中断服务函数
void TIM2_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&htim2);  // HAL库处理中断
}

2. HAL库中断配置

cs 复制代码
TIM_HandleTypeDef htim2;

void TIM2_Init(void)
{
    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 7200 - 1;
    htim2.Init.Period = 10000 - 1;
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    
    HAL_TIM_Base_Init(&htim2);
    HAL_TIM_Base_Start_IT(&htim2);  // 启动中断模式
}

四、重要注意事项

  1. 函数修饰符:通常不需要特殊修饰,但某些情况下可能需要:

    cs 复制代码
    __attribute__((interrupt))  // GCC编译器可选
    void TIM2_IRQHandler(void)  // Keil默认支持
  2. 必须清除中断标志:否则会不断触发中断

  3. 避免长时间操作:ISR应尽量简短,避免影响其他中断

  4. 中断优先级配置

    • 优先级数值越小,优先级越高

    • STM32支持中断嵌套

  5. 弱符号(Weak)定义:启动文件中的定义通常是弱符号,可以被用户定义覆盖

  6. 使用CubeMX生成代码时,会自动生成正确的中断服务函数框架

五、常见错误

  1. 命名错误TIM2_Handler ❌(正确:TIM2_IRQHandler ✅)

  2. 忘记清除标志位:导致无限中断

  3. 在ISR中调用阻塞函数 :如HAL_Delay()

  4. 未使能NVIC中断:只配置了外设,未使能NVIC

通过遵循这些规则和步骤,可以正确使用STM32的中断功能。

相关推荐
棒子陈6 小时前
使用cursor移植单片机的串口驱动(DMA+队列式串口驱动,APM32F103移植到PY32F071)
单片机·嵌入式硬件·cursor·py32f071
有来技术6 小时前
ASP.NET Core 权限管理系统(RBAC)设计与实现|vue3-element-admin .NET 后端
vue.js·后端·c#·asp.net·.net
大雷神6 小时前
HarmonyOS智慧农业管理应用开发教程--高高种地--第25篇:学习中心 - 课程详情与学习
学习·华为·harmonyos
好奇龙猫6 小时前
【大学院-筆記試験練習:线性代数和数据结构(21)】
学习
VALENIAN瓦伦尼安教学设备6 小时前
镭射对心仪在联轴器找正作用
大数据·数据库·人工智能·嵌入式硬件
dulu~dulu6 小时前
大英赛改错真题记录
笔记·英语·自用·英语改错
蓬荜生灰7 小时前
STM32(11)-- GPIO输出,库函数点灯
stm32·单片机·嵌入式硬件
许泽宇的技术分享7 小时前
Claude Code 完整学习计划
学习
香芋Yu7 小时前
【机器学习教程】第03章:SVD与矩阵分解
笔记·机器学习·矩阵
EmbedLinX7 小时前
FreeRTOS 学习笔记
c语言·笔记·学习