实验效果与我上一篇扫描按键点灯效果基本一致,所有就不放视频了,只不过扫描按键是松开按键有效,本文中断按键采用下降沿有效,即按下按键有效。
实验步骤
首先建立工程,添加如下文件
led.c可以参考我上期发布的stm32vet6扫描按键
本次重点在key.c中的初始化配置
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Led.h"
#define key_rcc RCC_APB2Periph_GPIOD
#define key_gpio GPIOD
#define key1 GPIO_Pin_0
#define key2 GPIO_Pin_1
#define key3 GPIO_Pin_2
#define key4 GPIO_Pin_3
void key_init()
{
//初始化按键输入的GPIO和选择通道的AFIO
RCC_APB2PeriphClockCmd(key_rcc|RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitTypeDef gpiostructure;
gpiostructure.GPIO_Mode=GPIO_Mode_IPU;
gpiostructure.GPIO_Pin=key1|key2|key3|key4;
gpiostructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(key_gpio,&gpiostructure);
//配置GPIO,PIN的中断通道,这是AFIO的功能,所以一定要初始化AFIO
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource0);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource1);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource2);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource3);
//配置外部中断的通道,下降沿触发,通道开启
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line0|EXTI_Line1|EXTI_Line2|EXTI_Line3;
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure);
//中断分组,此处为2抢占,2从占
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
//本次中断没有特别的优先级,固全部采用同一套
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
NVIC_Init(&NVIC_InitStructure); //初始化通道0
NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;
NVIC_Init(&NVIC_InitStructure); //初始化通道1
NVIC_InitStructure.NVIC_IRQChannel=EXTI2_IRQn;
NVIC_Init(&NVIC_InitStructure); //初始化通道2
NVIC_InitStructure.NVIC_IRQChannel=EXTI3_IRQn;
NVIC_Init(&NVIC_InitStructure); //初始化通道3
}
//这是扫描,与本次代码无关
uint16_t key_scan()
{
uint16_t key=0;
if(GPIO_ReadInputDataBit(key_gpio,key1)==Bit_RESET)
{Delay_ms(15);while(GPIO_ReadInputDataBit(key_gpio,key1)==Bit_RESET);Delay_ms(15);key=1;}
if(GPIO_ReadInputDataBit(key_gpio,key2)==Bit_RESET)
{Delay_ms(15);while(GPIO_ReadInputDataBit(key_gpio,key2)==Bit_RESET);Delay_ms(15);key=2;}
if(GPIO_ReadInputDataBit(key_gpio,key3)==Bit_RESET)
{Delay_ms(15);while(GPIO_ReadInputDataBit(key_gpio,key3)==Bit_RESET);Delay_ms(15);key=3;}
if(GPIO_ReadInputDataBit(key_gpio,key4)==Bit_RESET)
{Delay_ms(15);while(GPIO_ReadInputDataBit(key_gpio,key4)==Bit_RESET);Delay_ms(15);key=4;}
return key;
}
//下面是四个中断函数,判断中断标志位 置1,翻转灯,清除标志
void EXTI0_IRQHandler()
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
led1toggle();
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
void EXTI1_IRQHandler()
{
if(EXTI_GetITStatus(EXTI_Line1) != RESET)
{
led2toggle();
EXTI_ClearITPendingBit(EXTI_Line1);
}
}
void EXTI2_IRQHandler()
{
if(EXTI_GetITStatus(EXTI_Line2) != RESET)
{
led3toggle();
EXTI_ClearITPendingBit(EXTI_Line2);
}
}
void EXTI3_IRQHandler()
{
if(EXTI_GetITStatus(EXTI_Line3) != RESET)
{
led4toggle();
EXTI_ClearITPendingBit(EXTI_Line3);
}
}
主函数只需初始化一下led和key即可
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Led.h"
#include "Key.h"
int main()
{
led_init();key_init();
while(1)
{
}
}
实验结果
实验非常成功