十五、外部中断按键点灯
1. 配置流程
一般使用GPIO的外部中断功能,都需要有以下几个步骤。
- 开启时钟
- 配置GPIO的模式
- 使能NVIC中断并配置优先级
- 配置GPIO中断
- 使能中断和清除中断标志位
- 编写中断服务函数
STM32单片机的任意引脚都可以配置为外部中断触发,开发板的按键使用的是KEY_UP,接到了单片机的PA0引脚上,因此我们可以使能PA0的外部中断功能。
2. 开启时钟
开启GPIO时钟
C
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
1
开启AFIO时钟
c
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
1
3. 配置GPIO模式
按键配置
C
// 配置GPIO口
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPD;//下拉输入
GPIO_Init(GPIOA,&GPIO_InitStruct);
1
2
3
4
5
6
7
2
3
4
5
6
7
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
- 这行代码设置了要配置的GPIO引脚为第0脚。
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
- 这里将GPIO引脚的模式设置为下拉输入模式。
GPIO_Init将相同的配置应用到GPIOA端口的第0脚。这意味着GPIOA第0脚都被配置为输入模式,且都启用了下拉电阻。
4. 配置GPIO中断
C
// 使能EXTI中断线路
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
// 配置EXTI参数
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line=EXTI_Line0;//选择中断线
EXTI_InitStruct.EXTI_LineCmd=ENABLE;//选择EXTI的状态,使能/失能
EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;//选择EXTI的模式,中断响应/事件响应
EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Rising;//指定EXTI线上升沿触发
EXTI_Init(&EXTI_InitStruct);
// 配置NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn;//指定要启用的IRQ通道
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;//使能
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;//指定抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;//指定响应优先级
NVIC_Init(&NVIC_InitStruct);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
关于每个中断线对应的功能,如图所示。
5. 编写中断服务函数
使能中断之后,如果有中断触发,就会跳转到中断处理函数里面执行。需要编写中断处理函数。首先是中断函数名, 这个是固定的,在startup_stm32f10x.s
启动文件中有定义,如图所示。(部分截取)
在中断处理函数里需要检测中断标志位是否被置位。
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
- 这个函数是获取中断标志位。只有一个参数就是中断线。有一个返回值
FlagStatus
,返回值的状态为SET
和RESET
。 - 需要注意的是每次中断执行完毕之后都需要清除一下中断标志位等待下一次中断发生。
中断服务函数编写代码如下:
⚠警告
在中断处理程序中执行printf
是不推荐的,这里是为了更直观的看到中断服务函数的运行,所以这样写。在自己的程序中不推荐使用!
C
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) == SET)//判断是否为EXTI0中断
{
printf("EXTI0_IRQHandler!!\r\n");
EXTI_ClearITPendingBit(EXTI_Line0);// 清除中断标志位
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
6. 实验现象
关于这一章节的代码百度网盘下载,在立创·STM32F103C8T6开发板资料(标准库)/第03章软件资料/代码例程/007外部中断按键中断。
烧写我们的代码之后,按下一次按键会打印EXTI0_IRQHandler!!。如图所示。