在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的中断功能。

相关推荐
易水寒陈2 小时前
MultiTimer源码分析
stm32·单片机
凯_kyle2 小时前
Python 算法竞赛 —— 基础篇(更新ing)
笔记·python·算法
零一科技2 小时前
然然管理系统-学习搭环境-本地先跑起来
学习
白羽陌2 小时前
STM32入门教程
stm32·单片机·嵌入式硬件
走在路上的菜鸟2 小时前
Android学Dart学习笔记第二十三节 类-扩展类型
android·笔记·学习·flutter
愤怒学习的白菜2 小时前
0 trivial:UVM的空壳平台
学习·uvm·ic验证
快乐非自愿2 小时前
Java函数式接口——渐进式学习
java·开发语言·学习
心动啊1213 小时前
负载均衡 + Nginx的基本使用
学习·nginx·负载均衡
菜鸟‍3 小时前
【课程学习】
学习·信息与通信