当前位置: 首页 > news >正文

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

寄存器开发

  • 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内部,挂载在系统总线AHB上面的,单片机一上电AHB的时钟信号都开启了的,所以不需要我们在用代码开启时钟,关于总线时钟可以参考《stm32标准库入门教程》中的时钟树那一篇。
由于NVIC在参考手册里面没有关于它的寄存器介绍,但是在core_cm3.c的文件里面有关于NVIC的配置函数,如下图所示:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述其中中断源的来源如下图所示:
在这里插入图片描述
由上图得出,中断源和下图的中断向量表的排序是一比一对应的。
在这里插入图片描述
在这里插入图片描述
如上图中断向量表所示:表中黑色部分的中断源是由CPU内部产生的,而其他的都是由片上外设产生的,若没有配置NVIC的优先级,那么则按照表中的默认优先级进行执行中断。其他黑色部分的中断源来自于CPU内部,则无需在使能NVIC_EnableIRQ(),因为只有前面位置值为正数才需要使能NVIC_EnableIRQ()。
在这里插入图片描述

/* 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_ODR7void 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引脚的EXTIwhile(1){}
}

实物演示效果如下:

外部中断


http://www.mrgr.cn/news/43096.html

相关文章:

  • Lucene最新最全面试题及参考答案
  • 【JAVA开源】基于Vue和SpringBoot的服装生产管理系统
  • 在线计算FOC的kp ki
  • 数据驱动引领企业数字化转型——The Open Group 2024年度大会即将召开
  • 如何快速切换电脑的ip地址
  • 【pytorch】张量求导4
  • 我的第一个创作纪念日-128天
  • 家具行业数字化转型利器:三品PLM系统全生命周期管理方案
  • 动态规划基础1
  • MySQL的联合索引测试
  • LeNet学习
  • 45集 ESP32 ADC按键程序编写
  • 【C语言系统编程】【第一部分:操作系统知识】1.1.操作系统原理
  • 解决TortoiseGit文件夹图标不见的问题。
  • 【CUDA】【PyTorch】安装 PyTorch 与 CUDA 11.7 的详细步骤
  • 【Conda】修复 Anaconda 安装并保留虚拟环境的详细指南
  • Shell-使用函数
  • 大学生就业服务:Spring Boot技术实践
  • Python知识点:如何使用Multiprocessing进行并行任务管理
  • docker拉取镜像推送到阿里云镜像仓库