STM32F407ZE开发板外部中断驱动按键,实现按键控制LED灯的开关。
main.c部分:
#include 《stm32f4xx.h》 //该头文件作用和reg51.h是一样的
#include “sys.h”
#include “led.h”
#include “key.h”
#include “delay.h”
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 2分组
LED_Init(); //LED灯初始化
KEYEXTI_Init1(); //按键PA0的外部中断初始化
while(1)
{
}
}
sys.h部分:
#ifndef __SYS_H
#define __SYS_H
#include “stm32f4xx.h”
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr & 0xFFFFF)《《5)+(bitnum《《2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+20) //0x40020014
#define GPIOB_ODR_Addr (GPIOB_BASE+20) //0x40020414
#define GPIOC_ODR_Addr (GPIOC_BASE+20) //0x40020814
#define GPIOD_ODR_Addr (GPIOD_BASE+20) //0x40020C14
#define GPIOE_ODR_Addr (GPIOE_BASE+20) //0x40021014
#define GPIOF_ODR_Addr (GPIOF_BASE+20) //0x40021414
#define GPIOG_ODR_Addr (GPIOG_BASE+20) //0x40021814
#define GPIOH_ODR_Addr (GPIOH_BASE+20) //0x40021C14
#define GPIOI_ODR_Addr (GPIOI_BASE+20) //0x40022014
#define GPIOA_IDR_Addr (GPIOA_BASE+16) //0x40020010
#define GPIOB_IDR_Addr (GPIOB_BASE+16) //0x40020410
#define GPIOC_IDR_Addr (GPIOC_BASE+16) //0x40020810
#define GPIOD_IDR_Addr (GPIOD_BASE+16) //0x40020C10
#define GPIOE_IDR_Addr (GPIOE_BASE+16) //0x40021010
#define GPIOF_IDR_Addr (GPIOF_BASE+16) //0x40021410
#define GPIOG_IDR_Addr (GPIOG_BASE+16) //0x40021810
#define GPIOH_IDR_Addr (GPIOH_BASE+16) //0x40021C10
#define GPIOI_IDR_Addr (GPIOI_BASE+16) //0x40022010
//STM32中 对寄存器的访问 是不能单独访问寄存器的单个bit 只能以32bit地址访问寄存器
//这些位为只写形式,只能在字(word)--4byte、半字2byte 或字节模式下访问
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
#define PHout(n) BIT_ADDR(GPIOH_ODR_Addr,n) //输出
#define PHin(n) BIT_ADDR(GPIOH_IDR_Addr,n) //输入
#define PIout(n) BIT_ADDR(GPIOI_ODR_Addr,n) //输出
#define PIin(n) BIT_ADDR(GPIOI_IDR_Addr,n) //输入
#endif
led.h部分:
#ifndef _LED_H_
#define _LED_H_
#include 《stm32f4xx.h》
#include “sys.h”
void LED_Init(void);
#endif
led.c部分:
#include “led.h”
void LED_Init(void)
{
GPIO_InitTypeDef aaa;
//1、先开启对应用到的模块时钟节拍
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);//PE组时钟
//2、可以初始化配置GPIO F组的9号引脚
aaa.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
aaa.GPIO_Mode = GPIO_Mode_OUT;//输出模式
aaa.GPIO_Speed = GPIO_Fast_Speed;//快速 点灯和引脚速度无关
aaa.GPIO_OType = GPIO_OType_PP;//推挽输出
aaa.GPIO_PuPd = GPIO_PuPd_UP;//内部上拉
GPIO_Init(GPIOF,&aaa);
aaa.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;
GPIO_Init(GPIOE,&aaa);
//初始化完成 灭掉4盏灯
PFout(9) = 1;
PFout(10) = 1;
PEout(13) = 1;
PEout(14) = 1;
}
key.h部分:
#ifndef _KEY_H_
#define _KEY_H_
#include 《stm32f4xx.h》
#include “sys.h”
void KEY_Init(void);
void KEYEXTI_Init1(void);
#endif
key.c部分:
#include “key.h”
#include “delay.h”
void KEY_Init()
{
GPIO_InitTypeDef KEY1,KEY2;
//先开启对应用到的模块时钟节拍PA、PE
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
//初始化KEY1
KEY1.GPIO_Pin = GPIO_Pin_0 ;
KEY1.GPIO_Mode = GPIO_Mode_IN;
KEY1.GPIO_Speed = GPIO_Fast_Speed;
KEY1.GPIO_OType = GPIO_OType_PP;
KEY1.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA,&KEY1);
//初始化KEY2、KEY3、KEY4
KEY2.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
KEY2.GPIO_Mode = GPIO_Mode_IN;
KEY2.GPIO_Speed = GPIO_Fast_Speed;
KEY2.GPIO_OType = GPIO_OType_PP;
KEY2.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOE,&KEY2);
}
void KEYEXTI_Init1(void)
{
EXTI_InitTypeDef Keyexti_Struct1;
NVIC_InitTypeDef Keynvic_Struct1;
//0、使能SYSCFG EXTI相关时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
//1、先初始化按键引脚
KEY_Init();
//2、将PA0、PE2、PE3、PE4引脚用作为外部中断引脚
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource2);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource3);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource4);
//3、初始化EXTI(设置对应的中断线0,2,3,4)
Keyexti_Struct1.EXTI_Line = EXTI_Line0 | EXTI_Line2 | EXTI_Line3 | EXTI_Line4;
Keyexti_Struct1.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
Keyexti_Struct1.EXTI_Trigger = EXTI_Trigger_Falling; //上升沿--按键松开触发
Keyexti_Struct1.EXTI_LineCmd = ENABLE; //外部中断开启使能设置
EXTI_Init(&Keyexti_Struct1);
//4、NVIC初始化
Keynvic_Struct1.NVIC_IRQChannel = EXTI0_IRQn; //中断线0对应的函数
Keynvic_Struct1.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级设置
Keynvic_Struct1.NVIC_IRQChannelSubPriority = 0; //响应优先级
Keynvic_Struct1.NVIC_IRQChannelCmd = ENABLE; //开启NVIC管理
NVIC_Init(&Keynvic_Struct1);
Keynvic_Struct1.NVIC_IRQChannel = EXTI2_IRQn; //中断线2对应的函数
NVIC_Init(&Keynvic_Struct1);
Keynvic_Struct1.NVIC_IRQChannel = EXTI3_IRQn; //中断线3对应的函数
NVIC_Init(&Keynvic_Struct1);
Keynvic_Struct1.NVIC_IRQChannel = EXTI4_IRQn; //中断线4对应的函数
NVIC_Init(&Keynvic_Struct1);
}
void EXTI0_IRQHandler(void)
{
delay(80); //延时消抖
PFout(9) = !PFout(9); //LED1置位取反
EXTI_ClearITPendingBit(EXTI_Line0); //标志位清除
}
void EXTI2_IRQHandler(void)
{
delay(80); //延时消抖
PFout(10) = !PFout(10); //LED2置位取反
EXTI_ClearITPendingBit(EXTI_Line2); //标志位清除
}
void EXTI3_IRQHandler(void)
{
delay(80); //延时消抖
PEout(13) = !PEout(13); //LED3置位取反
EXTI_ClearITPendingBit(EXTI_Line3); //标志位清除
}
void EXTI4_IRQHandler(void)
{
delay(80); //延时消抖
PEout(14) = !PEout(14); //LED4置位取反
EXTI_ClearITPendingBit(EXTI_Line4); //标志位清除
}
delay.h部分:
#ifndef _DELAY_H_
#define _DELAY_H_
void delay(int tim);
#endif
delay.c部分:
#include “delay.h”
void delay(int tim)
{
int i;
while(tim--)
{
for(i =38400;i》0;i--);
}
}
----------------------------------------------------------分割线----------------------------------------------------------
设置外部中断,主要由下面函数设定:
void KEYEXTI_Init1(void)
{
EXTI_InitTypeDef Keyexti_Struct1;
NVIC_InitTypeDef Keynvic_Struct1;
//0、使能SYSCFG EXTI相关时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
//1、先初始化按键引脚
KEY_Init();
//2、将PA0、PE2、PE3、PE4引脚用作为外部中断引脚
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource2);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource3);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource4);
//3、初始化EXTI(设置对应的中断线0,2,3,4)
Keyexti_Struct1.EXTI_Line = EXTI_Line0 | EXTI_Line2 | EXTI_Line3 | EXTI_Line4;
Keyexti_Struct1.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
Keyexti_Struct1.EXTI_Trigger = EXTI_Trigger_Falling; //上升沿--按键松开触发
Keyexti_Struct1.EXTI_LineCmd = ENABLE; //外部中断开启使能设置
EXTI_Init(&Keyexti_Struct1);
//4、NVIC初始化
Keynvic_Struct1.NVIC_IRQChannel = EXTI0_IRQn; //中断线0对应的函数
Keynvic_Struct1.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级设置
Keynvic_Struct1.NVIC_IRQChannelSubPriority = 0; //响应优先级
Keynvic_Struct1.NVIC_IRQChannelCmd = ENABLE; //开启NVIC管理
NVIC_Init(&Keynvic_Struct1);
Keynvic_Struct1.NVIC_IRQChannel = EXTI2_IRQn; //中断线2对应的函数
NVIC_Init(&Keynvic_Struct1);
Keynvic_Struct1.NVIC_IRQChannel = EXTI3_IRQn; //中断线3对应的函数
NVIC_Init(&Keynvic_Struct1);
Keynvic_Struct1.NVIC_IRQChannel = EXTI4_IRQn; //中断线4对应的函数
NVIC_Init(&Keynvic_Struct1);
}
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)
参数1:EXTI_InitStruct
typedef struct
{
uint32_t EXTI_Line; // EXTI_Line0
EXTIMode_TypeDef EXTI_Mode; // EXTI_Mode_Interrupt
EXTITrigger_TypeDef EXTI_Trigger;
FunctionalState EXTI_LineCmd;
}EXTI_InitTypeDef;
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
参数1:NVIC_InitStruct
typedef struct
{
uint8_t NVIC_IRQChannel; //选择你要配置的中断的全局中断编号
//EXTI_Line0 该编号去stm32f4xx.h头文件
//查找 Line176 EXTI0_IRQn 6号
uint8_t NVIC_IRQChannelPreemptionPriority; //抢占优先级(第一)0~15
uint8_t NVIC_IRQChannelSubPriority; //响应优先级 (第二)0~15
//数字越小 优先级越高
规则1:当两个中断的抢占优先级不同时 响应优先级不考虑
①如果两个中断同时出发 限制性高抢占的
②如果高抢占先触发 低抢占后触发 低抢占只能排队等待高抢占的处理完 再做低抢占
③当低抢占先触发 并先被CPU响应了 ,但高抢占后触发 ,就会出现高抢占把低抢占的处理过程抢占了(中断嵌套)
规则2:当两个中断的抢占优先级相同 则去考虑响应优先级规则和上面一样 ,但是不能发生抢占
规则3: 关于设置这两个优先级的问题:
关于某个中断的优先级设置 ,只给记录优先级的数值提供了4bit的记录空间----分配问题
40 : 4bit给抢占 0000 ~1111 0bit给响应
31 : 3bit给抢占 1bit 给响应
22 : 0~3:抢占 0~3:响应
13
04
这个分组设置最好在我们的工程一开始就设置好,而且只要设置一次即可!!
FunctionalState NVIC_IRQChannelCmd; //ENABLE DISABLE
} NVIC_InitTypeDef;
STM32F407ZE开发板外部中断驱动按键,实现按键控制LED灯的开关。
main.c部分:
#include 《stm32f4xx.h》 //该头文件作用和reg51.h是一样的
#include “sys.h”
#include “led.h”
#include “key.h”
#include “delay.h”
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 2分组
LED_Init(); //LED灯初始化
KEYEXTI_Init1(); //按键PA0的外部中断初始化
while(1)
{
}
}
sys.h部分:
#ifndef __SYS_H
#define __SYS_H
#include “stm32f4xx.h”
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr & 0xFFFFF)《《5)+(bitnum《《2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+20) //0x40020014
#define GPIOB_ODR_Addr (GPIOB_BASE+20) //0x40020414
#define GPIOC_ODR_Addr (GPIOC_BASE+20) //0x40020814
#define GPIOD_ODR_Addr (GPIOD_BASE+20) //0x40020C14
#define GPIOE_ODR_Addr (GPIOE_BASE+20) //0x40021014
#define GPIOF_ODR_Addr (GPIOF_BASE+20) //0x40021414
#define GPIOG_ODR_Addr (GPIOG_BASE+20) //0x40021814
#define GPIOH_ODR_Addr (GPIOH_BASE+20) //0x40021C14
#define GPIOI_ODR_Addr (GPIOI_BASE+20) //0x40022014
#define GPIOA_IDR_Addr (GPIOA_BASE+16) //0x40020010
#define GPIOB_IDR_Addr (GPIOB_BASE+16) //0x40020410
#define GPIOC_IDR_Addr (GPIOC_BASE+16) //0x40020810
#define GPIOD_IDR_Addr (GPIOD_BASE+16) //0x40020C10
#define GPIOE_IDR_Addr (GPIOE_BASE+16) //0x40021010
#define GPIOF_IDR_Addr (GPIOF_BASE+16) //0x40021410
#define GPIOG_IDR_Addr (GPIOG_BASE+16) //0x40021810
#define GPIOH_IDR_Addr (GPIOH_BASE+16) //0x40021C10
#define GPIOI_IDR_Addr (GPIOI_BASE+16) //0x40022010
//STM32中 对寄存器的访问 是不能单独访问寄存器的单个bit 只能以32bit地址访问寄存器
//这些位为只写形式,只能在字(word)--4byte、半字2byte 或字节模式下访问
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
#define PHout(n) BIT_ADDR(GPIOH_ODR_Addr,n) //输出
#define PHin(n) BIT_ADDR(GPIOH_IDR_Addr,n) //输入
#define PIout(n) BIT_ADDR(GPIOI_ODR_Addr,n) //输出
#define PIin(n) BIT_ADDR(GPIOI_IDR_Addr,n) //输入
#endif
led.h部分:
#ifndef _LED_H_
#define _LED_H_
#include 《stm32f4xx.h》
#include “sys.h”
void LED_Init(void);
#endif
led.c部分:
#include “led.h”
void LED_Init(void)
{
GPIO_InitTypeDef aaa;
//1、先开启对应用到的模块时钟节拍
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);//PE组时钟
//2、可以初始化配置GPIO F组的9号引脚
aaa.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
aaa.GPIO_Mode = GPIO_Mode_OUT;//输出模式
aaa.GPIO_Speed = GPIO_Fast_Speed;//快速 点灯和引脚速度无关
aaa.GPIO_OType = GPIO_OType_PP;//推挽输出
aaa.GPIO_PuPd = GPIO_PuPd_UP;//内部上拉
GPIO_Init(GPIOF,&aaa);
aaa.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;
GPIO_Init(GPIOE,&aaa);
//初始化完成 灭掉4盏灯
PFout(9) = 1;
PFout(10) = 1;
PEout(13) = 1;
PEout(14) = 1;
}
key.h部分:
#ifndef _KEY_H_
#define _KEY_H_
#include 《stm32f4xx.h》
#include “sys.h”
void KEY_Init(void);
void KEYEXTI_Init1(void);
#endif
key.c部分:
#include “key.h”
#include “delay.h”
void KEY_Init()
{
GPIO_InitTypeDef KEY1,KEY2;
//先开启对应用到的模块时钟节拍PA、PE
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
//初始化KEY1
KEY1.GPIO_Pin = GPIO_Pin_0 ;
KEY1.GPIO_Mode = GPIO_Mode_IN;
KEY1.GPIO_Speed = GPIO_Fast_Speed;
KEY1.GPIO_OType = GPIO_OType_PP;
KEY1.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA,&KEY1);
//初始化KEY2、KEY3、KEY4
KEY2.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
KEY2.GPIO_Mode = GPIO_Mode_IN;
KEY2.GPIO_Speed = GPIO_Fast_Speed;
KEY2.GPIO_OType = GPIO_OType_PP;
KEY2.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOE,&KEY2);
}
void KEYEXTI_Init1(void)
{
EXTI_InitTypeDef Keyexti_Struct1;
NVIC_InitTypeDef Keynvic_Struct1;
//0、使能SYSCFG EXTI相关时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
//1、先初始化按键引脚
KEY_Init();
//2、将PA0、PE2、PE3、PE4引脚用作为外部中断引脚
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource2);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource3);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource4);
//3、初始化EXTI(设置对应的中断线0,2,3,4)
Keyexti_Struct1.EXTI_Line = EXTI_Line0 | EXTI_Line2 | EXTI_Line3 | EXTI_Line4;
Keyexti_Struct1.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
Keyexti_Struct1.EXTI_Trigger = EXTI_Trigger_Falling; //上升沿--按键松开触发
Keyexti_Struct1.EXTI_LineCmd = ENABLE; //外部中断开启使能设置
EXTI_Init(&Keyexti_Struct1);
//4、NVIC初始化
Keynvic_Struct1.NVIC_IRQChannel = EXTI0_IRQn; //中断线0对应的函数
Keynvic_Struct1.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级设置
Keynvic_Struct1.NVIC_IRQChannelSubPriority = 0; //响应优先级
Keynvic_Struct1.NVIC_IRQChannelCmd = ENABLE; //开启NVIC管理
NVIC_Init(&Keynvic_Struct1);
Keynvic_Struct1.NVIC_IRQChannel = EXTI2_IRQn; //中断线2对应的函数
NVIC_Init(&Keynvic_Struct1);
Keynvic_Struct1.NVIC_IRQChannel = EXTI3_IRQn; //中断线3对应的函数
NVIC_Init(&Keynvic_Struct1);
Keynvic_Struct1.NVIC_IRQChannel = EXTI4_IRQn; //中断线4对应的函数
NVIC_Init(&Keynvic_Struct1);
}
void EXTI0_IRQHandler(void)
{
delay(80); //延时消抖
PFout(9) = !PFout(9); //LED1置位取反
EXTI_ClearITPendingBit(EXTI_Line0); //标志位清除
}
void EXTI2_IRQHandler(void)
{
delay(80); //延时消抖
PFout(10) = !PFout(10); //LED2置位取反
EXTI_ClearITPendingBit(EXTI_Line2); //标志位清除
}
void EXTI3_IRQHandler(void)
{
delay(80); //延时消抖
PEout(13) = !PEout(13); //LED3置位取反
EXTI_ClearITPendingBit(EXTI_Line3); //标志位清除
}
void EXTI4_IRQHandler(void)
{
delay(80); //延时消抖
PEout(14) = !PEout(14); //LED4置位取反
EXTI_ClearITPendingBit(EXTI_Line4); //标志位清除
}
delay.h部分:
#ifndef _DELAY_H_
#define _DELAY_H_
void delay(int tim);
#endif
delay.c部分:
#include “delay.h”
void delay(int tim)
{
int i;
while(tim--)
{
for(i =38400;i》0;i--);
}
}
----------------------------------------------------------分割线----------------------------------------------------------
设置外部中断,主要由下面函数设定:
void KEYEXTI_Init1(void)
{
EXTI_InitTypeDef Keyexti_Struct1;
NVIC_InitTypeDef Keynvic_Struct1;
//0、使能SYSCFG EXTI相关时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
//1、先初始化按键引脚
KEY_Init();
//2、将PA0、PE2、PE3、PE4引脚用作为外部中断引脚
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource2);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource3);
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource4);
//3、初始化EXTI(设置对应的中断线0,2,3,4)
Keyexti_Struct1.EXTI_Line = EXTI_Line0 | EXTI_Line2 | EXTI_Line3 | EXTI_Line4;
Keyexti_Struct1.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
Keyexti_Struct1.EXTI_Trigger = EXTI_Trigger_Falling; //上升沿--按键松开触发
Keyexti_Struct1.EXTI_LineCmd = ENABLE; //外部中断开启使能设置
EXTI_Init(&Keyexti_Struct1);
//4、NVIC初始化
Keynvic_Struct1.NVIC_IRQChannel = EXTI0_IRQn; //中断线0对应的函数
Keynvic_Struct1.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级设置
Keynvic_Struct1.NVIC_IRQChannelSubPriority = 0; //响应优先级
Keynvic_Struct1.NVIC_IRQChannelCmd = ENABLE; //开启NVIC管理
NVIC_Init(&Keynvic_Struct1);
Keynvic_Struct1.NVIC_IRQChannel = EXTI2_IRQn; //中断线2对应的函数
NVIC_Init(&Keynvic_Struct1);
Keynvic_Struct1.NVIC_IRQChannel = EXTI3_IRQn; //中断线3对应的函数
NVIC_Init(&Keynvic_Struct1);
Keynvic_Struct1.NVIC_IRQChannel = EXTI4_IRQn; //中断线4对应的函数
NVIC_Init(&Keynvic_Struct1);
}
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)
参数1:EXTI_InitStruct
typedef struct
{
uint32_t EXTI_Line; // EXTI_Line0
EXTIMode_TypeDef EXTI_Mode; // EXTI_Mode_Interrupt
EXTITrigger_TypeDef EXTI_Trigger;
FunctionalState EXTI_LineCmd;
}EXTI_InitTypeDef;
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
参数1:NVIC_InitStruct
typedef struct
{
uint8_t NVIC_IRQChannel; //选择你要配置的中断的全局中断编号
//EXTI_Line0 该编号去stm32f4xx.h头文件
//查找 Line176 EXTI0_IRQn 6号
uint8_t NVIC_IRQChannelPreemptionPriority; //抢占优先级(第一)0~15
uint8_t NVIC_IRQChannelSubPriority; //响应优先级 (第二)0~15
//数字越小 优先级越高
规则1:当两个中断的抢占优先级不同时 响应优先级不考虑
①如果两个中断同时出发 限制性高抢占的
②如果高抢占先触发 低抢占后触发 低抢占只能排队等待高抢占的处理完 再做低抢占
③当低抢占先触发 并先被CPU响应了 ,但高抢占后触发 ,就会出现高抢占把低抢占的处理过程抢占了(中断嵌套)
规则2:当两个中断的抢占优先级相同 则去考虑响应优先级规则和上面一样 ,但是不能发生抢占
规则3: 关于设置这两个优先级的问题:
关于某个中断的优先级设置 ,只给记录优先级的数值提供了4bit的记录空间----分配问题
40 : 4bit给抢占 0000 ~1111 0bit给响应
31 : 3bit给抢占 1bit 给响应
22 : 0~3:抢占 0~3:响应
13
04
这个分组设置最好在我们的工程一开始就设置好,而且只要设置一次即可!!
FunctionalState NVIC_IRQChannelCmd; //ENABLE DISABLE
} NVIC_InitTypeDef;
举报