当前位置: 首页 > article >正文

ST32中的中断的概念

在STM32微控制器中,中断是一种允许设备在特定事件(例如外部引脚状态变化、定时器溢出、ADC转换完成等)发生时打断当前程序执行的机制。中断可以显著提高系统的实时响应能力,因为处理器无需主动等待特定事件,而是可以在事件发生时通过中断快速响应。

1. 中断基本概念

中断机制允许外设模块(如UART、GPIO、定时器等)向CPU发出请求,CPU会停止当前执行的代码,跳转到中断服务程序(ISR)中执行特定代码,处理完后返回原代码继续执行。STM32中断可分为以下两类:

  • 外部中断:由外部引脚(GPIO)变化或其他外围设备(如RTC、IWDG等)触发。
  • 内部中断:由芯片内部外设(如定时器、ADC、DMA等)触发。

2. 中断优先级

STM32的中断系统支持不同的优先级,以确保在多个中断源同时请求中断时,具有更高优先级的中断会优先得到响应。优先级分为以下两类:

  • 抢占优先级(Preemption Priority):决定了中断是否可以打断其他中断。
  • 子优先级(Sub Priority):决定了当具有相同抢占优先级的中断请求同时发生时,哪个中断会先被响应。

STM32的中断优先级配置通过NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)实现。

3. 中断控制器NVIC

在标准外设库中,NVIC的中断设置和控制主要通过NVIC_InitTypeDef结构体和NVIC_Init()函数来完成。这个方法将中断配置的各项参数集中在一个结构体中,使得配置过程更加便捷和一致。该方法包括以下关键步骤:

NVIC_InitTypeDef 结构体

NVIC_InitTypeDef是一个结构体,用于配置特定中断通道的参数:

  • NVIC_IRQChannel:指定要配置的中断源,即IRQ通道编号。
  • NVIC_IRQChannelPreemptionPriority:设置中断的抢占优先级。
  • NVIC_IRQChannelSubPriority:设置中断的子优先级,用于同一抢占优先级的中断排序。
  • NVIC_IRQChannelCmd:启用或禁用该中断。
配置NVIC的标准库方法

通过初始化NVIC_InitTypeDef结构体并调用NVIC_Init()函数即可实现中断配置。

NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;                  // 选择EXTI0通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;      // 抢占优先级设置为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;             // 子优先级设置为3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                   // 使能该中断通道
NVIC_Init(&NVIC_InitStructure);    

4. 中断配置步骤

步骤 1:配置中断源(以外部中断为例)

如果是外部中断(EXTI),首先配置GPIO引脚的中断模式。

  1. 使能GPIO时钟:打开对应的GPIO端口时钟。
  2. 配置GPIO引脚模式:将引脚设置为输入模式,并指定中断触发边沿(上升沿、下降沿或双边沿)。

配置PA0为外部中断引脚并设置为下降沿触发:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); // 使能GPIOA和AFIO时钟 
GPIO_InitTypeDef GPIO_InitStructure; 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入模式 
GPIO_Init(GPIOA, &GPIO_InitStructure); 
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); // 将GPIOA的0号引脚映射到EXTI0
步骤 2:配置外部中断控制(EXTI)

设置外部中断触发的边沿、引脚和通道等配置。

EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line0;               // 选择EXTI0,即对应PA0引脚
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;      // 设置为中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  // 下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;                // 使能EXTI线路
EXTI_Init(&EXTI_InitStructure);
步骤 3:配置NVIC

使用NVIC_InitTypeDef结构体配置中断通道、抢占优先级和子优先级,并使能中断。

NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;            // 指定中断通道(EXTI0中断)
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01; // 抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;       // 子优先级为3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             // 使能该中断
NVIC_Init(&NVIC_InitStructure);

6. 编写中断服务函数

当事件发生时,CPU会跳转到对应的中断服务程序。每个中断有一个固定的中断处理函数名,例如,EXTI0_IRQHandler() 负责处理EXTI0中断。

NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;            // 指定中断通道(EXTI0中断)
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01; // 抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;       // 子优先级为3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             // 使能该中断
NVIC_Init(&NVIC_InitStructure);

5. 其他常用NVIC函数

在标准库中,NVIC的相关配置可以通过NVIC_EnableIRQ()NVIC_DisableIRQ()NVIC_SetPriority()等函数进行操作,这些函数可以在不使用结构体的情况下直接控制中断:

  • NVIC_EnableIRQ(IRQn_Type IRQn):使能指定中断。
  • NVIC_DisableIRQ(IRQn_Type IRQn):禁用指定中断。
  • NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority):设置指定中断的优先级。
NVIC_SetPriority(EXTI0_IRQn, 1); // 设置优先级 NVIC_EnableIRQ(EXTI0_IRQn); // 使能中断

6. 常见应用场景

  • 按键检测:外部中断处理按键按下或松开等事件。
  • 定时任务:通过定时器中断实现定时任务,如周期性读取传感器数据。
  • 串口通信:通过串口中断处理数据收发,提升通信效率。
  • ADC采样完成:在ADC转换完成后触发中断,数据采集更高效。
  • DMA传输完成:在DMA完成数据传输后触发中断,进行数据后续处理。

7. 注意事项

  • 合理设置中断优先级:确保关键任务的中断优先级最高,以保证实时性。
  • 中断服务函数中避免阻塞操作:避免耗时的代码,以免影响系统响应。
  • 谨慎使用中断嵌套:避免嵌套过深导致系统不稳定。

通过标准外设库的中断配置,STM32可以实现实时响应的应用,适用于嵌入式系统的各种场景。

 


http://www.kler.cn/a/383991.html

相关文章:

  • 【论文解读】Med-BERT: 用于疾病预测的大规模结构化电子健康记录的预训练情境化嵌入
  • iOS用rime且导入自制输入方案
  • AI - 使用LangChain请求LLM结构化生成内容
  • python manage.py下的命令及功能
  • 实习冲刺Day15
  • MySQL45讲 第十讲 MySQL为什么有时候会选错索引?
  • 【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
  • 如何找到捏蛋糕和修牛蹄类型的解压视频素材?
  • Java1.8新特性
  • 探索React源码:React Diff
  • string模拟实现拷贝构造operator=
  • MySQL数据库单表查询习题
  • 安全工程师入侵加密货币交易所获罪
  • 考研日语 - 高频核心 2200 词(十四)
  • 前端加密方式详解与选择指南
  • 滑动变阻器有哪些分类?
  • 基于Spring Boot的在线装修管理系统的设计与实现,LW+源码+讲解
  • 梧桐数据库SQL高级查询技巧之计算用户每月登录次数及其变化
  • 107. 二叉树的层序遍历 II 队列+迭代
  • Visual Studio Code从安装到正常使用
  • 【rust】rust基础代码案例
  • 仪表板展示|DataEase看中国:历年双十一电商销售数据分析
  • MOE(Mixture of Experts,混合专家)
  • django图书管理系统-计算机毕业设计源码00648
  • 量化研究--年化57%全球动量模型策略回测,学习使用
  • nginx代理 proxy_pass