中断与事件的区别
相同点:中断和事件都是触发的一种,都是可以设置触发的;
异同点:
中断触发后必须有中断处理子程序IRQ handle,例如比如按键中断触发,实现一个LED的闪烁,可以在按键按下后,在中断处理程序中实现某个LED的电平反转
但在事件中,事件是没有中断处理子程序的,事件发生后,会直接发出一个脉冲信号给与之联动的操作,也可以同样实现LED电平的反转,只要有事件发生,就会有一个脉冲信号,这样的好处是,不需要CPU干预了,可以节省CPU的处理资源,相比中断处理,速度还更快,因为硬件的速度总是比软件处理快。
EXTI 功能框图
EXTI 可分为两大部分功能,一个是产生中断,另一个是产生事件,这两个功能从硬件上就有所 不同。
红色虚线指示的电路流程。它是一个产生中断的线路,最终信号流入到NVIC 控制器内。
(1)编号 1 是输入线,EXTI 控制器有 23 个中断/事件输入线,这些输入线可以通过寄存器设置为任意一个 GPIO,也可以是一些外设的事件,这部分内容我们将在后面专门讲解。输入线一般是存在电平变化的信号。
(2) 编号 2 是一个边沿检测电路,它会根据上升沿触发选择寄存器(EXTI_RTSR) 和下降沿触发选择寄存器 (EXTI_FTSR) 对应位的设置来控制信号触发。边沿检测电路以输入线作为信号输入端,如果检测到有边沿跳变就输出有效信号 1 给编号 3 电路,否则输出无效信号 0。而 EXTI_RTSR 和EXTIFTSR 两个寄存器可以控制器需要检测哪些类型的电平跳变过程,可以是只有上升沿触发、只有下降沿触发或者上升沿和下降沿都触发。
(3)编号3电路实际就是一个或门电路,它一个输入来自编号2电路,另外一输入来自软件中断事件寄存器 (EXTI_SWIER)。EXTI_SWIER 允许我们通过程序控制就可以启动中断/事件线,这在某些地方非常有用。我们知道或门的作用就是有”就为 1,所以这两个输入随便一个有有效信号 1 就可以输出 1 给编号 4 和编号 6 电路。
(4)编号 4 电路是一个与门电路,它一个输入编号 3 电路,另外一个输入来自中断屏蔽寄存器(EXTI_IMR)。与门电路要求输入都为 1 才输出 1,导致的结果EXTI_IMR 设置为 0 时,那不管编号 3 电路的输出信号是 1 还是 0,最终编号 4 电路输出的信号都为 0;如果 EXTI_IMR设置为 1 时,最终编号 4 电路输出的信号才由编号 3 电路的输出信号决定,这样我们可以简单的控制 EXTI_IMR 来实现是否产生中断的目的。编号 4 电路输出的信号会被保存到挂起寄存器(EXTI_PR) 内,如果确定编号 4 电路输出为 1 就会把 EXTI_PR 对应位置1。
(5)编号 5 是将 EXTI_PR 寄存器内容输出到 NVIC 内,从而实现系统中断事件控制
接下来我们来看看绿色虚线指示的电路流程。它是一个产生事件的线路,最终输出一个脉冲信号。
产生事件线路是在编号 3 电路之后与中断线路有所不同,之前电路都是共用的。编号 6 电路是一个与门,它一个输入编号 3 电路,另外一个输入来自事件屏蔽寄存器 (EXTI_EMR)。如果EXTI_EMR 设置为 0 时,那不管编号 3 电路的输出信号是 1 还是 0,最终编号 6 电路输出的信号都为 0;如果 EXTI_EMR 设置为 1 时,最终编号 6 电路输出的信号才由编号 3 电路的输出信号决定,这样我们可以简单的控制 EXTI_EMR 来实现是否产生事件的目的。
(1)编号 7 是一个脉冲发生器电路,当它的输入端,即编号 6 电路的输出端,是一个有效信号 1 时就会产生一个脉冲;如果输入端是无效信号就不会输出脉冲。
(2)编号 8 是一个脉冲信号,就是产生事件的线路最终的产物,这个脉冲信号可以给其他外设电路使用,比如定时器 TIM、模拟数字转换器 ADC 等等
中断程序的编写步骤
1.初始化需要连接到的EXTI的GPIO
2.初始化EXTI
3.配置NVIC中断优先级
4.编写中断服务函数
案例如下:
/*KEY1 宏定义*/
#define KEY1_INIT_GPIO_CLK RCC_AHB1Periph_GPIOA
#define KEY1_INIT_GPIO_PORT GPIOA
#define KEY1_INIT_GPIO_PIN GPIO_Pin_0
#define KEY1_INIT_GPIO_PORTSOURCE EXTI_PortSourceGPIOA
#define KEY1_INIT_GPIO_PINSOURCE EXTI_PinSource0
#define KEY1_INT_EXTI_LINE EXTI_Line0
#define KEY1_INT_EXTI_IRQ EXTI0_IRQn
#define KEY1_IRQHandler EXTI0_IRQHandler
/*KEY2 宏定义*/
#define KEY2_INIT_GPIO_CLK RCC_AHB1Periph_GPIOC
#define KEY2_INIT_GPIO_PORT GPIOC
#define KEY2_INIT_GPIO_PIN GPIO_Pin_13
#define KEY2_INIT_GPIO_PORTSOURCE EXTI_PortSourceGPIOC
#define KEY2_INIT_GPIO_PINSOURCE EXTI_PinSource13
#define KEY2_INT_EXTI_LINE EXTI_Line13
#define KEY2_INT_EXTI_IRQ EXTI15_10_IRQn
#define KEY2_IRQHandler EXTI15_10_IRQHandler
第一步:初始化需要连接到的EXTI的GPIO
void EXIT_KEY_Config(void){
/*第一步:初始化需要连接到EXIT线的GPIO*/
/*初始化GPIO时钟*/
RCC_AHB1PeriphClockCmd(KEY1_INIT_GPIO_CLK|KEY2_INIT_GPIO_CLK,ENABLE);//打开key1,key2的GPIO时钟
/*定义GPIO初始化结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*配置KEY1_GPIO初始化结构体成员*/
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;//输入模式
/*EXIT_KEY_Typedef.GPIO_OType=GPIO_OType_PP; 输入模式中用不到*/
GPIO_InitStructure.GPIO_Pin=KEY1_INIT_GPIO_PIN; //定义引脚
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;//无上下拉
GPIO_InitStructure.GPIO_Speed=GPIO_Low_Speed;//速度:LOW
/*调用GPIO初始化函数,把配置好的KEY1_GPIO初始化成员写入寄存器*/
GPIO_Init(KEY1_INIT_GPIO_PORT, &GPIO_InitStructure);
/*配置KEY2_GPIO初始化结构体成员,与KEY1_GPIO相一致,只需配置引脚*/
GPIO_InitStructure.GPIO_Pin=KEY2_INIT_GPIO_PIN; //定义引脚
/*调用GPIO初始化函数,把配置好的KEY2_GPIO初始化成员写入寄存器*/
GPIO_Init(KEY2_INIT_GPIO_PORT, &GPIO_InitStructure);
/*第二步:初始化EXIT*/
EXTI_Config();
/*第三步:配置NVIC中断优先级*/
NVIC_Config();
/*第四步:编写中断服务函数*/
//在stm32f4xx_it.c文件中编写了
}
第二步:初始化EXTI
void EXTI_Config(void){
/*使能 SYSCFG 时钟,使用GPIO外部中断时必须使能 SYSCFG 时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
/*连接 EXIT 中断源到 key1 引脚*/
SYSCFG_EXTILineConfig(KEY1_INIT_GPIO_PORTSOURCE,KEY1_INIT_GPIO_PINSOURCE);
/*连接 EXIT 中断源到 key2 引脚*/
SYSCFG_EXTILineConfig(KEY2_INIT_GPIO_PORTSOURCE,KEY2_INIT_GPIO_PINSOURCE);
/*定义中断初始化结构体*/
EXTI_InitTypeDef EXTI_InitStructure;
/*配置EXTI初始化结构体成员*/
//KEY1中断
EXTI_InitStructure.EXTI_Line=KEY1_INT_EXTI_LINE; //选择EXTI中断源
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//中断模式
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;//上升沿触发
/*使能中断/事件线*/
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStructure);
//KEY2中断,相同部分不许要配置
EXTI_InitStructure.EXTI_Line=KEY2_INT_EXTI_LINE; //选择EXTI中断源
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//下降沿触发
/*使能中断/事件线*/
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStructure);
第三步:配置NVIC中断优先级
/*配置NVIC优先级*/
void NVIC_Config(void){
/*定义NVIC初始化结构体*/
NVIC_InitTypeDef NVIC_InitStructure;
/*配置NVIC优先级组1*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/*配置中断源:KEY1*/
NVIC_InitStructure.NVIC_IRQChannel=KEY1_INT_EXTI_IRQ;
/*配置抢占优先级*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/*配置子优先级*/
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
/*中断使能通道*/
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
/*配置中断源:KEY2*/
NVIC_InitStructure.NVIC_IRQChannel=KEY2_INT_EXTI_IRQ;
/*中断使能通道*/
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
第四步:编写中断服务函数
void KEY1_IRQHandeler(void){
/*确保是否产生了EXTI Line中断*/
if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE)==SET)
{
/*灯翻转一次*/
}
/*清除中断标志位*/
EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
}
void KEY2_IRQHandeler(void){
/*确保是否产生了EXTI Line中断*/
if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE)==SET)
{
/*灯翻转一次*/
}
/*清除中断标志位*/
EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);
}
上一篇:STM32F429 Cubemx配置Timer实现5ms一个中断
下一篇:stm32系统时钟学习笔记
推荐阅读最新更新时间:2024-11-17 00:31
设计资源 培训 开发板 精华推荐
- LTC3877IUK 3+1 降压转换器的典型应用电路,在 90A 时为 0.6V 至 1.23V,在 30A 时为 1.2V
- 1.3寸ips 触摸屏 显示模块
- 1.8V, 2.5V, 3.3V, 5V, 6V DC-DC 单路输出电源充电器
- C722948_GL827L读卡器芯片方案验证板
- LTC2634-HZ8 四路、8 位数模转换器的典型应用
- 使用 Diodes Incorporated 的 PT8A3515 的参考设计
- 使用内部软启动的典型应用电路,VIN = 12 V,VOUT = 1.8 V,IOUT = 4 A,fSW = 600 kHz,适用于 ADP2384 20V、4A、同步降压直流至直流稳压器
- [DIY] 自制stm32开发版
- LT3758、12V 输出非隔离式反激电源的典型应用电路
- LT1207 的典型应用 - 双路 250mA/60MHz 电流反馈放大器