0

0

0

修罗

站点介绍

只有了解事实才能获得真正的自由

STM32中断系统

修罗 2025-08-19 1303 6条评论 stm32

首页 / 正文

STM32中断系统

1.1 中断的概念

中断指在程序正常执行过程中,因某个特定事件发生,使CPU暂停当前任务,转去执行专门的服务程序,执行完毕恢复断点处的程序执行,有点像给程序打了一个断点调试。

中断源就是引发中断的“原因”或“事件”。

  • 可能来自 外部硬件(例如定时器溢出、串口接收到数据、按键触发、外部引脚电平变化等)。
  • 也可能来自 内部异常/软件请求(例如除零错误、软件触发的中断指令),内部的中断有时候也叫异常。

断点指当中断发生时,CPU会自动保存当前正在执行的指令地址(也就是下一条要执行的位置),这个保存下来的位置就是所谓的“断点”。这样,当中断处理完毕后,CPU才能“回到刚才被打断的地方继续执行”。

中断服务程序(ISR):执行一段专门的代码去处理事件,这段程序就叫中断服务程序

image-20250819090733204.png

​ 正在执行中断程序的时候,这个时候有可能被另外一个中断源给中断,CPU转而去执行另外一个中断源的中断处理程序,这叫中断嵌套。

​ 中断B能否打断中断A,要看他们的优先级,优先级高的可以打断优先级低的,优先级低的无法打断优先级高的。

image-20250819090806647.png

1.2 为什么需要中断

​ 比如我们要检测按键是否按下,如果没有中断,则需要循环的方式不断的去检测按键对应的IO口的电平,这是比较耗费CPU的时间的。如果要检测的更多的话,CPU有可能会导致阻塞。

  1. 节省cpu资源

​ 使用中断后,CPU只在事件发生时才被打断处理,平时不用关心。

  1. 避免阻塞

    如果系统要同时检测多个外设(按键、串口、定时器、传感器),用轮询会占满CPU时间,主程序可能没机会执行其它任务。中断方式下,主程序专心做自己的事,外设自己触发中断来通知CPU

  2. 提高实时性

    有些事件(比如串口接收数据、定时器溢出)需要及时处理,否则可能丢数据。中断保证CPU能快速响应这些关键事件,而不是“等轮询到的时候才处理”

没有中断,单片机像一个人“盯着手机等通知”;
有了中断,单片机就像“有人按门铃才去开门”,效率高很多。

1.3 STM32的中断

​ Cortex-M3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。一般情况下,芯片厂商会对Cortex-M3的中断进行裁剪。

​ STM32有84个中断,包括16个内核中断和68个可屏蔽中断,具有16级可编程的中断优先级。

STM32F103系列70个中断有10个内核中断和60个可编程的外部中断

​ 下面的列表中,灰色背景的是内部中断(或者异常),其他的为外部中断。

image-20250819091653486.png

image-20250819091706785.png

image-20250819091722359.png

1.4 STM32的中断体系架构

1.4.1 NVIC

NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)是 ARM Cortex-M 内核里一个非常核心的模块。它的主要作用就是——帮CPU管理所有中断

作用:

  1. 统一管理中断源
  • Cortex-M 系列单片机里,中断源很多(外设中断、系统异常、硬Fault等)。
  • NVIC 就像“中断的大管家”,负责接收这些中断请求,决定哪个能打断CPU。
  1. 中断优先级管理
  • 每个中断都可以分配一个优先级。
  • NVIC根据优先级决定:

    • 谁可以先执行(高优先级先执行)。
    • 是否允许“嵌套”(在执行某个中断时,能否被更高优先级的中断再次打断)。
  1. 向量表管理
  • 每个中断有一个“入口地址”,即 ISR 的起始位置。
  • NVIC 根据中断号自动找到向量表里的入口地址,跳转到对应中断服务程序。
  1. 屏蔽/使能中断
  • 通过 NVIC 的寄存器,软件可以随时开启或关闭某个中断。
  • 比如临时不想处理某个外设的中断,可以直接在 NVIC 里屏蔽。

Cortex-M 系列内核里,NVIC 统一管理三类“中断/异常”来源:

image-20250819092642671.png

1.4.2 AFIO

​ GPIOA-G分别有16个引脚,16条线,AFIO将GPIOA-G端口的相同编号引脚组合成一根线接到EXTI,比如A0/B0/C0...接到EXTI0。

一条 EXTI 线一次只能选择一个端口,不能同时由 PA0 和 PB0 触发。写程序时,需要在程序里通过 AFIO 寄存器配置,告诉 EXTI 哪个 GPIO 引脚来触发中断,否则 EXTI 不知道要监听哪一条线。例如:EXTI0 默认接 PA0,如果写入 AFIO_EXTICR1 指定 PB0,就改为由 PB0 触发。

AFIO 模块主要干三件事:

  • GPIO 引脚接到 EXTI 线(外部中断配置)。
  • 外设功能映射到不同引脚(重映射)。
  • 调试端口的管脚释放出来(JTAG/SWD 配置)。

image-20250819093617782.png

  1. 外部中断 (EXTI) 配置
  • 作用:决定某个 EXTI 线由哪个 GPIO 引脚来触发。
  • 实现:通过 AFIO_EXTICR[1..4] 寄存器配置。
  • 特点

    • 每条 EXTI 线(EXTI0~EXTI15)只能对应到某个端口的相同编号引脚。
    • 比如:EXTI0 可以选择 PA0 / PB0 / PC0 / …,但一次只能选一个。

  1. 复用功能重映射 (Peripheral Remap)
  • 作用:允许改变某些外设的管脚分布,避免引脚冲突或优化 PCB 布局。
  • 实现:通过 AFIO_MAPRAFIO_MAPR2 寄存器配置。
  • 例子

    • USART1 默认 TX/RX = PA9 / PA10
    • 重映射后 TX/RX = PB6 / PB7
    • TIM2 通道可以映射到不同的 IO。

  1. 调试端口配置 (JTAG/SWD Remap)
  • 作用:释放调试接口占用的引脚,让它们当普通 GPIO 使用。
  • 实现:在 AFIO_MAPR 中配置 SWJ_CFG 位。
  • 选项

    • 全功能 JTAG-DP + SW-DP(默认,占用 5 根管脚)。
    • 仅 SW-DP(占用 2 根管脚,释放 PB3、PB4、PA15)。
    • 完全关闭 JTAG/SWD(释放所有调试引脚,但调试功能不可用)。

1.4.3 EXTI

AFIO = 信号路由器:负责把 GPIO 引脚“接”到某条 EXTI 线。

EXTI = 中断检测器:负责检测这条 EXTI 线上有没有触发条件,并产生中断请求。它只知道有中断线 EXTI0 ~ EXTI15,但是不知道这些线接在哪个 GPIO 引脚上。

EXTI根据配置的触发方式(上升沿/下降沿/双沿),判断是否触发中断/事件;

AFIO:决定“谁来汇报”

EXTI:决定“什么时候汇报”

NVIC:决定“怎么打断皇帝(CPU)去处理”

image-20250819095515973.png

1.4.4 NVIC中断优先级

​ NVIC为了方便管理中断,可以通过软件给每个中断设置优先级。NVIC用4个位来控制优先级,值小的优先级高。把优先级分为两种:抢占优先级和响应优先级

规则:

  1. 优先级值越小,优先级越高。
  2. 如果不设置优先级,则默认优先级为0。
  3. 先比较抢占优先级。抢占优先级高的可以打断抢占优先级低的。
  4. 若抢占优先级一样,再比较响应优先级。但是响应优先级不会导致中断嵌套。
  5. 若抢占优先级一样的同时挂起,则优先处理响应抢占优先级高的。
  6. 若挂起的优先级(抢占和响应)都一样,则查找中断向量表,值小的先响应。

​ NVIC对优先级分了5组,在程序中先对中断进行分组,而且分组只能分一次,若多次分,只有最后一次生效。下图[7:4]意思是7-4位:

image-20250819103558768.png

NVIC_SetPriorityGrouping(n)PRIGROUP抢占优先级bits响应优先级bits抢占优先级数(Group)响应优先级数(Sub)解释
40b011[7:4]None16None4 位全部作为抢占优先级,没有子优先级。中断可以被 16 级抢占。
30b100[7:5][4]823 位抢占优先级 + 1 位子优先级。可以有 8 级抢占优先级,每级有 2 级响应顺序。
20b101[7:6][5:4]442 位抢占优先级 + 2 位子优先级。
10b110[7][6:4]281 位抢占优先级 + 3 位子优先级。
00b111None[7:4]None16全部 4 位作为子优先级,没有抢占能力。中断之间不会互相打断。

NVIC 中通过 SCB->AIRCR 寄存器 的 PRIGROUP 位来配置中断优先级的划分方式。

PRIGROUP 决定 抢占优先级(Group Priority)响应优先级(Subpriority) 的位数分配。

中断 A 抢占优先级比 B 高时,A 可以打断 B。

1.4.5 外部中断控制器EXTI

image-20250819104956094.png

如下图,注意请求挂起寄存器被自动置1后,中断执行完手动置0

image-20250819105711648.png

整体流程

image-20250819105835765.png

1.5 配置片外中断步骤

1.5.1 使能 GPIO 时钟

首先需要使能对应 GPIO 端口的时钟:

// 例如使能 GPIOA 时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;

1.5.2 配置 GPIO 为输入模式

// 以 PA0 为例,配置为上拉输入
GPIOA->CRL &= ~(0xF << (0*4));  // 清除 PA0 的配置
GPIOA->CRL |= (0x8 << (0*4));   // 配置为上拉/下拉输入模式
GPIOA->ODR |= (1 << 0);         // 上拉

1.5.3. 配置 AFIO 时钟和 EXTI 线路

// 使能 AFIO 时钟
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

// 将 GPIO 引脚连接到 EXTI 线
// 例如 PA0 连接到 EXTI0
AFIO->EXTICR[0] &= ~AFIO_EXTICR1_EXTI0;  // 清除原有设置
AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI0_PA; // PA0 连接到 EXTI0

1.5.4. 配置 EXTI 触发方式

// 配置触发方式(上升沿、下降沿或双边沿)
EXTI->RTSR |= EXTI_RTSR_TR0;   // 使能 EXTI0 上升沿触发
EXTI->FTSR |= EXTI_FTSR_TR0;   // 使能 EXTI0 下降沿触发
// 如果只需要一种触发方式,只需设置其中一个

1.5.5. 使能 EXTI 中断

EXTI->IMR |= EXTI_IMR_MR0;     // 不屏蔽 EXTI0 中断

1.5.6. 配置 NVIC

// 设置优先级
NVIC_SetPriority(EXTI0_IRQn, 0);  // 设置优先级为0(最高)

// 使能中断
NVIC_EnableIRQ(EXTI0_IRQn);       // 使能 EXTI0 中断

1.5.7. 编写中断服务函数

void EXTI0_IRQHandler(void)
{
    if (EXTI->PR & EXTI_PR_PR0)  // 检查是否是 EXTI0 中断
    {
        // 处理中断
        
        EXTI->PR = EXTI_PR_PR0;  // 清除中断标志
    }
}

评论(6)

  1. 1 游客 2025-09-01 11:26 回复

    1

  2. 1 游客 2025-09-01 12:01 回复

    1

  3. @@NHZu2 游客 2025-09-01 12:02 回复

    1

  4. 1 游客 2025-09-01 12:03 回复

    1

  5. 1 游客 2025-09-01 12:05 回复

    1

  6. 1 游客 2025-09-01 12:06 回复

    1


最新评论

  • https://www.studyglobus.com/author/carroll34a5552/

    Ценники на вывоз мусора сейчас космос, любые лайфхаки по экономии в тему.

  • Richardgrold

    1xbet onlayn kazino platforması ilə vaxtınızı daha səmərəli və maraqlı keçirin. Saytın canlı kazino bölməsi istifadəçilərə fərqli bir dünya təklif edir. Burada canlı dilerli kazino oyunlarının hər bir növünü sınaqdan keçirə bilərsiniz. Krupyelərin peşəkarlığı oyunun dinamikasını və marağını artırır. Müntəzəm olaraq yenilənən oyun siyahısı cansıxıcılığa yol vermir. Hesabınızı artırmaq üçün onlarla fərqli və etibarlı üsul mövcuddur. Qazanılan pullar cəmi bir neçə dəqiqə ərzində şəxsi hesabınıza köçürülür. Aktiv fəaliyyətinizə görə fərdi bonuslar və hədiyyələr qazana bilərsiniz. Dəstək xidməti həm çat, həm də e-poçt vasitəsilə kömək göstərir. 1xbet ailəsinə qoşulun və böyük uduşlar üçün ilk addımı atın. onlayn kazino

  • 砂岩白丘

    我一直梦想, 看到你们相册那样的地方。真棒。

  • 城市地標

    我喜欢, 这里分享真实经验。你的项目 就是 属于这里的。请继续。

  • 宗教地標

    我热爱这样的想法, 去那么多国家。真的很鼓舞。

  • 觀景高地

    能感受到热爱。继续保持 感受。

  • 最佳季節

    我关注这样的资源, 写得很实在。你的网站 就是 属于这里的。加油。

  • 1

    1

  • 1

    1

  • -1' OR 2+158-158-1=0+0+0+1 or 'TKCTZnRa'='

    1

日历

2026年07月

   1234
567891011
12131415161718
19202122232425
262728293031 

文章目录

推荐关键字: Linux webpack js 算法 MongoDB laravel JAVA jquery javase redis