首页 > 代码库 > STM32学习之路-按键中断测试(外部中断)
STM32学习之路-按键中断测试(外部中断)
终于有时间再来学习STM32了~ 这几天都在忙着该死的考试.直接进入正题
开发板:奋斗V5
这个按键中断测试的要求是:按键2(K2)按下,LED2(V7)亮, 再一次按下就灭,循环..
好,先看看按键和LED的原理图
好吧~ 虽然图截得不是很好看,但是能看到K2接的是PC2, LED2接的是PD6
ok,剩下的就是配置工作了.. 先来理一理思路:
(1)初始化系统时钟
(2)初始化外部时钟(你所用到的东西)
(3)配置LED
(4)配置中断优先级
(5)配置外部中断线
(6)中断处理函数
恩,差不多就是这样了..
然后再来一条一条的看:(1)和(2)都属于RCC配置,可以放在一个功能模块里面:
<pre name="code" class="cpp">void RCC_Config(void) {
<span style="white-space:pre"> </span>SystemInit(); //系统时钟初始化 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG, ENABLE); }当然, 我们可以不用加SystemInit();这个函数也没事.原因是startup_stm32f10x_hd.s这个文件已经在帮我们干了这些事情了.. 它具体是怎么弄的,还有一些其它东西,目前还没
去研究过,下次再研究看看.
(3)LED配置
void LED_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; /*led config*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &GPIO_InitStructure); }LED的配置前面应该已经记录了,所以这里就不弄了
(4)配置中断优先级和(5)配置外部中断线,这两个我选择放在一个模块,因为都是和中断有关系的嘛
void EXTI_PC2_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* key for exti */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource2); EXTI_InitStructure.EXTI_Line = EXTI_Line2; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); }这也没什么好解释的了,前面的文章已经解释了
(6)中断处理函数
这家伙推荐在stm32f10x_it.c里面写,因为那里有命名的模版,跟着官方走,错不了
void EXTI2_IRQHandler(void) { if (EXTI_GetITStatus(EXTI_Line2) != RESET) //判断按键是否按下 { //LED取反 GPIO_WriteBit(GPIOD, GPIO_Pin_6, (BitAction)((1-GPIO_ReadOutputDataBit(GPIOD, GPIO_Pin_6)))); EXTI_ClearITPendingBit(EXTI_Line2); //清除中断标志位 } }这里要注意的就是前面EXTIx这里的数字问题了,1-4没什么问题,5-9就要稍微注意下.如果是应该是这样,它应该是EXTI9_5_IRQHandler
这儿我有个问题,为什么没看到外部中断6呢,也就是EXTI6或7,8这些单独的呢.. 原因可能是5-9他们都使用了同一个中断向量表,这个话我印象中好像在哪儿看过
好,到这里基本功能就完成了.. 现象是可以出了.但是会有个问题就是有时候按一些按键,LED等会没反应或者亮灭几下.. 这就是按键抖动的问题了;
好,接下来说说怎么削抖:
这里说软件消抖,硬件就不说了.. 传说中的抖动出现的原因就是你的手速不够快,使中断触发了一次以上.. 我想如果你以20年到30年的专业单身手速(右手哦)来按的话
肯定没这个问题..哈哈..好,直接上代码..借鉴人家的:
用下面这个方法,就要调整前面的代码了.
void KEY_DEL(void) { num = 0; if (_keyon == 1) //按键是否按下,在中断处理函数中 { if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0) { Delay(0x3ffff);//延迟,为的是让你的手速能跟上 if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0) //按键是否抖动 { while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0); //是否松开 num = 1; goto n_exit; } } } n_exit:; _keyon = 0; }
void EXTI2_IRQHandler(void) { if (EXTI_GetITStatus(EXTI_Line2) != RESET) { _keyon = 1;//按键按下标志 EXTI_ClearITPendingBit(EXTI_Line2); } }
#include "misc.h" #include "stm32f10x_gpio.h" #include "stm32f10x_exti.h" #include "stm32f10x_rcc.h" #include "system_stm32f10x.h" #define LED_ON GPIO_SetBits(GPIOD, GPIO_Pin_6); void LED_Config(void); void EXTI_PC2_Config(void); void RCC_Config(void); void KEY_DEL(void); void Delay(u32 times); unsigned char _keyon = 0, num = 0; int main(void) { unsigned char a = 0; RCC_Config(); LED_Config(); EXTI_PC2_Config(); LED_ON; while(1) { KEY_DEL(); if (num == 1 && a == 0) { GPIO_ResetBits(GPIOD, GPIO_Pin_6); a = 1; } else if(num == 1 && a == 1) { GPIO_SetBits(GPIOD, GPIO_Pin_6); a = 0; } } }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。