中断、异常

news2024/12/23 15:43:20

文章目录

      • 概念
        • CPU怎么直到中断/异常跳过来执行哪一个函数呢?
        • LR
      • 中断硬件框架:
        • 对于F103这块芯片,如果要PA0发出中断,那要做的操作有?
        • GPIO中断编程
        • 具体代码

概念

中断属于一种异常
image.png
保存现场、处理异常(中断)、恢复现场;
现场就是各种寄存器;
1、初始化、设置中断源、中断优先级
2、执行程序
3、产生中断,比如按下按键
4、cpu没执行完一条指令、都会检查有无中断、异常
5、发现异常、中断。跳去对应的地址去执行程序

CPU怎么直到中断/异常跳过来执行哪一个函数呢?

cortex M3、M4处理器
都是硬件来做的;
1、保存现场
2、硬件分辨异常/中断
3、跳转到向量表去执行
4、恢复:软件触发、硬件恢复

cortex A7处理器
硬件
1、切换模式,进入IRQ模式
2、跳转
3、执行代码
软件
4、保存现场
5、分辨中断
6、恢复现场
image.png
CPU的寄存器
R0和R3
调用者和被调用者之间传参;
现场:R0-R15, 以及PSR;

LR

LR并不是简单的存着一个返回地址,因为要恢复现场、其他保存好的寄存器也要恢复;
如果是简单的返回地址的话,那就直接返回了,其他保存的寄存器不会恢复;
LR = 特殊值;
调用完函数;
发现LR = 一个特殊的值;
image.png
M3、M4有两个sp,sp_mian、sp_process主栈寄存器和线程栈寄存器,一般用的主栈寄存器
对于A7处理器
image.png

中断硬件框架:

f103和157都是中断引脚只能配置一个;
image.png
image.png

对于F103这块芯片,如果要PA0发出中断,那要做的操作有?

实现按下按键产生中断,松开也产生中断,双边沿触发;PA0按键的引脚

1、外部中断寄存器,选择PA0发生中断;中断源
image.png
2、是上升沿、还是下降沿发生中断?
使能EXTI,以及配置中断触发方式
image.png
3、NVIC中断控制器
中断设置使能寄存器,里面有32bit,每一位对应一个寄存器;
把这个寄存器第0位设置位1,才能把对应的中断发给cpu
4、设置cpu是否处理中断
cpu内部的寄存器,bit0设置为0才可以处理中断;
image.png

GPIO中断编程

1、设置外部中断0,PA0
image.png
基地址+偏移地址
image.png
image.png
image.png

2、EXTI配置模式、以及使能
触发模式选择双边触发,也就是上升沿以及下降沿的两个寄存器都要设置;
找基地址
image.png
设置外部中断EXTI0,0就是第一个,第一位bit0,设置为上升沿触发bit0 = 1
image.png
使能EXTI,
这一位设置成1就是不屏蔽,也就是NVIC与EXTI0的通道打开了
image.png

3、NVIC
image.png
设置第6位为0:EXTI0
image.png

4、使能cpu中断
image.png
image.png

4、清除中断
清除外部中断控制器
写入1清除,基地址是EXTI的
image.png
清除NVIC中断控制器
设置为0;
image.png

具体代码

结构体对齐
image.png
直接用结构体来存这些寄存器的地址;
image.png

#include "string.h"
#include "exti.h"
#include "nvic.h"

/* stm32f103xe.h */

typedef struct
{
  volatile unsigned int EVCR;
  volatile unsigned int MAPR;
  volatile unsigned int EXTICR[4];
  volatile unsigned int RESERVED0;
  volatile unsigned int MAPR2;  
} AFIO_TypeDef;

void key_init(void)
{
	AFIO_TypeDef *afio = (AFIO_TypeDef *)0x40010000;
	
	unsigned int *pReg;
	unsigned int *pRegA;
	
	/* 1.初始化GPIO引脚PA0, 设置为输入引脚 */
	/* 使能GPIOB, GPIOA */
	pReg = (unsigned int *)(0x40021000 + 0x18);
	*pReg |= (1<<3) | (1<<2);
	
	/* 设置GPIOA0为输入引脚 */
	pRegA = (unsigned int *)(0x40010800 + 0x00);
	*pRegA &= ~(3);     /* mode0 = 0b00 */
	*pRegA &= ~(3<<2);  /* cnf0 = 0b00 */
	*pRegA |= (1<<2);   /* cnf0 = 0b01 */
	
	/* 2. 设置为EXTI0 */
	afio->EXTICR[0] &= ~0xf;  /* PA0 as EXTI0 */ 
}


void EXTI0_IRQHandler(void)
{
	/* GPIOA input data register */
	unsigned int * pRegA = (unsigned int *)(0x40010800 + 0x08);
	
		if ((*pRegA & (1<<0)) == 0) /* KEY1被按下 */
		{
			puts("KEY1 pressed!\n\r");
		}
		else
		{
			puts("KEY1 released!\n\r");
		}
		
		/* 清除中断 */
		exti_clear_int(0);
		nvic_clear_int(6);
}



typedef struct
{
  volatile unsigned int IMR;
  volatile unsigned int EMR;
  volatile unsigned int RTSR;
  volatile unsigned int FTSR;
  volatile unsigned int SWIER;
  volatile unsigned int PR;
} EXTI_TypeDef;


void exti_init(void)
{
	EXTI_TypeDef * exti = (EXTI_TypeDef *)0x40010400;
	
	/* 1. 设置触发方式:双边沿触发 */
	exti->RTSR |= (1<<0);
	exti->FTSR |= (1<<0);
	
	/* 2. 使能中断: 能够向NVIC发出中断 */
	exti->IMR |= (1<<0);
}

void exti_clear_int(int bit)
{
	EXTI_TypeDef * exti = (EXTI_TypeDef *)0x40010400;
	exti->PR |= (1<<bit);
}



/* core_cm3.h */
typedef struct
{
  volatile unsigned int ISER[8];         /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register           */
  volatile unsigned int RESERVED0[24];   
  volatile unsigned int ICER[8];         /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register         */
  volatile unsigned int RSERVED1[24];    
  volatile unsigned int ISPR[8];         /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register          */
  volatile unsigned int RESERVED2[24];   
  volatile unsigned int ICPR[8];         /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register        */
  volatile unsigned int RESERVED3[24];   
  volatile unsigned int IABR[8];         /*!< Offset: 0x200 (R/W)  Interrupt Active bit Register           */
  volatile unsigned int RESERVED4[56];   
  volatile unsigned char  IP[240];             /*!< Offset: 0x300 (R/W)  Interrupt Priority Register (8Bit wide) */
  volatile unsigned int RESERVED5[644];
  volatile unsigned int STIR;            /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register     */
}  NVIC_Type;


void nvic_init(void)
{
	NVIC_Type * nvic = (NVIC_Type *)0xE000E100;
	
	/* 1. 使能EXTI0中断 */
	nvic->ISER[0] |= (1<<6);
}

void nvic_clear_int(int bit)
{
	NVIC_Type * nvic = (NVIC_Type *)0xE000E100;
	
	if (bit <= 31)
		nvic->ICPR[0] |= (1<<bit);
}

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

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

相关文章

C# 植物大战僵尸---杂交版

开发框架&#xff1a;.Net Fra,ework4.0 游戏名称&#xff1a;植物大战僵尸-杂交版 游戏介绍&#xff1a;植物大战僵尸-杂交版是一款结合了经典塔防游戏《植物大战僵尸》的元素和创新杂交机制的游戏。玩家需要种植各种植或英雄物来抵御一波又一波的僵尸入侵。游戏的特色在于各…

迅为RK3588开发板可以实现双屏同显、双屏异显、三屏同显、三屏异显、标异屏切换

RK3588可以实现双屏同显、双屏异显、三屏同显、三屏异显、标异屏切换这主要取决于RK3588芯片内置了VOP控制器&#xff0c;支持三路视频同时输出可有效提高行业定制的拓展性。

《码农职场》(IT人求职就业手册)导读和理性书评

《码农职场》是为IT行业求职者量身定制的一本实用指南&#xff0c;涵盖了从求职准备到成功就业的全方位内容。书中分为“职前调整”和“就业指南”两大部分&#xff0c;每一部分都详尽地介绍了求职过程中的各个关键环节&#xff0c;旨在帮助求职者在竞争激烈的职场中脱颖而出。…

锡废水再生回收的回收处理

锡废水再生回收是一个涉及环境保护和资源再利用的重要过程&#xff0c;主要目的是从含有锡的废水中提取有价值的锡资源&#xff0c;同时减少环境污染。以下是对锡废水再生回收的详细解析&#xff1a; 一、锡废水再生回收的重要性 环境保护&#xff1a;回收废水中的锡可以减少对…

C# Null 合并运算符 ??

int&#xff1f; 在 C# 中&#xff0c;int? 是一个可空的 int 类型&#xff0c;它能够存储一个 32 位带符号整数或者 null 值。当你声明一个 int? 类型的变量并将其初始化为 null&#xff0c;你实际上是在创建一个可以容纳整数值的变量&#xff0c;但是初始时并没有赋予它任…

C++转Java基础知识

目录 1. Java基础知识 1.1 JDK和JVM 1.2 Java基础代码演示 1.3 Java中的注释 1.4 Java中的关键字 1.5 Java中的println和print的区别 2. Java中的数据类型 2.1 常量 2.2 标识符 2.3 变量 2.4 类型转换 2.5 自动类型转换 2.6 强制类型转换 3. 运算符 3.1 自增运算…

彻底删除和安装docker和docker-compose

一、Docker安装和卸载 1.1 离线安装docker 1.1.1 下载docker安装包 1.1.2 上传docker到服务器目录/opt/ 1.1.3 解压docker-19.03.9.tgz 进入opt目录解压docker-19.03.9.tgz 1.1.4 解压的docker文件夹全部移动至/usr/bin目录 1.1.5 将docker注册为系统服务 在/usr/lib/syst…

C++——多态经典案例(一)组装电脑

案例&#xff1a;小明打算买两台组装电脑&#xff0c;假设电脑零部件包括CPU、GPU和内存组成。 一台电脑使用intel的CPU、GPU和内存条 一台电脑使用Huawei的CPU、GPU和Intel的内存条 分析&#xff1a;使用多态进行实现 将CPU、GPU和内存条定义为抽象类&#xff0c;内部分别定义…

【LeetCode刷题笔记】LCR.27 回文链表

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多算法知识专栏&#xff1a;算法分析&#x1f525; 给大家跳段街舞感谢…

平价蓝牙耳机哪款具有超高的性价比?四个评分超高的爆款推荐!

随着现代人对蓝牙耳机的需求越来越大&#xff0c;是不是每次看到琳琅满目的蓝牙耳机都眼花缭乱的&#xff0c;特别是预算有限还要追求音质与耐用的小伙伴&#xff0c;不知道平价蓝牙耳机哪款具有超高的性价比&#xff1f;别怕&#xff0c;今天我这个蓝牙耳机小达人就来给你们带…

简单猜谜小程序开发

了解小程序的结构 项目根目录 包含小程序的配置文件和其他资源。 页面目录 每个页面都有独立的目录&#xff0c;通常包含 .json、.wxml、.wxss、.js 文件&#xff1a; .json&#xff1a;页面配置文件&#xff0c;用于配置页面的窗口表现等。 .wxml&#xff1a;页面的布局文件…

ArcGIS for js 缓冲(vue项目)

示例&#xff1a; 一、页面布局 <template><div id"viewDiv"><div class"content"><el-button-group class"btnGroup"><el-button type"button" click"toolClick(point)" title"缓冲点&qu…

查询表信息时有一个数据为null相关解决

查询的时候varchar类型的username一直查不到为null,这个问题干了我好久 当时我以为是连接mysql数据库的时候没有在url后面添加添加指定字符的编码、解码格式的参数约束.然后经过分析发现 我创建的这个Account对象 直接上结果&#xff0c;问题出在了setUsername()方法上 错误…

ICM-20948芯片详解(7)

接前一篇文章&#xff1a;ICM-20948芯片详解&#xff08;6&#xff09; 五、组件概览及详述 再次给出ICM-20948芯片的内部结构框图&#xff1a; 2. 组件详述 &#xff08;9&#xff09;传感器数据寄存器 传感器数据寄存器包含最新的陀螺仪、加速计、辅助传感器和温度测量数据…

Python获取Excel内容

Python获取Excel内容 目录 Python获取Excel内容1.读取Excel并登陆2.下载Excel中图片 数据存储到列表3.上传到接口 需求&#xff1a;获取xlsx files目录下的所有Excel信息&#xff0c;并将数据打包成字典格式上传到接口 示例数据&#xff1a; 1.读取Excel并登陆 import os impo…

只渲染阴影(blender的cycle渲染)

点击物体属性&#xff0c;visibility&#xff0c;mask的阴影收集器 shadow catcher 点出蒙版层 新建collection收集集合&#xff0c;点击蒙版让物体消失并挖洞&#xff0c;

我命由我不由天:我的计算机教师中级岗之旅

在计算机行业的洪流中&#xff0c;作为一名20年计算机专业毕业的博主&#xff0c;我深知这几年就业的坎坷与辉煌。今天&#xff0c;我想与大家分享我的故事&#xff0c;一段关于梦想、挑战与坚持的计算机教师中级岗之旅。希望我的经历能为大家提供一个发展方向&#xff0c;在计…

群晖第五篇-docker部署自动化程序并设置推送

因网络政策调整&#xff0c;我们今后在使用docker的时候会比较繁琐。。。 1.打开Container Manager配置docker源&#xff0c;在右侧注册表镜像URL中填入自己找到的可用的docker镜像地址&#xff0c;然后点击应用。 2.在注册表页面中搜索"qd"&#xff0c;下载第一个镜…

java 位运算符

java位运算符 位于算符符号解释&按位与 当两位同为1时返回1|按位或,只要有一位为1即返回1~按位非,将操作数每个位(包括符号位,全部取反)^按位异或 两位相同时返回0,不相同时返回1<<左移运算符>>右移运算符 符号的介绍: &(与) -> 有假则假|(或) ->…

ctfhub eval执行

url http://challenge-1e9b95e5c3c2862c.sandbox.ctfhub.com:10800/ 源码 <?php if (isset($_REQUEST[cmd])) {eval($_REQUEST["cmd"]); } else {highlight_file(__FILE__); } ?> 首先&#xff0c;isset($_REQUEST[cmd]) 用于检查是否通过 $_REQUEST &am…