STM32-07-STM32_外部中断

news2024/11/16 23:57:35

文章目录

  • STM32 中断系统
    • 1. 中断
    • 2. NVIC
    • 3. EXTI
    • 4. AFIO
    • 5. 中断配置步骤
    • 6. 外部中断代码

STM32 中断系统

1. 中断

  • 目的:中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。
  • 中断过程:当CPU正在处理某事件的时候外界发生了紧急事件请求 中断发生,要求CPU暂停当前的工作,转而去处理这个紧急事件 中断响应和中断服务,处理完以后,再回到原来被中断的地方,继续原来的工作 中断返回
  • 中断系统:实现中断功能的部件称为中断系统,请求CPU中断的请求源称为中断源。微型机的中断系统一般允许有多个中断源,当几个中断源同时向CPU请求中断,要求它服务的时候,这就存在CPU优先响应哪个中断源请求的问题。因此设置中断优先级,CPU总是先响应优先级别最高的中断请求。
  • 作用与意义
    1. 实时控制
    2. 故障处理
    3. 数据传输

2. NVIC

  • 什么是NVIC?

    Nested vectored interrupt controller 即嵌套向量中断控制器,属于内核。

    支持256个中断,其中包含了16个系统中断和240个外部中断,并且具有256级的可编程中断设置。

    对于STM32F103ZET6的系统中断10个,外部中断60个,16中断优先级

    特性:

    • 68个可屏蔽中断通道
    • 16个可编程的优先等级
    • 低延时的异常和中断处理
    • 电源管理的控制
    • 系统控制寄存器的实现
  • NVIC相关寄存器介绍

    NVIC相关寄存器位数寄存器个数备注
    中断使能寄存器(ISER)328每个位控制一个中断
    中断失能寄存器(ICER)328每个位控制一个中断
    应用程序中断及复位控制寄存器(AIRCR)321位[10:8]控制优先级分组
    中断优先级寄存器(IPR)82408个位对应一个中断,而STM32只使用高4位
  • 工作原理

    内核中断是不可屏蔽中断,直接由SHPR决定优先级,外部中断过来以后,会首先经过ISERICER寄存器进行使能或者失能,之后由IPR寄存器确定优先级,然后去抢占CPU执行中断。
    在这里插入图片描述

  • 中断优先级

    • 抢占优先级:高抢占优先级可以打断正在执行的低抢占优先级中断
    • 响应优先级:当抢占优先级相同时,响应优先级高的先执行,但是不能互相打断
    • 自然优先级:中断向量表的优先级
    • 抢占和响应优先级相同时,自然优先级高的先执行,数值越小,表示优先级越高
  • 优先级分组

    优先级分组AIRCR[10:8]IPRx bit[7:4]分配分配结果
    0111None :[7:4]0位抢占优先级,4位响应优先级
    1110[7] :[6:4]1位抢占优先级,3位响应优先级
    2101[7:6] :[5:4]2位抢占优先级,2位响应优先级
    3100[7:5] :[4]3位抢占优先级,1位响应优先级
    4011[7:4] :None4位抢占优先级,0位响应优先级
  • NVIC的使用

    1. 设置中断分组 SCB_AIRCR
    2. 设置中断优先级 NVIC_IPRx
    3. 使能中断 NVIC_ISER

3. EXTI

  • 什么是EXTI?

    External interrupt/event Controller 即外部中断/事件控制器,由20个产生事件/中断请求的边沿检测器组成,非互联型产品有19个边沿检测器。每个输入线可以独立地配置输入类型和对应的触发事件。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。

  • 特性:

    • 每个中断/事件都有独立地触发和屏蔽
    • 每个中断线都有专用的状态位
    • 支持多达20个软件的中断/事件请求
    • 检测脉冲宽度低于APB2时钟宽度的外部信号
  • 框图
    在这里插入图片描述

    功能框图包含两条主线:一是由输入线到NVIC中断控制器,二是由输入线到脉冲发生器。这就是EXTI的两大功能,产生中断与产生事件,两者从硬件上就存在不同。

    输入线是线路的信息输入端,它可以通过配置寄存器设置为任何一个GPIO口,或者是一些外设的事件。输入线一般都存在电平变化的信号。

    ①:边缘检测上升沿触发选择寄存器(EXTI_RTSR)和下降沿触发选择寄存器(EXTI_FTSR)。边沿检测电路以输入线作为信号输入端,如果检测到边缘跳变,就输出有效信号1,有效信号1会传输到②电路。

    ②:软件触发,两个信号输入端分别为软件中断事件寄存器(EXTI_SWIER)和边沿检测电路的输入信号。或门电路只要输入有效信号1,就会把有效信号输入到③和④电路。通过对软件中断事件寄存器的读写操作就可以启动中断/事件线。

    ③:中断屏蔽/清除,两个信号输入端分别为中断屏蔽寄存器(EXTI_IMR)和②电路,与门电路要求输入都为‘1’才输出‘1’,这样子的情况下,如果中断屏蔽寄存器EXTI_IMR)设置为0时,不管从标号②电路输出的信号特性如何,最终标号③电路输出的信号都是0;假如中断屏蔽寄存器(EXTI_IMR)设置为1时,最终标号③电路输出的信号才由标号②电路输出信号决定,这样子就可以简单控制EXTI_IMR来实现中断的目的。标号④电路输出‘1’就会把请求挂起寄存器(EXTI_PR)对应位置1。

    ④:事件屏蔽请求挂起寄存器(EXTI_PR)的内容就输出到 NVIC 内,实现系统中断事件的控制。

4. AFIO

  • Alternate Function IO,即复用功能IO,主要用于重映射和外部中断映射配置

    寄存器AFIO_EXTICR1~4,配置EXTI中断线0~15具体对应哪个IO口

  • EXTI与IO对应关系
    在这里插入图片描述

5. 中断配置步骤

在这里插入图片描述

  • EXTI配置步骤:
    1. 使能GPIO时钟
    2. 设置GPIO工作模式
    3. 使能AFIO
    4. 设置EXTI和IO对应关系
    5. 设置EXTI屏蔽,上下沿
    6. 设置NVIC
    7. 设计中断服务函数

  • HAL库配置步骤:

    1. 使能GPIO时钟

      __HAL_RCC_GPIOx_CLK_ENABLE();
      
    2. GPIO/AFIO/EXTI配置

      HAL_GPIO_Init();
      
    3. 设置中断分组

      HAL_NVIC_SetPriorityGrouping();
      
    4. 设置中断优先级

      HAL_NVIC_SetPriority();
      
    5. 使能中断

      HAL_NVIC_EnableIRQ();
      
    6. 设计中断服务函数

      EXTIx_IRQHandler();
      
    7. 编写中断处理回调函数

      HAL_GPIO_EXTI_Callback();
      
  • 中断回调处理机制
    在这里插入图片描述

6. 外部中断代码

Exti.h

#ifndef _EXTI_H
#define _EXTI_H


#include "./SYSTEM/sys/sys.h"

void exti_init(void);

#endif

EXTI.c

#include "./BSP/EXTI/exti.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"


//外部中断初始化
void exti_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    
    //1.打开GPIO的时钟
    __HAL_RCC_GPIOE_CLK_ENABLE();
    
    //2.配置GPIO
    gpio_init_struct.Pin = GPIO_PIN_4;
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOE, &gpio_init_struct);
    
    gpio_init_struct.Pin = GPIO_PIN_3;
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOE, &gpio_init_struct);
    
    gpio_init_struct.Pin = GPIO_PIN_2;
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOE, &gpio_init_struct);
    
    gpio_init_struct.Pin = GPIO_PIN_0;
    gpio_init_struct.Mode = GPIO_MODE_IT_RISING;
    gpio_init_struct.Pull = GPIO_PULLDOWN;
    HAL_GPIO_Init(GPIOA, &gpio_init_struct);
    
    //4.设置中断优先级
    HAL_NVIC_SetPriority(EXTI4_IRQn, 2, 0);
    HAL_NVIC_SetPriority(EXTI3_IRQn, 3, 0);
    HAL_NVIC_SetPriority(EXTI2_IRQn, 4, 0);
    HAL_NVIC_SetPriority(EXTI0_IRQn, 5, 0);
    
    //5.使能中断
    HAL_NVIC_EnableIRQ(EXTI4_IRQn);
    HAL_NVIC_EnableIRQ(EXTI3_IRQn);
    HAL_NVIC_EnableIRQ(EXTI2_IRQn);
    HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}


void EXTI4_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
    __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_4);
}

void EXTI3_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3);
    __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_3);
}

void EXTI2_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
    __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_2);
}

void EXTI0_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
    __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_0);
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{ 
    delay_ms(20);
    
    switch(GPIO_Pin)
    {
        case GPIO_PIN_0: 
            if(KEY_UP == 1)
                LED0(0); 
            break;
        case GPIO_PIN_2:
            if(KEY2 == 0)            
                LED0(1); 
            break;
        case GPIO_PIN_3: 
            if(KEY1 == 0)
                LED1(0); 
            break;
        case GPIO_PIN_4: 
            if(KEY0 == 0)
                LED1(1); 
            break;
        default : 
            break;
    }
}

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
#include "./BSP/BEEP/beep.h"
#include "./BSP/EXTI/exti.h"


int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    delay_init(72);                     /* 延时初始化 */
    led_init();                         /* LED初始化 */
    key_init();     //按键初始化
    beep_init();    //蜂鸣器初始化
    exti_init();    //外部中断初始化
    
    while(1)
    {     

    }
}

声明:资料来源(战舰STM32F103ZET6开发板资源包)

  1. Cortex-M3权威指南(中文).pdf
  2. STM32F10xxx参考手册_V10(中文版).pdf
  3. STM32F103 战舰开发指南V1.3.pdf
  4. STM32F103ZET6(中文版).pdf
  5. 战舰V4 硬件参考手册_V1.0.pdf

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1665459.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ESP-01S刷固件ESP8266_NonOS_AT_Bin_V1.7.5_1 笔记240510

ESP-01S刷固件ESP8266_NonOS_AT_Bin_V1.7.5_1 笔记240510 固件下载地址 ESP-AT固件页面: https://www.espressif.com.cn/zh-hans/products/sdks/esp-at/resource 直接下载ESP8266 NonOS AT Bin V1.7.5.zip: https://www.espressif.com.cn/sites/default/files/ap/ESP8266_No…

32.768kHz晶振的时间精度问题及其解决方法

32.768kHz晶振因其稳定性高、功耗低,被广泛应用于实时时钟(RTC)、计时电路及低功耗电子产品中。然而,在某些情况下,这些晶振可能出现时间偏差,影响设备正常工作。以下是可能导致32.768kHz晶振时间误差的原因及相应的解决策略。 温…

Snort规则编写

1)TCP NULL端口扫描的特征: 扫描者发送一个TCP SYN包到目标主机的某个端口,但不设置任何TCP标志位(即flag为NULL)。 如果端口关闭,目标主机会回应一个RST(复位)和ACK(确认…

数据结构之图——探索图论的奥秘

前言 在这篇文章中,我们一起来看看我们生活中都会用到,但却不那么熟悉的数据结构——图(英语:graph)。我们看下百科定义: 在计算机科学中,图(英语:graph)是一…

py黑帽子学习笔记_网络编程工具

tcp客户端 socket.AF_INET表示使用标准IPV4地址和主机名 SOCK_STREAM表示这是一个TCP客户端 udp客户端 udp无需连接,因此不需要client.connect这种代码 socket.SOCK_DGRAM是udp的 tcp服务端 server.listen(5)表示设置最大连接数为5 发现kill server后端口仍占用…

大模型微调之 在亚马逊AWS上实战LlaMA案例(九)

大模型微调之 在亚马逊AWS上实战LlaMA案例(九) 代码阅读 src/llama_recipes/inference/prompt_format_utils.py 这段代码是一个Python模块,它定义了几个类和模板,用于生成安全评估的提示文本。以下是对每一行代码的注释和提示词…

Datax数据采集

一、Datax介绍 官网: DataX/introduction.md at master alibaba/DataX GitHub DataX 是阿里云 DataWorks数据集成 的开源版本,在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。 DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、…

MySQL innodb_buffer_pool_size 相关常用语句

对于MySQL速度慢的问题,除了优化 SQL 以外,应该必须优先想到的即使 MySQL 数据库的 innodb_buffer_pool_size 配置问题。 一般来说,innodb_buffer_pool_size 的默认大小都是很小的,尤其是 win 下其默认大小更是只有离谱的 8M。Li…

2024 年最新本地、云服务器安装部署 miniconda 环境详细教程(更新中)

Anaconda 概述 Anaconda 是专门为了方便使用 Python 进行数据科学研究而建立的一组软件包,涵盖了数据科学领域常见的 Python 库,并且自带了专门用来解决软件环境依赖问题的 conda 包管理系统。主要是提供了包管理与环境管理的功能,可以很方便…

土壤墒情自动监测站—墒情异常数据报警提示

TH-TS600土壤墒情自动监测站通常配备有预警提示功能,用于在墒情出现异常情况时及时向用户发出警告。这一功能对于农业生产至关重要,因为它可以帮助农民或农田管理者及时发现土壤墒情的变化,并采取相应的措施来确保作物健康生长。 土壤墒情自动…

Excel实用技巧持续学习

1、Excel高效设置图标格式: 2、饼图可以统一设置数据标签在图外面!! 环形图不可以,但是可以中间手动加上白色圆形,将饼图变为圆环。 可以设置标签的文本显示: 3、饼图和环形图最好进行排序!显得…

睿尔曼机械臂ROS控制

下载git工程 git clone https://github.com/RealManRobot/rm_robot.git安装配置 catkin build rm_msgs source devel/setup.bash catkin build source setup.bash这里注意,如果采用setup.sh多半不会成功,必须要source setup.bash文件,ros才…

云渲染动画300帧需要多久呢?瑞云渲染为你揭秘

在动画制作过程中,渲染的速度非常关键。对于一个项目需要渲染的300帧来说,由于硬件的限制,许多公司的设备可能无法快速完成这项任务。此时,借助云渲染服务的强大计算能力,可以显著减少完成时间,从而提速整个…

使用Python和akshare完成个股信息统计和实时记录

标题:使用Python和akshare完成个股信息统计和实时记录 在金融投资领域,实时获取和记录个股信息对于投资者至关重要。Python 作为一种强大的编程语言,在金融数据分析和处理方面有着广泛的应用。akshare 是一个专门用于获取金融数据的 Python 库,提供了丰富的金融数据接口,可…

抽空学学go

2024年5月9日11:14:24 学习go 看课8小时转职Golang工程师(如果你想低成本学习Go语言)_哔哩哔哩_bilibili 文档[8小时转职Golang工程师 (yuque.com)]( 1.安装go 2024年5月9日11:27:16 2.安装 vscode go配置环境 vs code配置go开发环境 (zhihu.com) vscode里面配置代理&…

Rust使用HashSet对Vec类型的元素进行去重

在Rust语言中,对Vec类型的元素进行去重,一种常见的方法是使用一个HashSet来帮助我们快速检查元素是否已经存在。以下是使用HashSet对Vec进行去重的示例代码: use std::collections::HashSet;fn main() {let vec_numbers vec![1, 2, 2, 3, 4…

大数据比赛-环境搭建(一)

1、安装VMware Workstation 链接:https://pan.baidu.com/s/1IvSFzpnQFl3svWyCGRtEmg 提取码:ukpo 内有安装包及破解方式,安装教程。 2、下载Ubuntu系统 阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区 (aliyun.com) 点击下载&#xff…

The Sandbox 在利雅得的首次教育活动

2024年4月22日,The Sandbox 与沙特阿拉伯利雅得的 KACST(阿卜杜勒阿齐兹国王科技城)合作,举办了首次创作者研讨会。此次活动标志着沙特在推动生态系统增长和扩展方面的重要一步。 The Sandbox 的核心使命是通过无编程工具赋能下一…

在做题中学习(54):点名

LCR 173. 点名 - 力扣(LeetCode) 此题有不同的几种解法: 解法一:暴力枚举 O(n); 解法二:哈希表 把原数组丢入哈希表,遍历哈希表,看看哪个数值为0即可。 O(n)空间O(n)时间 解法三&…

【stm32-2】按键控制LED光敏传感器控制蜂鸣器

1.按键控制LED uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //读取输入数据寄存器某一个端口的输入值 uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx); //读取整个输入数据寄存器 uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDe…