mctrix 发表于 2015-1-30 17:06:20

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

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

很早就知道鸿哥的这篇大作(连载中...)从业将近十年!手把手教你单片机程序框架。,自己惰性很大,做事沉不下心来;
看到群里高手如云,内心嫉妒且感慨光阴如驹,希望自己能静下心,慢慢的累积,不做知识的”收藏夹“。把感悟体会写出来不奢求能解惑于他人。

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

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



mctrix 发表于 2015-1-30 17:15:37

不能修改吗?。。。
编辑比较乱!!!“三区一线”代码不知道怎么不全void main()
{
    initial_myself();                              //第一区:初始化单片机
    delay_long(100);                           //分割线:等待外围上电稳定
    initial_peripheral();                     //第二区:初始化外围
    while (1)                                    //第三区:循环扫描非中断应用函数
    {
      device_function();
    }
}

jianhong_wu 发表于 2015-1-30 20:56:16

mctrix 发表于 2015-1-30 17:15
不能修改吗?。。。
编辑比较乱!!!“三区一线”代码不知道怎么不全

很好的分享。果断加精。

mctrix 发表于 2015-1-31 08:49:19

    第二:是“按键”。其实就是对按键扫描功能的代码实现。
    在鸿哥的描述中按键分为独立按键和矩阵按键(其实都一回事);按键有上升沿触发;有单击触发,双击触发,按键长短按触发,按键按住加速匀速触发等。

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

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


mctrix 发表于 2015-1-31 08:50:25

mctrix 发表于 2015-1-31 08:49
第二:是“按键”。其实就是对按键扫描功能的代码实现。
    在鸿哥的描述中按键分为独立按键和矩阵按 ...

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

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



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


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


//4.按键按下时,按键松开时,其实最简单,第一个代码就是
if (key_sr == 1) //按键松开
{
    ucKeyStatus = 0;
    ucKeySec = 3; //按键松开一直触发
}
else
{
    ucKeyStatus = 1;
    ucKeySec = 4; //按键按下,一直触发
}

mctrix 发表于 2015-2-3 10:50:55

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

重庆-风雪 发表于 2015-2-5 19:57:18

说的好!
页: [1]
查看完整版本: 学习笔记之按键扫描_学“手把手教你单片机架构”