STM32复习(二)---EXTI外部中断各函数作用以及如何用外部中断按键控制灯

一、EXTI各函数作用

void EXTI_DeInit(void);  //调用它就可以把EXTI的配置全部清除,恢复成上电默认状态

void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);  //EXTI初始化函数

void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);  //调用这个函数,可以把函数传递的结构体变量赋一个默认值

void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);//这个函数用来软件触发外部中断,调用这个函数,参数给一个指定的中断线,就能软件触发一次这个外部中断

如果想在主程序里查看或清除标志位就用这两个函数
{
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);  //可以获取指定的标志位是否被置一了

void EXTI_ClearFlag(uint32_t EXTI_Line);  //可以对置一的标志位进行清除
}

如果想在中断函数里查看或清除标志位就用这两个函数
{
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);  //获取中断标志位是否被置一了

void EXTI_ClearITPendingBit(uint32_t EXTI_Line);  //清除中断挂起标志位
}

最后这四个函数总的来说都是读取状态寄存器

二、NVIC各函数作用

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
//★★★★用来中断分组,参数是中断分组的方式

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
//★★★★根据结构体里的参数初始化NVIC

void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);
//设置中断向量表

void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);
//系统低功耗配置

void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);
//这个函数用于配置 SysTick(系统定时器) 的时钟源


总的来说NVIC只要记住前两个函数就可以,后面三个用的不多
//先用第一个函数指定分组,然后用第二个函数初始化NVIC
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;//指定所选通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//打开通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//指定所选通道的抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//指定所选通道的响应优先级
	
    NVIC_Init(&NVIC_InitStructure);

 三、如何用外部中断按键控制灯 

如图所示,我们就用SW2按键来控制下面这个灯的亮灭

1.首先对按键进行初始化

#include "stm32f10x.h"
#include "key.h"

void key_Init(void)
{
	GPIO_InitTypeDef key_initstruct;
	EXTI_InitTypeDef exti_initstruct;
	NVIC_InitTypeDef nvic_initstruct;
//声明 GPIO、EXTI 和 NVIC 的初始化结构体
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);
//使能 GPIOA 端口和 AFIO(用于外部中断配置)时钟,必须在使用 GPIOA 和 EXTI 之前先打开时钟,否则外设无法工作。
	
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//设置中断优先级分组为 2,即:2 位抢占优先级 2 位子优先级
	
	key_initstruct.GPIO_Mode = GPIO_Mode_IPU;
//因为按键按下后为低电平,所以我们这里设置按键为上拉输入,也就是默认为高电平,以此来检查按键是否按下
	key_initstruct.GPIO_Pin  = GPIO_Pin_0;
	GPIO_Init(GPIOA,&key_initstruct);
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
//使能 PA0 作为 EXTI0 的输入信号源,使得 PA0 触发外部中断 EXTI0(说白了就是把这个GPIO口变为中断的作用)
	
	exti_initstruct.EXTI_Line    = EXTI_Line0; //选择通道(PA0,PB0...PG0全都是通道0)
	exti_initstruct.EXTI_Trigger = EXTI_Trigger_Falling; //按键按下后高电平变为低电平,所以选择下降沿触发中断
	exti_initstruct.EXTI_Mode    = EXTI_Mode_Interrupt; //配置为中断模式(而不是事件模式)
	exti_initstruct.EXTI_LineCmd = ENABLE; //使能该外部中断通道
	EXTI_Init(&exti_initstruct);
	
	nvic_initstruct.NVIC_IRQChannel = EXTI0_IRQn; //指定中断通道,即 EXTI0(对应 PA0)
	nvic_initstruct.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 0(最高优先级)
	nvic_initstruct.NVIC_IRQChannelSubPriority = 0; //子优先级0
	nvic_initstruct.NVIC_IRQChannelCmd = ENABLE; //使能该中断
	NVIC_Init(&nvic_initstruct);
	
}

 2.对LED灯进行初始化

#include "led.h"
#include "stm32f10x.h"

//初始化LED三部曲  定义(.c文件),声明(.h文件),调用(main.c)
void LED_Init(void)
{
	//1.初始化GPIOA
	GPIO_InitTypeDef led_initstruct;//定义GPIO结构体
	
	//2.初始化APB2下的GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	led_initstruct.GPIO_Pin = GPIO_Pin_1;
	led_initstruct.GPIO_Speed = GPIO_Speed_2MHz;
	led_initstruct.GPIO_Mode = GPIO_Mode_Out_PP;//初始化为推挽输出模式
	
	GPIO_Init(GPIOA,&led_initstruct);//初始化GPIO结构体
	
}

 3.编写主函数

#include "stm32f10x.h"    // Device header
#include "led.h"
#include "key.h"

void Delay(uint16_t time)//延时1ms
{
	uint16_t i = 0;
	while(time--)
	{
		i = 12000;
		while(i--);
	}
}

int main(void)
{
	
	LED_Init();
	key_Init();
	
	GPIO_SetBits(GPIOA,GPIO_Pin_1);//先把灯初始为熄灭状态
	
	while(1)
	{
		
	}
	
}

void EXTI0_IRQHandler()  //中断函数
{
	if(EXTI_GetITStatus(EXTI_Line0) != RESET) //判断按键是否被按下(判断是否在PA0检测到下降沿),也可以说是检测中断标志位是否被置1
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_1);//亮灯
		Delay(1000);                     //延时1s
		GPIO_SetBits(GPIOA,GPIO_Pin_1);  //熄灭灯
		Delay(1000);                     //延时1s
		
		EXTI_ClearITPendingBit(EXTI_Line0);  //★★★一定要记得在中断函数中清除掉标志位,要不然下次检测到下降沿将不会触发中断
	}
		
}


 注意:本次实验有几个不严谨的地方

1.没有进行按键消抖

2.Delay延时函数并不是那么精确

3.在中断函数中使用了Delay延时函数(本实验是为了现象比较明显才使用延时函数,一般在中断函数中不要使用延时函数,容易导致程序堵塞)

希望大家可以将此程序更加优化!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值