第三章 STM32F103C8T6的HAL库外部中断EXTI使用
文章目录
前言
本章开始学习外部中断EXTI的使用,掌握外部中断的触发方式,中断线,优先级,中断号,回调函数以及如何配置EXTI。末尾附带源代码供参考学习。
一、EXTI是什么?
EXTI是 允许将来自不同外设的中断 / 事件请求信号连接到微控制器的中断系统,实现对外设事件的快速响应。它可以检测外部输入信号的变化,如按键按下、传感器信号变化等,并触发相应的中断处理程序。
二、EXTI主要特点
1.支持多种触发方式
外部信号的形式一般都是以高低电平的形式发送,1为高电平,0为低电平,在低电平向高电平转变时会出现上升沿,在高电平向低电平转变时会出现下降沿,如下图所示,引脚初始化时处于上拉或者下拉状态,可根据不同使用情况进行配合,例如当输入信号是低电平时,可以采用上拉下降沿触发,当输入信号为高电平是,可采用下拉上升沿触发,当需要上升沿和下降沿都出触发时,模式选择无上拉或下拉。
上升沿触发:当外部信号从低电平变为高电平时触发中断。
gpio_init_struct.Mode = GPIO_MODE_IT_RISING;
下降沿触发:当外部信号从高电平变为低电平时触发中断。
gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;
双边沿触发:外部信号的上升沿和下降沿都能触发中断。
gpio_init_struct.Mode = GPIO_MODE_IT_RISING_FALLING;
2.中断优先级配置
抢占优先级:高抢占优先级可以打断正在执行的低抢占优先级中断。
响应优先级:当抢占优先级相同时,响应优先级高的先执行,但是不能互相打断。
数值越小,优先级越高。
通过设置中断优先级,可以确定不同中断源的响应顺序,高优先级的中断可以抢占低优先级的中断执行。如下面两条语句,0的优先级比1的优先级高,所以在同时产生中断时肯定第一条语句的中断服务函数先执行。
HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 2); /* 抢占0,子优先级2 */
HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 2); /* 抢占1,子优先级2 */
3.中断线
所有相同数字的引脚共用一条中断线,例如PA0和PB0共用一条中断线,一个中断线一次只能响应一个引脚的中断,当两个同时进入中断时,优先级高的先响应。
4.中断号
每个引脚有相应的中断号,0到4有自己一一对应的中断号,5到9共用一个中断号,10到15共用一个中断号。
5.中断服务函数及回调函数
当外部触发中断时会进入中断服务程序清楚中断标志位,同时会进入外部中断回调函数,在回调函数中执行相应的指令,回调函数括号中为该中断引脚号,所有中断服务函数都会调用回调函数,所以需要在回调函数中进行引脚号的判断。例如PA8的中断服务函数与回调函数。
/*中断服务函数*/
void EXTI9_5_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8); /* 调用中断处理公用函数 清除PA8所在中断线的中断标志位*/
}
/*外部中断回调函数*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_8)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
delay_ms(500);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);
}
}
三、程序编写
了解完EXTI的一些含义和特点就可以对外部中断进行配置,包括exti初始化配置,中断服务函数配置,回调函数指令编写。
首先可以先创建个exti.c和.h文件保存在工程文件夹下,此次仅以PA8引脚为例写一个配置函数,同样多次引用外部中断时可以在此基础上添加。
下面是exti.c库文件程序
#include "main.h"
/*中断服务函数*/
void EXTI9_5_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8); /* 调用中断处理公用函数 清除PA8所在中断线的中断标志位*/
}
/*外部中断回调函数*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_8)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
delay_ms(500);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);
}
}
void exti_init(void)
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_GPIOA_CLK_ENABLE();
gpio_init_struct.Pin = GPIO_PIN_8;
gpio_init_struct.Mode = GPIO_MODE_IT_FALLING; /* 下升沿触发 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 2); /* 抢占0,子优先级2 */
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); /* 使能中断线8 */
}
下面是exti.h文件
#ifndef __exti_H
#define __exti_H
void exti_init(void);
#endif
主函数main.c中对exti函数进行初始化,回调函数中要使用到delay延时,所以需要添加时钟配置,下一篇文章将讲解时钟配置相关内容,while可以进行空循环,等待外部中断信号。
#include "main.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
led_init();
key_init();
exti_init();
while(1)
{
}
}
最后是主函数main.h文件,将exti.h文件放入其中,方便其他函数调用。
#ifndef __main_H
#define __mian_H
#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
#include "stm32f1xx_it.h"
#include "delay.h"
#include "sys.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#endif
总结
以上就是今天要讲的内容,本文简单介绍了外部中断exti的使用,掌握exti的触发方式,优先级,在使用外部中断功能时需要了解该引脚的中断线,中断号,防止引脚使用同一个中断线,掌握exti的配置,中断服务函数与回调函数的使用,如果有疑问的地方可以私信我,若有讲错的地方还请批评指正,让我们一起学习,一起进步。
源代码链接:https://pan.baidu.com/s/1hzCq_nN06fB_h3cj6ShVmQ
提取码:zstu