STM32完全学习——外部中断
一、嵌套向量中断控制器
我们在这里使用标准库的方式来处理。因此只需要调用几个函数就可以了。
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //中断优先级分组 分1组
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); //使能AFIO时钟
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; //EXTI Line0 Interrupt
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级设置为0
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; //次优先级设置为1
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能中断
NVIC_Init(&NVIC_InitStruct); //进行行初始化
这里需要注意的是我们需要开启AFIO的时钟,这是因为中断事件需要在AFIO——EXTICRX寄存器里面进行配置。看下图就可明白
二、外部中断的配置
上面的设置只能说明使用了那个中断线,和中断的优先级。对于使用哪个引脚,上升沿还是下降沿触发,我们需要在外部中断里面进行设置。通过下面的设置我们就将GPIOB的端口0绑定到了外部中断线0,这样我们就可以进行外部中断了。但是这个时候我们还没有对GPIOB进行初始化
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line0; //使用中断线0
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //设置为中断模式
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; //设置为下降沿触发
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct); //进行初始化
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0); //将GPIOB绑定到中断线0
三、初始化GPIO
我们这里主要初始化GPIOA和GPIOB,GPIOA主要是控制LED,GPIOB主要是外部中断
GPIO_InitTypeDef *GPIO_InitStruct = (GPIO_InitTypeDef *)malloc(sizeof(GPIO_InitTypeDef));
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStruct->GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStruct->GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct->GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, GPIO_InitStruct);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
free(GPIO_InitStruct);
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //打开GPIOB的时钟
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
四、利用外部中断实现按键控制LED
我们的GPIOA0接LED的负极,GPIOB0接按键的引脚,按键的另一个引脚接GND。
我们只需要将上面的代码先运行,然后在写下面的这个外部中断处理函数就可以了。这个函数放在那里都可以。
void EXTI0_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line0) == 1) //判断确实是中断线0发生了中断
{
//实现按一次亮,然后再按灭,一直如此
GPIO_WriteBit(GPIOA, GPIO_Pin_1, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1)));
}
EXTI_ClearITPendingBit(EXTI_Line0); //清除外部中断线0的标志位
}