12F675 发表于 2008-10-4 22:11:38

请马老师指教:有关按键问题----建议学电子技术的大学生尝试思考和回答__马老师摆擂台

http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_439830.jpg

 (原文件名:无标题.jpg) 



马老师:

     在上图中,如果要检测按键的按下,如果要求在按键按下直至按键松开之后才定义一次按键完成,那么程序上如何检测P3。7的这种变化呢?(因P3。7这时的电平变化是一系列脉冲的)。请马老师指教,不胜感激。





=======================================================================================



首先谢谢捧场的朋友们。 



我把题目总结归纳,给出更具体的需求,便于大家出招打擂。 



1。原理图以楼主位的为基础,可以做稍微的改动,但要保持I/O复用的基本原则,也就是说,不能增加太多的I/O。最好还是原图的数目。 

2。要保证6个LED数码管显示正常,按键检测过程中不能出现闪烁、抖动、或破坏显示的现象 

3。系统需要使用组合键。即要能“同时”检测出多个键按下 

4。要考虑按键按下和释放过程中的消抖,消抖时间在10ms-20ms之间 

5。LZ位的要求是“在按键按下直至按键松开之后才定义一次按键完成”。这就是说不具备按键的“连_发”功能。我把要求改动为:按键不具备“连_发”功能。这样的话,按键稳定按下后就可以执行按键操作,但下一次按键的检测必需等待本次按键完全释放。这不违背LZ的“在按键按下直至按键松开之后才定义一次按键完成”原则,但在实际操作中用户使用方便。否则用户按下键后,没有见到相应的反映,会一直按着不放,这样这个按键过程会“永远”完不成了。 

6。给出相应的C代码(主要是显示和读键部分,以及上层的调用关系等),和电路图(如果改动的话)。但显示扫描和消抖过程禁止使用软件延时,必须考虑使用定时器中断。 





擂主:本专栏斑竹





在71楼我已经出了试探招数,亮了点底牌,请后来者看过后斟酌仔细,然后再杀上前来也。



=====================================================================================

擂主本人在93楼使出了绝招,剑法如下:



 一、硬件原理图。就是LZ的图:

http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_439830.jpg

 (原LZ位图) 



只是里面有点BUG,不能多键按下,按50楼的图改动,增加5个二极管。

http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_443092.jpg

 (原50楼硬件修改图) 



至于改动原因,就不说了,前面已经有点评了。



另外,电路中的LS47可以省掉,直接用P1输出8位段码(89C2051的驱动能力10mA,点1个LED没问题),反正其它的口也没用吗。



二、具体功能,也是按LZ位制定的原则

1。要保证6个LED数码管显示正常,按键检测过程中不能出现闪烁、抖动、或破坏显示的现象  

2。系统需要使用组合键。即要能“同时”检测出多个键按下  

3。要考虑按键按下和释放过程中的消抖,消抖时间在10ms-20ms之间  

4。LZ位的要求是“在按键按下直至按键松开之后才定义一次按键完成”。这就是说不具备按键的“连_发”功能。我把要求改动为:按键不具备“连_发”功能。这样的话,按键稳定按下后就可以执行按键操作,但下一次按键的检测必需等待本次按键完全释放。这不违背LZ的“在按键按下直至按键松开之后才定义一次按键完成”原则,但在实际操作中用户使用方便。否则用户按下键后,没有见到相应的反映,会一直按着不放,这样这个按键过程会“永远”完不成了。  

5。给出相应的C代码(主要是显示和读键部分,以及上层的调用关系等),和电路图(如果改动的话)。但显示扫描和消抖过程禁止使用软件延时,必须考虑使用定时器中断。



三、为了使学51的和AVR的都能使用,代码采用C编写。程序中采用P1、P3表示两个8位的I/O口,AVR可类似对应的使用PORTA,PORTC。键输入为P3.7,对应AVR,可理解为PINC.7。系统6个LED数码管采用动态扫描显示,有5个按键,有一个位选是不复用的。



四、显示扫描时间的计算与确定。每个LED点亮时间为2ms,6个LED循环扫描一遍为12ms。1秒内共循环1000/12=83次,超过25次,保证显示不出现闪烁、抖动等情况。按键读取插在LED的扫描过程中,不另外使用单独的时间。





五、代码框架



//=============定义全局变量

char dis_buff;                 // 这里存放每个LED显示段码值(BCD格式的)

char key_tmp,key_value = 0x00;    // 键值,8位,每位对应一个键,为0表示该位按键,为1表示无。高3位永远为0,

                                  // 因此。0b00011111表示无键按下;0b00011110表示0号键按下,0b00011100则表示0、1号键同时按下的组合键。



//==============主程序

main()

{

   while(1)

   {

     key_tmp = key_value;                // 读键值,放在key_tmp中,因key_value会在中断中变化的

     if (key_tmp < 128)                  // 有一次按键过程 

     {

        key_value = 128;                 // 防止多2次处理

        switch(key_tmp)                  //按键处理过程

        {

          case 0b00011110:

               // 0号键处理.......

               break;

        

          case 0b00011101:

               // 1号键处理..............

               break;

               ............



          case 0b00011100:

              // 2键组合键处理(0、1号键按下)..................... 

              break;

             ............

          case 0b00011000 

             // 3键组合处理(0、1、2号键按下)..................... 

             break;

        }

     ............. 

    }  

}

//--------------------------------------------

主程序就写这么多了,当然初始化部分都剩掉了,其它的系统功能我也不知道,这里重要的是键处理(千万不要在主程序的大循环中使用大量的软件延时,影响switch的执行,这样键的响应就会受到影响了)。另外重要的是我的代码中需要一个2ms的定时中断,不要忘记初始化一个定时器。这个不用写了。 

//================================================================







//===================2ms定时中断服务(完成LED扫描显示和读键,消抖,确认的功能)=======

//====注意,此服务2ms执行一次,但执行时间很短======================

//=====此外,为了容易理解,下面是以138的ABC接2051的p3.0/p3.1/p3.2处理,那个JP1的作用就不考虑了,我也不知道他准备做什么===



timer_2ms_int()

{

      static char posit = 0;

      static char read_key,pre_key,delay_time;

      static char key_state = 0;



      P3 = 0x87;                          //关显示,消影(138的ABC = 7,y7输出0,其它为1)

      P1 = dis_buff;               //送出BCD格式的段码值   

      P3 = 0x80 | posit;                  //开相应posit位的LED显示。 

      

      if (posit < 5)

      {

          read_key &= ~(1<<posit); 

          if (P3.7) read_key |= (1<<posir));     // 5次中断,读到5个键值

      }

      elas

      {                                                                 //这段12ms执行一次,消抖,判断都有了

          switch(key_state)

          {

                case 0:

                      if (pre_key == read_key)                          // 不管是单键还是多键,必须稳定的按下60ms后才算正式确认一次按键。

                      {   if (++delay_time>= 5) key_state = 1;}        // 调节delay_time的比较值,可以改变稳定确认的时间,如果实际按键

                      else                                              // 过程中感到120ms比较好,那么(++delay_time>= 10)。

                      {   delay_time = 0; }                             // 这里实际已经包含了按键按下和释放的消抖处理。

                      break;

                case 1:

                      key_value = pre_key;                              // 判断出一次有效的按键,注意:pre_key的高3位总是“0”

                      key_state = 2;

                      break;

                case 2:

                      if (read_key == 0b00011111)                       // 必须5个键全部释放才能进入下次按键操作

                      {                                                 // 只要开始发现释放了,就转到状态0,释放消抖在状态0中处理了。

                           delay_time = 0;

                           key_state = 0;

                      }

                      break;  

          }

          pre_key = read_key;      

      } 

      

      if ( ++posit> 5 ) posit = 0;     

}



=====================================================================

在此基础上做修改,可以非常容易的把“连_发”功能加上,不管是单键,还是多键,都能“连_发”。这个还是留给各位去实现吧。



剑法如何,欢迎各位后生评判。

本贴被 machao 编辑过,最后修改时间:2008-10-09,20:31:09.

machao 发表于 2008-10-5 00:49:59

留做练习题吧,看其它的人能给出解答吗?

xiaobendan 发表于 2008-10-5 08:11:56

在脉冲时检测电平,检测到了,计数器++,到一个数字时,按键按下。检测不到,计数器--,到0时,按键松开。

12F675 发表于 2008-10-5 20:34:30

还有其它办法吗?

machao 发表于 2008-10-6 00:58:50

这是一个复用I/O口的例子,首先要把硬件电路看明白,先不考虑按键,分析出基本的工作方式,然后看采用什么方法和途径能够非常方便的读键。

machao 发表于 2008-10-6 16:31:57

难道访问这个专栏的朋友水平都那么的“低”,回答不出?还是水平都非常“高”,不值得回答?



这是一个非常好的综合性的分析题目,尽管没有用AVR,使用的2051,但思路是相同的。实现的方法肯定有不同,大家可以尝试和讨论,看那种最好,最方便。



本站有如此之多的高校版块,应该有很多的学习电子技术的大学生吧,不要老是贴上个什么代码,这个才是真正的学习和思考方法,锻炼一下你们的能力吧。



这个也送给正在听我课的华东师范大学的同学,如果要真正学到点什么,这就是很好的锻炼和学习。



2楼的帖子,并没有清楚的说明问题和给出方法,比如有6个键,如何区别?怎样才能实现“按键按下直至按键松开之后才定义一次按键完成”?如果按键过程中有抖动如何处理?

本贴被 machao 编辑过,最后修改时间:2008-10-06,16:43:50.

mljda 发表于 2008-10-6 19:18:40

通过138位选按键和LED数码管。

1&nbsp;138【位】选输出高电平,P3.7读,(1)当前【位】选按钮没按下,则P3.7被接地置0,读值0(2)按键按下,则P3.7读高电平(由于下拉电阻10K,并不会把高电平拉到地)。



==========================================

第一点的分析已经错了,后面免谈。:)&nbsp;_________马



==========================================







2&nbsp;三极管作为LED【位】选驱动,所以138【位】选输出高电平时,三极管导通,【位】选LED数码管亮。由1;按下按键,不拉低三极管基极。

3&nbsp;同上1,2;当138【位】选LED数码管的同时也【位】选了一个按键。所以可以P3.7可以扫描按键是否按下。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;————————————————————————————————————————

程序流程

1&nbsp;输出138位选信号

2&nbsp;输出138位选对应的LED数码管段数据,读P3.7值,计入按键状态机变量。

3&nbsp;延时

4&nbsp;循环至1



注意:LED扫描周期小于按键件扫描周期。



-/////////////////////

罪过。138位选是低电平,P3.7是上拉VCC,三极管是PNP的,基极接0导通;



P3.7外接电阻向下,就一股脑看成接地了,其它就顺势看反了。

不仔细,就完全反了。罪过罪过。



通过138位选按键和LED数码管。

1&nbsp;138【位】选输出低电平,P3.7读,(1)当前【位】选按钮没按下,则P3.7被接VCC置1,读值0;(2)按键按下,则P3.7被拉低电平,读0。(由于上拉电阻10K,并不会把低电平拉到VCC)。

2&nbsp;三极管PNP作为LED【位】选驱动,所以138【位】选输出低电平时,三极管导通,【位】选LED数码管亮。由1;按下按键,不拉高三极管基极。

3&nbsp;同上1,2;当138【位】选LED数码管的同时也【位】选了一个按键。所以可以P3.7可以扫描按键是否按下。

本贴被 mljda 编辑过,最后修改时间:2008-10-07,08:19:53.

nokia0310 发表于 2008-10-6 19:42:12

p->000&nbsp;&nbsp;&nbsp;&nbsp;//==》&nbsp;这时显示的是什么东西?





if(p37==0)s5按下

p->001

if(p37==0)s4按下

...

p->101

if(p37==0)s1按下

重新扫描



本贴被 machao 编辑过,最后修改时间:2008-10-06,23:57:59.

314forever 发表于 2008-10-6 20:51:59

可以把扫描时P3.7电平变化的一系列脉冲依次左移或右移读到一个8bit的变量里,然后比较每次扫描得到的变量和上一次的不同之处就可以了,也就是说可以把这个变量当成PIN寄存器使用(51没用过,不知道有没有这个寄存器,反正就是类似的东西)。





=======================================

这个与51和AVR无关,你可以把控制器看成是AVR的I/O。



“扫描时P3.7电平变化的一系列脉冲”。。。到底是什么脉冲?如果你根本不知道应该是何种脉冲,那么又如何去检测和判断?

本贴被 machao 编辑过,最后修改时间:2008-10-07,00:01:17.

112233 发表于 2008-10-6 21:36:02

用四个位变量去保存四个按键,在每次扫描时去判断是否升起来了。MS很浪费时间的说。



只不过有一个好处:四个按键不管同时按下几只都可以准确判断哟。

machao 发表于 2008-10-7 00:06:26

以上各位,首先是你们的硬件水平就太差了,电路如何才能正确工作都分析不正确,后面怎么会继续下去?

machao 发表于 2008-10-7 00:19:28

阿莫:能否对能比较好的对这个问题给出解答的朋友给予支持:邮购部免费提供100元内的电子元器件。



提高大家的学习兴趣,提倡和支持踏踏实实的学习态度和学习方法。

hexixiaomao 发表于 2008-10-7 01:18:20

图太小&nbsp;&nbsp;上边的网络标号都看不清楚&nbsp;啊&nbsp;

本贴被 hexixiaomao 编辑过,最后修改时间:2008-10-07,01:29:39.

hexixiaomao 发表于 2008-10-7 01:28:16

&nbsp;&nbsp;嘿嘿&nbsp;用PHOTO&nbsp;SHOP放大了看看

本贴被 hexixiaomao 编辑过,最后修改时间:2008-10-07,01:30:33.

machao 发表于 2008-10-7 01:40:05

楼上的,丢人丢大了也。



4、5接地没问题的,到是怎么会得出“38译码器任何时候输出都只有一位是1,也就是任何时候都有5个数码管同时被选中啊”的分析?数字逻辑电路没学过138?



138译码器任何时候输出都只有一位是“0”!在图中只能有1个数码管被选中,或一个也不被选中(138的Y6、Y7输出0时)。





逃的还真快:),不用放大,以上的基本东西掌握不好,放大了也没用。

本贴被 machao 编辑过,最后修改时间:2008-10-07,01:42:42.

hexixiaomao 发表于 2008-10-7 02:19:53

http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_441951.jpg

&nbsp;(原文件名:未标题-1.jpg)&nbsp;&nbsp;&nbsp;

画了个时序图,方便分析。

基本原理:1数码管动态扫描&nbsp;略

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;关于按键的检测,

在每次扫描的中间时刻插入按键检测子程序,如果在某一次检测中,P3.7为低电平,那么就把

这时被点亮的数码管的序号记录下来。然后就只在这一位数码管被点亮的时候检测P3.7是否为

低电平,如果是计数器num加1,如果没有继续检测到低电平那么就说明按键抬起来了,这时对

num判断如果小于1(或者设定一个最小值)那么就认为按键无效,如果大于&nbsp;那么就认为按键有

效,将序号送出。



大概具体软件流程

keynum&nbsp;表示按下的按键序号&nbsp;0表示无任何按键按下

lednum&nbsp;被点亮的led的序号

temp

testkey&nbsp;0,表示未检测到按键,1表示检测到一次按键,程序在计数中。

num&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;计数器&nbsp;



1初始化

所有状态变量置零。



2开始循环



a&nbsp;检测keynum&nbsp;,如果不为零进入按键响应,执行完之后keynum&nbsp;置零。如果为0继续。

b&nbsp;点亮一位LED,lednum=此时led的序号。

c延时

d按键检测程序&nbsp;&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1)P3.7是否为0,

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果P3.7不为零那么&nbsp;检测num是否大于2(或者设定一个最小值),

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果小于&nbsp;那么就说明按无按键按下或者无效。num=0;temp=0;&nbsp;testkey=0;程序进入下一步e

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果大于2&nbsp;并且lednum=temp那么就说明这个按键有效,并且已经抬起。testkey=0;keynum=temp;temp=0;num=0;程序进入下一步e

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果P3.7为0&nbsp;&nbsp;那么检测testkey,

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果为0那么就说明这是第一次检测到低电平,temp=lednum。num++。testkey=1.程序进入下一步e。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果testkey为1,那么就说明程序在计数中,

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果lednum=temp;num++

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

e延时



d&nbsp;lednum++

回到2









本贴被 hexixiaomao 编辑过,最后修改时间:2008-10-07,11:05:14.

hexixiaomao 发表于 2008-10-7 04:13:54

上边的&nbsp;程序&nbsp;不能检测组合键&nbsp;如果有两个按键同时按下&nbsp;就只能检测到一个&nbsp;&nbsp;要想检测组合键&nbsp;就得为每一个按键分别设置一个变量

分别对其计数&nbsp;&nbsp;&nbsp;&nbsp;在对应某个的时刻&nbsp;连续检测到2个(或一个合适的阈值)以上低电平,和一个高电平之后&nbsp;就认为这个键有效。



本贴被 hexixiaomao 编辑过,最后修改时间:2008-10-07,04:19:04.

hexixiaomao 发表于 2008-10-7 04:28:16

不蒸馒头争口气&nbsp;&nbsp;不能让这的老大们看不起我们新来的菜鸟们。非得整明白不可&nbsp;。诶&nbsp;搞得头都大了&nbsp;先去睡觉咯&nbsp;。

明天继续!!!&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

luoyanfang 发表于 2008-10-7 05:46:34

哈哈,马老师上课了,学生也凑个热闹...

用到74HC138的六种状态:

http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_441970.jpg(原文件名:CAP27.jpg)

先设置,使Y0-Y4输出都为高,(例如74HC138的ABC输入分别为:HLH时),扫描P3.7。当有按键时,P3.7读出H状态,说明为有某一个按键按下;

然后改变p3.3~p3.5,动态扫描每一按键。例如:

74HC138的ABC输入分别为:LLL时,74HC138只有Y0输出为零,扫描P3.7。如果读出为L(低),则表示按键S5被按下;

...



该电路缺点:

一次只能够有一个按键按下。如果同时按下多个按键的情况,因为74HC138输出端都连在一起,很可能造成电路短接。



==================================================================

点评:



找到了硬件设计中不合理的地方,值得表扬一下,要加分的。



该电路的毛病就是不能同时按下多个键,这种情况后,轻者是影响到显示,按下键几个对应的LED数码管都亮显示同一个数。重者造成138输出脚烧掉,或系统电源出问题。



正确的应该串入5个二极管。具体可以参考我编写《AVR单片机嵌入式系统原理与应用实践》一书,487页,图16-16。













本贴被 machao 编辑过,最后修改时间:2008-10-07,13:12:42.

314forever 发表于 2008-10-7 08:28:13

数码管在工作时,单片机要不停地对其进行扫描;以楼主的图为例,也就是138的Y0-Y5要不停地依次输出低电平(通过P3.3-P3.5输出译码得到)。为读取按键状况,可以在每扫描一位数码管时(相应的Yx为低电平),读取P3.7的电平;这样对所有数码管扫描一遍之后将得到6个电平值,分别对应六个按键。如果没有键按下,则6个电平量都为高;如果有,则相应的电平值为低。这样既可以检测到按键按下(1->0),也可以检测到按键松开(0->1)。按键的去抖可以把通常方法中的延时换成数个数码管扫描周期即可。

AVR51 发表于 2008-10-7 09:25:32

看看,学习一下.

本贴被 AVR51 编辑过,最后修改时间:2008-10-07,14:20:35.

hyz_avr 发表于 2008-10-7 10:17:52

每扫描一位数码管检测一次P3.7的值,如果为低则有按键按下,记录此键值(根据当前显示的位).

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果为高则检查上次记录按键值是否此位,如果是则说明按键松开.

mtxmxt 发表于 2008-10-7 10:50:32

显示和按键程序分开写,可能结构上更合理.

显示时不检测按键,当检测按键时将显示关断(共阳的管,将字段IO口线送高电平),通过138将按键逐位拉低.读P3.7,如果为低则有按键按下,P3.3P3.4P3.5的值就是其键值

418425051 发表于 2008-10-7 11:22:08

马老师上课,我也来丢脸啦!BS上面逃跑的那位!



===>他没有逃,是很快发现自己分析不对,删掉了。但他是第一个比较详细给出按键检测的基本思路的,一直工作到凌晨4点才上床的(我在他后面休息的)。这样的精神值得表扬。





---------------------------------------------------

&nbsp;&nbsp;看了看大家的帖子,其实电路的基本原理都分析出来了,但是马老师的第二个问题还没有解决

“然后看采用什么方法和途径能够非常方便的读键。”

很多方法都可以读取键值,关键在于“非常方便”。即在不会对程序周期造成很大的影响下实现按键判定。

先上硬件电路分析:

&nbsp;&nbsp;&nbsp;此电路用74hc138实现了数码管动态扫描和键盘电路。

&nbsp;&nbsp;显示部分:74HC138将P3.3~P3.5的输出译为选通信号,使相应位的8550导通。从而驱动相应位的数码管共阳极。数码管数据由

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;74LS47和P1.3送出。

&nbsp;&nbsp;键盘部分:74HC138送出低电平扫描信号。P3.7作为输入端会在得到一个脉冲序列。文字太繁琐,上图:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;扫描:&nbsp;&nbsp;1.__----------&nbsp;&nbsp;2.--__--------&nbsp;&nbsp;3.----__------&nbsp;4.------__----&nbsp;5.--------__--&nbsp;6.----------__

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;无按键:1.------------&nbsp;&nbsp;2.------------&nbsp;&nbsp;3.------------&nbsp;4.------------&nbsp;5.------------&nbsp;6.------------

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;按键s1:1.------------&nbsp;&nbsp;2.------------&nbsp;&nbsp;3.------------&nbsp;4.------------&nbsp;5.--------__--&nbsp;6.------------&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;按键s2:1.------------&nbsp;&nbsp;2.------------&nbsp;&nbsp;3.------------&nbsp;4.------__----&nbsp;5.------------&nbsp;6.------------&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.......

硬件电路的问题:因为显示和键盘扫描公用驱动信号,如果在扫描键盘只是是简单的关显示会造成显示闪烁。

&nbsp;&nbsp;解决方案:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;显示和键盘扫描共用一个扫描周期。具体实现方法用程序来解释。



&nbsp;&nbsp;usinged&nbsp;char&nbsp;keyvalue;&nbsp;&nbsp;&nbsp;//取得的键值

&nbsp;&nbsp;usinged&nbsp;char&nbsp;keydownflag;//键盘按下标志

&nbsp;&nbsp;usinged&nbsp;char&nbsp;scaner;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//扫描变量

&nbsp;&nbsp;显示延时函数(){

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(P3.7==0)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;去抖动延时();

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(P3.7==0)keyvalue==scaner;&nbsp;&nbsp;//取键值

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;正常显示延时...

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;键值处理函数(){

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(keyvalue!=0)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(keydownflag==0)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keydownflag=keyvalue;&nbsp;&nbsp;//保存键值

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(keydownflag!=keyvalue)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;error;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//重键处理(此程序选取后扫描的键位,相当与可以自由设置按键优先级)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;&nbsp;&nbsp;//if(keyvalue==0);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(keydownflag!=0)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;keydownflag;&nbsp;//按键有效,返回键值

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

程序通过返回值就可以判定是那位键按下又释放了。

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;请马老师点评&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

本贴被 machao 编辑过,最后修改时间:2008-10-07,14:18:26.

machao 发表于 2008-10-7 14:07:21

首先谢谢捧场的朋友们。



我看了上面的一些回答,有2个帖子非常有价值:16楼和21楼。一个指出了基本的检测思路,一个找到了硬件电路的BUG。但真正比较好的检测方法还是没有出现。



我把题目总结归纳,给出更具体的需求,便于大家讨论。



1。原理图以楼主位的为基础,可以做稍微的改动,但要保持I/O复用的基本原则,也就是说,不能增加太多的I/O。最好还是原图的数目。

2。要保证6个LED数码管显示正常,按键检测过程中不能出现闪烁、抖动、或破坏显示的现象

3。系统需要使用组合键。即要能“同时”检测出多个键按下

4。要考虑按键按下和释放过程中的消抖,消抖时间在10ms-20ms之间

5。LZ位的要求是“在按键按下直至按键松开之后才定义一次按键完成”。这就是说不具备按键的“连_发”功能。我把要求改动为:按键不具备“连_发”功能。这样的话,按键稳定按下后就可以执行按键操作,但下一次按键的检测必需等待本次按键完全释放。这不违背LZ的“在按键按下直至按键松开之后才定义一次按键完成”原则,但在实际操作中用户使用方便。否则用户按下键后,没有见到相应的反映,会一直按着不放,这样这个按键过程会“永远”完不成了。

6。给出相应的代码,和电路图(如果改动的话)。但显示扫描和消抖过程禁止使用软件延时,必须考虑使用定时器中断。

---------------------------------------------------------------------------------

如果有能力,可考虑实现按键“连_发”功能,但与“组合键”功能会有冲突,需要进一步的定义一个组合先导键,该键不能连_发,用于与其它4个键构成组合键。而只其它4个键能连_发。





====================================================================

该题目非常好,如果作为研究生考题的话,我们系刚确定的直升学生中,会有50%的人不及格的。





本贴被 machao 编辑过,最后修改时间:2008-10-07,19:05:26.

hhjhhj 发表于 2008-10-7 15:02:19

//多键组合先串连二极管

//不检测按键释放

//显示延时后调用

//返回0xff没有键按下,其它为键值

uchar&nbsp;aaa()

{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;uchar&nbsp;flag;&nbsp;&nbsp;//按键有效

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;uchar&nbsp;i;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//有键按下计数器

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;uchar&nbsp;p;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//位显示计数器

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;uchar&nbsp;k=0xff;//按键值暂存

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;uchar&nbsp;m=0xff;//按键位暂存

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//显示()

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(p==7)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p=0;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(m==0xff)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i=0;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;k=0xff;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(k==m)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i++;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m=0xff;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;flag=0;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i=1;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;k=m;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m=0xff;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p++;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m=m&lt;&lt;1;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m=m+(P3&0x01);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if((flag==0)&&(k!=0xff)&&(i>?))//?需要按键延时时间(即显示循环次数)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;flag=1;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(k);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;return(0xff);

}

请马老师指正

本贴被 hhjhhj 编辑过,最后修改时间:2008-10-07,15:03:27.

yqing81 发表于 2008-10-7 15:12:47

马老师分析的非常中肯!!此题和我的毕业设计——多功能时钟定时器,有异曲同工之处(我的那功能更强大,有复合键和连_发功能),贴上来让大家欣赏一下!!

原理图ourdev_442392.pdf(文件大小:17K)&nbsp;(原文件名:Timer_sch.pdf)&nbsp;

源程序ourdev_442393.txt(文件大小:11K)&nbsp;(原文件名:timer.txt)&nbsp;



================================================================

硬件设计不错,估计你硬件功底比较扎实,蜂鸣器和掉电处理有创意。不过系统软件的设计不是最好,还是比较乱,许多功能混在一起,如果改动的话,就比较麻烦了。



另外,能介绍你的复合键和连_发功能的具体是如何定义的?比如当我按下A键1秒后又按下B键,那么是A键连_发,还是AB复合?



本贴被 machao 编辑过,最后修改时间:2008-10-07,20:54:57.

ssyniuej 发表于 2008-10-7 15:48:13

我也凑个热闹,写个思路。

&nbsp;&nbsp;&nbsp;&nbsp;这个电路利用138做输出,做为数码管的位选,同时做按键检测。(这里面有个硬件设计的问题,如果同时按下几个按键硬件就出现问题了!不考虑这种情况,否则会出现输出短路的情况,在这种前提下每次只会有一个按键按下)

&nbsp;&nbsp;&nbsp;&nbsp;以循环周期来算,可以利用一个字节来保存外部按键状态,利用移位方式,当检测到外部P3.7为1的时候就移进1,如果为0就移进0.

如果字节全部是1,那么表示所有按键输入为全放开的状态。只要不出现全1就表示有按键按下。

&nbsp;&nbsp;&nbsp;&nbsp;对于消抖动部分,因为外部接的是动态扫描显示数码管,所以一般情况下扫描一遍的时间就是10到20毫秒之间吧,这样只要在每次得到的外部按键字节都与上次的字节(扫描后会保留上一次的按键状态)是否相同,如果不同,则表示按键未稳定,保存一下这次的状态,直接返回。如果相同了,那么就表示按键稳定了,执行一次按键相应的功能。

&nbsp;&nbsp;&nbsp;&nbsp;针对楼主的问题,在这种情况下也很容易了,因为一旦键盘扫描字节变成了0XFF就表示按键放开了(消抖动后的状态),然后处理就行了。(为了判断在放开按键之间的按键,还要增加一个单元用来保存松开前的键值)

machao 发表于 2008-10-7 21:17:56

建议各位:



本贴的目的是学习和提高技术。能到这里贴上自己的见解朋友,通常都“算”是比较优秀的学生,具备一定的能力和自信(这里用“算”是指与你周围的同学或同事比较,甚至是比教你的老师都“强”)。但山外有山,请大家能先仔细看看别人的帖子,从中找到有价值的东西,然后综合考虑。不要死抱着自己的想法。



因为我知道目前大多数教课书所介绍的内容,都是最基本和简单,或仅局限于某单一功能实现的例子。用在实际的系统中远远不够,BUG多多。这些通常的思路和方法需要在实际应用中更加灵活的使用和变换。

huayan 发表于 2008-10-7 22:03:46

看看再说

machao 发表于 2008-10-7 22:25:01

到目前为止,在一天多的时间里本贴点击次数为678,但帖子数只有34,粗略评估回贴数还不到5%。



这到是一个非常好的证明,从某个侧面说明了我们现在学电子的学生的水平。



在我的专栏中,我曾经转贴一个帖子《转帖网友yanwang对电子专业毕业生的评价》(见http://www.ouravr.com/bbs/bbs_content_all.jsp?bbs_sn=797384)引起一些朋友的不满,说我看低了现在的电子专业的大学生。



那么这里到是一个机会,请那些不赞成我的说法或不服气的朋友,到这里晒晒你的本事。



老夫已经横刀立马在在此把关,后生们有本事就拍马冲上前来。如果已经被吓跑了,你们如何面对下一步激烈的社会竞争。支持20楼的说法:“不蒸馒头争口气&nbsp;&nbsp;不能让这的老大们看不起我们新来的菜鸟们”。



./emotion/em062.gif./emotion/em050.gif./emotion/em049.gif

12F675 发表于 2008-10-7 23:02:55

&nbsp;&nbsp;&nbsp;感谢马老师与各位的回复,我很喜欢这里讨论问题的氛围。

&nbsp;&nbsp;&nbsp;在各位的回复中,对同一问题有不同的看法,这拓宽了我的思路。

&nbsp;&nbsp;&nbsp;感谢各位!

machao 发表于 2008-10-7 23:21:30

楼上,不用客气。我借你的问题设下擂台,挑战一批学生,树立我的威信,我还要感谢你提供了非常好的机会。



不过,到目前为止,尽管你认为“拓宽了我的思路”,但我认为好的,比较完整的回答还没有。



再等上几天看看吧。到时侯我会晒上我的方法提供参考,或是大家排砖的目标。

wchuxin 发表于 2008-10-7 23:26:44

假如为了某种需要(比如抗干扰),在P3。7对地接上一个104的话,程序与没接电容是可能不同的。





====================================================================

104没变化,若10u的话,就不一样了。



你是想通过电容来消抖?可以试试。不过通常不这样用。

本贴被 machao 编辑过,最后修改时间:2008-10-07,23:34:55.

wchuxin 发表于 2008-10-7 23:43:49

以前的一个程序因为显示的扫描频率较高(整个程序差不多就是显示与键盘扫描了),只能用软件廷时外加104解决。但加上104后,按键廷时就不能用调用显示程序来实现了,否则将检测不到按键。

machao 发表于 2008-10-7 23:55:25

楼上,放弃你以前的程序吧。我已经讲了,不准使用软件延时。



ms级以上的延时采用软件方法,是小儿科的水平,不上台面。效率都给软件延时吃掉了,系统设计问题多多。要采用定时中断和状态机。



建议你先在本拦置顶贴中,下在我编写书的电子版,从第9章看,看看我如何教读键,做LED动态扫描的。

wchuxin 发表于 2008-10-7 23:57:34

不过电路与LZ不同。http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_442970.jpg

&nbsp;(原文件名:未标题-1.jpg)&nbsp;

wchuxin 发表于 2008-10-8 00:01:53

呵呵,我本来就是菜鸟一个,只能按N年前的方法扫描。

machao 发表于 2008-10-8 00:06:36

总不能停止不前吧。为什么不能放弃不好的方法,学习好的思路?

wchuxin 发表于 2008-10-8 00:13:08

谢谢。我现在只能用汇编,还学不会C语言呢。那个程序也是一边查指令表,一边写出来的,N年前学过51,用AVR也是今年才开始的。



===========================================================

不管是用汇编,还是用C,思想方法是一样的。用汇编也不提倡使用软件延时,除非是几个us的延时。

本贴被 machao 编辑过,最后修改时间:2008-10-08,00:36:53.

wchuxin 发表于 2008-10-8 00:13:46

见笑了。

machao 发表于 2008-10-8 02:14:31

hexixiaomao说今天继续的,看样子今天等不到了。&nbsp;

armok 发表于 2008-10-8 07:06:46

呵,这个帖子讨论得很好。COOL&nbsp;!

mashan75 发表于 2008-10-8 09:16:40

请马老师点评

1。电路图这样改

http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_443092.jpg

&nbsp;(原文件名:MACHAO&nbsp;TEA1.jpg)&nbsp;

2。流程图这样画

http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_443171.jpg

&nbsp;(原文件名:MACHAO&nbsp;TEA2.jpg)&nbsp;

本贴被 mashan75 编辑过,最后修改时间:2008-10-08,11:02:05.

luoyanfang 发表于 2008-10-8 12:26:35

楼上的电路图二极管接反了...



其实答案马老师已经都点到过了~~~

晕,怎么成负分了...

本贴被 luoyanfang 编辑过,最后修改时间:2008-10-08,12:28:56.

machao 发表于 2008-10-8 13:18:51

to&nbsp;51楼:图中二极管加的很正确吗。你再把它反过来,是否有新招?



我还没出手,各位自己不要沉不住气,不自信哈。



=================================================================

电脑一直放在床边上,通过无线挂在站上。终于看到的阿莫49楼的关注。



我请求阿莫帮助,能否将本贴作为【总论坛置顶】的帖子,挂上几天,我想把擂台摆到总站上,向所有访问本站的武林高手挑战。



建议阿莫在本站建立“华山论剑”技术专栏,把象类似这样的题目拿来开设擂台,并设立一定的获胜奖励。可以聘请几位裁判,或通过网友投票来决定获胜者。



在“华山论剑”中,那些是“真刀真枪”的实工夫,那些是“花拳绣腿”的三脚猫就一目了然了。同时大家也可以切磋武功,旁观者也能学上那么几招真正的功夫。另外也可以提高本站的人气和知名度。



“如此不起眼的一个小网站”没有关系,慢慢让它成长为“起眼的大网站”,阿莫有这个梦想吧。



我会尽力支持的。





下午有事要外出(是去学招数的,自己也要修_炼),晚上再来过招。

&nbsp;





本贴被 machao 编辑过,最后修改时间:2008-10-08,13:23:48.

lonely88 发表于 2008-10-8 13:33:39

惭愧,我只能做看客,帮马老师把贴顶起来。。。

hexixiaomao 发表于 2008-10-8 15:35:08

昨天&nbsp;来了&nbsp;改了下自己帖子的一个小错误&nbsp;&nbsp;就去忙着应聘去咯&nbsp;&nbsp;&nbsp;&nbsp;笔试过了&nbsp;第一轮面试过了&nbsp;&nbsp;等下还要去第二轮。。。。



晚上回来继续,(面试时已经想好一个点子咯)

liyinchao 发表于 2008-10-8 15:38:24

51楼何必加5个二极管,需要吗?理由是什么?

如果真的需要,加一个和加5个有什么区别?



我&nbsp;以前玩过这个电路

当时的思路是:

在定时器中断中搞的显示

以显示扫描周期为计时周期消抖

每显示一位&nbsp;判断一下P3.7

如果扫描到某位时P3.7为低,计数

如果连续多个扫描周期内为低就认为有键按下,计数清零

如果不到规定周期&nbsp;P3.7为高&nbsp;计数清零



伪代码



Disp_Key()

{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;......

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P3.7=1;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LED_ADDR_Port=LED_ADDR;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dip_Port=Disp_Buff;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(P3.7==0)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeyPressFlag++;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeyTmp=LED_ADDR;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeyPressFlag=0;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(KeyPressFlag>KeyTime)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myKey=KeyTmp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

}



===========================================================

再练练吧,功夫不到。前面已经有说明了,或许你有新的解释和设计?



本贴被 machao 编辑过,最后修改时间:2008-10-08,17:00:04.

ivws 发表于 2008-10-8 16:16:30

支持一下...



回楼上的...不加二极管的话..在几个按键同时按下时...138&nbsp;很可能出现短路现象.

本贴被 ivws 编辑过,最后修改时间:2008-10-08,16:30:19.

cowboy 发表于 2008-10-8 16:37:09

我也来谈一下自己的思路。这个是典型的&nbsp;按键/显示&nbsp;IO复用的情况。



显示/按键&nbsp;处理相对来说占用MUC时间较小,因而应该用定时中断扫描方式处理比较合适。

中断子程序处理应越快越好,以免和其它实性要求高的事件冲突。



中断处理程序:

MCU通过P3.3~P3.5控制138的Y0~Y5依次输出低电平,一方面选通数码管的位,另一方面对各按键进行扫描。

每次选通一位,都对P3.7检测一次,并用一变量通过移位记录下来。

一次循环下来,数码管完成一帧显示,刚才的记录变量也完成记录按键的状态。

按下不同的按键(包括组合键),记录变量有不同的值,这个值可作为键码。

得到键码后,不必在中断里进行处理,只需激活键码有效标志,按键处理过程应在程序主循环中。



主程序中的按键处理方法:

这一部分根据键码和按下时长,进行按键识别、消抖、处理长按、处理连_发、处理复合键。

设立一变量记录前一次键码,设立另一变量对按键时长进行计数。

当键码全为1(即没键按下)或者新键码与旧键码不同,清零计数器,其它不作处理。

当新旧键码相同,计数码加一,直到达到消抖时间要求,此时识别为某键按下。

新旧键码持续相同,计数器递增,达到一定值可视为长按(或连_发)。





==========================================================

很多人都会这样讲,把基本原理罗列一遍。但这是典型的“花拳绣腿”,属于应试教育的回答。



请用示例代码来说明,看你如何实现他们的组合,是否能正确完成功能,代码已经运行效率如何。这才是真本事。









本贴被 machao 编辑过,最后修改时间:2008-10-08,17:09:27.

lusson 发表于 2008-10-8 16:46:54

以前做过类似的,程序流程的话:是否需要更新显示-》(需要)先关闭显示,然后读键值(读键就不用详细说了吧),再更新显示,再处理按键值,再回到开始

按键的处理是利用更新显示的时间即每一个COM的时间来消抖和计时。

图上不能有二个按键同时按下



我以前用的是没有中断的单片机做的万年历,只有个定时器,要显示年月日(农历公历)时分秒星期==。

本贴被 lusson 编辑过,最后修改时间:2008-10-08,16:51:16.

machao 发表于 2008-10-8 16:57:26

设计产品,你可以在说明书中说明只有单键功能,但你不能说禁止按下2个键。



用户在使用中可能会误操作,或不会操作,甚至是有意的按下了2个键,结果你的系统显示不正常了,甚至坏了,烧掉了,这样的产品能进入市场吗?



“华山论剑”是比真工夫,要按合格产品的要求进行设计。

honey655729 发表于 2009-8-11 09:16:01

如果要一个按键按下,起来后才算一次按键,那么可以设定一个按键信息变量,key,在有按键按下时记录key直到按键宋爱才执行按键处理程序就可以
另外,想要按键过程中数码管显示不闪烁,我的方法是,在案件获取函数内,放入显示扫描函数做延时,和等待按键循环,前提是你的显示函数时间不能太大了,

还可以定义显示刷新频率,用定时器定时显示函数,每次中断刷新一次显示,应该不会闪烁了


======================================================================

兜了怎么一大弯,还是不能根本的解决问题的。要采用好是设计方法根本就不存在这样的问题。

建议你在本栏置顶的帖子中,下载我编写书的前2篇,看看我编写的按键和键盘扫描函数的处理思想。上面的问题都不会发生的。

liudeee 发表于 2009-8-11 09:37:57

学习了

juebuguake 发表于 2009-9-3 09:19:58

楼上的和我一样迟到了 唉

w48720770 发表于 2009-10-8 22:54:19

把这篇帖子 拿下去打印 再阅读了一番

很有进益   没想到许多东西可以这样啊

谢谢 马潮老师和各位顶帖的

希望 经常可以读到这种贴   然后自己慢慢的进入 讨论 的圈子

chengpiaopiao 发表于 2009-10-8 23:20:34

学习了

zyjclass 发表于 2009-12-23 12:12:08

怎么只有显示60个回复??马潮老师不是都出了93楼了 我想看看老师的解答 老师给的这个问题太有意思了

zyjclass 发表于 2009-12-23 12:13:01

难道要顶到71楼才能看到答案??

zyjclass 发表于 2009-12-23 12:13:29

要是这样的话我一天来顶一次

a1z26 发表于 2009-12-23 18:02:03

mark

zyjclass 发表于 2010-1-2 20:44:25

马老师现在是不是不在这里了

zyjclass 发表于 2010-1-2 20:44:59

新年 就来顶啦

zyjclass 发表于 2010-1-2 20:45:21

新年快乐大家

zyjclass 发表于 2010-1-2 20:46:03

继续

zyjclass 发表于 2010-1-2 20:46:27

还要一个

zyjclass 发表于 2010-1-2 20:47:14

最后一个了??

zyjclass 发表于 2010-1-2 20:47:46

到71楼看看

longjf-007 发表于 2010-4-19 00:15:55

mark

gdmfq 发表于 2010-4-19 08:37:57

mark

yhy630 发表于 2010-5-8 20:56:29

我来接一招吧。用proteus仿真,能实验单击和连_发功能,但在仿真时会出现按键按下,对应数码管灭,用示波器观察对应管脚波形正常,不知是不是软件原故,过两天做硬件测试。
我的想法是这样的,采用状态机检测键盘,放在显示程序中,键盘0态时检测P3.7口。键盘1态时,检测时间(说明这个时间一定要是显示数的整数倍,否则检测不到键盘),确认键盘后转2态。键盘2态, 同样先检测时间(这个时间也一样),确认后键盘跳转到3态.
键盘3态,也同样检测键盘。键盘子程序如下:主程序中通过key_return值来确认键盘,0为不响应,1为单击,2为连击。响应后清些值.
显示程序为1ms显示一位。
//说明:key=P3.7
disp();
key_return=0;
key_press=key;
switch(key_state)        //key_time一定要是显示位数的整数倍
{
    case 0:
          if(key_press==0)
                {
                  key_state=1;
                  key_old=dat_tt;//保留键值
                  key_time=0;
                }
                  break;
        case 1:
          if(++key_time==20)
                {
                  key_time=0;
                  if(key_press==0)
                        {
                           if(key_old==dat_tt)
                             { key_state=2;
                                   key_return=1; //单击
                                   key_time=0;
                                   key_data=dat_tt;
                               }
                               else
                               {
                                           key_state=0;
                                        key_time=0;
                                           key_data=0xff;       
                               }
                        }
                        else
                        {
                                key_state=0;
                                key_time=0;
                          key_data=0xff;//键盘       
                        }
                }
          break;
        case 2:
           if(++key_time>=1000)
           {
             if(key_press==0)
                        {
                                  key_state=3;
                                  key_time=0;
                                  key_return=2;//进入连击
                          }
                  else   
                           {
                                     key_state=0;
                                        key_time=0;
                                  key_data=0xff;//键盘       
                           }
           }
           break;
        case 3:
           if(++key_time>=200)
           {
             if(key_press==0)
                        {
                                  key_state=3;
                                  key_time=0;
                                  key_return=2;//进入连击
                          }
                  else   
                           {
                                     key_state=0;
                                        key_time=0;
                                  key_data=0xff;//键盘       
                           }
           }
           break;
   
        default :
          break;
}

yhy630 发表于 2010-5-8 20:57:25

上面是自己个人的想法,还清马潮老师批评指正。

moon0213 发表于 2010-5-9 01:18:08

受教!

eduhf_123 发表于 2010-5-10 11:24:26

GZ

flywhale 发表于 2010-5-13 12:26:23

mark

xinyou 发表于 2010-5-13 12:30:22

mark

guisi 发表于 2010-5-22 13:48:00

感觉按键反应不灵敏,再改delay_time都不行,请马老师指点!

monsoonw 发表于 2010-7-8 21:51:36

从手机上看的帖子,但看起来不方便。等电脑在身边时一定要好好钻研。好帖呀!

xslff 发表于 2010-7-8 22:01:42

如果每星期能出一个这样的贴子,那中国的电子技术短时间内必定会有质的飞跃!

gmolzc 发表于 2010-7-9 10:11:29

頂一下,有空好好看看!

xml2028 发表于 2010-7-24 09:12:23

頂一下,有空好好看看!

z0586 发表于 2010-7-24 09:31:16

mark

Notting_Hill 发表于 2010-8-10 14:50:36

mark

harng 发表于 2010-8-10 16:06:05

mark

guxingganyue 发表于 2010-9-5 21:30:53

mark,有空仔细看看,

yywin 发表于 2010-9-29 20:28:44

mark

lixin91985 发表于 2010-9-29 20:49:03

说说我的,意见,,,,,

二极管的方向就别说了 。高手看了下面的就知道了。

数码管的位选做按键的扫描脉冲,,,当一个位为高电平,同时按键按下,那么公共端就会出现高电平,


按键按下是从出现高电平开始,当扫描到某个按键没有出现高电平,则这个按键没有按下,,,

为每个按键设置低电平计数单元,以及设置 上次/当前 按键的状态标志位,

至于按键消抖,我想数码管的位扫描脉冲,不是最好的消抖时序嘛?

jielove2003 发表于 2010-9-29 20:58:32

mark

ifree64 发表于 2010-9-29 23:22:40

本贴没有93楼啊?

本题解决思路的关键在于有限状态机的运用。

jiaweiqiang 发表于 2010-11-23 23:20:47

标记,顶!!!

Magic_rA 发表于 2010-12-1 12:53:57

哇~~~    来的稍稍晚了些

lovefei 发表于 2010-12-7 16:32:28

本帖到此结束了吗?如果马老师没有给出最终答案的话,我想出招试一试!

wenfeiexe 发表于 2010-12-7 16:53:33

cool

xydxyd 发表于 2010-12-25 22:08:20

做个标记,

xydxyd 发表于 2010-12-25 22:18:59

其实马老师书中有关于定时中断扫描显示,扫描键盘,再利用状态机来判断按键,我想这也正是是处理这种电路的方法吧!

alice5208 发表于 2011-1-6 17:04:30

MARK

beixue 发表于 2011-1-7 16:18:05

回家看看

CooL.WD 发表于 2011-5-17 02:03:12

回复一下......都08的贴了

xiaohong.zhang 发表于 2011-6-29 13:57:54

mark
页: [1] 2
查看完整版本: 请马老师指教:有关按键问题----建议学电子技术的大学生尝试思考和回答__马老师摆擂台