STM32学习笔记(一)stm32c8t6实现按键的单击、连击、长按。

news/2024/11/30 15:27:30/

记录一下自己学习的过程

1.硬件连接

用的是c8t6的最小系统板,通过面包板连接按键,将PB11口用作按键输入。同时还连接了一块oled的屏方便查看现象。

2.代码部分

核心思想和代码总体框架来自博客:(7条消息) stm32【按键处理:单击、连击、长按】_Elven-C的博客-CSDN博客_stm32 按键中断多次进入最佳解决办法作了一些简化。

首先是头文件部分

#ifndef __KEY_H
#define __KEY_H#include "sys.h"
#include "delay.h"
#include "OLED.h"#define KEY_NULL   0    //无事件
#define KEY_LONG   1    //长按事件
#define KEY_SHORT  2    //短按事件
#define KEY_DOUBLE 3    //连按事件#define KEY_DOWN   1    //按键按下状态
#define KEY_UP     0    //按键松手状态
#define KEY_NONE   2    //按键初始状态#define KEY_CONTINUE 50 //按下的最长时间
#define KEY_IDLE     40 //松手最长时间
#define KEY_PIN    PBin(11)//PB11用作按键输入void Key_Init(void);
int Key_Scan(void);
void Key_Process(void);#endif

 Key.c部分

struct KEY
{u8 key_prevent;    //前一次按键事件u8 key_event;      //当前按键事件u8 key_state;      //按键状态 按下或松开u8 key_cnt;        //按键按下的次数u8 key_continue;   //按键按下的时间u8 key_idle;       //按键松手的时间u8 key_flag;       //按键状态发生改变的标志u8 key_event_flag; //产生一次按键事件的标志
}key={KEY_NULL,KEY_NONE,0,0,0,0,0};//结构体初始化

GPIO和定时器的配置

void Exit_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;EXTI_InitTypeDef EXTI_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;						//配置为上拉输入GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStructure);GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource11);EXTI_DeInit();EXTI_InitStructure.EXTI_Line = EXTI_Line11;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //上升下降沿中断,这样按下或松手就都能触发中断EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure); }void TIM2_Config(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);TIM_TimeBaseStructure.TIM_Prescaler= 71;//预分频					TIM_TimeBaseStructure.TIM_Period=9999; //相当于每10ms进入一次中断TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;	// 计数器计数模式,向上计数// 初始化定时器TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);TIM_ARRPreloadConfig(TIM2, ENABLE);			//使能TIM重载寄存器ARRTIM_ClearFlag(TIM2, TIM_FLAG_Update);		// 清除计数器中断标志位TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);	// 开启计数器中断TIM_Cmd(TIM2, DISABLE);						// 关闭定时器的时钟,等待使用
}//配置中断
void NVIC_Exit_GPIO_Config(void)
{NVIC_InitTypeDef	NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}void NVIC_TIM2_Config(void)
{NVIC_InitTypeDef	NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn  ;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}

中断函数 

void EXTI15_10_IRQHandler()
{Delay_ms(20);                 //按键消抖if(KEY_PIN==0)                //KEY_PIN==0代表按键按下{key.key_flag=1;           //代表按键状态发生改变的标志key.key_state=KEY_DOWN;   //按键状态key.key_continue=0;       //按键按下的时间清零}else                          //else的情况就是按键松手  {key.key_flag=1;            key.key_state=KEY_UP;key.key_idle=0;           按键松手的时间清零}EXTI_ClearITPendingBit(EXTI_Line11);    //清除中断标志
}void TIM2_IRQHandler(void)        //定时器中断每隔10ms进入一次中断
{Key_Process();                //每隔10ms调用一次TIM_ClearITPendingBit(TIM2 , TIM_IT_Update);//清除中断标志位
}

Key_Process();

void Key_Process(void)
{switch(key.key_state){case KEY_DOWN://按键按下进入{if(key.key_continue<KEY_CONTINUE){key.key_continue++;}//每隔10ms,key.key_continue++,if判断防止它一直增加//当按下的时间超出了设定的值后,说明此次为长按if(key.key_continue>=KEY_CONTINUE){if(key.key_cnt>1)//这个if判断是防止连按之后在长按会被判定为一次长按{OLED_ShowString(4,1,"DOUBLE");//这个if判断把连按之后的长按判断为连按OLED_ShowNum(2,1,key.key_cnt,2);//的一部分key.key_event=KEY_DOUBLE;key.key_prevent=key.key_event;}else//正常的长按{key.key_event=KEY_LONG;    //当按下的时间超出了设定的值后判断为长按key.key_event_flag=1;        //产生了一次按键事件key.key_prevent=key.key_event;OLED_ShowString(4,1,"LONG  ");    //打印到OLED屏上观察}}if(key.key_flag)//按键按下就会进入这个if判断{key.key_flag=0;//清除按键状态发生改变的标志位if(key.key_idle<KEY_IDLE){key.key_cnt++;}//判断松手的时间是否超时,没超时就说明是连按,按键按下次数加一else{key.key_cnt=1;}//否则已超时,此次只能为单机或长按//单击和连击的判断放到下面松手的部分通过按键次数来判断key.key_event=KEY_SHORT;}break;}//按键松开case KEY_UP:{key.key_flag=0;//清楚标志位,其实这一部分没有这个也一样if(key.key_idle<KEY_IDLE){key.key_idle++;}//松手时间小于设定值就增加if(key.key_idle>=KEY_IDLE)//大于松手时间,代表按键事件产生{//这个if判断防止长按被识别为单击,应为这一部分是靠按下次数来判断//单击或长按,而单击和长按按下次数都为1,但长按的按键事件一定会判定为//长按,通过key.key_event判断当前是长按还是单击if(key.key_cnt==1 && key.key_event!=KEY_LONG){key.key_event=KEY_SHORT;key.key_prevent=key.key_event;OLED_ShowString(4,1,"SHORT ");OLED_ShowNum(2,1,key.key_cnt,2);}else if(key.key_cnt>1)//按下次数为>1次的情况{if(key.key_prevent==KEY_LONG)//这个if判断防止前一次的长按被当作连按的一部分key.key_cnt--;//减去长按的一次计数if(key.key_cnt==1)//一次说明为单击{key.key_event=KEY_SHORT;key.key_prevent=key.key_event;OLED_ShowString(4,1,"SHORT ");OLED_ShowNum(2,1,key.key_cnt,2);}else//大于1次为连击{key.key_event=KEY_DOUBLE;OLED_ShowString(4,1,"DOUBLE");OLED_ShowNum(2,1,key.key_cnt,2);//oled输出连击次数}}}break;}}}
void Key_Init(void)
{Exit_GPIO_Config();TIM2_Config();NVIC_Exit_GPIO_Config();NVIC_TIM2_Config();TIM_Cmd(TIM2, ENABLE);	//使能时钟
}	

main.c部分 

#include "Key.h"int main()
{SystemInit();OLED_Init();OLED_ShowString(1,1,"Ready:");Key_Init();while(1){}
}

测试

测试


http://www.ppmy.cn/news/751369.html

相关文章

2·ESP32-C3入门教程——按键基本法

【写在前面】经过了点灯→定时器点灯→PWM点灯的学习之后&#xff0c;逐渐开始对ESP32 C3整体的框架有了一定认识【 点灯模块链接指路&#xff1a;http://t.csdn.cn/xOBmI】也掌握了一些理解和学习代码的思路&#xff0c;这一章咱们聊一聊按键的控制。 目录 GPIO输出与按键控制…

2022年12月份青少年软件编程Python等级考试试卷三级真题(含答案)(未完成)

2022-12 Python三级真题 分数&#xff1a;100 题数&#xff1a;38 测试时长&#xff1a;60min 一、单选题(共25题&#xff0c;共50分) 1. 列表L1中全是整数&#xff0c;小明想将其中所有奇数都增加1&#xff0c;偶数不变&#xff0c;于是编写了如下图所示的代码。请问&a…

STM32F4 | 按键输入实验

文章目录 一、STM32F4 IO 口简介二、硬件设计三、软件设计四、实验现象五、STM32CubeMX 配置 IO 口输出 这一章&#xff0c;我们将通过 ALIENTEK阿波罗 STM32 开发板上载有的 4 个按钮&#xff08; KEY_UP、 KEY0、 KEY1 和 KEY2&#xff09;&#xff0c;来控制板上的 2 …

STM32按键消抖的几种实现方式-STM32 Button Debouncing

一、按键抖动的现象 按键按下和松开的时候&#xff0c;按键金属片之间的贴合、分离有一个过程。给STM32输入的信号并不是理想的0和1切换的过程。而是如下图所示的&#xff0c;按下和松开的一小段时间内按键信号出现抖动&#xff08;jitter&#xff09;&#xff0c;这种现象称为…

stm32【按键处理:单击、连击、长按】

按键处理 测试平台&#xff1a;STM32F103C8T6 库版本&#xff1a;官方标准库3.5.0版本 按键&#xff1a;机械按键&#xff08;需消除抖动影响&#xff09;或触摸按键&#xff0c; 单片机硬件需求&#xff1a;定时器1个&#xff0c;IO口外部中断功能 按键处理是单片机底层驱动…

linux电脑滚轮不能用,鼠标滚轮不能用,小编教你电脑鼠标滚轮不能用怎么办

电脑用户最近遇到了一个问题&#xff0c;他们发现鼠标滚轮在一些应用下会不起作用。比如&#xff0c;我们用edge浏览器打开网页时&#xff0c;鼠标滚轮上下滚动会失效&#xff0c;而在原有的程序里则正常&#xff0c;那么怎么解决鼠标滚轮不能用的问题呢&#xff1f;下面&#…

服务器没有此伴奏文件,yy开直播,播放伴奏就一卡一卡的,不放伴奏就不卡,。是为什么...

1、关闭下载软件&#xff1a; 很多时候在观看直播的时候&#xff0c;下载游戏或者软件&#xff0c;会很大的影响网速&#xff0c;所以在观看YY直播之前&#xff0c;先把下载软件关闭。 2、设置网速优先&#xff1a; 观看YY直播的时候&#xff0c;也许还会聊天&#xff0c;还会做…

计算机鼠标左键不起作用,鼠标左键失灵怎么办 鼠标左键失灵处理方法【详解】...

现在使用电脑的特别多&#xff0c;我们使用电脑时使用最频繁的就是鼠标和键盘了&#xff0c;我们输入都是需要它们的&#xff0c;但是使用时间长了之后&#xff0c;难免会出现鼠标点击能听到咔哒的声音&#xff0c;但是就没反应&#xff0c;或者是一单机就变成双击&#xff0c;…