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

网站移动端做pc端的301跳转广告联盟广告点击一次多少钱

网站移动端做pc端的301跳转,广告联盟广告点击一次多少钱,厦门市住房和城乡建设局网站,wordpress总结按键收集单击,双击和长按 引言 在我们生活中, 按键是必不可少的, 不同的电器, 有不同的按键, 但是按键总有不够用的时候, 那么给与一个按键赋予不同的功能,就必不可少了. 一个按键可以通过按下的时间长短和频次, 来定义其类型。 一次按键收集, 都是在一个按键收集周…

按键收集单击,双击和长按

引言

在我们生活中, 按键是必不可少的, 不同的电器, 有不同的按键, 但是按键总有不够用的时候, 那么给与一个按键赋予不同的功能,就必不可少了. 一个按键可以通过按下的时间长短和频次, 来定义其类型。

一次按键收集, 都是在一个按键收集周期的, 比如500毫秒内, 我要收集一个按键类型, 在500毫秒内,按键按下一次按键, 那么到达500毫秒后, 我们就宣布答案, 此次按键是单击。

同理, 在500毫秒内, 如果我们按下了, 两次按键,那么就是双击, 以此类推。

那长按呢? 长按就是, 在500毫秒内, 我们按下了按键,并且500ms时间到时, 按键还未松开, 就代表着长按。

本博客最终修改项目链接下载:

点击下载

https://wwyz.lanzoul.com/itXC327v9dra

按键收集模型

image-20240818183801773

单片机实现方法

因为按键, 需要每时每刻的去检测, 是否按下, 如果使用while阻塞循环, 则会大大影响程序效率, 所以我们使用外部中断去检测中断。

按键事件触发检测

按键按下的瞬间, 单片机的io口, 就会被从高电平拉到低电平, 然后单片机io口就会检测到, 从而触发下降沿中断。

此时,就代表着按键事件已经触发了。

按键类型判断

​ 按键事件触发,仅仅代表着我们按下了按键, 但是我们想区分单击,双击和长按, 那么我们就得从按键按下开始计算,直到按键计算周期结束,这一段时间我们定义成 500毫秒。

所以, 我们在按键事件触发后,我们需要启动定时器,计时500ms, 然后500ms时间到后, 判断按键按下的次数, 还有按键此时是否仍然被按下.

在这 500毫秒内, 我们重复按下按键, 就需要重复的检测按键按下的事件, 然后计入按键次数内.

所以我们的处理模型是

image-20240818193546975

代码实现

按键中断

按键中断初始化

我们初始化io端口PB1,配置下降沿中断

image-20240819125528156

void Key_Init(void)
{GPIO_InitTypeDef gpio_initstruct;EXTI_InitTypeDef exti_initstruct; NVIC_InitTypeDef nvic_initstruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		//打开GPIOB的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);		//打开复用时钟gpio_initstruct.GPIO_Mode = GPIO_Mode_IPU;				//设置为输出gpio_initstruct.GPIO_Pin = GPIO_Pin_1;						//将初始化的Pin脚gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;				//可承载的最大频率GPIO_Init(GPIOB, &gpio_initstruct);							//初始化GPIOGPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);exti_initstruct.EXTI_Line = EXTI_Line1;exti_initstruct.EXTI_Mode = EXTI_Mode_Interrupt;exti_initstruct.EXTI_Trigger = EXTI_Trigger_Falling;exti_initstruct.EXTI_LineCmd = ENABLE;EXTI_Init(&exti_initstruct);nvic_initstruct.NVIC_IRQChannel = EXTI1_IRQn;nvic_initstruct.NVIC_IRQChannelPreemptionPriority = 2;nvic_initstruct.NVIC_IRQChannelSubPriority = 2;nvic_initstruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&nvic_initstruct);}
触发中断,按键标志位赋1

image-20240819125747163

extern _Bool key_down;
void EXTI1_IRQHandler(void)
{if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0){//代表按键按下(按键标志清除--一次时间处理完成)key_down = 1;}EXTI_ClearITPendingBit(EXTI_Line1);
}	
定时器中断扫描判断按键是否按下

当触发中断后,我们把key_down置成1后, 就会被定时器扫描,检测到, 我们就 把按键次数加1, 并且启动 500ms的计时, count = 1, 然后if(count >0), 就会启动 count++计时, 因为我们定时器是1ms运行一次,所以当count == 500的时候,进行按键类型检测

image-20240819125930008

按键类型判断

当到达500ms后, 我们就可以通过判断按键次数, 区分单双击, 单击的情况下,通过判断500ms时,io口的状态,从而判断单击还是长按。

单击和长按区分

单击和长按, 按键次数 button_count 都是1, 不同的是,500毫秒之后,单击按键类型, 已经松开, 长按,则是按下状态, 所以我们通过读取检测500ms时间到时, io的状态, 就可以区分长按和单击了。

长按, io口是低电平, 单击,io是高电平, (我们是下降沿触发, 按键一端连io口,一端连 地, io口输出状态是, 推挽输出)

button_mode = 1代表 单击 ,

button_mode = 3代表 长按

image-20240819130853341

image-20240819141941257

uint8_t key_scan(void)
{uint8_t value;value = 0;	//默认是不是一直低电平//检测是否长按if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)// 判断按键是否仍然在按下{//这时候还是按下状态, 不一定是真正的按键按下, 有可能是抖动造成的,接下来延时消抖//再次判断按键是否按下, 如果按下, 代表真正的按键仍然在按下if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0){//那就等抬起了再做事value = 1;//这时候才可以判断是 长按下}}return value;
}
双击区分

通过判断, 按键的次数, 就可以得知双击, 记得按键类型判断完毕后, 要把按键次数置0, 为下次判断做准备。 button_mode = 2, 代表按键双击

image-20240819142123007

定时器扫描函数代码

void TIM4_IRQHandler(void)
{if(TIM_GetFlagStatus(TIM4,TIM_FLAG_Update))//一毫秒运行一次{//当 button_atom的时候,才能进行读取按键信息if(key_down == 1){	key_down = 0;button_count++;count = 1;	//开始计时}if(count > 0){count++;if(count > 500){count = 0;if(button_count == 1){button_count = 0;if(key_scan() == 0)	//短按button_mode = 1;else if(key_scan() == 1)	//长按button_mode = 3; }else if(button_count == 2){button_count = 0;button_mode = 2;		}else{button_count = 0;//判断完,到时间照样得button_count 清零,为后面做准备}}}		TIM_ClearFlag(TIM4,TIM_FLAG_Update);}
}

现象调试

判断按键类型方式

我们通过代码实操 ,已经可以得知我们按下的按键是单击,双击还是长按了,通过判断 button_mode 的数值。

image-20240819143221376

调用相关现象

我们选用PA0, PA1, PA2, 来分别代表 单击,双击和长按的小灯。

我们在检测到 button_mode 的数值改变的时候, 就赋值对应的小灯亮灭,这样我们就可以看到现象了

image-20240819144039916

初始化PA0,PA1,PA2

设置这三个io口分别为推挽输出模式

image-20240819181926289

void Led_Init(void)
{/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟//使用各个外设前必须开启时钟,否则对外设的操作无效/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;					//定义结构体变量GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;		//GPIO模式,赋值为推挽输出模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;				//GPIO引脚,赋值为第0号引脚GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//GPIO速度,赋值为50MHzGPIO_Init(GPIOA, &GPIO_InitStructure);					//将赋值后的构体变量传递给GPIO_Init函数//函数内部会自动根据结构体的参数配置相应寄存器//实现GPIOA的初始化GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;		//GPIO模式,赋值为推挽输出模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;				//GPIO引脚,赋值为第0号引脚GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//GPIO速度,赋值为50MHzGPIO_Init(GPIOA, &GPIO_InitStructure);					//将赋值后的构体变量传递给GPIO_Init函数//函数内部会自动根据结构体的参数配置相应寄存器//实现GPIOA的初始化GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;		//GPIO模式,赋值为推挽输出模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;				//GPIO引脚,赋值为第0号引脚GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//GPIO速度,赋值为50MHzGPIO_Init(GPIOA, &GPIO_InitStructure);					//将赋值后的构体变量传递给GPIO_Init函数//函数内部会自动根据结构体的参数配置相应寄存器//引脚初始化led_go(0,0);led_go(1,0);led_go(2,0);		
}	

单独设置对应的小灯亮灭

void led_go(uint8_t led,_Bool go)

比如我们控制 PA0 io口, 我们传入 0, 代表我们要控制位序为0的小灯, 第二个参数 go = 1, 代表着让灯两, go = 0, 代表着让灯灭。这样我们就可以灵活的控制小灯亮灭了。

image-20240819182225221
void led_go(uint8_t led,_Bool go)
{if(led == 0){if(go == 1){GPIO_SetBits(GPIOA, GPIO_Pin_0);	//亮}else{GPIO_ResetBits(GPIOA, GPIO_Pin_0); //灭}}elseif(led == 1){if(go == 1){GPIO_SetBits(GPIOA, GPIO_Pin_1);	//亮}else{GPIO_ResetBits(GPIOA, GPIO_Pin_1); //灭}		}	elseif(led == 2){if(go == 1){GPIO_SetBits(GPIOA, GPIO_Pin_2);	//亮}else{GPIO_ResetBits(GPIOA, GPIO_Pin_2); //灭}		}	
}

根据 button_mode亮灭小灯

还是那个图, 我们有了底层构建, 我们根据单双击,然后会有不同的butoon_mode 按键模式, 所以我们根据这个数值, 赋值对应的小灯亮灭, 这样我们就可以看到现象了.

led控制图(ctrl 加鼠标左键,快速跳转)

image-20240819182628204
void chose_led(void)
{if(button_mode == 0){led_go(0,0);led_go(1,0);led_go(2,0);}else if(button_mode == 1){led_go(0,1);led_go(1,0);led_go(2,0);}else if(button_mode == 2){led_go(0,0);led_go(1,1);led_go(2,0);}else if(button_mode == 3){led_go(0,0);led_go(1,0);led_go(2,1);}	
}	

main.c主函数调用

初始化,按键和定时器, 还有调试的小灯, 我们根据按键模式, 控制对应的小灯亮灭, 观察现象

image-20240819182827540
_Bool key_down = 0;	//按键是否按下
uint16_t count;	//定时器计数毫秒数(按键按下时长)
uint8_t button_count = 0; 
uint8_t button_mode = 0;	//按键模式:无-0 , 单击- 1, 双击 - 2, 长按 - 3
int main(void)
{Key_Init();TIM4_Init();Led_Init();while(1){chose_led();}
}	

工程代码构建

我们上面, 代码的逻辑思路, 已经构建完毕, 同时我们也提供构建完成的工程, 我们这里带领大家, 复制黏贴

1.基本工程构建方法

创建stm32f103c8t6基本工程_stm32f103c8启动文件配置-CSDN博客

2.我们工程名字叫做

Key_detection_model

点击品字,然后修改工程名字

image-20240819183230023

3.我们用到main函数, 所以有User用户文件夹

我们用到按键检测, 所以用到 Key_model按键模型

我们用到系统的延时函数, 所以用到System系统文件夹

我们用到定时器,所以用到Time定时器文件夹

User
Key_model
System
Time

4.具体文件添加方式, 看最小例程构建,从第九步开始

我们User文件夹下, 添加

main.c
led.c
led.h

image-20240819183721379

Key_model文件夹下添加

key.c
key.h
image-20240819183757371

System文件夹下添加

delay.c
delay.h
sys.h
image-20240819200115950

Time文件夹下添加

TIM4.c
TIM4.h
image-20240819200130023

5.记得包含对应的文件夹路径

image-20240819200342838

6.按键收集模型代码快速复制

各文件对应的代码

跳转复制

  1. 构建完成如图

image-20240819201343274

8.编译运行,烧录

烧录方法

9.小灯辨别正负极方法

灯芯放在光下看, 大头是负极,小头是正极, 我们正极插在io口, 负极插在地, io口分别是 PA0, PA1, PA2

10.按键演示视频

按键演示视频_哔哩哔哩_bilibili

http://www.hkea.cn/news/734566/

相关文章:

  • 做学校网站素材图片合肥seo代理商
  • 真题真做报名网站淘宝搜索关键词排名
  • 免费的黄冈网站有哪些平台?培训行业seo整站优化
  • 寿县住房与城乡建设局网站真正免费的网站建站平台
  • 常德seo招聘网站seo站长工具
  • 网站开发多久完成俄罗斯搜索引擎yandex推广入口
  • 漳州做网站建设建网站免费
  • 网站建设服务上海广州软文推广公司
  • 做一个网站app需要多少钱web制作网站的模板
  • 网站建设的财务计划新媒体营销策略有哪些
  • 网站建设分金手指专业二八宁波品牌网站推广优化
  • 清远网站建设公司百度游戏风云榜
  • 网上可以自学什么技术win7系统优化软件
  • 嘉兴建站软件如何做好企业网站的推广
  • 在凡科做网站短视频推广
  • 深圳推广公司推荐q群排名优化软件
  • 什么网站做简历模板宁德市医院
  • 用什么软件做公司网站游戏推广赚佣金的平台
  • 购物网站 后台模板河北seo技术培训
  • 聊城建设委员会官方网站google seo
  • 广西建设网郭业棚seo推广具体做什么
  • 武汉网站seo诊断谷歌下载官网
  • 做地方网站能赚钱吗免费seo网站诊断
  • 图片设计在线网站推广优化外包便宜
  • 武汉平价做网站网络软文推广案例
  • 新产品线上推广方案鞍山seo外包
  • 网站建网站建设和优佛山网络推广培训
  • 毕业设计做网站怎么样微信crm管理系统
  • 个人网站开发多少钱电脑培训班零基础
  • 互联网有哪些岗位宁波免费seo在线优化