STM32学习笔记4——EXTI中断

学习资料:《野火零死角玩转STM32——F103》

EXTI

EXTI——外部中断/事件控制器。可单独配置中断或者事件,及触发事件的属性(?)。

 

中断编程步骤

1.初始化产生中断的GPIO

当GPIO作为中断的输入源时(如按键按下产生中断),需要初始化GPIO,配置为输入模式。如配置GPIOC13作为输入源:

    GPIO_InitTypeDef  GPIO_InitStruct;  

	 //初始化GPIO
	RCC_APB2PeriphClockCmd(KEY2_INT_GPIO_CLK, ENABLE); 
     //KEY2_INT_GPIO_CLK为宏,即RCC_APB2Periph_GPIOC ,该库函数使能GPIOC的时钟

	GPIO_InitStruct.GPIO_Pin = KEY2_INT_GPIO_PIN;  
     //KEY2_INT_GPIO_PIN为宏,即GPIO_Pin_13,指定GPIO指针

	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
     //配置GPIO为浮点输入模式

	GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStruct); 
     //输入GPIO配置

2.初始化EXTI

类似于GPIO的初始化,EXTI的初始化也有相应的初始化结构体 EXTI_InitTypeDef,用于设置EXTI的中断/事件线、EXTI模式、触发类型。

由于EXTI有20个中断/事件线(EXTI0~EXTI19),根据不同的输入源选择不同的EXTI事件线,如下表:STM32学习笔记4——EXTI中断_第1张图片

EXTI模式可选择为中断或事件,中断触发类型可配置为上升沿触发、下降沿触发、或上升沿下降沿都触发。

EXTI初始化结构体如下:


	EXTI_InitTypeDef  EXTI_InitStruct;

	 //配置中断优先级
	EXTI_NVIC_Config();
	
	 //初始化EXTI
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
     //AFIO_EXTICRx,外部中断配置寄存器,用于选择EXTI外部中断的输入源,因此需要使能AFIO时钟
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);
     //选择GPIO指针作为中断/事件线
    EXTI_InitStruct.EXTI_Line = 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);
     //输入配置
		

3.配置NVIC

NVIC是嵌套向量中断控制器,控制芯片中断相关的功能,是内核中的外设。主要配置中断的中断源、抢占优先级、子优先级、使能中断请求。

    NVIC_InitTypeDef  NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;
	//设置中断源频道,不同中断源的中断频道不一样,其成员配置可参考 stm32f10x.h 头文件里面的 IRQn_Type 结构体定义
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //优先级分组
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;  //主优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;    //子优先级	 
	/*根据下表格设按需要设置优先级
	--------------------------------------------------------------------------
	|      优先级分组       |   主优先级     |  子优先级   |      描述         |
	--------------------------------------------------------------------------
	| NVIC_PriorityGroup_0 |      0         |     0-15   |  主-0bit,子-4bit |
	| NVIC_PriorityGroup_1 |      0-1       |     0-7    |  主-1bit,子-3bit |
	| NVIC_PriorityGroup_2 |      0-3       |     0-3    |  主-2bit,子-2bit |
	| NVIC_PriorityGroup_3 |      0-7       |     0-1    |  主-3bit,子-1bit |
	| NVIC_PriorityGroup_4 |      0-15      |     0      |  主-4bit,子-0bit |
	--------------------------------------------------------------------------*/
	
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	//使能中断请求
	NVIC_Init(&NVIC_InitStruct);
	//输入配置

 

4.编写中断服务函数

在启动文件 startup_stm32f10x_hd.s 中初始化了中断向量表。中断服务函数统一写在stm32f10x——it.c库文件中,函数名称根据中断向量表选择。

在stm32f10x_it.c文件最下方编写中断服务函数,如使用EXTI13作为中断/事件线:

void EXTI15_10_IRQHandler(void)/*EXTI15_10_IRQHandler是根据启动文件中的向量表进行选择的,
选择不对尽管编译无错误,但中断无效*/
{
   /*确保是否产生了 EXTI Line 中断,该库函数用于获取EXTI的中断标志位状态,如果EXTI线有中断,返回SET(1),否则返回RESET(0)
	    实际上该库函数是读取EXTI_PR寄存器来判断EXTI线的状态*/
	if (EXTI_GetITStatus(EXTI_Line13) != RESET)
	{
        //中断后关闭所有LED灯
		LED_ALL(OFF);
		 //清除中断标志位
		 EXTI_ClearITPendingBit(EXTI_Line13);
	 }
	
}

完整程序

在编程时,第1-3点在自定义的c文件中编写,并在其头文件中声明;第4点在stm32f10x_it.c文件中编写;主函数中包含所需要的头文件,并调用。

main.c

#include "stm32f10x.h" 
#include "bsp_led.h"   //led的控制头文件
#include "bsp_key.h"   //key的控制头文件
#include "bsp_exti.h"

 int main(void)
 {
	 

	 LED_GPIO_Config(); 
	 KEY1_GPIO_Config(); 
	 EXTI_KEY2_Config();
	 LED_ALL(OFF);
	 here:
	 while(1)
   {
	   if (KEY1_SCAN(KEY1_GPIO_PORT , KEY1_GPIO_PIN) == KEY_ON)
	   {
			 LED_ALL(OFF);
 		   LED_R(ON);
			 while(1)
			 {
			   if (KEY1_SCAN(KEY1_GPIO_PORT , KEY1_GPIO_PIN) == KEY_ON)
				 {
				   LED_ALL(OFF);
					 LED_G(ON);
					 while(1)
					 {
             if (KEY1_SCAN(KEY1_GPIO_PORT , KEY1_GPIO_PIN) == KEY_ON)		
						 {
						 LED_ALL(OFF);
					   LED_B(ON);
							 
							 
								goto here;
								
							 
						 }							 
					 }
						 
				 } 
				
			 }
				 
	   }
		 
   }
 
 }//main

bsp_exti.c

#include "bsp_exti.h"

static void EXTI_NVIC_Config(void)
{
  NVIC_InitTypeDef  NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;
	//设置中断源频道,不同中断源的中断频道不一样,其成员配置可参考 stm32f10x.h 头文件里面的 IRQn_Type 结构体定义
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //优先级分组
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;  //主优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;    //子优先级	 
	/*根据下表格设按需要设置优先级
	--------------------------------------------------------------------------
	|      优先级分组       |   主优先级     |  子优先级   |      描述         |
	--------------------------------------------------------------------------
	| NVIC_PriorityGroup_0 |      0         |     0-15   |  主-0bit,子-4bit |
	| NVIC_PriorityGroup_1 |      0-1       |     0-7    |  主-1bit,子-3bit |
	| NVIC_PriorityGroup_2 |      0-3       |     0-3    |  主-2bit,子-2bit |
	| NVIC_PriorityGroup_3 |      0-7       |     0-1    |  主-3bit,子-1bit |
	| NVIC_PriorityGroup_4 |      0-15      |     0      |  主-4bit,子-0bit |
	--------------------------------------------------------------------------*/
	
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	//使能中断请求
	NVIC_Init(&NVIC_InitStruct);
	//输入配置
}

void EXTI_KEY2_Config(void)
{

  GPIO_InitTypeDef  GPIO_InitStruct;  
	EXTI_InitTypeDef  EXTI_InitStruct;

	//配置中断优先级
	EXTI_NVIC_Config();
	
	//初始化GPIO
	RCC_APB2PeriphClockCmd(KEY2_INT_GPIO_CLK, ENABLE); //APB2外设时钟使能库函数,打开GPIOA时钟使能
	GPIO_InitStruct.GPIO_Pin = KEY2_INT_GPIO_PIN;  
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStruct); //调用库函数初始化GPIOC,&表示取结构体的地址
	
	//初始化EXTI
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);	
  EXTI_InitStruct.EXTI_Line = 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);
		
}
	

bsp_exti.h

#ifndef __BSP_EXTI_H
#define __BSP_EXTI_H

#include "stm32f10x.h"

#define KEY2_INT_GPIO_PORT           GPIOC         
#define KEY2_INT_GPIO_CLK            RCC_APB2Periph_GPIOC    
#define KEY2_INT_GPIO_PIN            GPIO_Pin_13   

void EXTI_KEY2_Config(void);
#endif /*__BSP_EXTI_H*/

 

你可能感兴趣的:(STM32学习笔记4——EXTI中断)