完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
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; |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1602 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1536 浏览 1 评论
967 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
680 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1579 浏览 2 评论
1860浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
640浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
513浏览 3评论
527浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
500浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-19 09:34 , Processed in 1.015025 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号