这次笔记的主要目的是学习中断,并运用中断,利用外部按键使得自己设置的LED的反转。
外部中断
STM32
的每个
IO
口都可以作为中断输入,这点很好很强大。要把
IO
口作为外部中断输入,
有以下几个步骤:
1
)初始化
IO
口为输入。
这一步设置你要作为外部中断输入的
IO
口的状态,可以设置为上拉
/
下拉输入,也可以设
置为浮空输入,但浮空的时候外部一定要带上拉,或者下拉电阻。否则可能导致中断不停的触
发。在干扰较大的地方,就算使用了上拉
/下拉,也建议使用外部上拉/下拉电阻,这样可以一
定程度防止外部干扰带来的影响。
2
)开启
IO
口复用时钟,设置
IO
口与中断线的映射关系。
STM32
的
IO
口与中断线的对应关系需要配置外部中断配置寄存器
EXTICR
,这样我们要
先开启复用时钟,然后配置
IO
口与中断线的对应关系。才能把外部中断与中断线连接起来。
3
)开启与该
IO
口相对的线上中断
/
事件,设置触发条件。
这一步,我们要配置中断产生的条件,
STM32
可以配置成上升沿触发,下降沿触发,或者
任意电平变化触发,但是不能配置成高电平触发和低电平触发。这里根据自己的实际情况来配
置,同时要开启中断线上的中断。这里需要注意的是:如果使用外部中断,并设置该中断的
EMR
位的话,会引起软件仿真不能跳到中断,而硬件上是可以的。而不设置
EMR
,软件仿真就可以
进入中断服务函数,并且硬件上也是可以的。建议不要配置
EMR
位。
4
)配置中断分组(
NVIC
),并使能中断。
这一步,我们就是配置中断的分组,以及使能,对
STM32
的中断来说,只有配置了
NVIC
的设置,并开启才能被执行,否则是不会执行到中断服务函数里面去的。关于
NVIC
的详细介
绍,请参考
5.2.6
节。
5
)编写中断服务函数。
这是中断设置的最后一步,中断服务函数,是必不可少的,如果在代码里面开启了中断,
但是没编写中断服务函数,就可能引起硬件错误,从而导致程序崩溃!所以在开启了某个中断
后,一定要记得为该中断编写服务函数。在中断服务函数里面编写你要执行的中断后的操作。
通过以上几个步骤的设置,我们就可以正常使用外部中断了。
重点
STM32 将中断分为
5
个组,组
0~4
。该分组的设 置是由 SCB->AIRCR
寄存器的
bit10~8
来定义的。具体的分配关系如表
所示:

通过这个表,我们就可以清楚的看到组 0~4 对应的配置关系,例如组设置为
3
,那么此时 所有的 68
个中断,每个中断的中断优先寄存器的高四位中的最高
3
位是抢占优先级,低
1
位是 应优先级。每个中断,你可以设置抢占优先级为 0~7
,响应优先级为
1
或
0
。抢占优先级的 级别高于响应优先级。而数值越小所代表的优先级就越高。
1)如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;
2)高优先级的抢占优先级是可以打断正在进行的低抢占优先级 中断的。而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断。
虽然我的功能与代码没能展现出优先级,但这必须懂。
我的引脚
PB5,PB6连接外部按键,PB7连接外部LED,通过中断检查按键,实现LED的反转。
我的代码
exti.c
//外部中断9~5服务程序
void EXTI9_5_IRQHandler(void)
{
delay_ms(10); //消抖
if(KEY0 ==0) //按键0
{
LED0=!LED0;
}
EXTI->PR=1<<5; //清除LINE5上的中断标志位
}
void EXTI_Init(void)
{
KEY_Init();
Ex_NVIC_Config(GPIO_B,5,FTIR); //上升沿触发
MY_NVIC_Init(2,1,EXTI9_5_IRQn,2); //抢占2,子优先级1,组2
}
key.c
void KEY_Init(void)
{
RCC->APB2ENR|=1<<3; //使能PORTB时钟
GPIOB->CRL&=0XF00FFFFF; //清零
GPIOB->CRL|=0X03800000;
GPIOB->ODR|=1<<5;
PBout(6)=0;//将PB6设置为低电平
}
led.h
#ifndef __LED_H
#define __LED_H
#include "sys.h"
//LED端口定义
#define LED0 PBout(7)// PB7
void LED_Init(void); //初始化
#endif
led.c
void LED_Init(void)
{
RCC->APB2ENR|=1<<3; //使能PORTB时钟
GPIOB->CRL&=0X0FFFFFFF;
GPIOB->CRL|=0X30000000;//PB7 推挽输出
GPIOB->ODR|=1<<7; //PB8 输出高
}
tect.c
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "exti.h"
int main(void)
{
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
uart_init(72,9600); //串口初始化为9600
LED_Init(); //初始化与LED连接的硬件接口
EXTI_Init(); //外部中断初始化
LED0 =1;
while(1)
{
printf("OK\r\n");
delay_ms (1000);
}
}
代码的运行
当检测的按键的下升时,中断响应函数开始运行,中断初始化函数对中断与优先级进行初始化,并对按键进行了初始化,然后LED进行翻转。