打印

按键释放问题,请过来看看

[复制链接]
3072|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
myhmz|  楼主 | 2007-6-27 08:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我写了一个程序8个按键控制8个led,也通过了,这个是4X4矩阵键盘,P1口接键盘,当按一下P1_0时,led1闪烁,按一下P1.1时,led2闪烁。。。。。
但是现在却是要按键不放才能闪烁,找不出原因,请各位给看看,问题出在哪?

#include <AT89X51.H> 

unsigned char keyscan() 
{ unsigned char row,col,i;
  
  P1=0xf0;
  row=P1&0xf0;
  //row=P1&0xf0;   (这一行可以不要,为什么有的教程上要多写一行??)
  P1=0x0f;
  col=P1&0x0f;
  //col=P1&0x0f;
  i=~(col|row);
 // while((P1&0xf0)!=0xf0    );
  return  i;}
void delay10ms(void) 
 {   unsigned char i,j; 
    for(i=20;i>0;i--) 
     for(j=248;j>0;j--){;;}
     } 

void delay02s(void) 

{ unsigned char i; 

  for(i=20;i>0;i--) 

    {delay10ms(); 

    } 



void main(void) 
{
  unsigned char key;  
   while(1)
   { 
          key=keyscan();
      switch(key)

        {  
          case 0x18:

            P0_0=~P0_0; 

            delay02s(); 
        
            break; 

          case 0x14: 

            P0_1=~P0_1; 

            delay02s(); 

            break; 

          case 0x12: 

            P0_2=~P0_2; 

            delay02s();     break; 
    case 0x28: 
            P0_3=~P0_3;
            delay02s();     break; 
    case 0x24: 
            P0_4=~P0_4; 
            delay02s();     break; 
    case 0x22: 
            P0_5=~P0_5; 
            delay02s();    break; 
    case 0x48: 
            P0_6=~P0_6;
            delay02s();    break; 
    case 0x44: 
            P0_7=~P0_7; 
            delay02s();    break; 
    case 0x42: 
            P0=0xff; 
            delay02s();    break; 
    case 0x84:
            P0=0x0;
            delay02s();   break;         
        }  

        
        }
              }
        

相关帖子

沙发
wjy1107| | 2007-6-27 08:18 | 只看该作者

因为按键抬起的时候KEY已经变啦

因为你的程序是在不停的进行按键扫描,当按键抬起的时候还在执行key=keyscan();那个值当然就不对了
看看下面的该法好不好用,呵呵!
void main(void)
{
  unsigned char key;  
   while(1)
   {
         if( keyscan()!=0)
      {
        key=keyscan();
      }
      switch(key)

        {  
          case 0x18:

            P0_0=~P0_0;

            delay02s();
        
            break;

          case 0x14:

            P0_1=~P0_1;

            delay02s();

            break;

          case 0x12:

            P0_2=~P0_2;

            delay02s();     break;
    case 0x28:
            P0_3=~P0_3;
            delay02s();     break;
    case 0x24:
            P0_4=~P0_4;
            delay02s();     break;
    case 0x22:
            P0_5=~P0_5;
            delay02s();    break;
    case 0x48:
            P0_6=~P0_6;
            delay02s();    break;
    case 0x44:
            P0_7=~P0_7;
            delay02s();    break;
    case 0x42:
            P0=0xff;
            delay02s();    break;
    case 0x84:
            P0=0x0;
            delay02s();   break;         
        }  

        
        }
              }
  
  return  i;}

使用特权

评论回复
板凳
燕南啸| | 2007-6-27 08:23 | 只看该作者

你程序设置的就是得一直按下才闪烁

你的程序中每一次循环都重新扫描按键,你松手当然就不闪烁了。

你可以定义一个变量来保存按键值,每次循环开始都过行判断,如果没有键按下,就让key等于上一次的按键值

使用特权

评论回复
地板
myhmz|  楼主 | 2007-6-27 08:43 | 只看该作者

还有点问题

unsigned char keyscan() 
{ unsigned char row,col,i;
  
  P1=0xf0;
  row=P1&0xf0;
  //row=P1&0xf0;   (这一行可以不要,为什么有的教程上要多写一行??)
  P1=0x0f;
  col=P1&0x0f;
  //col=P1&0x0f;
  i=~(col|row);
// while((P1&0xf0)!=0xf0    );
  return  i;}



老兄,我这个键盘扫描程序,为什么有的教程要判断两次啊,我用一次也可以啊,就像我括号里说的?

还有你的程序最后一行 return i,为什么放在最后??? keyscan() 中不用了吗??

使用特权

评论回复
5
wjy1107| | 2007-6-27 08:49 | 只看该作者

不好意思,贴错了

只要把key=keyscan();换成下面的语句就行了
         if( keyscan()!=0)
      {
        key=keyscan();
      }
   用重复的两行,我个人感觉是为了产生一定的延时,为了让外围的硬件有个反应的时间。

使用特权

评论回复
6
myhmz|  楼主 | 2007-6-27 09:11 | 只看该作者

能不能用定时器延时

void delay10ms(void) 
{   unsigned char i,j; 
    for(i=20;i>0;i--) 
     for(j=248;j>0;j--){;;}
     } 

void delay02s(void) 

{ unsigned char i; 

  for(i=20;i>0;i--) 

    {delay10ms(); 

    } 



还有就是,能不能用定时器来做代替以上的延时呢?放在呢比较恰当?


使用特权

评论回复
7
wjy1107| | 2007-6-27 09:37 | 只看该作者

可以用定时器阿

而且用定时器才是正理儿哈。
至于放在哪儿,没办法告诉你啦,因为如果用定时器现在的程序就需要改很多地方啦。

使用特权

评论回复
8
myhmz|  楼主 | 2007-6-27 09:48 | 只看该作者

是吧

也就是说,我们程序中用循环延时,在实际应用中是不可取的?也没有那样做?

使用特权

评论回复
9
wjy1107| | 2007-6-27 09:52 | 只看该作者

我写的监控程序除了主函数有个循环外

其他的都用条件判别语句代替,这样做的好处是,在没有多任务管理的情况下,程序总是向下执行,最大限度的保证了监控的实时性能。

使用特权

评论回复
10
myhmz|  楼主 | 2007-6-27 10:05 | 只看该作者

变成常亮了

只要把key=keyscan();换成下面的语句就行了
         if( keyscan()!=0)
      {
        key=keyscan();
      }
 

我按昭这个把程序改了,led不闪烁了。。。只是常亮

使用特权

评论回复
11
myhmz|  楼主 | 2007-6-27 10:10 | 只看该作者

可以了,谢谢

谢谢,各位,终于是我想要的了!这里热心人挺不少的!多谢了

使用特权

评论回复
12
wjy1107| | 2007-6-27 10:13 | 只看该作者

为人民服务

使用特权

评论回复
13
myhmz|  楼主 | 2007-6-27 10:24 | 只看该作者

还有一个问题

还有一点就是,在切换按键的时候,上一个灯的状态不定,有时是灭,有时是亮的,应该在哪加条语句,控制他的状态????

使用特权

评论回复
14
wjy1107| | 2007-6-27 13:05 | 只看该作者

那就需要在键值改变的时候把LED都关掉了

if( keyscan()!=0)
      {
        if(key!=keyscan();)
        {
           PO=?关是1还是0阿?自己填吧
        }
        key=keyscan();
      }

使用特权

评论回复
15
myhmz|  楼主 | 2007-6-27 13:39 | 只看该作者

谢谢

谢谢楼上的。。热心人

使用特权

评论回复
16
孤独泪| | 2007-6-27 14:16 | 只看该作者

按键程序放在定时器才是正理儿

使用特权

评论回复
17
myhmz|  楼主 | 2007-6-28 09:34 | 只看该作者

但是现在还不能十分灵活运用中断

可是,现在还不能很灵活的运用中断。。。

使用特权

评论回复
18
古董| | 2007-6-28 13:31 | 只看该作者

一直用汇编,见个C,学习下.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

41

帖子

0

粉丝