STM32笔记——EXTI外部中断

目录

一、概述

二、主要外设介绍

2.1 AFIO复用IO口

2.2 EXTI简介

EXTI框图:

 2.3 NVIC中断优先级分组

三、EXTI外部中断整体结构

四、实验程序

4.1 对射式红外传感器模块

4.2 旋转编码器模块

五、实验现象


一、概述

        关于EXTI外部中断,首先,简单介绍一下要用到的外设AFIO、EXTI、NVIC等等;然后,介绍触发外部中断到CPU响应中断函数的过程;最后,就是外部中断的简单应用,包含两个实验:①对射式红外传感器计数;②旋转编码器计次。

二、主要外设介绍

2.1 AFIO复用IO口

  • 在这里AFIO主要功能就是中断引脚选择。AFIO由很多的数据选择器组成,可完成数据选择,这样就可以减少IO口。例如:STM32F103C8T6有两组GPIO,GPIOA和GPIOB,共有32个引脚,都可以触发中断,但是相同Pin脚不能同时触发中断,假如一个IO口一个中断通道,就要32个通道,太占IO资源。如图所示,从PA0、PB0中选择一位进入EXTI0通道;PA1、PB1选择一位进入EXTI1通道...所以相同Pin脚不能同时触发中断。

2.2 EXTI简介

EXTI框图:

  • EXTI(Extern Interrupt)外部中断
  • EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序
  • 支持的触发方式:上升沿/下降沿/双边沿/软件触发
  • 支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断
  • 通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
  • 触发响应方式:中断响应/事件响应

 2.3 NVIC中断优先级分组

  • NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级
  • 抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队

分组方式

抢占优先级

响应优先级

分组0

0位,取值为0

4位,取值为0~15

分组1

1位,取值为0~1

3位,取值为0~7

分组2

2位,取值为0~3

2位,取值为0~3

分组3

3位,取值为0~7

1位,取值为0~1

分组4

4位,取值为0~15

0位,取值为0

三、EXTI外部中断整体结构

  1.  AFIO中断引脚选择。选择合适的中断通道,PA0、PB0就是EXTI0通道,PA1、PB1就是EXTI1通道...,为节省通道资源,EXTI5-EXTI9就合成一个通道EXTI9_5,EXTI10-EXTI15就合成一个通道EXTI15_10。
  2. EXTI边沿检测及控制。设置触发的方式:上升沿/下降沿/双边沿/软件触发;设置中断响应还是事件响应等等。
  3. NVIC优先级分组。分为高n位的抢占优先级和低4-n位的响应优先级。

四、实验程序

4.1 对射式红外传感器模块

  •  无遮挡时,D0输出低电平,有遮挡时输出高电平。

模块程序如下:

#include "stm32f10x.h"                  // Device header
uint16_t count;
/*
      *函数名      :CountSensor_Init(void)
      *函数功能    :红外传感器触发外部中断初始化
      *输入        :无
      *输出        :无
*/
void CountSensor_Init(void)
{	
	//GPIO初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB时钟
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);//GPIOB初始化
	//AFIO初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//使能AFIO时钟
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);//选择EXTI14线
	//EXIT初始化
	EXTI_InitTypeDef EXTI_InitStruct;
	EXTI_InitStruct.EXTI_Line=EXTI_Line14;
	EXTI_InitStruct.EXTI_LineCmd=ENABLE;
	EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStruct);//EXIT初始化
	//NVIC初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择NVIC2组
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel=EXTI15_10_IRQn;//EXTI14线属于EXTI15_10通道
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStruct);	//NVIC初始化
}
/*
      *函数名      :Getcount(void)
      *函数功能    :返回计数数据
      *输入        :无
      *输出        :count:计数数据
*/
uint16_t Getcount(void)
{
	return count;
}
void EXTI15_10_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line14)==SET)//判断是否EXTI14线申请的中断
	{
		EXTI_ClearITPendingBit(EXTI_Line14);//软件清零中断标志位
		count++;
	}
}

4.2 旋转编码器模块

  •  由上图可知,不旋转时,A,B初始电平都为高电平。
  • 旋转时输出信号都为方波信号。
  • 顺时针旋转时,A相超前B相90°。
  • 逆时针旋转时,B相超前A相90°。

模块程序如下:

  • 和上面差不多,多了一个GPIO口引脚触发中断
#include "stm32f10x.h" 
int16_t count;
/*
      *函数名      :Encode_Init(void)
      *函数功能    :旋转编码器外部中断初始化
      *输入        :无
      *输出        :无
*/

void Encode_Init(void)
{
	//GPIO初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	//AFIO初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);

	//EXIT初始化
	EXTI_InitTypeDef EXTI_InitStruct;
	EXTI_InitStruct.EXTI_Line=EXTI_Line0|EXTI_Line1;
	EXTI_InitStruct.EXTI_LineCmd=ENABLE;
	EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStruct);
	//NVIC初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStruct);
	
	NVIC_InitStruct.NVIC_IRQChannel=EXTI1_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=2;
	NVIC_Init(&NVIC_InitStruct);
}

int16_t Getencode(void)
{
	int16_t temp=0;
	temp=count;
	count=0;
	return temp;
}
void  EXTI0_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line0)==SET)
	{
		EXTI_ClearITPendingBit(EXTI_Line0);
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==1)
		{
			count--;
		}
	}
}
void  EXTI1_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line1)==SET)
	{
		EXTI_ClearITPendingBit(EXTI_Line1);
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==1)
		{
			count++;
		}
	}
}

五、实验现象

  • 用遮挡板遮挡红外传感器的凹槽,当拿开遮挡板时,计数加一。
  • 顺时针旋转旋转编码器时,计数加一;逆时针旋转时,计数减一。

猜你喜欢

转载自blog.csdn.net/ssssshhbh/article/details/129387192