EXIT外部中断

EXIT外部中断

使用中断的注意事项

1.最好不要在主函数和中断程序内 操作可能产生冲突的硬件
2.中断函数的实现应当简洁 仅使用变量、标志位或者函数作为借口

中断系统

中断

在主程序运行过程中,出现了特定的中断触发条件(中断源),
使得CPU暂停当前正在运行的程序,转而去处理中断程序,
处理完成后又返回原来被暂停的位置继续运行

中断优先级

当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源

NVIC优先级分组

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

NVIC基本结构

image

中断嵌套

当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回
image

EXIT

触发方式

上升沿
下降沿
双边沿
软件触发

image

支持的GPIO口

所有GPIO口,但相同的Pin不能同时触发中断

通道数

16个GPIO_Pin
PVD输出
RTC闹钟
USB唤醒
以太网唤醒

触发响应模式

中断响应
事件响应

EXTI基本结构

RCC->GPIOA/GPIOB/...->AFIO->EXTI->NVIC->CPU
image

AFIO复用IO口

1)复用功能引脚重映射
2)中断引脚选择

代码部分

AFIO常用函数

void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
//GPIO重映射:通过禁用某些pin的默认配置来进行重定义

例如

GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);
// 改变指定管脚的映射 GPIO_Remap_SWJ_Disable SWJ 完全禁用(JTAG+SW-DP)
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
// 改变指定管脚的映射 GPIO_Remap_SWJ_JTAGDisable ,JTAG-DP 禁用 + SW-DP 使能

//这时就可对引脚进行IO口的定义
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
//选择某引脚定义为外部中断引脚

例如

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);

EXIT常用函数

【判断在该中断线上的中断是否发生】
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);
//直接判断中断是否发生【在主函数内查看】

ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
//先判断中断是否使能 再判断中断标志位【在中断函数内查看】
【清除标志位】
void EXTI_ClearFlag(uint32_t EXTI_Line);
//【在主函数内查看】

void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
//【在中断函数内查看】

NVIC常用函数

【NVIC中断分组】
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
//NVIC_PriorityGroup : NVIC_PriorityGroup_0/1/2/3/4/5
!!!!!此分组配置在整个工程中仅需调用一次
若有多个中断,可以把此代码放在main函数内,while循环之前

【设置中断向量表】
NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset)
//NVIC_VectTab:指定向量表的位置   NVIC_VectTab_RAM/FLASH
//Offset:指定向量表的偏移地址
!!!!!每个中断函数都有自己专属的写函数的位置
!!!!!不需要在.h函数内声明
void EXTI15_10_IRQHandler(void)//要注意中断函数的名字和参数!!!
{
	if (EXTI_GetITStatus(EXTI_Line14) == SET)
	//判断是否是外部中断14号线触发的中断
	{
		/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
		{
			CountSensor_Count ++;	//计数值自增一次
		}
		EXTI_ClearITPendingBit(EXTI_Line14);//清除外部中断14号线的中断标志位
								//中断标志位必须清除
								//否则中断将连续不断地触发,导致主程序卡死
}

初始化

void CountSensor_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		//开启GPIOB的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);		//开启AFIO的时钟,外部中断必须开启AFIO的时钟
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//将PB14引脚初始化为上拉输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);	
	
	/*AFIO选择中断引脚*/【在GPIO库里】
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
	//将外部中断的14号线映射到GPIOB,即选择PB14为外部中断引脚
	
	/*EXTI初始化*/【在EXIT库里】
	EXTI_InitTypeDef EXTI_InitStructure;//定义结构体变量
	EXTI_InitStructure.EXTI_Line = EXTI_Line14;	//选择配置外部中断的14号线
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;	//指定外部中断线使能
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	//指定外部中断线为中断模式
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;	//指定外部中断线为下降沿触发
	EXTI_Init(&EXTI_InitStructure);	//将结构体变量交给EXTI_Init,配置EXTI外设
	
	/*NVIC中断分组*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//配置NVIC为分组2
	//即抢占优先级范围:0~3,响应优先级范围:0~3
	//此分组配置在整个工程中仅需调用一次
	//若有多个中断,可以把此代码放在main函数内,while循环之前
	//若调用多次配置分组的代码,则后执行的配置会覆盖先执行的配置
	
	/*NVIC配置*/【在misc杂项里】
	NVIC_InitTypeDef NVIC_InitStructure;//定义结构体变量
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;//选择配置NVIC的EXTI15_10线
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	//指定NVIC线路使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//指定NVIC线路的抢占优先级为1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//指定NVIC线路的响应优先级为1
	NVIC_Init(&NVIC_InitStructure);	//将结构体变量交给NVIC_Init,配置NVIC外设
}
posted @ 2024-11-02 14:38  White_ink  阅读(16)  评论(0编辑  收藏  举报