【ARM】Day8 中断

news2025/1/12 23:00:22

1. 思维导图

 

2. 实验要求: 实现KEY1/LEY2/KE3三个按键,中断触发打印一句话,并且灯的状态取反 key1 ----> LED3灯状态取反 key2 ----> LED2灯状态取反 key3 ----> LED1灯状态取反

key3.h

#ifndef __KEY3_H__
#define __KEY3_H__

#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_uart.h"
#include "stm32mp1xx_gic.h"
#include "stm32mp1xx_exti.h"

//key1-->PF9
//key2-->PF7
//key3-->PF8

typedef enum
{
	EXTI_NUM1 = 0,
	EXTI_NUM2,
	EXTI_NUM3,
	EXTI_NUM4,
	EXTI_NUM5,
	EXTI_NUM6,
	EXTI_NUM7,
	EXTI_NUM8,
	EXTI_NUM9,
	EXTI_NUM10,
	EXTI_NUM11,
	EXTI_NUM12,
	EXTI_NUM13,
	EXTI_NUM14,
	EXTI_NUM15
}exti_num_t;


typedef enum
{
	EXTI1 = 1,
	EXTI2,
	EXTI3,
	EXTI4,
	EXTI5,
	EXTI6,
	EXTI7,
	EXTI8,
	EXTI9,
	EXTI10,
	EXTI11,
	EXTI12,
	EXTI13,
	EXTI14,
	EXTI15
}exti_select_t;


typedef enum
{
    EXTI_RISING_TRIGGER = 0,
    EXTI_FALLING_TRIGGER
} exti_trigger_t;

void hal_exti_init(exti_num_t extinum,exti_select_t ground,exti_trigger_t trigger); 	//RCC/GPIO/EXTI章节初始化
void hal_gic_init(unsigned int interruptid,unsigned int priority); 	//GIC章节初始化


#endif

led.h

#ifndef _LED_H__   //防止头文件重复包含_
#define _LED_H__

#include "stm32mp1xx_gpio.h"

//RCC_MP_AHB4ENSETR寄存器封装
#define	RCC_MP_AHB4ENSETR (*(volatile unsigned int*)0x50000A28)


//对引脚编号进行封装
#define GPIO_PIN_0 0
#define GPIO_PIN_1 1
#define GPIO_PIN_2 2
#define GPIO_PIN_3 3
#define GPIO_PIN_4 4
#define GPIO_PIN_5 5
#define GPIO_PIN_6 6
#define GPIO_PIN_7 7
#define GPIO_PIN_8 8
#define GPIO_PIN_9 9
#define GPIO_PIN_10 10
#define GPIO_PIN_11 11
#define GPIO_PIN_12 12
#define GPIO_PIN_13 13
#define GPIO_PIN_14 14
#define GPIO_PIN_15 15


//使用枚举封装MODER寄存器
typedef enum{
	INPUT,	//输入 0
	OUTPUT,	//输出 1
	ALT,	//复用 2
	ANALOG	//模拟 3
}gpio_moder_t;

//使用枚举封装OTYPER寄存器
typedef enum{
	PP,	//推挽 0
	DP	//开漏 1
}gpio_otyper_t;


//使用枚举封装OSPEEDR寄存器
typedef enum{
	LOWSPEED,	//低速 0
	MEDSPEED,	//中速 1
	HIGHSPEED,	//高速 2
	VERYHIGHSPEED	//快速 3 
}gpio_ospeedr_t;

//使用枚举封装PURDR寄存器
typedef enum{
	NO_PUPDR,	//禁止上下拉电阻 0
	PU,	//上拉 1
	PD	//下拉 2
}gpio_pupdr_t;


//封装初始化结构体
typedef struct{
	gpio_moder_t moder;	//模式寄存器
	gpio_otyper_t otyper;	//输出类型寄存器
	gpio_ospeedr_t ospeedr;	//输出速率寄存器
	gpio_pupdr_t pupdr;	//是否上下电阻寄存器
}gpio_init_t;

//使用枚举封装ODR寄存器
typedef enum{
	GPIO_RESET_T,	//熄灭 0
	GPIO_SET_T	//点亮 1
}gpio_status_t;


//函数功能:GPIO引脚初始化操作
//参数1:GPIO组号
//参数2:引脚编号
//参数3:初始化内容
void hal_gpio_init(volatile gpio_t * gpiox,unsigned int pin,gpio_init_t* init);


//函数功能:GPIO引脚操作,写1点亮,写0熄灭
//参数1:GPIO组号
//参数2:引脚编号
//参数3:写的内容
void hal_gpio_write(volatile gpio_t* gpiox,unsigned int pin,gpio_status_t status);


#endif

key3.c

#include "key3.h"


//key1 -----> PF9
//key2 -----> PF7
//key3 -----> PF8
void hal_exti_init(exti_num_t extinum,exti_select_t ground,exti_trigger_t trigger) 	//RCC/GPIO/EXTI章节初始化
{
	//RCC章节初始化
		//使能GPIOF组控制器  -----> RCC_MP_AHB4ENSETR[5] = 1
	RCC->MP_AHB4ENSETR |= (0x1 << 5);

	//GPIO章节初始化
  		//设置KEY1按键为输入模式  -----> GPIOF_MODER[19:18] = 00
  		//设置KEY2按键为输入模式  -----> GPIOF_MODER[15:14] = 00
  		//设置KEY3按键为输入模式  -----> GPIOF_MODER[17:16] = 00
	GPIOF->MODER &= (~(0x3f << 14));

	//EXTI章节初始化
	//1、EXTI_EXTICRn(n=1~4):EXTI external interrupt selection register  ===> 外部中断选择寄存器, 
		//设置KEY1按键与EXTI9进行连接,EXTI_EXTICR3[15:8] = 0x05,
		//设置KEY2按键与EXTI7进行连接,EXTI_EXTICR2[31:24] = 0x05
		//设置KEY1按键与EXTI8进行连接,EXTI_EXTICR3[7:0] = 0x05
	switch(extinum / 4)
	{
		case 0:
			EXTI->EXTICR1 &= (~(0xff << (extinum % 4 *8)));
			EXTI->EXTICR1 |= (ground << (extinum % 4 *8));
			break;
		case 1:
			EXTI->EXTICR2 &= (~(0xff << (extinum % 4 *8)));
			EXTI->EXTICR2 |= (ground << (extinum % 4 *8));
			break;
		case 2:	
			EXTI->EXTICR3 &= (~(0xff << (extinum % 4 *8)));
			EXTI->EXTICR3 |= (ground << (extinum % 4 *8));
			break;
		case 3:	
			EXTI->EXTICR4 &= (~(0xff << (extinum % 4 *8)));
			EXTI->EXTICR4 |= (ground << (extinum % 4 *8));
			break;
		default:break;
	}

	//2、EXTI_FTSR1:EXTI falling trigger selection register ===> 下降沿触发选择寄存器,EXTI_FTSR1[9] = 1,EXTI_FTSR1[7] = 1,EXTI_FTSR1[8] = 1
	EXTI->FTSR1 |= (0x1 << extinum);
	//3、设置中断屏蔽寄存器,EXTI_IMR1[9] = 1,EXTI_IMR1[7] = 1,EXTI_IMR1[8] = 1
	EXTI->C1IMR1 |= (0x1 << extinum);
}

void hal_gic_init(unsigned int interruptid,unsigned int priority) 	//GIC章节初始化
{
//1.GICD章节初始化
//设置GICD层组0使能, GICD control register (GICD_CTLR):  GICD_CTLR[0] = 1
	GICD->CTRL |= 1;
//设置GICD层中断使能,GICD interrupt set-enable register x (GICD_ISENABLERx)
	//key1 ----> PF9  ----> EXTI9 ----> 中断号99 ---->  99 / 32 = 3.......3 ----> GICD_ISENABLER3[3] = 1
   	//key2 ----> PF7  ----> EXTI7 ----> 中断号97 ---->  97 / 32 = 3.......1 ----> GICD_ISENABLER3[1] = 1
    //key3 ----> PF8  ----> EXTI8 ----> 中断号98 ---->  98 / 32 = 3.......2 ----> GICD_ISENABLER3[2] = 1
	GICD->ISENABLER[interruptid / 32] |= (0x1 << (interruptid % 32));
//设置GICD层中断优先级寄存器,GICD interrupt priority register x (GICD_IPRIORITYRx)
	//key1 ----> PF9  ----> EXTI9 ----> 中断号99 ---->  99 / 4 = 24.......3 ----> GICD_IPRIORITYR24[31:27] = 0b00000
    //key2 ----> PF7  ----> EXTI7 ----> 中断号97 ---->  97 / 4 = 24.......1 ----> GICD_IPRIORITYR24[15:11]  = 0b00000
   	//key3 ----> PF8  ----> EXTI8 ----> 中断号98 ---->  98 / 4 = 24.......2 ----> GICD_IPRIORITYR24[23:19]  = 0b0000
	GICD->IPRIORITYR[interruptid / 4] &= (~(0x1f << (interruptid % 4 * 8+3)));
	GICD->IPRIORITYR[interruptid / 4] &= (~(priority << (interruptid % 4 * 8+3)));
//设置GICD层中断目标分配给CPU0,GICD interrupt processor target register x (GICD_ITARGETSRx)
	//key1 ----> PF9  ----> EXTI9 ----> 中断号99 ---->  99 / 4 = 24.......3 ----> GICD_ITARGETSR24[25:24] =  0b01 
    //key2 ----> PF7  ----> EXTI7 ----> 中断号97 ---->  97 / 4 = 24.......1 ----> GICD_ITARGETSR24[9:8]   =  0b01 
   	//key3 ----> PF8  ----> EXTI8 ----> 中断号98 ---->  98 / 4 = 24.......2 ----> GICD_ITARGETSR24[17:16]   =  0b01 
	GICD->ITARGETSR[interruptid / 4] &= (~(0x3 << (interruptid % 4 * 8)));
	GICD->ITARGETSR[interruptid / 4] |= (0x1 << (interruptid % 4 * 8));

//2.GICC章节初始化
	//设置GICC层组0使能,GICC input priority mask register (GICC_PMR),GICC_CTLR[0] = 1
	GICC->CTRL |= 1;
	//设置GICC层中断优先级寄存器,GICC control register (GICC_CTLR),GICC_PMR[7:3] = 0b11111
	GICC->PMR |= (0x1f << 3);
	//获取中断号,GICC interrupt acknowledge register (GICC_IAR)
	//清除获取到的中断号,GICC end of interrupt register (GICC_EOIR)	
}

led.c

#include "led.h"

//函数功能:GPIO引脚初始化操作
//参数1:GPIO组号
//参数2:引脚编号
//参数3:初始化内容
void hal_gpio_init(volatile gpio_t* gpiox,unsigned int pin,gpio_init_t* init)
{
	//1. 设置GPIO引脚模式
	gpiox->MODER &= (~(0x3 << (pin*2)));
	gpiox->MODER |= (init->moder << (pin*2));
	//2. 设置GPIO引脚输出类型
	gpiox->OTYPER &= (~(0x1<<pin));
	gpiox->OTYPER |= (init->otyper << pin);
	//3. 设置GPIO引脚输出速率
	gpiox->OSPEEDR &= (~(0x3 << (pin*2)));
	gpiox->OSPEEDR |= (init->ospeedr << (pin*2));
	//4. 设置GPIO引脚是否需要上下拉电阻
	gpiox->PUPDR &= (~(0x3 << (pin*2)));
	gpiox->PUPDR |= (init->pupdr << (pin*2));
}

//函数功能:GPIO引脚操作,写1点亮,写0熄灭
//参数1:GPIO组号
//参数2:引脚编号
//参数3:写的内容
void hal_gpio_write(volatile gpio_t* gpiox,unsigned int pin,gpio_status_t status)
{
	if(status == GPIO_RESET_T)	//熄灭
	{
		gpiox->ODR &= (~(0x1<<pin));
	}
	else if(status == GPIO_SET_T) 	//点亮
	{
		gpiox->ODR |= (0x1<<pin);
	}
}

do_irq.c

extern void printf(const char *fmt, ...);
unsigned int i = 0;

#include "stm32mp1xx_gic.h"
#include "stm32mp1xx_exti.h"
#include "led.h"

//中断处理函数
void do_irq(void) 
{
	//1.获取中断号 IAR[9:0]
	unsigned int interrupt_id = GICC->IAR & (0x3ff);
	//2.判断终端号,并执行相关操作......
	switch(interrupt_id)
	{
		case 99:
			printf("key1键按下\n");
			hal_gpio_write(GPIOE,GPIO_PIN_8,GPIO_SET_T);	//LED3, PE8
			//3.清除EXTI层中断挂起标志位
			EXTI->FPR1 |= (0x1 << 9);  //key1
			//4.清除GICD层中断挂起标志位
			GICD->ICPENDR[3] |= (0x1 << 3);  //ke1
			break;
		case 98:
			printf("key3键按下\n");
			hal_gpio_write(GPIOE,GPIO_PIN_10,GPIO_SET_T);	//LED1, PE10
			//3.清除EXTI层中断挂起标志位
			EXTI->FPR1 |= (0x1 << 8);  //key3
			//4.清除GICD层中断挂起标志位
			GICD->ICPENDR[3] |= (0x1 << 2);  //key3
			break;
		case 97:
			printf("key2键按下\n");
			hal_gpio_write(GPIOF,GPIO_PIN_10,GPIO_SET_T);	//LED2, PF10
			//3.清除EXTI层中断挂起标志位
			EXTI->FPR1 |= (0x1 << 7);  //key2
			//4.清除GICD层中断挂起标志位
			GICD->ICPENDR[3] |= (0x1 << 1);  //key2
			break;	
	}

	//5.清除中断号
	GICC->EOIR = interrupt_id;
	
}

main.c

#include "key3.h"
#include "led.h"
extern void printf(const char *fmt, ...);
void delay_ms(int ms)
{
	int i,j;
	for(i = 0; i < ms;i++)
		for (j = 0; j < 1800; j++);
}

int main()
{
	RCC_MP_AHB4ENSETR |= (0x3<<4);	//使能GPIOE/GPIOF组
	gpio_init_t init = {OUTPUT,PP,LOWSPEED,NO_PUPDR};  //初始化GPIO结构体
 
	//初始化LED灯
	hal_gpio_init(GPIOE,GPIO_PIN_10,&init);	//LED1, PE10
	hal_gpio_init(GPIOF,GPIO_PIN_10,&init);	//LED2, PF10
	hal_gpio_init(GPIOE,GPIO_PIN_8,&init);	//LED3, PE8

	hal_exti_init(EXTI9,0x05, EXTI_FALLING_TRIGGER) ; //key1初始化
	hal_exti_init(EXTI7,0x05, EXTI_FALLING_TRIGGER) ; //key2初始化
	hal_exti_init(EXTI8,0x05, EXTI_FALLING_TRIGGER) ; //key3初始化
	hal_gic_init(99,9);
	hal_gic_init(97,7);
	hal_gic_init(98,8);

	while(1)
	{	

	}
	return 0;
}

运行结果:

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

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

相关文章

每日两题 203移除链表元素 104二叉树的最大深度

203 题目 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5]示例 2&#xff1a; 输入…

【ES】笔记-迭代器

迭代器概念 迭代器(Iterator)是一种接口&#xff0c;为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口&#xff0c;就可以完成遍历操作。 ES6 创造了一种新的遍历命令for…of循环&#xff0c;Iterator接口主要供for…of消费原生具备iterator接口的…

Kubernetes(K8S) kubesphere 介绍

官网地址&#xff1a;https://kubesphere.com.cn/ KubeSphere 是个全栈的Kubernetes容器云PaaS解决方案 KubeSphere 是在目前主流容器调度平台 Kubernetes 之上构建的企业级分布式多租户容器平台&#xff0c;提供简单易用的操作界面以及向导式操作方式&#xff0c;在降低用户使…

数据封装与解封装过程

2.2数据封装与解封装过程(二) 如果网络世界只有终端设备&#xff0c;那么将不能称之为网络。正因为有很多中转设备才形成了今天如此复杂的Internet网络&#xff0c;只不过一贯作为网络用户的我们没有机会感知它们的存在&#xff0c;这都是传输层的“功劳”&#xff0c;由于传输…

【C语言】自定义数据类型:枚举+共用体

前言 之前我们学习了自定义数据类型里的结构体&#xff0c;还顺带着学习了位段 今天&#xff0c;我们就来学习枚举和共用体&#xff0c;我们开始吧 自定义类型&#xff1a;结构体 位段详解 枚举 枚举就是一一列举 枚举类型的定义 枚举类型的创建 enum Day {mon,//此处是…

【前端从0开始】JavaSript——自定义函数

函数 函数是一个可重用的代码块&#xff0c;用来完成某个特定功能。每当需要反复执行一段代码时&#xff0c;可以利用函数来避免重复书写相同代码。函数包含着的代码只能在函数被调用时才会执行&#xff0c;就可以避免页面载入时执行该脚本在JavaScript中&#xff0c;可以使用…

ChatGpt开源项目完美运行配置(ChatGml2)

&#xff08;以下所有软件均可免费在网盘获取。&#xff09; 任务描述 本节任务是安装和配置chatgpt项目所需的软件以及chatgpt项目所需要的python库包&#xff0c;同时编写python代码来完成chatgpt项目的人机对话功能。 实验工具 显卡GTX1070&#xff08;专用内存需要大于等…

map和set等关联式容器特性

1. 关联式容器 在初阶阶段&#xff0c;我们已经接触过 STL 中的部分容器&#xff0c;比如&#xff1a; vector 、 list 、 deque 、 forward_list(C11) 等&#xff0c;这些容器统称为序列式容器&#xff0c;因为其底层为线性序列的数据结构&#xff0c;里面 存储的是元素本身…

2023河南萌新联赛第(六)场:河南理工大学 L - 阴晴不定的大橘学长

2023河南萌新联赛第&#xff08;六&#xff09;场&#xff1a;河南理工大学 L - 阴晴不定的大橘学长 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld 题目描述 在通往院楼的道路上&a…

Android学习之路(9) Intent

Intent 是一个消息传递对象&#xff0c;您可以用来从其他应用组件请求操作。尽管 Intent 可以通过多种方式促进组件之间的通信&#xff0c;但其基本用例主要包括以下三个&#xff1a; 启动 Activity Activity 表示应用中的一个屏幕。通过将 Intent 传递给 startActivity()&…

【SQL应知应会】索引(三)• MySQL版:聚簇索引与非聚簇索引;查看索引与删除索引;索引方法

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习&#xff0c;有基础也有进阶&#xff0c;有MySQL也有Oracle 索引 • MySQL版 前言一、索引1.简介2.索引类型之逻…

Struts vs. Struts 2:Java Web 开发框架的升级之路与竞争力分析

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

算法 | 活用双指针完成复写零操作

Problem: 1089. 复写零 文章目录 题目解析算法原理分析找到最后一个复写的位置从后往前进行复写操作 代码展示 题目解析 首先我们来分析一下本题的题目意思 可以看到题目中给到了一个数组&#xff0c;意思是让我们将数组中的零元素都复写一遍&#xff0c;然后将其余的元素向后平…

VMware和ubuntu配置Hadoop环境

本博客主要是为了学校课程”大数据与云计算“需要安装Hadoop而写&#xff0c;希望这篇博客对各位阅读这篇博客的人有所帮助。废话不多说&#xff0c;下面直接开始配置教程。 一、获取VMware安装包 VMware获取方法有很多种&#xff0c;这里我准备了官网获取和从我准备的资料中获…

jstat -gcutil PID命令分析

jstat -gcutil命令打印出的数据可以用来分析Java应用程序的垃圾回收情况。 jstat -gcutil命令打印出的数据可以用来分析Java应用程序的垃圾回收情况。该命令输出的数据包括以下几个关键指标&#xff1a;- S0&#xff1a;幸存者空间0&#xff08;Survivor Space 0&#xff09;的…

详解I/O多路转接模型:select poll epoll

文章技术分享思路&#xff1a;从select模型开始&#xff0c;先了解select模型的理论基础&#xff0c;然后编写简单的基于select的tcp服务器&#xff0c;接着分析出select的特点和缺点。引出poll模型&#xff0c;了解了poll模型的基础理论&#xff0c;编写简单的基于poll的tcp服…

十二、执行引擎

这里写自定义目录标题 一、执行引擎概述二、Java代码的编译和执行的流程三、机器码、指令、汇编语言四、解释器五、JIT编译器 一、执行引擎概述 二、Java代码的编译和执行的流程 三、机器码、指令、汇编语言 高级语言 四、解释器 五、JIT编译器

Wlan——Wlan服务集与Wlan漫游的概念

目录 Wlan服务集的基本概念 无线漫游基本概念 无线漫游的分类 无线漫游的数据转发路径 二层本地转发漫游 三层本地转发漫游 二/三层集中转发漫游 无线漫游注意事项 Wlan服务集的基本概念 概念 全称 描述 BSS 基本服务集BSS 无线网络的基本服务单元 可以理解为1个A…

【0822作业】定义一个学生的结构体,设置私有权限,共有函数实现赋值并输出

定义一个学生的结构体&#xff0c;包含学生的姓名&#xff0c;年龄&#xff0c;成绩&#xff0c;性别&#xff0c;学生的成绩&#xff0c;姓名&#xff0c;定义为私有权限&#xff1b;定义一个学生类型的结构体变量&#xff0c;设置公有函数用于给学生的成绩和名字进行赋值&…

Ajax 请求到底应该放在 created 里还是 mounted 里???

示例代码 定义了一个数据 list&#xff0c;默认是空数组 定义了一个 API 请求&#xff0c;getDat 还定义了两个生命周期钩子 created 和 mounted 分析在 created 里的情况 这个时候&#xff0c;我们是能够成功发送 API 请求获取到数据的&#xff0c;控制台会打印 created&…