【STM32学习笔记】基于中断实现LED点亮、熄灭

目标:按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
	{
	}
}

四:效果展示

经验分享 程序员 微信小程序 职场和发展