04:(寄存器开发)使用外部中断按键控制LED

news2024/10/5 1:39:12

寄存器开发

  • 1、选择外部引脚配置
  • 2、上升沿触发/下降沿触发
  • 3、NVIC的配置
  • 4、完整代码

关于外部中断的AFIO,NVIC的基础知识请参考《stm32标准库入门教程》
链接: link

1、选择外部引脚配置

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
如上图所示:外部中断配置寄存器AFIO_EXTICR(1~4)中选择EXTI(0 ~ 15),在选择好的EXTI中填入对应的数值选择引脚。

本次实验:我们需要对引脚PB0进行外部中断检测,来控制LED灯的亮灭,则选择的寄存器是外部中断配置寄存器1(AFIO_EXTICR1),选择寄存器中的位0~位3(EXTI0)填入数值0001(选择PB0)

实物连接如下图所示:
在这里插入图片描述
具体的配置代码如下:

/* 1. 开启时钟:GPIOB和AFIO */
/* 1.1 GPIOB */
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; 

/* 1.2 AFIO */
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; 

/* 2. 将GPIOB0配置为上拉输入:MODE = 00,CNF = 10,上拉:ODR = 1 */
GPIOB->CRL &= ~GPIO_CRL_MODE0;
GPIOB->CRL &= ~GPIO_CRL_CNF0_0;
GPIOB->CRL |= GPIO_CRL_CNF0_1;
GPIOB->ODR |= GPIO_ODR_ODR0;//ODR = 1:表示上拉

/* 3. 配置AFIO ,选用EXTI0*/
AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI0_PB;//其中EXTIR[0]是EXTIR数组的第一个元素,
										 //AFIO_EXTICR1_EXTI0_PB = 0001

2、上升沿触发/下降沿触发

在这里插入图片描述
在这里插入图片描述

/* 1. 配置EXTI:下降沿触发,使能EXTI中断屏蔽 */
EXTI->FTSR |= EXTI_FTSR_TR0;//配置为下降沿触发
EXTI->IMR |= EXTI_IMR_MR0;//使能EXTI开关,只有使能这个开关中断信号才能传递到NVIC

3、NVIC的配置

NVIC是中断管理器,将请求来的中断进行优先级分组等操作。NVIC和RCC是处于CPU内部,挂载在系统总线SYSCLK上面的,单片机一上电SYSCLK的时钟信号都开启了的,所以不需要我们在用代码开启时钟,关于总线时钟可以参考《stm32标准库入门教程》中的时钟树那一篇。
由于NVIC在参考手册里面没有关于它的寄存器介绍,但是在core_cm3.c的文件里面有关于NVIC的配置函数,如下图所示:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述其中中断源的来源如下图所示:
在这里插入图片描述

/* 5. 配置NVIC  */
/* 5.1 优先级分组*/
NVIC_SetPriorityGrouping(0x04);//设置4位抢占优先级,0位子优先级

/* 5.2 优先级赋值*/
NVIC_SetPriority(EXTI0_IRQn,0);

/* 5.3 使能中断源请求*/
NVIC_EnableIRQ(EXTI0_IRQn);

综上的分析:总结的外部中断的大体结构如下图所示:

在这里插入图片描述

4、完整代码

①Key.c的文件代码如下:

#include "stm32f10x.h"                  // Device header
#include "Key.h"  
#include "LED.h"
#include "Delay.h"
/*
 * 引脚的初始化:
 * 1、给按键对应的引脚IO口工作模式:上拉输入
 * 2、配置AFIO(复用外部中断)
 * 3、配置EXTI(外部中断控制器)
 * 4、配置NVIC
 */
 
 void Key_EXTI_Init(void)
 {
   /* 1. 开启时钟:GPIOB和AFIO */
   /* 1.1 GPIOB */
   RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; 
   /* 1.2 AFIO */
   RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; 
   
   /* 2. 将GPIOB0配置为上拉输入:MODE = 00,CNF = 10,上拉:ODR = 1 */
   GPIOB->CRL &= ~GPIO_CRL_MODE0;
   GPIOB->CRL &= ~GPIO_CRL_CNF0_0;
   GPIOB->CRL |= GPIO_CRL_CNF0_1;
   
   GPIOB->ODR |= GPIO_ODR_ODR0;//ODR = 1:表示上拉
   
   /* 3. 配置AFIO ,选用EXTI0*/
   AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI0_PB; 
   
   /* 4. 配置EXTI:下降沿触发,使能EXTI中断屏蔽 */
   EXTI->FTSR |= EXTI_FTSR_TR0;
   EXTI->IMR |= EXTI_IMR_MR0;
   
   /* 5. 配置NVIC  */
   /* 5.1 优先级分组*/
   NVIC_SetPriorityGrouping(0x04);
   /* 5.2 优先级赋值*/
   NVIC_SetPriority(EXTI0_IRQn,0);
   /* 5.3 使能中断请求*/
   NVIC_EnableIRQ(EXTI0_IRQn);
 }
 
 
 /*
  * 中断服务函数:按下按键时,执行一次中断函数
  */
void EXTI0_IRQHandler(void)
{
  /* 除中断挂起标志位 */
  EXTI->PR |= EXTI_PR_PR0;
  
  Delay_ms(10);//在中断里面添加延迟是不被允许的,但是这里是学习中断,我们忽略
  
  if((GPIOB->IDR & GPIO_IDR_IDR0) != 0)//检测输入引脚是否被真的按下
  {
    //不等于0说明还在抖动
  }
  else
  {
    /* LED0翻转 */
    LED_Turn(LED0);
  }
}

②LED.c文件的代码如下:

#include "stm32f10x.h"                  // Device header
#include "LED.h"

/*
 * PA0~PA7引脚的初始化
 */
void LED_Init(uint32_t PA_x)
{
	/* 1. 打开GPIOA的时钟 */
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
	
	/* 2. 将PA0~PA7配置为通用输出开漏模式  */
	if(PA_x != PA_ALL)
	{
		GPIOA->CRL |= PA_x; 
		GPIOA->CRL &= ~(PA_x << 2);
	}else{
		GPIOA->CRL |= PA_ALL;
		GPIOA->CRL &= PA_ALL;
	}
}

/*
 * 点亮LEDx
 */
void LED_ON(uint16_t LEDx)
{
	GPIOA->ODR |= LEDx;
}


/*
 * 熄灭LEDx
 */
void LED_OFF(uint16_t LEDx)
{
	GPIOA->ODR &= ~LEDx;
}


/*
 * 翻转LEDx
 */
void LED_Turn(uint16_t LEDx)
{
	/* 如果是关闭那么就打开,如果是打开那么就关闭 */
	if((GPIOA->ODR & LEDx) == 0)//关闭
	{
		LED_ON(LEDx);
	}else{
		LED_OFF(LEDx);
	}
}

③LED.h的文件代码如下:

#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"                  // Device header

#define PA_0  0x00000003 //GPIO_CRH_MODE0
#define PA_1  0x00000030 //GPIO_CRH_MODE1
#define PA_2  0x00000300 //GPIO_CRH_MODE2
#define PA_3  0x00003000 //GPIO_CRH_MODE3
#define PA_4  0x00030000 //GPIO_CRH_MODE4
#define PA_5  0x00300000 //GPIO_CRH_MODE5
#define PA_6  0x03000000 //GPIO_CRH_MODE6
#define PA_7  0x30000000 //GPIO_CRH_MODE7
#define PA_ALL  0x33333333 //GPIO_CRH_MODE

#define LED0 GPIO_ODR_ODR0
#define LED1 GPIO_ODR_ODR1
#define LED2 GPIO_ODR_ODR2
#define LED3 GPIO_ODR_ODR3
#define LED4 GPIO_ODR_ODR4
#define LED5 GPIO_ODR_ODR5
#define LED6 GPIO_ODR_ODR6
#define LED7 GPIO_ODR_ODR7

void LED_Init(uint32_t PA_x);
void LED_ON(uint16_t LEDx);
void LED_OFF(uint16_t LEDx);
void LED_Turn(uint16_t LEDx);

#endif

④主函数文件的代码如下:

#include "stm32f10x.h"                
#include "Delay.h"
#include "LED.h"
#include "Key.h"

/*
	使用外部中断按键控制LED
*/
int main(void)
{
	LED_Init(PA_0);//初始化PA0引脚
	Key_EXTI_Init();//初始化PB0引脚的EXTI
  
	while(1)
	{
        
	}
}

实物演示效果如下:

外部中断

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

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

相关文章

开源模型应用落地-模型微调-模型研制-环境准备(一)

一、前言 在自然语言处理&#xff08;NLP&#xff09;的快速发展中&#xff0c;语料采集作为基础性的步骤显得尤为重要。它不仅为机器学习模型提供了所需的训练数据&#xff0c;还直接影响模型的性能和泛化能力。随着数据驱动技术的不断进步&#xff0c;如何有效并高效地收集、…

链式前向星(最通俗易懂的讲解)

链式前向新&#xff1a;用于存储图的 边集 数组 前言 当我们存储图的时候&#xff0c;往往会使用 邻接矩阵 或是 邻接表。 邻接矩阵 好写&#xff0c;但太浪费空间&#xff0c;节点一多就存不下&#xff1b; 邻接表 效率高&#xff0c;但涉及指 &#xff0c;不好写容易出错…

大语言模型入门(三)——提示词编写注意事项

一、提示词编写原则 提示词的编写应当遵循两个原则&#xff0c; 一个是指令必须清晰且具体&#xff0c;另一个是应当给模型充足的时间去思考。首先&#xff0c;你的指令足够清晰和具体&#xff0c;才能让大模型明确你需要它执行的任务&#xff0c;从而降低我们得到无关或者不正…

C# 入坑JAVA 潜规则 注解 列表 listMch,该列表存储了一个映射(Map)的集合 等 入门系列3

java注解 好像和C# 特性 差不多 Data Builder NoArgsConstructor AllArgsConstructor 在Java中&#xff0c;Data、Builder、NoArgsConstructor和AllArgsConstructor是Lombok库提供的注解&#xff0c;它们用于简化Java对象的创建和处理。Lombok是一个流行的Java库&#xff0c;…

java部分总结

一、Java语言发展简史 Java 语言源于 1991 年 4 月&#xff0c; Sun 公司 James Gosling 博士 领导的绿色计划 (Green Project) 开始启动&#xff0c;此计划最 初的目标是开发一种能够在各种消费性电子产品( 如机顶盒、冰箱、收音机等 ) 上运行的程序架构。这个就是 Jav…

基于Pulid-Flux一致性换脸

Pulid-Flux 简介 Pulid-Flux是风格一致性保持和迁移组件&#xff0c;是字节Pulid团队继SDXL的Pulid版本沉淀基础上再次出发布的PuLID-FLUX-v0.9.0 Flux版本风格一致性组件。能够提供了一个无需调整的身份ID一致性和定制化解决方案&#xff0c;能够被应用于风格一致性保持领域包…

如何写出更牛的验证激励

前言 芯片验证是为了发现芯片中的错误而执行的过程&#xff0c;它是一个破坏性的过程。完备的验证激励可以更有效地发现芯片错误&#xff0c;进而缩短验证周期。合格的验证激励必须能产生所有可能的验证场景(完备性)&#xff0c;包括合法和非法的场景&#xff0c;并保持最大的…

Stable Diffusion绘画 | 来训练属于自己的模型:炼丹启动

经过前面几轮辛苦的准备工作之后&#xff0c;现在开始进入终篇的炼丹环节。 在「上传素材」页面&#xff0c;点击「开始训练」&#xff1a; 可以在「查看进度-进度」中&#xff0c;查看模型训练的整体进度&#xff1a; 求助&#xff01;&#xff01;&#xff01;操作「开始训练…

date:10.4(Content:Mr.Peng)( C language practice)

void reverse(char* p, int len) {char* left p;char* right p len - 2;while (left < right){char* temp left;*left *right;//当*left*right后&#xff0c;*temp已经被改为f了*right *temp;//你再*temp赋值给*right时&#xff0c;已经没用了left;right--;}}int main…

前端学习第三天笔记 JavaScript JavaScript的引入 数据类型 运算符 条件语句 字符串

这里写自定义目录标题 JavaScriptJavaScript引入到文件嵌入到HTML文件中引入本地独立js文件引入网络来源文件 JavaScript的注释方式嵌入在HTML文件中的注释JavaScript的输出方式数据类型原始类型&#xff08;基础类型&#xff09;合成类型&#xff08;复合类型&#xff09; 运算…

Github优质项目推荐-第二期

文章目录 Github优质项目推荐 - 第二期一、【hello-algo】&#xff0c;96.1k stars - 算法与数据结构动画图解二、【tabby】&#xff0c;58.6k stars - ssh工具三、【mem0】&#xff0c;22.1k stars - 大模型长期记忆四、【HivisionIDPhotos】&#xff0c;10.6k stars - AI证件…

多智能体协作强化学习中的知识共享

本文提出了一种名为谨慎乐观知识共享&#xff08;CONS&#xff09;的新方法&#xff0c;用于解决合作多智能体强化学习&#xff08;MARL&#xff09;中的知识共享问题。针对传统的行动建议方法可能导致团队探索受阻的情况&#xff0c;即经验丰富的智能体会分享其知识而较不成熟…

【C++算法】10.滑动窗口_长度最小的子数组

文章目录 题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a;图解 题目链接&#xff1a; 209. 长度最小的子数组 题目描述&#xff1a; 解法 解法一&#xff1a;暴力求解&#xff08;会超时&#xff09; 暴力枚举出所有子数组的和。 查找子数组n2&#xff0…

03:(寄存器开发)OLED的简单使用

OLED的简单使用 将江科大的标准库开发OLED的代码进行移植&#xff0c;修改的部分代码如下&#xff1a; /*引脚配置*/ //#define OLED_W_SCL(x) GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)(x)) //#define OLED_W_SDA(x) GPIO_WriteBit(GPIOB, GPIO_Pin_9, (BitAction)(x))…

mybatis-plus使用总结

基本使用 mybatis-plus依赖 <!-- mybatis-plus开始 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.7</version></dependency><dependency>&l…

D27【 python 接口自动化学习】- python 基础之判断与循环

day27 判断和循环中常见错误 学习日期&#xff1a;20241004 学习目标&#xff1a;判断与循环&#xfe63;-38 避坑指南&#xff1a;判断和循环中的常见错误 学习笔记&#xff1a; 循环过程中改变遍历次数 遍历中修改列表导致误操作 循环嵌套中的缩进导致运行语句有差别 总结…

17 链表——21. 合并两个有序链表 ★

17 链表 21. 合并两个有序链表 将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入:l1 = [1,2,4], l2 = [1,3,4] 输出:[1,1,2,3,4,4] 算法设计: 合并两个有序链表,并保持有序性,可以采用迭代法和递归法两种…

小白必看web专题!渗透测试还是src?

大家好&#xff0c;我是Dest1ny&#xff01; 今天是回答问题的&#xff0c;有小伙伴私信我&#xff1a; 渗透测试还是src&#xff1f; 今天回答一下&#xff01; 渗透测试&#xff08;Penetration Testing&#xff09;&#xff1a; 渗透测试是一种模拟真实攻击者的技术手段&…

Vue3+TS项目 - ref和useTemplateRef获取组件实例

在Vue2中&#xff0c;子组件使用的是选项式 API &#xff0c;被引用的组件实例和该子组件的 this 完全一致&#xff0c;这意味着父组件对子组件的每一个属性和方法都有完全的访问权。这使得在父组件和子组件之间创建紧密耦合的实现细节变得很容易&#xff0c;当然也因此&#x…