STM32学习笔记(白话文理解版)—外部IO中断实验
目录
一、什么是中断
理解定义:
中断是指一个突发事件,中止了CPU当前的工作,转而处理突发事件,处理完成后再回到当前工作中继续执行。
二、中断分类
STM32允许多种多样的中断,如外部IO、ADC、USART、I2C、RTC、USB、PVD等
三、嵌套向量中断控制器(NVIC)
理解:
根据上文我们知道STM32允许多种多样的中断,那同时发生中断怎么办呢?让哪个中断先发生哪个后发生呢?(各个中断间会产生优先级),因此我们需要管理这些中断,NVIC(嵌套向量中断控制器)便能设置各个中断的优先级来管理这些中断
上图分析
- 假设我们要使用外部IO中断,我们要开启相应的中断,同时也要开启中断控制器,确保各中断可以进入中断控制器
- 当产生中断信号时,中断信号进入中断控制器,中断控制器对各中断信号进行排序有先有后,将排序最高的中断任务发送给ARM内核进行处理,处理完成后中断控制器继续发送其他较低优先级的中断进行处理。
四、中断之——EXIT外部IO中断
特点:
- 所有GPIO口都可设置为中断输入
- 外部IO可有上升沿、下降沿、高低电平三种触发方式
- 可选择中断触发或事件触发
五、外部IO中断使用步骤
- 配置时钟(使能GPIO时钟,启用复用时钟)
- IO口关联中断通道
- 配置EXTI中断
- 配置中断控制器
- 编写中断处理函数
六、外部IO中断实验
(1)实验功能
最开始LED灯处于熄灭状态,给PA4引脚一个下降沿,进入中断处理函数,其中中断处理函数功能为,使LED灯点亮
(2)主函数部分
函数功能:
函数从主函数依次向下执行:
- 初始化LED
- 将LED灯设置为低电平,这是LED灯处于熄灭状态
- 设置中断优先级(初学默认)
- 将中断通道进行初始化
#include "stm32f10x.h"
#include "sys.h"
#include "led.h"
#include "nvic.h"
#include "delay.h"
int main(void)
{
LED_Init();//初始化LED(将引脚PA10初始化)
LED_Low();//设置LED最开始为灭(将引脚PA10设置为低电平)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级(初学者默认设置就好)
KEYLED();//中断的初始化
while(1)
{
};
}
(3)LED部分
设置了三个函数:
LED_Init()函数:进行LED灯的初始化,其中包括两部分:
* RCC_APB2PeriphClockCmd()函数:使能时钟
* GPIO_Init()函数:IO引脚的初始化函数,进行个个引脚的初始化配置,主要接受两个参数(配置引脚组,配置的参数)LED_Low()函数:熄灭LED灯
* GPIO_ResetBits()函数:(引脚组,引脚组中的几号)使此IO口输出低电平LED_High()函数:点亮LED灯
* GPIO_SetBits()函数:(引脚组,引脚组中的几号)使此IO口输出高电平
#include "sys.h"
#include "led.h"
void LED_Init(void)//点灯函数初始化
{
//定义结构体为初始化引脚(GPIO_Init函数)做准备
GPIO_InitTypeDef GPIO_InitStruct;
//配置时钟rcc 使能APB2这个时钟,时钟于STM32就像是人的心脏,只有开启心脏,并将心脏置于正确的模式,单片机才能更好的工作
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//配置引脚gpio
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//设置引脚为 推挽输出模式(初学记住就行)
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;//配置的是哪个引脚?引脚10
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//配置是什么速度?
GPIO_Init(GPIOA,&GPIO_InitStruct);
}
void LED_Low(void)//熄灭LED灯
{
//输出低电平
GPIO_ResetBits(GPIOA,GPIO_Pin_10);//引脚组A,引脚组A的10号引脚
}
void LED_High(void)//点亮LED灯
{
//输出高电平
GPIO_SetBits(GPIOA,GPIO_Pin_10);//引脚组A,引脚组A的10号引脚
}
(4)中断部分
配置步骤:
- 配置时钟
- IO口关联中断通道
- 配置EXTI中断
- 配置中断控制器
#include "nvic.h"
#include "sys.h"
#include "led.h"
/*
1.配置时钟
2.IO口关联中断通道(见下图)
3.配置EXTI中断
4.配置中断控制器
*/
void KEYLED(void)
{
NVIC_InitTypeDef NVIC_InitStruct; //定义结构体变量
EXTI_InitTypeDef EXTI_InitStruct;
//1.配置时钟:时钟对于STM32就像是人的心脏,我们启动心脏,并讲心脏设置为合理的模式,STM32才能正确的运行
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //启动GPIO时钟 (需要与复用时钟一同启动)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO , ENABLE);//配置端口中断需要启用复用时钟
//2.IO口关联中断通道(见图解)
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource4); //定义 GPIO 中断
//3.配置EXTI中断(和点灯配置相同)
EXTI_InitStruct.EXTI_Line=EXTI_Line4; //定义中断线
EXTI_InitStruct.EXTI_LineCmd=ENABLE; //中断使能
EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt; //中断模式为 中断
EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling; //下降沿触发
EXTI_Init(& EXTI_InitStruct);//中断初始化:上面4条语句都是为这条铺垫,因为这条的函数参数是结构体变量
//4.配置中断控制器(和点灯配置相同)
NVIC_InitStruct.NVIC_IRQChannel=EXTI4_IRQn; //中断线
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; //使能中断
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2; //抢占优先级 2
NVIC_InitStruct.NVIC_IRQChannelSubPriority=2; //子优先级 2
NVIC_Init(& NVIC_InitStruct);//中断控制器初始化:上面4条语句都是为这条铺垫,因为这条的函数参数是结构体变量
}
//中断执行函数:
void EXTI4_IRQHandler(void){
if(EXTI_GetITStatus(EXTI_Line4)!=RESET){//判断某个线上的中断是否发生
//如果发生中断执行下面语句
LED_High();//开启灯(将引脚PA10设置为高电平)
EXTI_ClearITPendingBit(EXTI_Line4); //清除 LINE 上的中断标志位
}
}
关于2. IO口关联中断通道解释:
STM32的IO口有100多个,但供IO口使用的中断线只有16个,那我们就需要将16个中断线和100多个IO口对应起来,使每个中断标志位对应了许多个GPIO引脚
eg:EXIT4 对应了PA4、PB4、PC4…PG4故配置外部IO中断部分时需要将IO口和中断联系起来,以此来说明使用了哪个IO口的中断
eg:本例子使用了PA4引脚的中断,根据图示应该关联EXTI4标志位,关联后就可根据EXTI_Init()函数 进行外部中断EXTI的配置了
六、总结
最开始时LED灯为熄灭状态,通过对外部IO中断的设置,设置为给一个IO端口下降沿后,进入中断处理函数,中断处理函数内执行点亮LED的操作,而后跳出中断处理函数,继续执行主函数。
本篇粗浅介绍了什么是中断,中断的分类,中断中外部IO中断的应用步骤,浅薄的理解了外部IO中断实验,如有不对之处还请批评指正。