功能:按下KEY键灯亮,再按KEY键灯灭 本实验步骤: 1、一些初始化 2、使能IO口时钟/LED灯外设时钟/使能SYSCFG时钟(中断必打开) 3、GPIO与中断线的重映射 4、初始化LED及KEY寄存器 5、初始化线上中断EXTI_Init() 6、配置中断分组NVIC 7、编写中断服务函数
基本概念
中断数量、抢占优先级与响应优先级、中断步骤
中断数量: 共有92个中断,10个内核中断,82个可屏蔽中断(常用); 16级可编程的中断优先级
抢占优先级与响应优先级: 抢占优先级越高,中断程序优先级越高; 若:中断1抢占优先级为2,中断2抢占优先级为1 响应优先级 若:两中断抢占优先级相同时,中断1响应优先级是3,中断2响应优先级为2(先响应中断2再响应中断1)
中断重要步骤: 1、使能IO口时钟 2、使能SYSCFG时钟(中断必打开) 3、GPIO与中断线的重映射 4、初始化线上中断EXTI_Init() 5、配置中断分组NVIC 6、编写中断服务函数:判断中断是否发生;清除某中断线的中断标志位
1、一些初始化
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure1;
EXTI_InitTypeDef EXIT_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
2、使能IO口时钟/LED灯外设时钟/使能SYSCFG时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
3、GPIO与中断线的重映射
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource15);
4、初始化LED及KEY寄存器
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure1.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure1);
注意: 输出模式寄存器-不需要设置上拉/下拉寄存器 输入模式寄存器-使用按键时需要将上拉/下拉寄存器设置为上拉状态
5、初始化线上中断EXTI_Init()
EXIT_InitStructure.EXTI_Line = EXTI_Line15;
EXIT_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXIT_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXIT_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXIT_InitStructure);
注意: KEY引脚 为PA15 中断线为15
6、配置中断分组NVIC
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//LED默认为点亮状态,此处将该处电平置高设置为不亮状态
GPIO_SetBits(GPIOC, GPIO_Pin_13);
7、编写中断服务函数
//判断中断是否发生 //清除某中断线的中断标志位
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line15)!=RESET)
{
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)==1)
{
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
}
else
{
GPIO_SetBits(GPIOC, GPIO_Pin_13);
}
}
EXTI_ClearITPendingBit(EXTI_Line15);
#include "stm32f4xx.h"
#include "delay.h"
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure1;
EXTI_InitTypeDef EXIT_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_IN;
GPIO_Init(GPIOA, &GPIO_InitStructure1);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource15);
EXIT_InitStructure.EXTI_Line = EXTI_Line15;
EXIT_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXIT_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXIT_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXIT_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
GPIO_SetBits(GPIOC, GPIO_Pin_13);
while(1);
}
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line15)!=RESET)
{
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)==1)
{
GPIO_ResetBits(GPIOC, GPIO_Pin_13);
}
else
{
GPIO_SetBits(GPIOC, GPIO_Pin_13);
}
}
EXTI_ClearITPendingBit(EXTI_Line15);
}
碎碎念:
中断服务函数作用: 发生了中断就执行该函数内的操作 出错的原因: 中断服务函数逻辑存在问题,应该判断灯亮或不亮,按键处的状态本身就有中断发生的状态判断不需要重复进行判断。由于该处是逻辑问题,之前查找了很久问题才发现
|