独闷闷网

 找回密码
 立即注册
搜索
查看: 10233|回复: 6
收起左侧

[分享] 学习笔记之按键扫描_学“手把手教你单片机架构”

[复制链接]
发表于 2015-1-30 17:06:20 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
—————***********************************—————


很早就知道鸿哥的这篇大作(连载中...)从业将近十年!手把手教你单片机程序框架。,自己惰性很大,做事沉不下心来;

看到群里高手如云,内心嫉妒且感慨光阴如驹,希望自己能静下心,慢慢的累积,不做知识的”收藏夹“。把感悟体会写出来不奢求能解惑于他人。


—————***********************************—————


     最近,把鸿哥的按键扫描部分看完,并且每节都亲自动手再写一遍,感觉收获很大。回想整下,脑海里留下了”框架“和”按键“两个词。
                  首先,”框架“--三区一线
                            鸿哥一开始便提出”三区一线“的框架结构,把单片机代码分成可视的几个部分:
                               拿开会(中国会议多)打个比方:我要主持个会议,那我需要提前到会议现场整理下会议资料(第一区);然后等待所有与会人员到场(分割线);与会人员都到了,交代下会议注意事项不                                 能抽烟,都关掉手机(第二区);最后开始具体的开会内容(第三区)。
  1. //三区一线结构
  2. void main()        //主函数
  3. {
  4.      initial_myself();                    //第一区:初始化单片机
复制代码
                          有什么用?别人的代码就完全没有三区一线吗?有,如果你听过别人介绍自己的代码的话,我想一定听过,"main()开头几行,我是初始化下*****”;
                          如果你把鸿哥的代码去掉initial_myself();去掉delay_long(100);去掉initial_peripheral();
  1. //没有三区一线 的LED灯闪烁
  2. void main()
  3. {
  4.      led_dr = 1;            //LED灭
  5.    
  6.     while (1)                //循环代码
  7.     {
  8.         ed_dr = 0;
  9.         delay_long(30);
  10.         led_dr = 1;
  11.        delay_long(30);
  12.     }
  13. }
复制代码
                         对比上面代码,使用三区一线和不要三区一线,有什么差别!功能上面没有差别,都能实现LED灯的闪烁;但是给人的印象完全不同,使用三区一线,整体的打眼一看,你就知道代码的”思路“,                          要实现的功能。
                                                                                                     --------------------…………………框架的总结……………………… --------------------
                       不管是”三区一线“还是initial_myself();     delay_long(100);  initial_peripheral();    转换到现实生活,其实就是-------->命名,俗称”起个名字“;
                        那为什么要命名呢?打个比方,你公司来个上司,坐在你旁边,就是没有名字,每天你都要找他回报工作,询问计划,沟通交流;你不会发现少点什么吗?在外边偶遇,他没有看到你,你看到了                           他,然后你”喂“?”嗨“?”那个“?            所以总结:框架是概括,对概括的整理命名,命名是为了方便(记忆、理解;加深理解)。                 



乐于分享,勇于质疑!
 楼主| 发表于 2015-1-30 17:15:37 | 显示全部楼层
不能修改吗?。。。
编辑比较乱!!!“三区一线”代码不知道怎么不全
  1. void main()
  2. {
  3.     initial_myself();                                //第一区:初始化单片机
  4.     delay_long(100);                           //分割线:等待外围上电稳定
  5.     initial_peripheral();                       //第二区:初始化外围
  6.     while (1)                                      //第三区:循环扫描非中断应用函数
  7.     {
  8.         device_function();
  9.     }
  10. }
复制代码


乐于分享,勇于质疑!
发表于 2015-1-30 20:56:16 | 显示全部楼层
mctrix 发表于 2015-1-30 17:15
不能修改吗?。。。
编辑比较乱!!!“三区一线”代码不知道怎么不全

很好的分享。果断加精。
乐于分享,勇于质疑!
 楼主| 发表于 2015-1-31 08:49:19 | 显示全部楼层
    第二:是“按键”。其实就是对按键扫描功能的代码实现。
    在鸿哥的描述中按键分为独立按键和矩阵按键(其实都一回事);按键有上升沿触发;有单击触发,双击触发,按键长短按触发,按键按住加速匀速触发等。

独立按键:
    A.独立按键之按键单击触发

        这里个人感觉最重要的就是一个按键单击触发:为什么?因为简单,所以好理解,其他按键触发都是在此基础上的修改:
            按键单击触发可以分解为两个重点:按键上升沿获取;按键防抖动;
            1.按键上升沿获取:其实是单片机对需求的c语言翻译。“按钮按下,蜂鸣器嘀一声”---->蜂鸣器什么时候响,按钮按下的时候。是按下一直响吗?是按钮一直按,松开的时候响吗?都不是,是按钮刚按下,蜂鸣器就动作。其实我们在听到这句话的时候,如果没听过单片机的话,肯定不会想那么多,什么上升沿,下降沿,”按下,蜂鸣器响不就成了“。但是对于单片机来说,你就是要分解的这么细,按钮按下到松开,对它来说有很多步骤。问题来了,如何获取按键上升沿呢?我们回想下,什么是上升沿,就是信号有无到有这个状态;那我们抓这个状态不就成立,当然前提是你给单片机的能区分这个“有”和“无”,先附上代码:
  1. //1.按下、松开对应信号有无
  2. if (key_sr == 1)      //按钮松开,对应信号无
  3. {
  4.     ucKeyStatus = 0;
  5. }
  6. else
复制代码
       未完待续。


乐于分享,勇于质疑!
 楼主| 发表于 2015-1-31 08:50:25 | 显示全部楼层
mctrix 发表于 2015-1-31 08:49
第二:是“按键”。其实就是对按键扫描功能的代码实现。
    在鸿哥的描述中按键分为独立按键和矩阵按 ...

为什么代码老是,粘不全
  1. //1.按下、松开对应信号有无
  2. if (key_sr == 1) //按钮松开,对应信号无
  3. {
  4.     ucKeyStatus = 0;
  5. }
  6. else

  7.      ucKeyStatus = 1 //按钮按下,对应信号有



  8. //2.以上我们只是抓了个有、无状态,现在我们抓上升沿状态
  9. if (key_sr ==1)
  10. {
  11.     ucKeyStatus = 0;
  12. }
  13. else if (ucKeyStatus == 0) //按钮按下的瞬间信号无-->其实就是这个状态,要上升沿就是要从0再到1
  14. {
  15.      ucKeyStatus = 1;
  16.      ucKeySec = 1; //触发了上升沿状态
  17. }


  18. //3.那么下降沿呢?同样
  19. if (key_sr == 0)
  20. {
  21.     ucKeyStatus = 1; //按钮按下,对应信号有
  22. }
  23. else if (ucKeyStatus ==1) //按钮松开瞬间,信号由有到无--就是下降沿
  24. {
  25.     uckeyStatus =0;
  26.     ucKeyStec = 2; //按键触发下降沿
  27. }


  28. //4.按键按下时,按键松开时,其实最简单,第一个代码就是
  29. if (key_sr == 1) //按键松开
  30. {
  31.     ucKeyStatus = 0;
  32.     ucKeySec = 3; //按键松开一直触发
  33. }
  34. else
  35. {
  36.     ucKeyStatus = 1;
  37.     ucKeySec = 4; //按键按下,一直触发
  38. }
复制代码
乐于分享,勇于质疑!
 楼主| 发表于 2015-2-3 10:50:55 | 显示全部楼层
2.按键去抖动:
    按键按下的波形情况如图:                                          

按钮按下松开波形

按钮按下松开波形

    可以看出,在按下和松开的时候,波形不是理想的立即切换,而是存在频繁的切换(抖动),然后再稳定的。如果只是使用上升沿来扫描按键按下瞬间的话,如上图在按下过程中会有很多的上升沿,这就可能导致按键按下的误触发,触发多次。这显然不是我们想要的结果--按键太灵敏导致。那如何让按键变得迟钝一点------>那我们就把波动部分滤除掉------>出现波动的话,就取消触发,稳定的我们才触发按键。从波形图中,我们分析,如果按键按下的状态能持续一段时间的话,我们就可以借此来说明按键是按下的。
  1. //第一个代码老是显示不全,此为测试
复制代码
  1. //按键去抖动
  2. if (key_sr == 1)
  3. {
  4.     ucKeyLock = 0;
  5.     uiKeyTimeCnt = 0;                      //引入按键按下累计时间计数器,计时清零,为按键按下计时做准备
  6. }
  7. else if (ucKeyLock == 0)
  8. {
  9.     uiKeyTimeCnt++;
  10.     if (uiKeyTimeCnt > CONST_KEY_SENSITIVE)          //按键按下状态持续设定时间的话,我们就任务按键按下了,若达不到设定时间,我们就认为是抖动,不处理
  11.     {
  12.          uiKeyTimeCnt = 0;                //计时清零,为下次计时准备
  13.          ucKeySec = 1;
  14.     }
  15. }
复制代码


乐于分享,勇于质疑!
发表于 2015-2-5 19:57:18 | 显示全部楼层
说的好!
乐于分享,勇于质疑!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|独闷闷网 ( 粤ICP备12007667号-2 )

GMT+8, 2024-3-28 22:06 , Processed in 0.180460 second(s), 20 queries .

快速回复 返回顶部 返回列表