搜索
bottom↓
回复: 105

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

[复制链接]

出0入0汤圆

发表于 2008-10-4 22:11:38 | 显示全部楼层 |阅读模式


 (原文件名:无标题.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的图:



 (原LZ位图) 



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



 (原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[6];                 // 这里存放每个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会在中断中变化的

&#160;&#160;&#160;&#160;&#160;if&#160;(key_tmp&#160;<&#160;128)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//&#160;有一次按键过程&#160;

&#160;&#160;&#160;&#160;&#160;{

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

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;switch(key_tmp)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//按键处理过程

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;case&#160;0b00011110:

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//&#160;0号键处理.......

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;break;

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;case&#160;0b00011101:

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//&#160;1号键处理..............

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;break;

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;............



&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;case&#160;0b00011100:

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

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;break;

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;............

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;case&#160;0b00011000&#160;

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

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;break;

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}

&#160;&#160;&#160;&#160;&#160;.............&#160;

&#160;&#160;&#160;&#160;}&#160;&#160;

}

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

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

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







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

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

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



timer_2ms_int()

{

&#160;&#160;&#160;&#160;&#160;&#160;static&#160;char&#160;posit&#160;=&#160;0;

&#160;&#160;&#160;&#160;&#160;&#160;static&#160;char&#160;read_key,pre_key,delay_time;

&#160;&#160;&#160;&#160;&#160;&#160;static&#160;char&#160;key_state&#160;=&#160;0;



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

&#160;&#160;&#160;&#160;&#160;&#160;P1&#160;=&#160;dis_buff[posit];&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;//送出BCD格式的段码值&#160;&#160;&#160;

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

&#160;&#160;&#160;&#160;&#160;&#160;

&#160;&#160;&#160;&#160;&#160;&#160;if&#160;(posit&#160;<&#160;5)

&#160;&#160;&#160;&#160;&#160;&#160;{

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;read_key&#160;&=&#160;~(1<<posit);&#160;

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

&#160;&#160;&#160;&#160;&#160;&#160;}

&#160;&#160;&#160;&#160;&#160;&#160;elas

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

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;switch(key_state)

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;case&#160;0:

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

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

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

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

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;break;

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;case&#160;1:

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

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;key_state&#160;=&#160;2;

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;break;

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;case&#160;2:

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

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

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;delay_time&#160;=&#160;0;

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;key_state&#160;=&#160;0;

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;break;&#160;&#160;

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}

&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;pre_key&#160;=&#160;read_key;&#160;&#160;&#160;&#160;&#160;&#160;

&#160;&#160;&#160;&#160;&#160;&#160;}&#160;

&#160;&#160;&#160;&#160;&#160;&#160;

&#160;&#160;&#160;&#160;&#160;&#160;if&#160;(&#160;++posit>&#160;5&#160;)&#160;posit&#160;=&#160;0;&#160;&#160;&#160;&#160;&#160;

}



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

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



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

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

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2008-10-5 00:49:59 | 显示全部楼层
留做练习题吧,看其它的人能给出解答吗?

出0入0汤圆

发表于 2008-10-5 08:11:56 | 显示全部楼层
在脉冲时检测电平,检测到了,计数器++,到一个数字时,按键按下。检测不到,计数器--,到0时,按键松开。

出0入0汤圆

 楼主| 发表于 2008-10-5 20:34:30 | 显示全部楼层
还有其它办法吗?

出0入0汤圆

发表于 2008-10-6 00:58:50 | 显示全部楼层
这是一个复用I/O口的例子,首先要把硬件电路看明白,先不考虑按键,分析出基本的工作方式,然后看采用什么方法和途径能够非常方便的读键。

出0入0汤圆

发表于 2008-10-6 16:31:57 | 显示全部楼层
难道访问这个专栏的朋友水平都那么的“低”,回答不出?还是水平都非常“高”,不值得回答?



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



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



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



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

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

出0入0汤圆

发表于 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.

出0入0汤圆

发表于 2008-10-6 19:42:12 | 显示全部楼层
p[35...33]->000&nbsp;&nbsp;&nbsp;&nbsp;//==》&nbsp;这时显示的是什么东西?





if(p37==0)s5按下

p[35...33]->001

if(p37==0)s4按下

...

p[35...33]->101

if(p37==0)s1按下

重新扫描



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

出0入0汤圆

发表于 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.

出0入0汤圆

发表于 2008-10-6 21:36:02 | 显示全部楼层
用四个位变量去保存四个按键,在每次扫描时去判断是否升起来了。MS很浪费时间的说。



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

出0入0汤圆

发表于 2008-10-7 00:06:26 | 显示全部楼层
以上各位,首先是你们的硬件水平就太差了,电路如何才能正确工作都分析不正确,后面怎么会继续下去?

出0入0汤圆

发表于 2008-10-7 00:19:28 | 显示全部楼层
阿莫:能否对能比较好的对这个问题给出解答的朋友给予支持:邮购部免费提供100元内的电子元器件。



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

出0入0汤圆

发表于 2008-10-7 01:18:20 | 显示全部楼层
图太小&nbsp;&nbsp;上边的网络标号都看不清楚&nbsp;啊&nbsp;

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

出0入0汤圆

发表于 2008-10-7 01:28:16 | 显示全部楼层
&nbsp;&nbsp;嘿嘿&nbsp;用PHOTO&nbsp;SHOP放大了看看

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

出0入0汤圆

发表于 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.

出0入0汤圆

发表于 2008-10-7 02:19:53 | 显示全部楼层


&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.

出0入0汤圆

发表于 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.

出0入0汤圆

发表于 2008-10-7 04:28:16 | 显示全部楼层
不蒸馒头争口气&nbsp;&nbsp;不能让这的老大们看不起我们新来的菜鸟们。非得整明白不可&nbsp;。诶&nbsp;搞得头都大了&nbsp;先去睡觉咯&nbsp;。

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

出0入0汤圆

发表于 2008-10-7 05:46:34 | 显示全部楼层
哈哈,马老师上课了,学生也凑个热闹...

用到74HC138的六种状态:

(原文件名: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.

出0入0汤圆

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

出0入0汤圆

发表于 2008-10-7 09:25:32 | 显示全部楼层
看看,学习一下.

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

出0入0汤圆

发表于 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;如果为高则检查上次记录按键值是否此位,如果是则说明按键松开.

出0入0汤圆

发表于 2008-10-7 10:50:32 | 显示全部楼层
显示和按键程序分开写,可能结构上更合理.

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

出0入0汤圆

发表于 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.

出0入0汤圆

发表于 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.

出0入0汤圆

发表于 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.

出0入0汤圆

发表于 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.

出0入0汤圆

发表于 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就表示按键放开了(消抖动后的状态),然后处理就行了。(为了判断在放开按键之间的按键,还要增加一个单元用来保存松开前的键值)

出0入0汤圆

发表于 2008-10-7 21:17:56 | 显示全部楼层
建议各位:



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



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

出0入0汤圆

发表于 2008-10-7 22:03:46 | 显示全部楼层
看看再说

出0入0汤圆

发表于 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;不能让这的老大们看不起我们新来的菜鸟们”。



出0入0汤圆

 楼主| 发表于 2008-10-7 23:02:55 | 显示全部楼层
&nbsp;&nbsp;&nbsp;感谢马老师与各位的回复,我很喜欢这里讨论问题的氛围。

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

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

出0入0汤圆

发表于 2008-10-7 23:21:30 | 显示全部楼层
楼上,不用客气。我借你的问题设下擂台,挑战一批学生,树立我的威信,我还要感谢你提供了非常好的机会。



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



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

出0入0汤圆

发表于 2008-10-7 23:26:44 | 显示全部楼层
假如为了某种需要(比如抗干扰),在P3。7对地接上一个104的话,程序与没接电容是可能不同的。





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

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



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

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

出0入0汤圆

发表于 2008-10-7 23:43:49 | 显示全部楼层
以前的一个程序因为显示的扫描频率较高(整个程序差不多就是显示与键盘扫描了),只能用软件廷时外加104解决。但加上104后,按键廷时就不能用调用显示程序来实现了,否则将检测不到按键。

出0入0汤圆

发表于 2008-10-7 23:55:25 | 显示全部楼层
楼上,放弃你以前的程序吧。我已经讲了,不准使用软件延时。



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



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

出0入0汤圆

发表于 2008-10-7 23:57:34 | 显示全部楼层
不过电路与LZ不同。

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

出0入0汤圆

发表于 2008-10-8 00:01:53 | 显示全部楼层
呵呵,我本来就是菜鸟一个,只能按N年前的方法扫描。

出0入0汤圆

发表于 2008-10-8 00:06:36 | 显示全部楼层
总不能停止不前吧。为什么不能放弃不好的方法,学习好的思路?

出0入0汤圆

发表于 2008-10-8 00:13:08 | 显示全部楼层
谢谢。我现在只能用汇编,还学不会C语言呢。那个程序也是一边查指令表,一边写出来的,N年前学过51,用AVR也是今年才开始的。



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

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

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

出0入0汤圆

发表于 2008-10-8 00:13:46 | 显示全部楼层
见笑了。

出0入0汤圆

发表于 2008-10-8 02:14:31 | 显示全部楼层
hexixiaomao说今天继续的,看样子今天等不到了。&nbsp;
头像被屏蔽

出0入0汤圆

发表于 2008-10-8 07:06:46 | 显示全部楼层
呵,这个帖子讨论得很好。COOL&nbsp;!

出0入0汤圆

发表于 2008-10-8 09:16:40 | 显示全部楼层
请马老师点评

1。电路图这样改



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

2。流程图这样画



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

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

出0入0汤圆

发表于 2008-10-8 12:26:35 | 显示全部楼层
楼上的电路图二极管接反了...



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

晕,怎么成负分了...

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

出0入0汤圆

发表于 2008-10-8 13:18:51 | 显示全部楼层
to&nbsp;51楼:图中二极管加的很正确吗。你再把它反过来,是否有新招?



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



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

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



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



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



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



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



我会尽力支持的。





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

&nbsp;





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

出0入0汤圆

发表于 2008-10-8 13:33:39 | 显示全部楼层
惭愧,我只能做看客,帮马老师把贴顶起来。。。

出0入0汤圆

发表于 2008-10-8 15:35:08 | 显示全部楼层
昨天&nbsp;来了&nbsp;改了下自己帖子的一个小错误&nbsp;&nbsp;就去忙着应聘去咯&nbsp;&nbsp;&nbsp;&nbsp;笔试过了&nbsp;第一轮面试过了&nbsp;&nbsp;等下还要去第二轮。。。。



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

出0入0汤圆

发表于 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[LED_ADDR];

&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.

出0入0汤圆

发表于 2008-10-8 16:16:30 | 显示全部楼层
支持一下...



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

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

出0入0汤圆

发表于 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.

出0入54汤圆

发表于 2008-10-8 16:46:54 | 显示全部楼层
以前做过类似的,程序流程的话:是否需要更新显示-》(需要)先关闭显示,然后读键值(读键就不用详细说了吧),再更新显示,再处理按键值,再回到开始

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

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



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

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

出0入0汤圆

发表于 2008-10-8 16:57:26 | 显示全部楼层
设计产品,你可以在说明书中说明只有单键功能,但你不能说禁止按下2个键。



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



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

出0入0汤圆

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

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


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

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

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

出0入0汤圆

发表于 2009-8-11 09:37:57 | 显示全部楼层
学习了

出0入0汤圆

发表于 2009-9-3 09:19:58 | 显示全部楼层
楼上的和我一样迟到了 唉

出0入0汤圆

发表于 2009-10-8 22:54:19 | 显示全部楼层
把这篇帖子 拿下去打印 再阅读了一番

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

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

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

出0入0汤圆

发表于 2009-10-8 23:20:34 | 显示全部楼层
学习了

出0入0汤圆

发表于 2009-12-23 12:12:08 | 显示全部楼层
怎么只有显示60个回复??马潮老师不是都出了93楼了 我想看看老师的解答 老师给的这个问题太有意思了

出0入0汤圆

发表于 2009-12-23 12:13:01 | 显示全部楼层
难道要顶到71楼才能看到答案??

出0入0汤圆

发表于 2009-12-23 12:13:29 | 显示全部楼层
要是这样的话我一天来顶一次

出0入0汤圆

发表于 2009-12-23 18:02:03 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-1-2 20:44:25 | 显示全部楼层
马老师现在是不是不在这里了

出0入0汤圆

发表于 2010-1-2 20:44:59 | 显示全部楼层
新年 就来顶啦

出0入0汤圆

发表于 2010-1-2 20:45:21 | 显示全部楼层
新年快乐大家

出0入0汤圆

发表于 2010-1-2 20:46:03 | 显示全部楼层
继续

出0入0汤圆

发表于 2010-1-2 20:46:27 | 显示全部楼层
还要一个

出0入0汤圆

发表于 2010-1-2 20:47:14 | 显示全部楼层
最后一个了??

出0入0汤圆

发表于 2010-1-2 20:47:46 | 显示全部楼层
到71楼看看

出0入0汤圆

发表于 2010-4-19 00:15:55 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-19 08:37:57 | 显示全部楼层
mark

出0入0汤圆

发表于 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;  
  }

出0入0汤圆

发表于 2010-5-8 20:57:25 | 显示全部楼层
上面是自己个人的想法,还清马潮老师批评指正。

出0入0汤圆

发表于 2010-5-9 01:18:08 | 显示全部楼层
受教!

出0入0汤圆

发表于 2010-5-10 11:24:26 | 显示全部楼层
GZ

出0入0汤圆

发表于 2010-5-13 12:26:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-13 12:30:22 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-22 13:48:00 | 显示全部楼层
感觉按键反应不灵敏,再改delay_time都不行,请马老师指点!

出0入0汤圆

发表于 2010-7-8 21:51:36 | 显示全部楼层
从手机上看的帖子,但看起来不方便。等电脑在身边时一定要好好钻研。好帖呀!

出0入0汤圆

发表于 2010-7-8 22:01:42 | 显示全部楼层
如果每星期能出一个这样的贴子,那中国的电子技术短时间内必定会有质的飞跃!

出0入0汤圆

发表于 2010-7-9 10:11:29 | 显示全部楼层
頂一下,有空好好看看!

出675入8汤圆

发表于 2010-7-24 09:12:23 | 显示全部楼层
頂一下,有空好好看看!

出0入0汤圆

发表于 2010-7-24 09:31:16 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-10 14:50:36 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-10 16:06:05 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-5 21:30:53 | 显示全部楼层
mark,有空仔细看看,

出0入0汤圆

发表于 2010-9-29 20:28:44 | 显示全部楼层
mark

出0入22汤圆

发表于 2010-9-29 20:49:03 | 显示全部楼层
说说我的,意见,,,,,

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

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


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

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

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

出0入0汤圆

发表于 2010-9-29 20:58:32 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-29 23:22:40 | 显示全部楼层
本贴没有93楼啊?

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

出0入0汤圆

发表于 2010-11-23 23:20:47 | 显示全部楼层
标记,顶!!!

出0入0汤圆

发表于 2010-12-1 12:53:57 | 显示全部楼层
哇  ~~~    来的稍稍晚了些

出0入0汤圆

发表于 2010-12-7 16:32:28 | 显示全部楼层
本帖到此结束了吗?如果马老师没有给出最终答案的话,我想出招试一试!

出0入0汤圆

发表于 2010-12-7 16:53:33 | 显示全部楼层
cool

出0入0汤圆

发表于 2010-12-25 22:08:20 | 显示全部楼层
做个标记,

出0入0汤圆

发表于 2010-12-25 22:18:59 | 显示全部楼层
其实马老师书中有关于定时中断扫描显示,扫描键盘,再利用状态机来判断按键,我想这也正是是处理这种电路的方法吧!

出0入0汤圆

发表于 2011-1-6 17:04:30 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-1-7 16:18:05 | 显示全部楼层
回家看看

出0入0汤圆

发表于 2011-5-17 02:03:12 | 显示全部楼层
回复一下......都08的贴了

出0入0汤圆

发表于 2011-6-29 13:57:54 | 显示全部楼层
mark
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 03:07

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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