当前位置: 首页 > news >正文

宁志网站两学一做昆明百度推广开户

宁志网站两学一做,昆明百度推广开户,游戏网站规划方案,网上接单哪个平台比较靠谱今天来分享一个使用EXIT外部中断加TIM计时器实现按键长短按以及双击操作,不过笔者在双击上有点瑕疵,就是当你按下双击第一下停顿几秒按第二下依然会识别为双击操作,笔者猜测只要板子不停电即便到第二天按下第二下依旧会识别双击操作&#xff…

今天来分享一个使用EXIT外部中断加TIM计时器实现按键长短按以及双击操作,不过笔者在双击上有点瑕疵,就是当你按下双击第一下停顿几秒按第二下依然会识别为双击操作,笔者猜测只要板子不停电即便到第二天按下第二下依旧会识别双击操作,正常来说2秒内如果没有按下第二下会认为双击操作失败,重新开始,不过整体使用效果还可以,解决这个问题的方案笔者抽时间在好好想想。

下面为大家介绍以下大体思路,我们知道每个I/O端口都会对应一个EXIT中断,由此我们可以使用EXIT的双边沿触发来实现TIM定时器的开启关闭,当检测按下时开启TIM定时器,当检测松开按键时关闭TIM定时器,从而记录按键按下的时间,根据按键按下的时间长短不同可以判断按键的长短按,另外需要设定标志位来判断双击,下面开始上代码。

首先是TIM计时器的代码,笔者使用的是TIM2计时器,大家找一个板子上没用到的计时器即可。

time2.h

/*********** @Author : 桃杬* @describe : TIM2计时器,在此处主要用来实现计时操作* @Data : 2024.06.06
***************/#ifndef _TIME2_H
#define _TIME2_H#include "stm32f10x.h"extern uint16_t Time_Count; //外部声明,让Time_Count成为全局变量void TIME2_Init(uint16_t arr,uint16_t psc);#endif

下面是time.c的代码,具体解释笔者在里面都有备注,需要注意的是笔者设置每次发生溢出的时间为10ms,即Time_Count每10ms都会计数加1,实际时间 = Time_Count * 10,单位ms。

time2.c

#include "time2.h"/******** TIM溢出次数 Tout(溢出时间) = (arr+1)/(psc+1)/Tclk(时钟分割)* 当 arr = 10000, psc = 72 时,10ms溢出一次
*******/
uint16_t Time_Count;void TIME2_Init(uint16_t arr,uint16_t psc)
{//定义TIM结构体TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//定义NVIC嵌套向量中断NVIC_InitTypeDef NVIC_InitStrucure;//使能时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);TIM_InternalClockConfig(TIM2); //配置TIM2内部时钟,可以不配置,默认是一直开着的//配置TIMTIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //不用时钟分割TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数方式TIM_TimeBaseStructure.TIM_Period = arr - 1; //自动装载值TIM_TimeBaseStructure.TIM_Prescaler = psc - 1; //预分频系数TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //周期计数器值,这个是高级定时器,基本通用定时器不用开启TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);TIM_ClearFlag(TIM2,TIM_FLAG_Update); //清除TIM的挂起标志TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //使能指定TIM中断,寻去中断更新//配置NVICNVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置优先级分组NVIC_InitStrucure.NVIC_IRQChannel = TIM2_IRQn; //中断源NVIC_InitStrucure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道NVIC_InitStrucure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级NVIC_InitStrucure.NVIC_IRQChannelSubPriority = 1; //子优先级(也是响应优先级)NVIC_Init(&NVIC_InitStrucure);
}void TIM2_IRQHandler(void)
{if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET){//进入中断表示定时器计数(CNT)溢出, 自增(10ms溢出一次, 可通过配置ARR, PSC和Tclk自定义溢出时间)Time_Count++;TIM_ClearITPendingBit(TIM2,TIM_IT_Update); //清除定时器溢出中断}
}

接下来便是key.h代码,如果需要移植的话只需要修改每个按键定义以及中断部分,其他部分不需要修改,笔者这里使用了四个按键,如果大家是少于四个按键可以将按键启用的值改为0即可,即禁用不需要的按键,如将isEnableKey4 该为 0就会禁用按键4。如果大家的按键大于4个可以按照笔者写的格式增加按键,下面可以参考笔者写的代码。

key.h

/*********** @Author : 桃杬* @describe : 实现按键长短按 双击操作* @Data : 2024.06.06
***************/#ifndef _KEY_H
#define _KEY_H#include "stm32f10x.h"/**** 是否启用按键* 根据个人需求修改* 1 启用按键 0 失能按键* 默认都启用
****/
#define isEnableKey1 1
#define isEnableKey2 1
#define isEnableKey3 1
#define isEnableKey4 1#if isEnableKey1
//定义KEY1按键引脚以及中断
#define KEY1_GPIO_CLK RCC_APB2Periph_GPIOC //使能时钟端口
#define KEY1_GPIO_PORT GPIOC //KEY1端口
#define KEY1_GPIO_PIN GPIO_Pin_1 //KEY1引脚
#define KEY1_GPIO_EXTI_PORT_SOURCE GPIO_PortSourceGPIOC //外部中断源端口
#define KEY1_GPIO_EXTI_PIN_SOURCE GPIO_PinSource1 //外部中断源引脚
#define KEY1_EXTI_LINE EXTI_Line1 //EXTI事件线
#define KEY1_IRQN EXTI1_IRQn //中断源
#endif#if isEnableKey2
//定义KEY2按键引脚以及中断
#define KEY2_GPIO_CLK RCC_APB2Periph_GPIOC //使能时钟端口
#define KEY2_GPIO_PORT GPIOC //KEY2端口
#define KEY2_GPIO_PIN GPIO_Pin_5 //KEY2引脚
#define KEY2_GPIO_EXTI_PORT_SOURCE GPIO_PortSourceGPIOC //外部中断源端口
#define KEY2_GPIO_EXTI_PIN_SOURCE GPIO_PinSource5 //外部中断源引脚
#define KEY2_EXTI_LINE EXTI_Line5 //EXTI事件线
#define KEY2_IRQN EXTI9_5_IRQn //中断源
#endif#if isEnableKey3
//定义KEY3按键引脚以及中断
#define KEY3_GPIO_CLK RCC_APB2Periph_GPIOC //使能时钟端口
#define KEY3_GPIO_PORT GPIOC //KEY3端口
#define KEY3_GPIO_PIN GPIO_Pin_4 //KEY3引脚
#define KEY3_GPIO_EXTI_PORT_SOURCE GPIO_PortSourceGPIOC //外部中断源端口
#define KEY3_GPIO_EXTI_PIN_SOURCE GPIO_PinSource4 //外部中断源引脚
#define KEY3_EXTI_LINE EXTI_Line4 //EXTI事件线
#define KEY3_IRQN EXTI4_IRQn //中断源
#endif#if isEnableKey4
//定义KEY4按键引脚以及中断
#define KEY4_GPIO_CLK RCC_APB2Periph_GPIOA //使能时钟端口
#define KEY4_GPIO_PORT GPIOA //KEY4端口
#define KEY4_GPIO_PIN GPIO_Pin_0 //KEY4引脚
#define KEY4_GPIO_EXTI_PORT_SOURCE GPIO_PortSourceGPIOA //外部中断源端口
#define KEY4_GPIO_EXTI_PIN_SOURCE GPIO_PinSource0 //外部中断源引脚
#define KEY4_EXTI_LINE EXTI_Line0 //EXTI事件线
#define KEY4_IRQN EXTI0_IRQn //中断源
#endif//定义读取按键状态
#if isEnableKey1
#define KEY1 GPIO_ReadInputDataBit(KEY1_GPIO_PORT,KEY1_GPIO_PIN) //读取按键 LEFT
#endif#if isEnableKey2
#define KEY2 GPIO_ReadInputDataBit(KEY2_GPIO_PORT,KEY2_GPIO_PIN) //读取按键 RIGHT
#endif#if isEnableKey3
#define KEY3 GPIO_ReadInputDataBit(KEY3_GPIO_PORT,KEY3_GPIO_PIN) //读取按键 DOWN
#endif#if isEnableKey4
#define KEY4 GPIO_ReadInputDataBit(KEY4_GPIO_PORT,KEY4_GPIO_PIN) //读取按键 WAKEUP
#endif/******** 定义返回值状态 **********/
#if isEnableKey1
//KEY1返回值
#define KEY1_ShortPress_Value 0x0001  //短按
#define KEY1_LongPress_Value 0x0002   //长按
#define KEY1_DoubleClick_Value 0x0004 //双击
#endif#if isEnableKey2
//KEY2返回值
#define KEY2_ShortPress_Value 0x0010  //短按
#define KEY2_LongPress_Value 0x0020   //长按
#define KEY2_DoubleClick_Value 0x0040 //双击
#endif#if isEnableKey3
//KEY3返回值
#define KEY3_ShortPress_Value 0x0100  //短按
#define KEY3_LongPress_Value 0x0200   //长按
#define KEY3_DoubleClick_Value 0x0400 //双击
#endif#if isEnableKey4
//KEY4返回值
#define KEY4_ShortPress_Value 0x1000  //短按
#define KEY4_LongPress_Value 0x2000   //长按
#define KEY4_DoubleClick_Value 0x4000 //双击
#endif/**************** 函数部分 ********************/
void Key_Init(void); //初始化按键
void Key_Scan(void); //检测按键是否按下
uint16_t GetKeyNum(void); //返回按键值#endif

注意的是delay.h中是笔者写的简单的延迟函数,自行使用大家的延迟函数即可,只在消抖处用到了延时函数,其余部分没用用到。其次,中断处理双击中又嵌套了两个if else,时间上有点大,有点屎山代码的味道了😂,目前能想到的是开一个定时器,每当符合双击第一次时开启计数器,当检测到双击第二次时停止计数器,在2s内算是符合双击操作,否则丢弃,当然这只是笔者目前的想法🤣,后续笔者会完善以下。

key.c

#include "key.h"
#include "delay.h"
#include "time2.h"/*** 最终返回状态值 长按 短按 ***/
uint16_t Key_Value = 0x0000;/*** 记录上次最终返回状态值 ***/
uint16_t Old_Key_Value = 0x0000;//初次进入中断标志位
uint8_t Key_IT_Flag = 0;//初级进入双击标志位
uint8_t DoubleClickFlag = 0;//记录上次按键的值
uint16_t Old_KeyNum = 0x0000;/***按键按下宏定义***/
#if isEnableKey1
static uint8_t Key1_Press = 0;
#endif#if isEnableKey2
static uint8_t Key2_Press = 0;
#endif#if isEnableKey3
static uint8_t Key3_Press = 0;
#endif#if isEnableKey4
static uint8_t Key4_Press = 0;
#endif/*****
* @func : Key_Init(void)
* @describe : 初始化按键 外部中断 以及嵌套向量中断控制器
* @param : void
* @return : void
* @note : 移植时除了控制优先级和子优先级在此处需改外其他不需要修改这里
*****/
void Key_Init(void)
{//定义GPIO结构体GPIO_InitTypeDef GPIO_InitStructure;//定义外部中断EXTI机构体EXTI_InitTypeDef EXTI_InitStructure;//定义嵌套向量中断控制器NVIC结构体NVIC_InitTypeDef NVIC_InitStructure;//使能时钟#if isEnableKey1RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK,ENABLE); //key1所在的时钟#endif#if isEnableKey2RCC_APB2PeriphClockCmd(KEY2_GPIO_CLK,ENABLE); //key2所在的时钟#endif#if isEnableKey3RCC_APB2PeriphClockCmd(KEY3_GPIO_CLK,ENABLE); //key3所在的时钟#endif#if isEnableKey4RCC_APB2PeriphClockCmd(KEY4_GPIO_CLK,ENABLE); //key4所在的时钟#endifRCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//配置KEYGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;#if isEnableKey1GPIO_InitStructure.GPIO_Pin = KEY1_GPIO_PIN;GPIO_Init(KEY1_GPIO_PORT,&GPIO_InitStructure);#endif#if isEnableKey2GPIO_InitStructure.GPIO_Pin = KEY2_GPIO_PIN;GPIO_Init(KEY2_GPIO_PORT,&GPIO_InitStructure);#endif#if isEnableKey3GPIO_InitStructure.GPIO_Pin = KEY3_GPIO_PIN;GPIO_Init(KEY3_GPIO_PORT,&GPIO_InitStructure);#endif#if isEnableKey4GPIO_InitStructure.GPIO_Pin = KEY4_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;GPIO_Init(KEY4_GPIO_PORT,&GPIO_InitStructure);#endif#if isEnableKey1//配置KEY1外部中断及嵌套向量中断控制器GPIO_EXTILineConfig(KEY1_GPIO_EXTI_PORT_SOURCE,KEY1_GPIO_EXTI_PIN_SOURCE); //选择EXTI的信号源EXTI_InitStructure.EXTI_Line = KEY1_EXTI_LINE; //选择EXTI事件线EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //EXTI中断模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //双边沿中断EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能中断EXTI_Init(&EXTI_InitStructure);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置优先级分组NVIC_InitStructure.NVIC_IRQChannel = KEY1_IRQN; //中断源NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级NVIC_Init(&NVIC_InitStructure);#endif#if isEnableKey2//配置KEY2外部中断及嵌套向量中断控制器GPIO_EXTILineConfig(KEY2_GPIO_EXTI_PORT_SOURCE,KEY2_GPIO_EXTI_PIN_SOURCE); //选择EXTI的信号源EXTI_InitStructure.EXTI_Line = KEY2_EXTI_LINE; //选择EXTI事件线EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //EXTI中断模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //双边沿中断EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能中断EXTI_Init(&EXTI_InitStructure);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置优先级分组NVIC_InitStructure.NVIC_IRQChannel = KEY2_IRQN; //中断源NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级NVIC_Init(&NVIC_InitStructure);#endif#if isEnableKey3//配置KEY3外部中断及嵌套向量中断控制器GPIO_EXTILineConfig(KEY3_GPIO_EXTI_PORT_SOURCE,KEY3_GPIO_EXTI_PIN_SOURCE); //选择EXTI的信号源EXTI_InitStructure.EXTI_Line = KEY3_EXTI_LINE; //选择EXTI事件线EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //EXTI中断模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //双边沿中断EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能中断EXTI_Init(&EXTI_InitStructure);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置优先级分组NVIC_InitStructure.NVIC_IRQChannel = KEY3_IRQN; //中断源NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级NVIC_Init(&NVIC_InitStructure);#endif#if isEnableKey4//配置KEY4外部中断及嵌套向量中断控制器GPIO_EXTILineConfig(KEY4_GPIO_EXTI_PORT_SOURCE,KEY4_GPIO_EXTI_PIN_SOURCE); //选择EXTI的信号源EXTI_InitStructure.EXTI_Line = KEY4_EXTI_LINE; //选择EXTI事件线EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //EXTI中断模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //双边沿中断EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能中断EXTI_Init(&EXTI_InitStructure);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置优先级分组NVIC_InitStructure.NVIC_IRQChannel =KEY4_IRQN; //中断源NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级NVIC_Init(&NVIC_InitStructure);#endif
}/*****
* @func : Key_Scan(void)
* @describe : 检测按键状态
* @param : void
* @return : void
* @note : 1 按下按键 0 松开按键
*****/
void Key_Scan(void)
{#if isEnableKey1if(KEY1 == RESET) //检测到按键1{delay_ms(20); //消抖if(KEY1 == RESET) //再次检测按键1{Key1_Press = 1; //记录此时按键状态}}elseKey1_Press = 0;#endif#if isEnableKey2if(KEY2 == RESET) //检测到按键2{delay_ms(20); //消抖if(KEY2 == RESET) //再次检测按键2Key2_Press = 1; //记录此时按键状态}elseKey2_Press = 0;#endif#if isEnableKey3if(KEY3 == RESET) //检测到按键3{delay_ms(20); //消抖if(KEY3 == RESET) //再次检测按键3Key3_Press = 1; //记录此时按键状态}elseKey3_Press = 0;#endif#if isEnableKey4if(KEY4 == SET) //检测到按键4  注意的是按键四是高电平检测到按键按下{delay_ms(20); //消抖if(KEY4 == SET) //再次检测按键4Key4_Press = 1; //记录此时按键状态}elseKey4_Press = 0;#endif
}/*****
* @func : GetKeyNum(void)
* @describe : 返回按键值
* @param : void
* @return : 按键值
*       @ret : 11 按键1短按; 12 按键1长按; 13 按键1双击
*       @ret : 21 按键2短按; 22 按键2长按; 23 按键2双击
*       @ret : 31 按键3短按; 32 按键3长按; 33 按键3双击
*       @ret : 41 按键4短按; 42 按键4长按; 43 按键4双击
* @note : 返回值如 xx 形式
*         其十位代表按键几 个位则代表长短双击, 1 短按 2 长按 3 双击
*****/
uint16_t GetKeyNum(void)
{//最终返回值static uint8_t keyNum = 0;Key_Scan();if(!Key_IT_Flag){switch(Key_Value){#if isEnableKey1case 0x0001:keyNum = 11;  //按键1短按Old_Key_Value = Key_Value;Key_Value = 0x0000;break;case 0x0002:keyNum = 12;  //按键1长按Old_Key_Value = Key_Value;Key_Value = 0x0000;break;case 0x0004:keyNum = 14;  //按键1双击Old_Key_Value = 0x0000;Key_Value = 0x0000;break;#endif#if isEnableKey2case 0x0010:keyNum = 21;  //按键2短按Old_Key_Value = Key_Value;Key_Value = 0x0000;break;case 0x0020:keyNum = 22;  //按键2长按Old_Key_Value = Key_Value;Key_Value = 0x0000;break;case 0x0040:keyNum = 24;  //按键2双击Old_Key_Value = 0x0000;Key_Value = 0x0000;break;#endif#if isEnableKey3case 0x0100:keyNum = 31;  //按键3短按Old_Key_Value = Key_Value;Key_Value = 0x0000;break;case 0x0200:keyNum = 32;  //按键3长按Old_Key_Value = Key_Value;Key_Value = 0x0000;break;case 0x0400:keyNum = 34;  //按键3双击Old_Key_Value = 0x0000;Key_Value = 0x0000;break;#endif#if isEnableKey4case 0x1000:keyNum = 41;  //按键4短按Old_Key_Value = Key_Value;Key_Value = 0x0000;break;case 0x2000:keyNum = 42;  //按键4长按Old_Key_Value = Key_Value;Key_Value = 0x0000;break;case 0x4000:keyNum = 44;  //按键4双击Old_Key_Value = 0x0000;Key_Value = 0x0000;break;#endifdefault:keyNum = 0;Key_Value = 0x0000;break;}}return keyNum;
}#if isEnableKey1
/*****
* @func : EXTI1_IRQHandler()
* @describe : 中断函数
* @param : void
* @return : void
* @note : 中断需要的处理的操作在此处执行
*****/
void EXTI1_IRQHandler()
{static uint8_t Key1State = 0; //静态按键1状态 0 松开 1按下if(EXTI_GetITStatus(KEY1_EXTI_LINE) != RESET){if(Key1_Press && Key1State) //松开按键{Key1State = 0; //松开标志Key_IT_Flag = 0; //退出中断标志位TIM_Cmd(TIM2,DISABLE); //关闭时钟if(Time_Count > 0 && Time_Count <= 20) //短按时间判断{if(!DoubleClickFlag) //第一次双击按下{DoubleClickFlag = 1; //改变标志位Old_KeyNum |= KEY1_DoubleClick_Value; //记录按下值Old_Key_Value = Old_KeyNum; //记录上次返回的状态值}else {Old_KeyNum &= 0x0000; //清除记录Old_KeyNum |= KEY1_DoubleClick_Value; //更新上一次的值if(Old_Key_Value != Old_KeyNum)  //上次最终返回的状态值与记录第一次双击按下值不一致Old_Key_Value = Old_KeyNum;  //更新最后返回状态值 else{DoubleClickFlag = 0; //重置双击按下标志位Old_Key_Value = 0x0000; //重置最后返回状态Old_KeyNum = 0x0000; //重置按下值Key_Value |= KEY1_DoubleClick_Value; //双击返回状态值}}}else if(Time_Count > 20 && Time_Count <= 40)  //短按时间判断Key_Value |= KEY1_ShortPress_Value;  //短按时间返回状态值else if(Time_Count > 40)  //长按时间判断Key_Value |= KEY1_LongPress_Value;  //长按时间返回状态值//            printf("Time_Count : %d\n",Time_Count); //测试时使用} else if(!Key_IT_Flag && !Key1State) //按下按键{Key1State = 1; //按下标志位Key_IT_Flag = 1; //已进入中断标志位Time_Count = 0; //每次按下从0开始计时TIM_Cmd(TIM2,ENABLE); //开启时钟}EXTI_ClearITPendingBit(KEY1_EXTI_LINE); //清除中断标志位}
}#endif#if isEnableKey2
/*****
* @func : EXTI9_5_IRQHandler()
* @describe : 中断函数
* @param : void
* @return : void
* @note : 中断需要的处理的操作在此处执行
*****/
void EXTI9_5_IRQHandler()
{static uint8_t Key2State = 0; //静态按键1状态 0 松开 1按下if(EXTI_GetITStatus(KEY2_EXTI_LINE) != RESET){if(Key2_Press && Key2State) //松开按键{Key2State = 0; //松开标志Key_IT_Flag = 0; //退出中断标志位TIM_Cmd(TIM2,DISABLE); //关闭时钟if(Time_Count > 0 && Time_Count <= 20) //短按时间判断{if(!DoubleClickFlag) //第一次双击按下{DoubleClickFlag = 1; //改变标志位Old_KeyNum |= KEY2_DoubleClick_Value; //记录按下值Old_Key_Value = Old_KeyNum; //记录上次返回的状态值}else {Old_KeyNum &= 0x0000; //清除记录Old_KeyNum |= KEY2_DoubleClick_Value; //更新上一次的值if(Old_Key_Value != Old_KeyNum)  //上次最终返回的状态值与记录第一次双击按下值不一致Old_Key_Value = Old_KeyNum;  //更新最后返回状态值 else{DoubleClickFlag = 0; //重置双击按下标志位Old_Key_Value = 0x0000; //重置最后返回状态Old_KeyNum = 0x0000; //重置按下值Key_Value |= KEY2_DoubleClick_Value; //双击返回状态值}}}else if(Time_Count > 20 && Time_Count <= 40)  //短按时间判断Key_Value |= KEY2_ShortPress_Value;  //短按时间返回状态值else if(Time_Count > 40)  //长按时间判断Key_Value |= KEY2_LongPress_Value;  //长按时间返回状态值//            printf("Time_Count : %d\n",Time_Count); //测试时使用} else if(!Key_IT_Flag && !Key2State) //按下按键{Key2State = 1; //按下标志位Key_IT_Flag = 1; //已进入中断标志位Time_Count = 0; //每次按下从0开始计时TIM_Cmd(TIM2,ENABLE); //开启时钟}EXTI_ClearITPendingBit(KEY2_EXTI_LINE); //清除中断标志位}
}#endif#if isEnableKey3
/*****
* @func : EXTI4_IRQHandler()
* @describe : 中断函数
* @param : void
* @return : void
* @note : 中断需要的处理的操作在此处执行
*****/
void EXTI4_IRQHandler()
{static uint8_t Key3State = 0; //静态按键1状态 0 松开 1按下if(EXTI_GetITStatus(KEY3_EXTI_LINE) != RESET){if(Key3_Press && Key3State) //松开按键{Key3State = 0; //松开标志Key_IT_Flag = 0; //退出中断标志位TIM_Cmd(TIM2,DISABLE); //关闭时钟if(Time_Count > 0 && Time_Count <= 20) //短按时间判断{if(!DoubleClickFlag) //第一次双击按下{DoubleClickFlag = 1; //改变标志位Old_KeyNum |= KEY3_DoubleClick_Value; //记录按下值Old_Key_Value = Old_KeyNum; //记录上次返回的状态值}else {Old_KeyNum &= 0x0000; //清除记录Old_KeyNum |= KEY3_DoubleClick_Value; //更新上一次的值if(Old_Key_Value != Old_KeyNum)  //上次最终返回的状态值与记录第一次双击按下值不一致Old_Key_Value = Old_KeyNum;  //更新最后返回状态值 else{DoubleClickFlag = 0; //重置双击按下标志位Old_Key_Value = 0x0000; //重置最后返回状态Old_KeyNum = 0x0000; //重置按下值Key_Value |= KEY3_DoubleClick_Value; //双击返回状态值}}}else if(Time_Count > 20 && Time_Count <= 40)  //短按时间判断Key_Value |= KEY3_ShortPress_Value;  //短按时间返回状态值else if(Time_Count > 40)  //长按时间判断Key_Value |= KEY3_LongPress_Value;  //长按时间返回状态值//            printf("Time_Count : %d\n",Time_Count); //测试时使用} else if(!Key_IT_Flag && !Key3State) //按下按键{Key3State = 1; //按下标志位Key_IT_Flag = 1; //已进入中断标志位Time_Count = 0; //每次按下从0开始计时TIM_Cmd(TIM2,ENABLE); //开启时钟}EXTI_ClearITPendingBit(KEY3_EXTI_LINE); //清除中断标志位}
}#endif#if isEnableKey4
/*****
* @func : EXTI0_IRQHandler()
* @describe : 中断函数
* @param : void
* @return : void
* @note : 中断需要的处理的操作在此处执行
*****/
void EXTI0_IRQHandler()
{static uint8_t Key4State = 0; //静态按键1状态 0 松开 1按下if(EXTI_GetITStatus(KEY4_EXTI_LINE) != RESET){if(Key4_Press && Key4State) //松开按键{Key4State = 0; //松开标志Key_IT_Flag = 0; //退出中断标志位TIM_Cmd(TIM2,DISABLE); //关闭时钟if(Time_Count > 0 && Time_Count <= 20) //短按时间判断{if(!DoubleClickFlag) //第一次双击按下{DoubleClickFlag = 1; //改变标志位Old_KeyNum |= KEY4_DoubleClick_Value; //记录按下值Old_Key_Value = Old_KeyNum; //记录上次返回的状态值}else {Old_KeyNum &= 0x0000; //清除记录Old_KeyNum |= KEY4_DoubleClick_Value; //更新上一次的值if(Old_Key_Value != Old_KeyNum)  //上次最终返回的状态值与记录第一次双击按下值不一致Old_Key_Value = Old_KeyNum;  //更新最后返回状态值 else{DoubleClickFlag = 0; //重置双击按下标志位Old_Key_Value = 0x0000; //重置最后返回状态Old_KeyNum = 0x0000; //重置按下值Key_Value |= KEY4_DoubleClick_Value; //双击返回状态值}}}else if(Time_Count > 20 && Time_Count <= 40)  //短按时间判断Key_Value |= KEY4_ShortPress_Value;  //短按时间返回状态值else if(Time_Count > 40)  //长按时间判断Key_Value |= KEY4_LongPress_Value;  //长按时间返回状态值//            printf("Time_Count : %d\n",Time_Count); //测试时使用} else if(!Key_IT_Flag && !Key4State) //按下按键{Key4State = 1; //按下标志位Key_IT_Flag = 1; //已进入中断标志位Time_Count = 0; //每次按下从0开始计时TIM_Cmd(TIM2,ENABLE); //开启时钟}EXTI_ClearITPendingBit(KEY4_EXTI_LINE); //清除中断标志位}
}#endif

最后main函数代码进行测试,大家注意的是需要对printf函数进行重写。

main.c

#include "stm32f10x.h"
#include "sys.h"
#include "usart.h"
#include "key.h"
#include "time2.h"int main()
{uint16_t keyNum = 0;USART1_Init(115200); //初始化USARTTIME2_Init(10000,72); //初始TIM2Key_Init(); //按键初始化while(1){keyNum = GetKeyNum();switch(keyNum){case 11:printf("按键1短按\n");printf("短按返回值 keyNum = %2d\n",keyNum);puts("");break;case 12:printf("按键1长按\n");printf("长按返回值 keyNum = %2d\n",keyNum);puts("");break;case 14:printf("按键1双击\n");printf("双击返回值 keyNum = %2d\n",keyNum);puts("");break;case 21:printf("按键2短按\n");printf("短按返回值 keyNum = %2d\n",keyNum);puts("");break;case 22:printf("按键2长按\n");printf("长按返回值 keyNum = %2d\n",keyNum);puts("");break;case 24:printf("按键2双击\n");printf("双击返回值 keyNum = %2d\n",keyNum);puts("");break;case 31:printf("按键3短按\n");printf("短按返回值 keyNum = %2d\n",keyNum);puts("");break;case 32:printf("按键3长按\n");printf("长按返回值 keyNum = %2d\n",keyNum);puts("");break;case 34:printf("按键3双击\n");printf("双击返回值 keyNum = %2d\n",keyNum);puts("");break;case 41:printf("按键4短按\n");printf("短按返回值 keyNum = %2d\n",keyNum);puts("");break;case 42:printf("按键4长按\n");printf("长按返回值 keyNum = %2d\n",keyNum);puts("");break;case 44:printf("按键4双击\n");printf("双击返回值 keyNum = %2d\n",keyNum);puts("");break;default:break;}}
}

最后的最后献上测试截图,感谢大家的观看👀。

http://www.hengruixuexiao.com/news/47733.html

相关文章:

  • 知乎网站建设入门书广告网络推广怎么做
  • wordpress 多站点 插件产品推广营销
  • 网站建设海报图片上海网络推广公司
  • 建设网站商城百度图片查找
  • 专业网站seo优化公司网站流量数据分析
  • 永州做网站百度人工客服24小时电话
  • 网站名称设置网络运营推广合作
  • b2b电商网站建设十大营销策划公司排名
  • 怎样安全做黑色彩票网站信息流广告案例
  • 海南百度推广公司长春seo推广
  • 哪个网站可以做问卷凡科建站登录官网
  • 企业网站的建立主要用于企业内部发布信息秦皇岛seo优化
  • 日照网红民宿班级优化大师下载安装
  • 哪些企业会考虑做网站厦门seo怎么做
  • php网站开发技术课程一个公司可以做几个百度推广
  • 做的最好的美女视频网站百度竞价在哪里开户
  • 百度做的网站字体侵权吗上海疫情最新数据
  • 网站开发视频教程下载18款禁用看奶app入口
  • 专业的高密做网站的杭州优化外包
  • ps做汽车网站下载地址互联网营销师课程
  • 网站顾客评价百度浏览器在线打开
  • 北京知名网站设计公司ios微信上的pdf乱码
  • 任丘网站制作搜索引擎优化的基本内容
  • asp.net制作网站开发国内seo公司排名
  • html5新闻网站站长工具樱花
  • 医院网站建设方案详细综合权重查询
  • logo在线设计免费生成器网站关键词优化推广哪家好
  • 网站改版的方式大致有品牌整合推广
  • 公司宣传网站怎么做nba最新消息新闻
  • 建设股份公司网站网站分析培训班