stm32外部中断EXTI-------对射式红外传感器和旋转编码器实例

00.EXTI基本结构

根据外部中断的结构图来进行外部中断的配置步骤如下

  • 1.配置所涉及外设的系统时钟RCC
  • 2.配置GPIO
  • 3.配置AFIO,选择需要用的GPIO,连接到后面的EXTI
  • 4.配置EXTI,选择 边沿触发方式,比如上升沿、下降沿或者双边沿,选择触发响应方式 中断响应 和事件响应
  • 5.配置NVIC,设置中断的优先级,最后外部中断信号就能进入CPU了

下面将进行详细的说明


01.配置所涉及外设的系统时钟RCC

根据EXTI的基本结构从左到右 

开启GPIO的时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启GPIOB的时钟

注意:此句代码为 开启APB2总线GPIOB 外设的时钟。不同的APB总线 有不同的外设注意区分下面同理

开启AFIO的时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO的时钟

开启EXTI和NVIC两个外设

由于这两个外设时钟是一直打开的所以不需要再额外开启,NVIC是内核外设,内核外设都不需要开启时钟。


02配置GPIO

步骤如下:

  • 1.定义结构体
GPIO_InitTypeDef GPIO_InitStructure;
  • 2.给结构体成员赋值
    GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//对于外部中断 可选 浮空输入 上拉输入 下拉输入
	GPIO_InitStructure.GPIO_Pin= GPIO_Pin_14;//GPIOB的引脚
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz ;
  • 3.调用GPIO_Init函数 参数1 为使用的哪一个GPIO 外设,参数2 为结构体的地址
GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化

03配置AFIO

AFIO相关函数说明

  • void GPIO_AFIODeInit(void); 复位AFIO外设,调用后AFIO外设的配置就会清除
  • void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);锁定GPIO配置,防止意外更改
  • void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);配置AFIO的事件输出功能
  • void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);配置AFIO的数据选择器 选择想要的中断引脚
GPIO_EXTILineConfig( GPIO_PortSourceGPIOB,GPIO_PinSource14);

当执行完这个函数,AFIO的第14个数据选择器就配置好了,输入端是GPIOB外设,输出端连接的事EXTI的第14个中断线路。


04配置EXTI

EXTI相关函数

  • void EXTI_DeInit(void); 清除配置 恢复成默认状态
  • void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);根据结构体配置EXTI外设 初始化主要用
  • void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);
  • void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);软件触发外部中断,参数为指定中断线
  • FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);获取指定标志位是否被置1
  • void EXTI_ClearFlag(uint32_t EXTI_Line); 清除置1标志位
  • ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);中断函数里查看标志位
  • void EXTI_ClearITPendingBit(uint32_t EXTI_Line);中断函数里清除标志位

配置EXTI

    /*4.配置EXTI
	*将EXTI的第14个线路配置为中断模式 下降沿触发 开启中断
	*/
	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);

05配置NVIC

NVIC相关函数

  • void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);指定中断分组
  • void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);初始化NVIC

配置NVIC

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//指定中断分组
	NVIC_InitTypeDef NVIC_InitStruct;//定义结构体
	NVIC_InitStruct.NVIC_IRQChannel=EXTI15_10_IRQn;//指定中断通道开启或关闭
	NVIC_InitStruct.NVIC_IRQChannelCmd =ENABLE;//中断通道使能
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;//指定中断通道的抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;//指定中断通道的响应优先级
	
	NVIC_Init(&NVIC_InitStruct);//传入结构体初始化NVIC

注: 指定中断分组的代码 整个工程只需要执行一次即可,如果把这行代码放到模块中 则需要保证每个模块的中断分组是相同的即可,要么放到主函数里面

优先级表如下



 

06定义中断函数

中断函数无参数无返回值 不需要调用

//中断函数 自动执行
void EXTI15_10_IRQHandler(void)
{
//中断标志位的判断
	if(EXTI_GetITStatus(EXTI_Line14)==SET)//执行中断程序
	{
		CountSensor_Count++;
		EXTI_ClearITPendingBit(EXTI_Line14);//清除中断标志位
	}
	
	
}

07对射式红外传感器实例函数完整代码

接线图

下面贴出完整代码

硬件驱动CountSensor.c

#include "stm32f10x.h" // Device header

uint16_t CountSensor_Count;//统计中断执行次数的变量
void CountSensor_Init(void)
{
	/*
	*配置外部中断的流程
	*1.配置RCC 打开时钟 
	*2.配置GPIO 选择输入的端口为输入模式
	*3.配置AFIO,选择我们要用的这一路的GPIO,连接到后面的EXTI
	*4.配置EXTI,选择 边沿触发方式,比如上升沿、下降沿或者双边沿,选择触发响应方式 中断响应 和事件响应
	*5.配置NVIC,设置中断的优先级,最后外部中断信号就能进入CPU了
	*/
	//开启时钟 EXTI和NVIC 不需要开启时钟(NVIC是内核外设),RCC管理内核外的外设
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启GPIOB的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO的时钟
	
	/*
	*配置GPIO的流程
	*1.定义结构体 GPIO_InitTypeDef GPIO_InitStructure;
	*2.引出结构体的成员变量
	*3.初始化GPIO
	*
	*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//对于外部中断 可选 浮空输入 上拉输入 下拉输入
	GPIO_InitStructure.GPIO_Pin= GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz ;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	/*
	*配置AFIO
	*void GPIO_AFIODeInit(void);复位AFIO外设,调用后AFIO外设的配置就会清除
	*void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);锁定GPIO配置,防止意外更改
	*void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);配置AFIO的事件输出功能
	*void GPIO_EventOutputCmd(FunctionalState NewState);
	*
	*
	*void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);用于引脚重映射,para1 选择重映射的方式 para2 新的状态
	*void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);配置AFIO的数据选择器 选择想要的中断引脚
	*void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);以太网相关函数
	*/
	
	GPIO_EXTILineConfig( GPIO_PortSourceGPIOB,GPIO_PinSource14);
	
	/*4.配置EXTI
	*将EXTI的第14个线路配置为中断模式 下降沿触发 开启中断
	*/
	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);
	
	
	/*4.配置NVIC
	*
	*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//指定中断分组
	NVIC_InitTypeDef NVIC_InitStruct;//定义结构体
	NVIC_InitStruct.NVIC_IRQChannel=EXTI15_10_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd =ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
	
	NVIC_Init(&NVIC_InitStruct);//传入结构体初始化NVIC
	
}
uint16_t CountSensor_Get(void)
{
	return CountSensor_Count;
}

//中断函数 自动执行
void EXTI15_10_IRQHandler(void)
{
//中断标志位的判断
	if(EXTI_GetITStatus(EXTI_Line14)==SET)//执行中断程序
	{
		CountSensor_Count++;
		EXTI_ClearITPendingBit(EXTI_Line14);//清除中断标志位
	}
	
	
}


 

 硬件驱动CountSensor.h

#ifndef __COUNT_SENSOR_H
#define __COUNT_SENSOR_H

void CountSensor_Init(void);
uint16_t CountSensor_Get(void);
#endif 

主函数main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"

uint8_t KeyNum;

int main(void)
{
	OLED_Init();
	CountSensor_Init();
	
	OLED_ShowString(1,1,"Count:");
	while(1) 
	{
	 OLED_ShowNum(1,7,CountSensor_Get(),5);
	}
}

08旋转编码器计次(双中断配置)

接线图

对于双中断配置只需要改变如下代码即可

//GPIO配置
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_0 |GPIO_Pin_1;
//AFIO配置
GPIO_EXTILineConfig( GPIO_PortSourceGPIOB,GPIO_PinSource0);
GPIO_EXTILineConfig( GPIO_PortSourceGPIOB,GPIO_PinSource1);
//EXTI配置
EXTI_InitStruct.EXTI_Line=EXTI_Line0|EXTI_Line1;
//NVIC配置
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);

//分别设置中断函数
void EXTI0_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line0)==SET)
	{
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==0)
		{
			Encoder_Count--;
		}
		
	   EXTI_ClearITPendingBit(EXTI_Line0);
	}
}

void EXTI1_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line1)==SET)
	{
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0)
		{
			
			Encoder_Count++;
		}
	   EXTI_ClearITPendingBit(EXTI_Line1);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值