stm32外部中断的简单理解与操作简单范例——按键控制LED翻转

目录

0        前言

1        必要的概念介绍

(1)中断源及其中断向量

(2)外部中断系统结构

(3)中断优先级控制

2        外部中断使用流程配置

(1)NVIC设置

(2)中断端口的配置

(3)中断处理 

3       程序的实现 

 bsp_exti

 bsp_led

中断服务及其返回

主函数

代码资源包 (下载)


0        前言

        STM32F10x最多有84个中断,包括16个内核中断和68个可屏蔽中断,具有16个可屏蔽中断优先级。

        下文我所用的STM32F103系列具有60个可屏蔽中断。

1        必要的概念介绍

(1)中断源及其中断向量

          STM32F103中断系统提供10个系统异常和60个可屏蔽中断,具有16个可屏蔽中断优先级。

          可屏蔽中断源包括外部中断、定时器中断、串口中断、直接内存访问中断(DMA)、模数转换中断(A/D)、集成电路总线中断、串口外设接口中断等。

        其中,本帖子用到的外部中断由嵌套向量中断控制器NVIC和外部中断/事件控制器EXTI来控制。

(2)外部中断系统结构

查看源图像

        中断/事件请求可以来源于芯片引脚输入的外部中断/事件,也可以通过软件在软件中断寄存器写1,来产生一个中断/事件请求。(对应上图3号或门

         外部中断/事件信号从芯片引脚输入,经过边沿检测电路处理后,与软件中断事件寄存器通过或门进入。然后进入挂起请求寄存器,最后与中断屏蔽寄存器相与输出到嵌套向量中断控制器NVIC。

                               

        从GPIO端口与外部中断/事件的映射关系来看,每一组相同编号的GPIO端口都被映射到同一个外部中断/事件寄存器中。

(3)中断优先级控制

         STM32的中断向量有两个属性,抢占属性和响应属性(属性编号越小,优先级越高),其优先级由中断优先级寄存器IPR控制

0组对应的是0位抢占优先级(父优先级),4位响应优先级(子优先级)。那么无抢占优先级,响应优先级可以设置为0-15级的任意一种

1组对应的是1位抢占优先级(父优先级),2位响应优先级(子优先级)。那么抢占优先级设置为0与1级的任意一种,响应优先级可以设置为0-7级的任意一种.

以此类推

当然,我们判断的时候先看抢占优先级,如果抢占优先级相同再看响应优先级的高低,如果再相同就看中断通道的向量地址。

2        外部中断使用流程配置

(1)NVIC设置

        首先对中断优先级进行分组,确定父子优先级的个数 

        选择中断通道(不同的优先级对应不同的中断通道,在stm32f10x.h头文件中定义了中断通道结构体IRQn_Type)

        根据系统要求设置中断父子优先级

        使能相应的中断,完成NVIC配置

                        

 

(2)中断端口的配置

         首先进行GPIO配置

         然后对外部中断方式进行配置(包括中断线路配置、中断或事件的选择、触发方式的设置、使能中断线)

(3)中断处理 

         1 中断请求

         2 中断响应

         3 中断服务程序

         4  中断返回

void EXTI0_IRQHandler(void)
{
  if(RESET != EXTI_GetFlagStatus(EXTI_Line0))      //判断中断标志位
  {
    LED_G_TOGGLE;//中断服务内容
    EXTI_ClearFlag(EXTI_Line0);                     //清除
  }
}

3        程序的实现 

         首先我实现的是用按键控制LED灯的翻转,我的板子上面有两个按键,我也就写了两个按键

         bsp_exti

                头文件 

#ifndef __BSP_EXTI_H
#define __BSP_EXTI_H

#include "stm32f10x.h"

#define KEY1_INT_GPIO_PIN				GPIO_Pin_0
#define KEY1_INT_GPIO_PORT			    GPIOA
#define KEY1_INT_GPIO_CLK				RCC_APB2Periph_GPIOA
#define KEY2_INT_GPIO_PIN				GPIO_Pin_13
#define KEY2_INT_GPIO_PORT			    GPIOC
#define KEY2_INT_GPIO_CLK				RCC_APB2Periph_GPIOC




#endif /*__BSP_EXTI_H*/

 bsp_exti函数

#include "bsp_exti.h"


/*============NVIC设置===================
  ============中断端口配置================
  ============中毒那处理==================*/


static void EXTI_NVIC_Config()
{
	/*====3====初始化NVIC处理中断*/
	NVIC_InitTypeDef	NVIC_Initstruct;									//声明NVIC初始化结构体
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);							//选择中断分组

	NVIC_Initstruct.NVIC_IRQChannel = EXTI0_IRQn;							//选择中断通道
	NVIC_Initstruct.NVIC_IRQChannelPreemptionPriority = 1;					//抢占优先级(父优先级)
	NVIC_Initstruct.NVIC_IRQChannelSubPriority = 1;							//响应优先级 (子优先级)
	NVIC_Initstruct.NVIC_IRQChannelCmd = ENABLE;							//使能

	NVIC_Init(&NVIC_Initstruct);											//调用初始化函数完成配置
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	NVIC_Initstruct.NVIC_IRQChannel = EXTI15_10_IRQn;							//选择中断通道
	NVIC_Initstruct.NVIC_IRQChannelPreemptionPriority = 1;					//抢占优先级(父优先级)
	NVIC_Initstruct.NVIC_IRQChannelSubPriority = 2;							//响应优先级 (子优先级)
	NVIC_Initstruct.NVIC_IRQChannelCmd = ENABLE;							//使能

	NVIC_Init(&NVIC_Initstruct);											//调用初始化函数完成配置
}


void EXTI_Key_Config()
{
	GPIO_InitTypeDef	GPIOI_Initstruct;                                   //声明GPIO初始化结构体
	EXTI_InitTypeDef	EXTI_Initstruct;									//声明EXTI初始化结构体

	//配置终端优先级
	EXTI_NVIC_Config();

	/*====1=====初始化GPIO*/
	RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE); 					//开时钟                	
	GPIOI_Initstruct.GPIO_Pin = KEY1_INT_GPIO_PIN;                        //选择GPIO引脚 
  	GPIOI_Initstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;                     //模式为浮空输入(按键)
	GPIO_Init(KEY1_INT_GPIO_PORT, &GPIOI_Initstruct);                     //GPIO初始化函数

	RCC_APB2PeriphClockCmd(KEY2_INT_GPIO_CLK,ENABLE); 					//开时钟                	
	GPIOI_Initstruct.GPIO_Pin = KEY2_INT_GPIO_PIN;                        //选择GPIO引脚 
  	GPIOI_Initstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;                     //模式为浮空输入(按键)
	GPIO_Init(KEY2_INT_GPIO_PORT, &GPIOI_Initstruct);                     //GPIO初始化函数

	/*====2====初始化EXTI产生中断*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);					//开时钟
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);			//选择中断输入线(中断引脚)
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);			//选择中断输入线(中断引脚)

	EXTI_Initstruct.EXTI_Line = EXTI_Line0 | EXTI_Line13;								//产生中断线路
	EXTI_Initstruct.EXTI_Mode = EXTI_Mode_Interrupt;					//选择中断模式
	EXTI_Initstruct.EXTI_Trigger = EXTI_Trigger_Falling;					//触发方式------上升沿
	EXTI_Initstruct.EXTI_LineCmd = ENABLE;								//使能
	EXTI_Init(&EXTI_Initstruct);										//exti初始化函数


	

}

                bsp_led

                                头文件 

#ifndef __BSP_LED_H
#define __BSP_LED_H

#include "stm32f10x.h"

#define LED_G_GPIO_PIN      GPIO_Pin_0
#define LED_B_GPIO_PIN      GPIO_Pin_1
#define LED_R_GPIO_PIN      GPIO_Pin_5
#define LED_G_GPIO_PORT     GPIOB
#define LED_R_GPIO_PORT     GPIOB
#define LED_G_TOGGLE    {LED_G_GPIO_PORT->ODR ^= LED_G_GPIO_PIN;}
#define LED_R_TOGGLE    {LED_R_GPIO_PORT->ODR ^= LED_R_GPIO_PIN;}
void LED_GPIO_Config(void);

#endif  /*__BSP_LED_H*/

 函数

#include "bsp_led.h"

void LED_GPIO_Config(void)
{
	GPIO_InitTypeDef  GPIOI_Initstruct;                                   //初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);                 	//打开ABP2时钟
	
	GPIOI_Initstruct.GPIO_Pin=LED_G_GPIO_PIN;                             //选PIN绿led
  	GPIOI_Initstruct.GPIO_Mode=GPIO_Mode_Out_PP;                          //模式为推挽输出
	GPIOI_Initstruct.GPIO_Speed=GPIO_Speed_50MHz;                         //速度50MHZ
	GPIO_Init(GPIOB, &GPIOI_Initstruct);                                   //GPIO初始化函数
	
	GPIOI_Initstruct.GPIO_Pin=LED_R_GPIO_PIN;                             //选PIN R led
  	GPIOI_Initstruct.GPIO_Mode=GPIO_Mode_Out_PP;                          //模式为推挽输出
	GPIOI_Initstruct.GPIO_Speed=GPIO_Speed_50MHz;                         //速度50MHZ
	GPIO_Init(GPIOB, &GPIOI_Initstruct);                                   //GPIO初始化函数
 	
	LED_R(OFF);LED_G(OFF);
}

中断服务及其返回

void EXTI0_IRQHandler(void)
{
  if(RESET != EXTI_GetFlagStatus(EXTI_Line0))      //判断中断标志位
  {
    LED_G_TOGGLE;//中断服务内容
    EXTI_ClearFlag(EXTI_Line0);                     //清除
  }
}

主函数

#include "stm32f10x.h"      //相当于51的 #include<reg52.h>

#include "bsp_led.h"
#include "bsp_exti.h"
void delay(uint32_t count)
{
	for(;count!=0;count--);
}

int main(void)
{
    //在这里系统的函数已经被配置成72M
  LED_GPIO_Config();
  EXTI_Key_Config();
	
	while(1)
	{
	  
	}
}

代码资源包 (下载)

https://download.csdn.net/download/m0_58193842/86627026

                

                          

                               

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨CX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值