完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛
|
我是来学习的
![]() ![]()
|
|
|
|
|
|
|
|
|
很久没来看了,最近有些颓废了。。。 刚看了组合和双击的,想到如果一个按钮既可以单击,双击,长按,与其他键组合,这个该怎么写了????
|
|
|
|
|
|
|
|
|
本帖最后由 dubeixian 于 2013-10-23 23:53 编辑
很久没看鸿哥的帖子了,今天一看哇,组合键,不错,思路清晰。现在我来抛砖引玉,只修改了鸿哥的独立按键扫描函数如下:
|
|
|
|
|
|
|
|
|
else if(key_sr1==0)可以改成else. 整体思路还是挺不错的,如果一个按键同时实现短按和长按两种状态,那么还有一个小毛病,欲知详情请听下回分解。 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
虽然暂时看不出自己的存在什么问题,下回继续好好学习领略鸿哥的精彩 |
|
|
|
|
|
|
|
|
本帖最后由 jianhong_wu 于 2013-11-8 11:46 编辑
第五十七节:按键的花样技巧----同一个按键短按与长按的区别触发 开场白: 从这一节开始,我准备花几个章节来讲讲按键的几种常用花样技巧。 (1) 功能需求: 按住一个按键,在短时间内松手,则认为是短按,触发蜂鸣器短鸣一声。如果一直按住这个按键不松手,那么超过规定的长时间内,则认为是长按,触发蜂鸣器长鸣一声。 (2) 硬件原理: 独立按键和有源蜂鸣器的硬件原理请参考本连载文章的第二节。 (3) 源码适合的单片机: PIC16F73,晶振为3.579545MHz。 (4)单片机的C语言源代码讲解: #include #define cnt_delay_short 100 //按键短按的规定时间 具体是多少我没验证过,请读者根据实际情况调整大小 #define cnt_delay_long 800 //按键长按的规定时间 具体是多少我没验证过,请读者根据实际情况调整大小 #define cnt_voice_short 60 //蜂鸣器短鸣 具体是多少我没验证过,请读者根据实际情况调整大小 #define cnt_voice_long 480 //蜂鸣器长鸣 具体是多少我没验证过,请读者根据实际情况调整大小 //补充说明:吴坚鸿程序风格是这样的,凡是输出IO后缀都是_dr,凡是输入的IO后缀都是_sr #define beep_dr RB1 //蜂鸣器输出 #define key_sr1 RB6 //组合按键的其中之一 //补充说明:吴坚鸿程序风格是这样的,按键扫描函数通常放在定时中 //断里,按键服务程序通常放在main函数循环里。有人说不应该把子程序放在中断里,别听他们,信鸿哥无坎坷。 void key_scan(); //按键扫描函数,放在定时中断里 void key_service(); //按键服务函数,放在main函数循环里 unsigned char short_touch_comfirm1=0; //按键短按有效标志 unsigned char key_lock1=0; //按键自锁标志 unsigned int delay_cnt1=0; //按键去抖动的延时计数器的变量 unsigned int voice_time_cnt; //蜂鸣器响的声音长短的计数延时 unsigned char key_sec=0; //哪个按键被触发 main() //主程序 { ADCON0=0x41; //设置AD模式 ADCON1=0x04; //RA0作为AD输入通道,本程序中没有用到AD,不用管它 TRISB1=0; //蜂鸣器设置成输出 beep_dr=0; //上电初始化蜂鸣器 TRISB6=1; //组合按键的其中之一 设置为输入 T1CON=0x24; //定时中断配置 TMR1H=0xFE; TMR1L=0xEF; INTCON=0xC0; TMR1IF=0; TMR1IE=1; PEIE=1; //外围中断允许 GIE=1; //开总中断 TMR1ON=1; //启动定时器中断 while(1) { CLRWDT(); //喂单片机内部自带的看门狗,大家可以不管它 key_service(); //按键服务 } } void key_scan() //按键扫描函数 { if(key_sr1==1) //IO是高电平,说明按键没有被按下,这时要及时清零一些标志位 { key_lock1=0; //按键自锁标志清零 delay_cnt1=0; //按键去抖动延时计数器清零,此行非常巧妙,仔细品味,回味无穷,在按键去抖动期间,如果低电平掺杂了干扰的高电平,则计数器重新清零计数,极大增强了抗干扰的能力。 if(short_touch_comfirm1==1) //短按如果被激活了 { short_touch_comfirm1=0; key_sec=1; //触发1号短按键 } } else if(key_lock1==0) //有按键按下,且是第一次被按下 { ++delay_cnt1; //延时计数器 if(delay_cnt1>cnt_delay_short) //短按 { short_touch_comfirm1=1; //激活按键短按的有效标志 } if(delay_cnt1>cnt_delay_long) //长按 { delay_cnt1=0; key_lock1=1; //自锁按键置位,避免一直触发 short_touch_comfirm1=0; //清除按键短按的有效标志 key_sec=2; //触发2号长按键 } } } void key_service() //按键服务函数 { switch(key_sec) //按键服务状态切换 { case 1:// 1号短按键 voice_time_cnt= cnt_voice_short; //蜂鸣器短鸣 key_sec=0; //相应完按键处理程序之后,把按键选择变量清零,避免一直触发 break; case 2:// 2号长按键 voice_time_cnt= cnt_voice_long; //蜂鸣器长鸣 key_sec=0; //相应完按键处理程序之后,把按键选择变量清零,避免一直触发 break; } } void interrupt timer1rbint(void) //中断程序入口 { if(TMR1IE==1&&TMR1IF==1) //定时中断程序 { TMR1IF=0; TMR1ON=0; key_scan(); //按键扫描函数 if(voice_time_cnt) //控制蜂鸣器声音的长短 { beep_dr=1; //蜂鸣器响 --voice_time_cnt; //蜂鸣器响的声音长短的计数延时 } else { beep_dr=0; //蜂鸣器停止 } TMR1H=0xFF; TMR1L=0xC8; TMR1ON=1; } } (5)下集预告: 按键花样技巧----按住一个按键的连续触发 (未完待续,下节更精彩,不要走开哦!) |
|
|
|
|
|
|
|
|
看了鸿哥的长短按键触发例程,觉得鸿哥的例程更具有人性化,它只区分短按与长按两种情况,并且长按不放手时能实现触发对应的长按事件,让按键的人知道:长按到此时可以松手了,因为想要的长按事件已经发生了。(当然不松手也没影响) 而你(dubeixian)的程序,短按是能轻松实现的,但你的长按却分为了稍长,中长,特长这几个级别,以为这样可以让按键具有更多的功能,可以处理更多的不同事件,实际上你的想法是比较难实现的(除非按键的人受过专门的训练)——因为你的程序每次都是在松手后才检查按键按下的时长,再根据时长的不同去触发相应的事件。 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
本帖最后由 dubeixian 于 2013-10-25 22:45 编辑
我只是分了几个等级。。。其实完全可以用2个代替啊....你把我的改成2个if就和鸿哥的一样了,而且程序更精简 |
|
|
|
|
|
|
|
只有小组成员才能发言,加入小组>>
求解外围电路实现的是4脚给持续低电平复位并正常工作,高电平不工作的原因
2382 浏览 1 评论
4240 浏览 3 评论
PIC1946程序有一个变量在运行过程中恢复初始值其他变量保持不变
2619 浏览 2 评论
3118 浏览 0 评论
PIC16F1825的RC5引脚,在主程序中操作无效,在中断中可以改变是为什么?
4572 浏览 5 评论
有套STM32与西门子200程序需要代写,有兴趣的工程师与有联系!
2487浏览 1评论
用XC8编译PIC18F25K80时提示下面Error,求怎么解决这个问题
6799浏览 0评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-13 20:09 , Processed in 1.403430 second(s), Total 84, Slave 74 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖