stm32学习笔记-外部中断

让人想犯罪 __ 提交于 2020-02-21 07:27:31

1、stm32f103外部中断控制器EXTI。

1.1外部中断的映像

外部中断只有0~18共19个,那如何给每一个GPIO口配置上中断,通过一个映像把所有具有相同下标的GPIO口映像成相应下标的外部中断。
在这里插入图片描述

参考手册:
在这里插入图片描述

1.2 外部中断/事件的框图

在这里插入图片描述
中断大致过程如下:

  1. 通过配置 上升沿/下降沿触发选择寄存器 选择 边沿检测电路 所要检测的边沿跳变。
  2. 边沿检测电路 根据 输入线 是否有相应的边沿跳变,检测到则输出信号1,否则输出信号0。
  3. 通过一个 或门,或门 以 边沿检测电路软件中断事件寄存器(中断事件可以通过软件产生) 作为输入。两者之一有一个产生信号1,或门就输出信号1。
  4. 或门输出的信号1。输出的信号1发至 请求挂起寄存器
  5. 请求挂起寄存器对应寄存器的位置1,然后请求挂起寄存器会产生一个信号1。(不懂,这里暂略)
  6. 请求挂起寄存器、中断屏蔽寄存器同时输出信号1,则发生信号1到NVIC中断控制器。(注意:这里可以看出中断屏蔽也就是一个与操作。)

事件大致过程如下:

  1. 通过配置 上升沿/下降沿触发选择寄存器 选择 边沿检测电路 所要检测的边沿跳变。
  2. 边沿检测电路 根据 输入线 是否有相应的边沿跳变,检测到则输出信号1,否则输出信号0。
  3. 通过一个 或门,或门 以 边沿检测电路软件中断事件寄存器(中断事件可以通过软件产生) 作为输入。两者之一有一个产生信号1,或门就输出信号1。
  4. 或门输出的信号1。若事件屏蔽寄存器也产生信号1,则产生一个信号1发至脉冲发生器,脉冲发生器产生脉冲。

1.3 外部中断的编程。

外部中断配置思路

思路:

  1. 时钟配置(GPIO时钟、AFIO时钟)
  2. GPIO配置(中断功能,映射)
  3. EXTI配置(触发方式,中断使能,)
  4. NVIC配置(优先级分组,中断使能)
  5. 中断服务子程序(判断标志,清除标志)

相关寄存器

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

相关库函数

  1. GPIO映射函数:
    在这里插入图片描述
  2. 外部中断复位配置函数在这里插入图片描述
  3. 外部中断初始化配置函数在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  4. NVIC在这里插入图片描述
  5. 清除挂起位标志函数在这里插入图片描述

1.4 按键中断实例。

电路图
在这里插入图片描述
代码:

exit_init()
{
	
	GPIO_InitTypeDef gpiost;
	EXTI_InitTypeDef extist;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	//时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

	//GPIO
	gpiost.GPIO_Mode=GPIO_Mode_IPU;
	gpiost.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4;
	gpiost.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOE,&gpiost);//配置PE3,PE4位上拉输出
	gpiost.GPIO_Mode=GPIO_Mode_IPD;
	gpiost.GPIO_Pin=GPIO_Pin_0;
	gpiost.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&gpiost);。。配置PA0为下拉输出
	//GPIO映射到EXTI,
	//注意:这个函数写参数不能用与运算偷懒,如:GPIO_PinSource3|GPIO_PinSource4,这么写会映射不了,这里搞了半天才发现这里有bug
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
	
	//EXTI
	EXTI_DeInit();
	extist.EXTI_Line=EXTI_Line3|EXTI_Line4;
	extist.EXTI_LineCmd=ENABLE;
	extist.EXTI_Mode=EXTI_Mode_Interrupt;
	extist.EXTI_Trigger=EXTI_Trigger_Falling;
	EXTI_Init(&extist);//外部中断3、外部中断4 下降沿触发
	extist.EXTI_Line = EXTI_Line0;
	extist.EXTI_Trigger = EXTI_Trigger_Rising;
	EXTI_Init(&extist);//外部中断0 上降沿触发
	
	//NVIC
	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;			//使能按键KEY1所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//主优先级2 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;					//从优先级1 
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
  	
  	NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;			//使能按键KEY0所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;					//子优先级0 
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}

//外部中断3服务程序 
void EXTI3_IRQHandler(void)
{
	//做些什么,如:led1=0;
	EXTI_ClearITPendingBit(EXTI_Line3); //清除LINE3上的中断标志位  
}

//外部中断4服务程序 
void EXTI4_IRQHandler(void)
{
	//做些什么,如:led2=0;
	EXTI_ClearITPendingBit(EXTI_Line4);  //清除LINE4上的中断标志位  
}

//外部中断0服务程序 
void EXTI0_IRQHandler(void)
{
	//做些什么,如:led1=1;led2=1;
	EXTI_ClearITPendingBit(EXTI_Line0);//清除LINE0上的中断标志位  
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!