目标:按KEY1,LED亮, 再按KEY1, LED灭。
一:什么是中断?
1.切断A,去做B;做完B,在做A。
二.中断相关知识点
2.1stm32参考手册->向量中断控制器(NVIC)->异常向量表
灰色的是arm公司的中断跳转,地址不可更改。其他为意法半导体公司外设中断跳转。
例:给10086按1,铁定跳到1的功能
中断优先级:谁先去执行中断的功能,优先级可以更改
2.2 Stm32f10x.md.s中断与异常向量表一一对应,如下:
发生特定的中断,铁定跳到指定地址。(实现指定的功能)
2.3里面为什么没有实现一些功能?
实际上,arm和意法半导体公司,其实是给你提供了一个遇到中断自动跳转到某一函数的功能。(路给你铺好了,遇到中断跳过来,让你写函数实现)。
二:中断可以干啥?
前面的文章我们讲过(文章链接),PA0可以被配置成检测低电平输入的方式,来检测按键按下。
于是我们提出疑问:PA0可以被配置成检测中断的方式,来检测按键按下吗?
答:当然可以!!!
三:问题:怎么把PA0配置成检测外部中断作用?
3.1.初始化向量中断控制器(NVIC)
前文说过,中断跟向量中断控制器有关,那有关于初始化中断控制器(NVIC)的函数吗?因为我们用到某一功外设时,首先要初始化外。。
我们到库函数手册里找找------提到NVIC的函数
有!!!调用。
NVIC_InitTypeDef NVIC_InitStructure;//声明结构体对象
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//对象成员赋值
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//EXTI0_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);//调用函数
三步:声明结构体对象, 对象赋值, 调用Init函数
3.2.初始化管脚(PA0),配置成外部中断(检测到低电平表示中断)
1.因为原理图不带上拉输入功能,但可以利用STM32芯片内部提供的上拉输入,检测到低电平表示中断 。MODE 选择上拉输入模式。
2.选择PA0管脚,配置成外部中断功能,函数在GPIO库函数中。
GPIO_InitTypeDef GPIO_InitStructure;//结构体对象
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//对象赋值
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //按键按下,PA0检测到低电平。上拉输入(按下之前一直是高电平)
GPIO_Init(GPIOA, &GPIO_InitStructure);//调用初始化函数
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
3.3.初始化外部中断库函数
EXTI_InitTypeDef EXTI_InitStructure;//结构体对象
EXTI_InitStructure.EXTI_Line = EXTI_Line0;//对象赋值
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断请求
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);//调用函数
1.外部中断线0,中断请求,下降沿触发中断(因为是上拉输入)。
3.4.开启GPIOA时钟和复用功能时钟
外设工作前要开启时钟,GPIOA挂载在PB2总线。开启GPIOA时钟和功能复用时钟。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);5.
3.5.进中断处理函数
1.再次检测是否有中断(跟按键消抖原理一样, 再次检查低电平)
2.灯状态反转
GPIOA->ODR ^= GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;(很方便)
3.清除中断标志位(很重要)
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) == SET)
{
GPIOA->ODR ^= GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
//wait(10000000);
EXTI_ClearITPendingBit(EXTI_Line0);
}
else
{
}
}
四:效果展示
https://www.bilibili.com/video/BV1ia411i7iM?spm_id_from=333.999.0.0https://www.bilibili.com/video/BV1ia411i7iM?spm_id_from=333.999.0.0https://www.bilibili.com/video/BV1ia411i7iM?spm_id_from=333.999.0.0https://www.bilibili.com/video/BV1ia411i7iM?spm_id_from=333.999.0.0