一、了解外部中断的概念(以STM32F4XX系列芯片为例)
STM32F4的每个IO都可以作为外部中断输入。
STM32F4的中断控制器支持22个外部中断/事件请求:
EXTI线0~15:对应外部IO口的输入中断。
EXTI线16:连接到PVD输出。
EXTI线17:连接到RTC闹钟事件。
EXTI线18:连接到USB OTG FS唤醒事件。
EXTI线19:连接到以太网唤醒事件。
EXTI线20:连接到USB OTG HS(在FS中配置)唤醒事件。
EXTI线21:连接到RTC入侵和时间戳事件。
EXTI线22:连接到RTC唤醒事件。
每个外部中断线可以独立的配置触发方式(上升沿,下降沿或者双边沿触发),触发/屏蔽,专用的状态位。 从上面可以看出,STM32F4供IO使用的中断线只有16个,但是STM32F4xx系列的IO口多达上百个, 那么中断线怎么跟io口对应呢?
二、外部中断/事件线路映像:
在STM32参考手册中找到中断线映射表可以知道,IO口对应的中断线。
三、外部中断/事件控制器框图:
四、以按键触发输入信号,判断输入的是高电平还是低电平(PA0为例)
五、驱动代码配置步骤如下:
我们驱动代码编写使用STM32标准库函数,寄存器不贴出来了。
1.开启IO端口时钟,配置对应的IO管脚为输入模式。
2.使能系统配置控制器 (SYSCFG)
3.映射IO口到对应的中断线上
4.配置中断初始化函数参数
5.配置中断优先级分组
6.配置中断控制器初始化函数
7.使能中断通道(配置中断控制器初始化后可以不用调用)
8.调用中断服务函数
9.清除中断标志
#include "stm32f4xx.h"
int main(void)
{
//1.开启IO端口时钟,配置对应的IO管脚为输入模式。
GPIO_InitTypeDef Gpio_Key_Init; //定义GPIO结构体变量
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //开启GPIOA时钟
Gpio_Key_Init.GPIO_Pin = GPIO_Pin_0; //选中0引脚
Gpio_Key_Init.GPIO_Mode = GPIO_Mode_IN; //输入模式
Gpio_Key_Init.GPIO_PuPd = GPIO_PuPd_DOWN; //下拉
GPIO_Init(GPIOA,&Gpio_Key_Init); //选中PA组并进行参数初始化配置
//2.使能系统配置控制器 (SYSCFG)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE); //开启系统配置控制器 (SYSCFG)时钟
//3.映射IO口到对应的中断线上
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0); //映射PA0引脚到EXTI0线
//4.配置中断初始化函数参数
EXTI_InitTypeDef EXTI_Key_Init; //定义EXTI外部中断结构体变量
EXTI_Key_Init.EXTI_Line = EXTI_Line0; //选中第0线
EXTI_Key_Init.EXTI_LineCmd = ENABLE; //开放来自第0线线的中断请求
EXTI_Key_Init.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
EXTI_Key_Init.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
EXTI_Init(&EXTI_Key_Init); //初始化外部中断配置
//5.配置中断优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //选择主优先级组2
//6.配置中断控制器初始化函数
NVIC_InitTypeDef NVIC_Key_Init; //定义EXTI外部中断结构体变量
NVIC_Key_Init.NVIC_IRQChannel=EXTI0_IRQn; //选择中断源
NVIC_Key_Init.NVIC_IRQChannelCmd=ENABLE; //使能中断源
NVIC_Key_Init.NVIC_IRQChannelPreemptionPriority=2; //设置抢占优先级
NVIC_Key_Init.NVIC_IRQChannelSubPriority=2; //设置响应优先级
NVIC_Init(&NVIC_Key_Init); //初始化中断控制器参数配置
//7.使能中断通道(配置中断控制器初始化后可以不用调用)
// NVIC_EnableIRQ(EXTI0_IRQn); //使能外部中断线0进行工作
while(1)
{
}
}
//8.调用中断服务函数
void EXTI0_IRQHandler(void)
{
//9.清除中断EXTI0线的标志位
EXTI_ClearFlag(EXTI_Line0);
//可以点灯,可以调用打印函数等等,设立标志位,验证可以通过
}
总结:
按键使用外部中断是经常用到的,可以避免主循环时扫描不到按键输入。