stm32mp157——通过按键中断实现LED灯的亮灭

news2024/9/22 12:55:32
EXTI章节初始化
void hal_exit_init(EXTI编号,GPIOF组编号,中断触发方式)
调用:hal_exit_init(EXTI9,0x05,下降沿触发)
调用: hal_exit_init(EXTI7,0x05,下降沿触发)
调用: hal_exit_init(EXTI8,0x05,下降沿触发)
GIC章节初始化
void hal_gic_init(中断号,中断优先级)
调用: hal_gic_init(99,9)
调用: hal_gic_init(97,7)
调用: hal_gic_init(98,8)
实现key1/ key2/key3三个按键触发
1)打印一句话 2)灯的状态取反
key1按下之后,打印key1 press ,LED1灯状态取反
key2按下之后,打印key2 press,LED2灯状态取反
key3按下之后,打印key3 press,LED3灯状态取反
//头文件
#ifndef __KEY_H__
#define __KEY_H__

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

#define rising  1
#define falling 0
#define EXTI9 9
#define EXTI8 8
#define EXTI7 7
#define GPIO_PIN_10 10 
#define GPIO_PIN_8  8  

#define GPIO_RESET 0
#define GPIO_SET   1

//对RCC GPIO EXTI进行初始化
void hal_key_exti_init(int extix,int extix_gpiox,int status);

//对GIC进行初始化
void hal_key_gic_init(int num, int priority);

//LED初始化
void led_init(gpio_t * gpio,unsigned int pin,int gpio_status);
#endif
//功能函数

#include "key.h"
extern void printf(const char *fmt, ...);
                       //exti编号,exti对应组编号,触发方式
void hal_key_exti_init(int extix,int extix_gpiox,int status)
{
	/*******RCC章节初始化**********/
	//GPIOF组使能
	RCC->MP_AHB4ENSETR |= (0x1 << 5);

	/*******GPIO章节初始化*********/
	//设置模式为输入模式
	// key1(PF9): GPIOF_MODER[19:18] = 00   
	// key2(PF7): GPIOF_MODER[15:14] = 00    
	// key3(PF8): GPIOF_MODER[17:16] = 00 	
	GPIOF->MODER &= (~(0x3f << 14));	

	/*******EXTI章节初始化*********/
	int quotient  = extix / 4;        //商
	int remainder = extix % 4;        //余数


	//1.外部中断选择寄存器
	if (quotient == 0)       //EXTICR1
	{
		EXTI->EXTICR1 |= (extix_gpiox << remainder*8);      //余数 * 8:操作8位中的最低位	
	}
	else if(quotient == 1)   //EXTICR2
	{
		EXTI->EXTICR2 |= (extix_gpiox << remainder*8);
	}
	else if(quotient == 2)   //EXTICR3
	{
		EXTI->EXTICR3 |= (extix_gpiox << remainder*8);
	}

	//2.EXTI触发选择寄存器   	
	if(status == falling)      //下降沿触发
	{
		EXTI->FTSR1 |= (0x1 << extix);
	}
	else if(status == rising)
	{
		EXTI->RTSR1 |= (0x1 <<extix);
	}

	//3.EXTI中断屏蔽寄存器
	EXTI->C1IMR1 |= (0x1 << extix);

}

void hal_key_gic_init(int num, int priority)
{
	/********GICD初始化**********/
	//1.使能GICD层组0中断:GICD_CTLR[0] = 1
	GICD->CTRL |= (0x1 << 0);

	//2.中断设置使能寄存器	
	int quo  = num / 32;        //商
	int rem  = num % 32;        //余数
    // 商:操作哪个寄存器
    // 余数:操作寄存器的位数
    GICD->ISENABLER[quo] |= (0x1 << rem);
	
	//3.GICD层中断优先级寄存器
	quo = num / 4;
	rem = num % 4;
    //商:操作哪个寄存器
    //余数*8+3:操作寄存器的位数
	GICD->IPRIORITYR[quo] |= (0x1 << (rem*8+3));
	
	//4.GICD层中断目标分配寄存器
	
    //商:操作哪个寄存器
    //余数*8:操作寄存器的位数	
	GICD->ITARGETSR[quo] |= (0b01 << rem*8);
	
	/********GICC初始化**********/
	//1.使能GICC层组0中断:GICC_CTLR[0] = 1
	GICC->CTRL |= (0x1 << 0);
	
	//2.GICC层中断优先级屏蔽寄存器
 	//GICC_PMR[7:3] = 中断优先级值
	if(priority > 1)
	{
		GICC->PMR |= (priority << 3);
	}
	else
	{
		printf("优先级输入有误\n");
	}
}

void led_init(gpio_t * gpio,unsigned int pin,int gpio_status)
{
	//RCC初始化
	RCC->MP_AHB4ENSETR |= (0x3 << 4);  //将第4 5位置1 
                                                                   
    //设置模式01                                                      
    gpio->MODER &= (~(0x3 << (2*pin)));                               
    gpio->MODER |= (0x1 << (2*pin));                                  
                                                                      
    //设置输出类型 推挽 0                                             
    gpio->OTYPER &= ~(0x1 << pin);                                    
                                                                      
    //设置输出速度 00                                                 
    gpio->OSPEEDR &= ~(0x3 << (2 * pin));                             
                                                                      
    //设置禁止上下拉电阻 00                                           
    gpio->PUPDR &= ~(0x3 << (2 * pin));                               
                                                                      
    //判断输入的值是否为低电平                                        
    if(gpio_status == GPIO_RESET)                                     
    {                                                                 
        gpio->ODR &= (~(0x1 << pin));                                 
    }                                                                 
    else                                                              
    {                                                                 
        gpio->ODR |= (0x1 << pin);                                    
    }                                                                                                                                     
}
//中断处理函数
#include "key.h"
extern void printf(const char *fmt, ...);

void do_irq(void) 
{
	unsigned int num;
	//获取中断
	num=GICC->IAR & (0x3ff);
	
	//判断中断号
	//99---->key1----->printf(key1)
	//98---->key2
	//97---->key3
	//清除对应中断挂起的标志位
	switch (num)
	{
		case 97:
			printf("key2 press!! LED2状态取反\n");
			//清除EXTI层中断挂起标志位
			EXTI->FPR1 |= (0x1 << 7);
			//清除GICD层中断挂起标志位
			GICD->ICPENDR[3] |= (0x1 <<1);			
			//LED2状态取反
			GPIOF->ODR ^= (0x1 << 10);
			break;
		case 98:
			printf("key3 press!! LED3状态取反\n");
			//清除EXTI层中断挂起标志位
			EXTI->FPR1 |= (0x1 << 8);
			//清除GICD层中断挂起标志位
			GICD->ICPENDR[3] |= (0x1 <<2);			
			//LED3状态取反	
			GPIOE->ODR ^= (0x1 << 8);
			break;
		case 99:
			printf("key1 press!! LED1状态取反\n");
			//清除EXTI层中断挂起标志位
			EXTI->FPR1 |= (0x1 << 9);
			//清除GICD层中断挂起标志位
			GICD->ICPENDR[3] |= (0x1 <<3);			
			//LED1状态取反	
			GPIOE->ODR ^= (0x1 << 10);
	break;
	}
	//清除获取到的中断号
	GICC->EOIR = num;
}
//主函数
#include "key.h"
extern void printf(const char *fmt, ...);


int main()
{
	hal_key_exti_init(EXTI9,0x05,falling);
	hal_key_exti_init(EXTI8,0x05,falling);
	hal_key_exti_init(EXTI7,0x05,falling);
	hal_key_gic_init(99,2);
	hal_key_gic_init(98,3);
	hal_key_gic_init(97,4);

	led_init(GPIOE,GPIO_PIN_10,GPIO_RESET);
	led_init(GPIOF,GPIO_PIN_10,GPIO_RESET);
	led_init(GPIOE,GPIO_PIN_8,GPIO_RESET);
	while(1)
	{
	}

	return 0;
}

结果

 

 

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

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

相关文章

Redis - 一篇讲解根据 Key 前缀统计分析内存占用

问题描述 今天遇到一个 Redis 内存打挂了的问题&#xff0c;想看看哪个前缀 Key 占用内存比较大&#xff1f;&#xff01; 原因分析 我们都知道如果直接用 Keys 参数去做统计很危险&#xff0c;而且也只能统计数量&#xff0c;当然也可以排序去前几名的占用内存 Key 对应的大…

ESP32(掌控板) 电子琴

ESP32&#xff08;掌控板&#xff09; 电子琴 本程序实现了电子琴功能&#xff0c;通过机械按键改变变量的值实现“翻页”&#xff08;每个八度分两页&#xff0c;共六页&#xff09;&#xff0c;通过触摸按键弹奏&#xff08;包含半音&#xff09;&#xff0c;屏幕显示当前触摸…

基于微信小程序充电桩预约管理系统的设计与实现(论文+源码)_kaic

摘要 微信小程序的充电桩预约管理系统是一个复杂的系统&#xff0c;需要遵循不同的设计原则和方法&#xff0c;在实现高可用性、高性能、高安全性和高稳定性等特点的同时&#xff0c;还要注重用户体验和易用性&#xff0c;不断改进和迭代优化&#xff0c;以提高系统性能和用户满…

replicaSet,DaemonSet and Job

ReplicaSet 上一篇讲到的 ReplicationController 是用于复制和在异常的时候重新调度节点的 K8S 组件&#xff0c;后面 K8S 又引入了 ReplicaSet 资源来替代 ReplicationController ReplicationController 和 ReplicaSet 有什么区别呢&#xff1f; ReplicationController 和 …

Java中一个类可以继承多个类吗?揭秘多重继承的秘密!

大家好&#xff0c;我是你们的小米&#xff01;今天&#xff0c;我们来聊聊Java中一个备受争议的话题——"一个类可以继承多个类吗&#xff1f;"这是一个让许多Java初学者困惑的问题&#xff0c;也是一个常常被问及的热门话题。那么&#xff0c;到底Java中是否允许一…

Multi-Aspect Explainable Inductive Relation Prediction by Sentence Transformer

摘要 最近关于知识图(KGs)的研究表明,通过预先训练的语言模型授权的基于路径的方法在提供归纳和可解释的关系预测方面表现良好。本文引入关系路径覆盖率和关系路径置信度的概念,在模型训练前过滤掉不可靠的路径,以提高模型的性能。此外,我们提出了知识推理句子转换器(Know…

MySQL索引介绍及底层数据结构B+树介绍

索引 1. 索引概述1.1 索引1.2 索引的优缺点1.2.1 优点1.2.2 缺点 2. InnoDB中的索引2.1 主键索引设计方案2.2 索引底层数据结构2.3 常见索引2.3.1 聚簇索引2.3.1.1 优点2.3.1.2 缺点 2.3.2 非聚簇索引2.3.3 联合索引 3. MyISAM中的索引3.1 MyISAM 与 InnoDB对比 1. 索引概述 1…

代码随想录算法训练营第59天 | 503.下一个更大元素 II + 42.接雨水

今日任务 目录 503.下一个更大元素 II - Medium 42.接雨水 - Hard 503.下一个更大元素 II - Medium 题目链接&#xff1a;力扣-503. 下一个更大元素 II 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nu…

vmware提示此平台不支持虚拟化的Intel VT-x/EPT. 不使用虚拟化的Intel VT-x/EPT,是否继续?

当打开虚拟机时会发现弹出提示框显示不支持&#xff0c;只要检查三个步骤保证能正常使用 1、检查vmware虚拟机设置中处理器右边是否勾选虚拟化引擎 2、检查物理机中的windows组件是否冲突 打开控制面板选择程序和功能之后点击启用或关闭windows功能&#xff0c;取消Hyper-V 取…

插值算法

插值法在较少的数据模型的基础上模拟产生新的靠谱数值&#xff0c;可以用来预测。 利用已知的点建立合适的插值函数 f(x) ,未知点 x_i 由插值函数 f(x) 可以求出函数值 f(x_i) &#xff0c;用求得的 (x_i,f(x_i))近似代替未知点。 基本概念&#xff1a; yf(x)在[a,b]上有定义 x…

MySQL之概述、安装和使用(一)

一、概述 关系数据库概述&#xff1a; https://blog.csdn.net/qq_21370419/article/details/128568920 二、数据库的安装 参考我的两篇博客&#xff1a; win10 安装mysql 5.6.36版本_windows 安装mysql5.6_人……杰的博客-CSDN博客 wind 10 安装 mysql 8.0_人……杰的博客…

二十三种设计模式第十五篇--模版方法模式

模板方法模式是一种行为型设计模式&#xff0c;它定义了一个算法的骨架&#xff0c;而将一些步骤延迟到子类中实现。通过使用这种模式&#xff0c;我们可以在不改变算法结构的情况下&#xff0c;重新定义算法中的某些特定步骤。 模版方法的思想 模板方法模式的核心思想是将一…

WebDAV之π-Disk派盘 + FE文件管理器

FE File Explorer是一款功能强大且易于使用的文件管理器&#xff0c;它可以让你轻松地管理内部和外部存储器上的文件和文件夹&#xff0c;支持云存储服务&#xff0c;如派盘、Dropbox等。结合FE File Explorer和派盘可以实现更加高效便捷的文件管理体验。 π-Disk派盘 – 知识…

#systemverilog#进程控制问题#(二)终止进程

二 线程的终止 2.1 命名块 + diable Block,也就是语句块,SystemVerilog提供了两种类型的语句块,分别是begin…end为代表的顺序语句块,还有以fork…join为代表的并发语句块。 这两种block都是工程项目中常用的block,但是,大家可能都不知道block也是可以命名的,就像我…

基于Prometheus 和 Grafana 实现springboot应用监控和服务器监控

目录 1.Prometheus环境搭建 1.1 下载和安装Prometheus 1.2 配置Prometheus 1.3 配置Prometheus抓取Spring Boot应用Metrics 1.4 启动Prometheus 2.Grafana环境搭建 2.1 下载和安装Grafana 2.2 配置Grafana数据源 2.3 创建Dashboard 3、NodeExporter&#xff08;服务器…

华为云Astro出品《低代码开发者101问》电子书上线

这四年来&#xff0c;在低代码平台的运营和客户支持过程中&#xff0c;我们有幸见证了华为云低代码的成长&#xff0c;也有幸认识了很多有思想、有热情、有行动力的低代码开发者朋友&#xff0c;我们自身对低代码领域的认识和理解也在不断整合、刷新。与开发者、客户、伙伴以及…

Vue3使用混入(混合)

minixs/entity.js&#xff1a;混入代码 //混入的实体类 import { reactive } from vue;const userEntityMixin {setup() {const Admin reactive({id: -1,account: "",userPassword: "",});const Teacher reactive({id: -1,account: "",userP…

Nginx启动、关闭及信息查看命令

1、查找Nginx的位置 ps -aux | grep nginx 2、启动Nginx nginx直接启动&#xff0c;这时候可能出现两种情况&#xff1a; 第一种&#xff0c;就是Nginx已经启动过了&#xff0c;会提示端口被占用&#xff0c;启动失败 我们尝试杀掉占用端口的进程&#xff0c;然后重启 sys…

基于springboot图书个性化推荐系统的设计与实现【附ppt和万字文档(Lun文)和搭建文档】

主要功能 前台登录&#xff1a; ①首页&#xff1a;图书名称查询、图书信息推荐、好书推荐、图书信息展示 ②图书信息&#xff1a;图书类别、图书名称、名称类别作者查询、图书详情、收藏、点赞、评论 ③好书推荐&#xff1a;图书展示、点击查看 ④留言反馈&#xff1a;用户可…

爆肝整理,Docker容器测试-常见问题+解决(汇总)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 问题1&#xff1a…