Interrupt
1> 硬件框图
NVIC:Nested Vectored Interrupt Controller【嵌套向量中断控制器】
管理内核外设和片上外设的所有中断功能;
EXTI:External Interrupt 【外部中断控制器】
管理GPIO的中断;
2> NVIC 中断管理
3> EXTI 中断管理
3.1> EXTI与NVIC
STM32F103ZET6总共19个外部中断
PA0~PG0,7个引脚中只有一个可以映射到EXTI0;
外部中断EXTI 9 ~ 5 合并为EXTI9_5中断;
外部中断EXT 15~10 合并为EXT15_10中断;
3.2> EXTI内部框图
4> 外部中断实验
4.1> 实验概述
用2个按键控制2个LED状态翻转,用外部中断方式
4.2> 程序设计
main.c: 主程序
int main(void)
{
LED_Init();
KEY_Init();
LED_Off();
while(1) /* stop */;
//return 0;
}
bsp_led.c: LED灯初始化及开关函数
void LED_Init(void)
{
GPIO_InitTypeDef gpio_Struct_tmp = {0};
// 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
// PB5
gpio_Struct_tmp.GPIO_Pin = GPIO_Pin_5;
gpio_Struct_tmp.GPIO_Speed = GPIO_Speed_50MHz;
gpio_Struct_tmp.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_Init(GPIOB, &gpio_Struct_tmp);
// PE5
gpio_Struct_tmp.GPIO_Pin = GPIO_Pin_5;
gpio_Struct_tmp.GPIO_Speed = GPIO_Speed_50MHz;
gpio_Struct_tmp.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_Init(GPIOE, &gpio_Struct_tmp);
}
void LED_On(void)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_5);
GPIO_ResetBits(GPIOE, GPIO_Pin_5);
}
void LED_Off(void)
{
GPIO_SetBits(GPIOB, GPIO_Pin_5);
GPIO_SetBits(GPIOE, GPIO_Pin_5);
}
bsp_key.c: 按键初始化
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_tmp;
EXTI_InitTypeDef EXTI_tmp;
NVIC_InitTypeDef NVIC_tmp;
/*-------------Step 1> 配置GPIO ---------------*/
// 2话不说开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
GPIO_tmp.GPIO_Mode = GPIO_Mode_IPU;
GPIO_tmp.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_3; // PE4, PE3
GPIO_tmp.GPIO_Speed = GPIO_Speed_50MHz;
// PE4, PE3 上拉输入
GPIO_Init(GPIOE, &GPIO_tmp);
/*------------- Step 2> 配置AFIO ------------*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource4); // EXTI_Line4
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource3); // EXTI_Line3
/*------------- Step 3> 配置EXTI ------------*/
EXTI_tmp.EXTI_Line = EXTI_Line4;
EXTI_tmp.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_tmp.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_tmp.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_tmp); // EXTI_Line4
EXTI_tmp.EXTI_Line = EXTI_Line3;
EXTI_tmp.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_tmp.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_tmp.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_tmp); // EXTI_Line3
/*------------- Step 4> 配置NVIC ------------*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 中断优先级分组
NVIC_tmp.NVIC_IRQChannel = EXTI4_IRQn;
NVIC_tmp.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_tmp.NVIC_IRQChannelSubPriority = 0;
NVIC_tmp.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_tmp);
NVIC_tmp.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_tmp.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_tmp.NVIC_IRQChannelSubPriority = 0;
NVIC_tmp.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_tmp);
}
4步配置GPIO的外部中断:
Step 1> 配置GPIO
Step 2> 配置AFIO
Step 3> 配置EXTI
Step 4> 配置NVIC
stm32f10x_it.c: 中断处理函数
// EXTI3 处理函数, key1;
void EXTI3_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line3);
LED_On();
}
// EXTI4 处理函数, key0;
void EXTI4_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line4);
LED_Off();
}
5> 中断向量表
中断数量:70个
STM32F103ZET6有70个中断 = 60外设中断 + 10个系统中断;
6> 总中断开关
// 文件core_cm3.h:
static __INLINE void __enable_irq() { __ASM volatile ("cpsie i"); }
static __INLINE void __disable_irq() { __ASM volatile ("cpsid i"); }
7> 总结
GPIO, AFIO, EXTI, NVIC等功能模块,学习它们们时各个击破;
了解他们内部结构,内部寄存器,找点感觉,
重点看看每个模块的函数如何使用,
会使用后,看看内部如何编写的,非常能提高编程技能;