硬件平台: stm32f407ve
软件平台: win10 (OS Name: Microsoft Windows 10 Enterprise
OS Version: 10.0.18363 N/A Build 18363)
Keil5 5.26.2
HAL库版本: 2.14.0(目前下载的最新的)
中断:这个概念一般有点难以理解,但是又是一个非常重要的功能,基本所有的单片机(或者说处理器)都有中断。可见中断的重要性。51单片机都有5个中断源,这是我接触到的最简单的中断系统了。
打个比方,还是手机的那个例子,上次我说的是查询方式,这次我们的手机有了铃声了。那你需要接听任何一个电话还需要一直盯着屏幕吗?那很明显,不需要了,只要把手机带在身边,你随时可以被铃声暂停手头的事情(可能你在吃饭,睡觉,打豆豆等待各种日常生活),来接听呼入的电话。暂停手头的事情,接听电话就对应着cpu的中断处理过程(实际过程比这个要复杂一些),暂停当前的程序,跳到中断处理程序处理事件,然后返回继续当前的工作(当然接完电话,你也会回来继续干手中的事情)。还有一个比较小的细节就是,当你接电话的时候,实际你会在大脑中记住你刚刚在干嘛,不然等一下你放下电话就不知道要继续干嘛了。这个细节对应cpu也是同样需要处理的,所以就会有中断跳转之前会有现场保护(主要是寄存器值得保存到栈里),一会中断处理完之后(将之前保存到栈里的值重新返回寄存器,这个部分比较底层,涉及到cpu在执行指令时会用到哪些寄存器及cpu怎么执行指令的理论部分,这个地方不了解的话,确实不太好理解)还能回来接着干活。
但是你要意识到一个问题,程序可以跳转,还能跳转回来,这个需要一些复杂的机制才能处理,绝对不是直接跳来跳去。
回到正题,我们处理这个按键中断,stm32f407支持的中断比较多,外部中断只是其中的中断一个小部分。外部中断是指外部引脚电平的变化引起的中断事件。Stm32f407ve有82个引脚,82个引脚都可以设置中断,但是最多只能设置16个中断。这个因为GPIOA1,GPIOB1....GPIOH1共用了一个外部中断,如果GPIOB1设置了中断,那么其他组的1脚就无法设置为中断方式了。
这个地方可以参考中文参考手册的部分,比较详细。
按键中断有利于改善cpu的效率,cpu不用一直查询按键的状态,等到有按键按下的时候,直接打断cpu的执行,做中断处理。所以cpu在其他时间就可以完成很多任务了。(所有中断有利于改善cpu对于输入事件的处理效率)。
中断优先级(stm32f4的中断一共有81个吧,这么多中断一起的话,不可能都是同一个优先级,某些中断肯定要有些优越感,优先级高,有些中断就会被冷落,不重要就优先级低。这里同样注意一个问题,不一定我们每个中断都要设置优先级,我们只需要设置我们需要使用的中断就可以了。),程序中我们暂不处理这个问题,大家有点印象,就是多个中断同时发生的时候,优先级高的,可以被优先处理,如果优先级相同,就选择最先监测到中断的那个开始执行中断处理。还有一个会涉及到抢占,比如一个优先级的中断正在处理,但是一个比这个优先级更高的中断发生了,那么系统会再次打断正在处理的中断程序,处理更高优先级的事件。当然如果时低优先级的中断发生了,那么是不会被打断的。按键这个地方我们的优先级一般会设置一样,另一个角度来讲,几个按键同时触发中断的可能性极低,其实也不需要把某个按键做更紧急的处理(至少在我的程序中不需要这么处理)。
好,说了这么多,还是写程序,改动会比较大。
1.Keil的组件要增加外部中断的部分。
增加以下代码
设置按键中断模式
设置按键中断处理函数
主函数中修改按键的初始化函数,修改主循环(这里什么都不做,空转)
#include void led_init(void) { GPIO_InitTypeDef GPIO_Init; //1.时钟使能 __HAL_RCC_GPIOE_CLK_ENABLE(); //2.端口设置 GPIO_Init.Mode = GPIO_MODE_OUTPUT_OD; //输出开漏模式 GPIO_Init.Pin = GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; GPIO_Init.Pull = GPIO_PULLUP; GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW; // GPIO_Init.Alternate = ; //GPIO的mode设置位复用功能的时候,才会配置复用功能 HAL_GPIO_Init(GPIOE, &GPIO_Init); //3.点亮或熄灭灯 } /*按键初始化*/ void key_init(void) { GPIO_InitTypeDef GPIO_Init; //1.时钟使能,按键使用的时GPIOE __HAL_RCC_GPIOE_CLK_ENABLE(); //2.端口设置 GPIO_Init.Mode = GPIO_MODE_INPUT; //输入模式 GPIO_Init.Pin = GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; //设置的引脚 GPIO_Init.Pull = GPIO_NOPULL; //上拉电阻可以有也可以没有,电路本身有上拉 // GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW; //这个是设置输出速度,输入模式可以不管 // GPIO_Init.Alternate = ; //GPIO的mode设置位复用功能的时候,才会配置复用功能 HAL_GPIO_Init(GPIOE, &GPIO_Init); } /*按键中断方式初始化*/ void key_int_init(void) { GPIO_InitTypeDef GPIO_Init; //1.时钟使能,按键使用的时GPIOE __HAL_RCC_GPIOE_CLK_ENABLE(); //2.端口设置 GPIO_Init.Mode = GPIO_MODE_IT_FALLING; //下降沿中断模式 GPIO_Init.Pin = GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; //设置的引脚 GPIO_Init.Pull = GPIO_NOPULL; //上拉电阻可以有也可以没有,电路本身有上拉 HAL_GPIO_Init(GPIOE, &GPIO_Init); NVIC_SetPriority(EXTI15_10_IRQn,0xA0); //设置简单的中断优先级 NVIC_EnableIRQ(EXTI15_10_IRQn); //外部中断,10-15共用一个外部中断 } /* 按键测试程序,我的例子实现为,(这是最简单的方法) 第一个按键按下的时候,第一个灯点亮 第二个按键按下的时候,第二个灯点亮 第三个按键按下的时候,第三个灯点亮 */ int main(void) { int i; GPIO_PinState pins; HAL_Init(); //必须在第一个语句执行 led_init(); key_int_init(); while(1) { //什么事都不做,空转 } } void EXTI15_10_IRQHandler(void) { uint32_t ret; EXTI_HandleTypeDef hexti; int i; uint32_t arr[3] = {EXTI_LINE_10,EXTI_LINE_11,EXTI_LINE_12}; uint32_t ledarr[3] = {GPIO_PIN_13,GPIO_PIN_14,GPIO_PIN_15}; for(i=0;i<3;i++) { hexti.Line = arr[i]; //哪一个外部中断线触发中断 ret = HAL_EXTI_GetPending(&hexti, EXTI_TRIGGER_FALLING); if(ret) { //中断处理比较简单,直接翻转led HAL_GPIO_TogglePin(GPIOE, ledarr[i]); //清中断标志 HAL_EXTI_ClearPending(&hexti, EXTI_TRIGGER_FALLING); //下降沿 } } } void SysTick_Handler(void) { HAL_IncTick(); } github的工程源码: https://github.com/zhaozhi0810/stm32f407_hal_keil5
上一篇:7. Stm32f407 key外部中断
下一篇:5. Stm32f407 key查询方式示例
推荐阅读最新更新时间:2024-11-16 22:04
设计资源 培训 开发板 精华推荐
- 基于ESP32S2以及MaixBit的智能网络台灯
- ADZS-21479-EZLITE、ADSP-2147x EZ-KIT Lite 评估系统基于 SHARC 数字信号处理器 (DSP)
- DC2174A-A,用于 LTC3882EUJ 的演示板 7V = VIN = 14V,0.5V = VOUT0 = 2V @ 35A,0.5V = VOUT1 = 2V @ 35A
- TP78-基于CH582M的小红点VIA三模客制化键盘
- #第二届立创大赛#交直流电子负载 & 电源模拟器
- 恩智浦面向Alexa语音服务的EdgeReady MCU解决方案
- LTC3405AES6-1.5 同步降压型稳压器的典型应用电路
- 便携式移动电源
- LT6654BMPS6-2.5 扩展电源范围电压基准的典型应用
- 使用 Infineon Technologies AG 的 IRU1117 的参考设计