实验功能:使用EXTI控制按键,按下按键1绿灯变亮,按下按键2并且弹开,蓝灯亮
首先新建两个文件 bsp_exti.c和bsp_exti.h
bsp_exti.c是对中断按键的配置
1:初始化用于中断的GPIO
2:初始化EXTI,包括GPIO_EXTILineConfig以及EXTI_InitStructure初始化结构体中成员的配置,和初始化GPIO类似。
3:配置NVIC(是内核里面的外设,故在misc.c中)。要写一个NVIC按键配置函数。首先初始化NVIC结构体,然后要配置优先级,选择NVIC_PriorityGroup_1,然后配置抢占优先级和子优先级。然后对NVIC结构中的成员赋值。
4:在stm32f10x_it.c配置中断服务函数。首先要确定中断服务函数的名称,在start_up里。当中断来时,中断服务函数会被执行,我们就可以在中断服务函数中实现一些控制。一旦发生中断,我们就会调用中断服务函数中中断标志位状态读取函数EXTI_GetITStatus()来读取外设中断标志位并判断标志位状态。
在bsp_exti.c
#include "bsp_exti.h"
static void EXTI_NVIC_Config(void) //static限制这个函数只能被EXTI_Key_Config()调用
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel=KEY1_INT_EXTI_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel=KEY2_INT_EXTI_IRQ;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI_Key_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; // 定义初始化结构体
EXTI_InitTypeDef EXTI_InitStructure;
//配置中断优先级
EXTI_NVIC_Config();
/*配置按键1*/
//初始化用于中断的GPIO(具体的外设)
RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE); //开按键1的时钟
RCC_APB2PeriphClockCmd(KEY2_INT_GPIO_CLK,ENABLE); //开按键2时钟
GPIO_InitStructure.GPIO_Pin=KEY1_INT_GPIO_PIN; //选择GPIO要控制的引脚0
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY1_INT_GPIO_PORT,&GPIO_InitStructure);
//初始化EXTI(具体的外设)
GPIO_EXTILineConfig(KEY1_INT_EXTI_PortSource,KEY1_INT_EXTI_PinSource); //配置输入源
EXTI_InitStructure.EXTI_Line=KEY1_INT_EXTI_LINE; //因为是PA0,所以是Line0
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStructure); //把结构体成员写到相应的寄存器里
/*配置按键2*/
//初始化用于中断的GPIOC(具体的外设)
GPIO_InitStructure.GPIO_Pin=KEY2_INT_GPIO_PIN; //选择GPIO要控制的引脚0
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY2_INT_GPIO_PORT,&GPIO_InitStructure);
//初始化EXTI(具体的外设)
GPIO_EXTILineConfig(KEY2_INT_EXTI_PortSource,KEY2_INT_EXTI_PinSource); //配置输入源
EXTI_InitStructure.EXTI_Line=KEY2_INT_EXTI_LINE; //因为是PA0,所以是Line0
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStructure); //把结构体成员写到相应的寄存器里
}
在bsp_exti.h中
#ifndef _BSP_EXTI_H
#define _BSP_EXTI_H
#include "stm32f10x.h"
#define KEY1_INT_GPIO_PIN GPIO_Pin_0 //按键1
#define KEY1_INT_GPIO_PORT GPIOA
#define KEY1_INT_GPIO_CLK (RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO)
#define KEY1_INT_EXTI_PortSource GPIO_PortSourceGPIOA
#define KEY1_INT_EXTI_PinSource GPIO_PinSource0
#define KEY1_INT_EXTI_LINE EXTI_Line0
#define KEY1_INT_EXTI_IRQ EXTI0_IRQn
#define KEY1_IRQHandler EXTI0_IRQHandler
#define KEY2_INT_GPIO_PIN GPIO_Pin_13 //按键2
#define KEY2_INT_GPIO_PORT GPIOC
#define KEY2_INT_GPIO_CLK (RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO)
#define KEY2_INT_EXTI_PortSource GPIO_PortSourceGPIOC
#define KEY2_INT_EXTI_PinSource GPIO_PinSource13
#define KEY2_INT_EXTI_LINE EXTI_Line13
#define KEY2_INT_EXTI_IRQ EXTI15_10_IRQn
#define KEY2_IRQHandler EXTI15_10_IRQHandler
void EXTI_Key_Config(void);
#endif
在stm32f10x_it.c中,要包含bsp_led.h和bsp_exti.h
//EXTI0_IRQHandler中断服务函数
void KEY1_IRQHandler(void)
{
if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) !=RESET)
{
LED1_TOGGLE;
EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
}
}
//EXTI15_10_IRQHandler中断服务函数
void KEY2_IRQHandler(void)
{
if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) !=RESET)
{
LED2_TOGGLE;
EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);
}
}
在main.c
#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_exti.h"
//软件延时函数1ms
void delay_ms(uint32_t time)
{
uint32_t i;
while(time--)
{
i=12000;
while(i--);
}
}
int main(void)
{
LED_GPIO_Config();
EXTI_Key_Config();
while(1)
{
}
}