微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 51单片机独立按键扫描程序出现问题

51单片机独立按键扫描程序出现问题

时间:10-02 整理:3721RD 点击:
最近家里买了一个3节LED等连在一起的手电筒,我想设计一个按下按键1,3个LED以流水灯的样子闪烁,按下按键2,LED1亮,按下按键3,LED2亮,按下按键1,LED3亮,查看了大量资料,尝试着自己写了个,但是在独立按键扫描消抖这一块出现问题了,我是根据矩阵按键的程序重新修改的,出现问题后自己努力了几天,网上也找过资料看,还是不懂,大家帮我看看。#include <reg52.h>
sbit SW1 = P1^2;
sbit SW2 = P1^3;
sbit SW3 = P1^4;
sbit SW4 = P1^5;
sbit LED1 = P0^0;
sbit LED2 = P0^1;
sbit LED3 = P0^2;
unsigned char SWSTA[4] = {1,1,1,1};
unsigned char backup[4] = {1,1,1,1};
void main()
{  static unsigned char i=0,j=0;
   unsigned char cnt = 0;
   EA = 1;
   TMOD = 0x01;
   TH0 = 0xFC;
   TL0 = 0x67;
   ET0 = 1;
   TR0 = 1;
   while (1)
   {
    for (i=0;i<4;i++)
        {
         if (backup[i] != SWSTA[i])
         {
           backup[i] = SWSTA[i];
            }
        }
   }
  if ( SWSTA[0] == 0 )
  {
   P0 = ~(0x01 <<j);       
   if ( TF0 == 1 )
   {
    TF0 = 0;
    TH0 = 0xFC;
    TL0 = 0x67;
        cnt++;
        }
        if (cnt >= 100)
        {
        cnt = 0;
       
        }
        j++        ;
        if(j>=3)
                {
                        j = 0;
                }
}
if (SWSTA[1] == 0 )
{
  LED1 = 0;
}
  if (SWSTA[2] == 0 )
{
  LED2 = 0;
}
  if (SWSTA[3] == 0 )
{
  LED3 = 0;
}                       
}
void interrupTimer()interrupt 1
{static unsigned char i=0;                          
static unsigned char SWOUT = 0;
  TH0 = 0xFC;
  TL0 = 0x67;
  for ( i=0;i<4;i++ )
{
  if(SWSTA[i] & 0x0F == 0x00)
  {
   SWSTA[i] = 0;
  }
  else if(SWSTA[i] & 0x0F == 0x0F)
  {
   SWSTA[i] = 1;
  }
}
SWOUT++;
SWOUT = SWOUT & 0x03;

}                  
还有,我尝试着直接把按键上的状态给LED灯,按键没按下之前是高位状态,按下后是低位状态,把地位状态的值给LED,按说是应该亮的,但就是不亮,我现在也搞不清楚了。
#include <reg52.h>
sbit SW1 = P1^2;
sbit SW2 = P1^3;
sbit SW3 = P1^4;
sbit SW4 = P1^5;
sbit LED1 = P0^0;
sbit LED2 = P0^1;
sbit LED3 = P0^2;
void main()
{  
while(1)
{      LED1 = SW1;  //按下时为0,对应的LED点亮
        LED2 = SW2;
        LED3 = SW3;        }
}
这个直接控制按键来控制LED亮灭,假入我把while语句里面的改为
if(SW1==0)
{LED1=0;}
else
{LED1=1;}
这样改过后,按下按键1,LED1就亮,不按就不亮,但是改成第二段程序就不亮。
请教下大家,第一个程序的按键扫描与消抖该如何处理,第二个程序我是哪里出错了。


已经弄好了程序,但是现在出现个问题?怎么跳出while(1)循环语句。如果我按下SW1,它一直在执行while(1)循环语句,按其他按键也没反应,如果是按SW2,SW3,SW4,都会执行相应语句,唯有一按SW1,它就执行while(1)循环语句,怎么都挑不出来。
#include <reg52.h>
  sbit SW1 = P1^2;
  sbit SW2 = P1^3;
  sbit SW3 = P1^4;
  sbit SW4 = P1^5;
  sbit LED1 = P0^0;
  sbit LED2 = P0^1;
  sbit LED3 = P0^2;
  unsigned char keyscan(void);
  void delayus2x(unsigned char t);
  void delayma(unsigned char t);


   void main()
   { unsigned char num;
             unsigned int cnt=0;
   unsigned int i=0;
           unsigned char m;

   while(1)
   {
            num = keyscan();//循环扫描按键
   if (num==1)
   {       
        while(1)       
        {   
       
               
                P0 = ~(0x01 <<cnt);
            delayma(10);
            cnt++;
                if(cnt>=3)
                {
                        cnt = 0;
                }
          
                  }       
          
   }
   else if (num==2)
   { m=1;
        P0=0x06;
   }
   else if (num==3)
   {
        P0=0x05;
   }
   else if (num==4)
   {
   P0=0x03;
   }
   }
   }
   void delayus2x(unsigned char t)//软件延时,大致的,不够精确,可以用中断延时
   {while(--t) ;
   }
   void delayma(unsigned char t)
   {
   while(t--)
   {
            //大致延时1ms
         delayus2x(245);
         delayus2x(245);
   }
   }
   unsigned char keyscan(void)         //按键扫描消抖
{
    if(!SW1)//如果按键值为非
  {
  delayma(10);//延时10秒  去抖
  if(!SW1)
  {
  while(!SW1)        //如果确认按下按键等待释放,没有一直等待
  {
  }
  return 1;        //返回值num=1
  }
  }
       
         if(!SW2)
  {
  delayma(10);
  if(!SW2)
  {
  while(!SW2)
  {
  }
  return 2;
  }
  }
  if(!SW3)
  {
  delayma(10);
  if(!SW3)
  {
  while(!SW3)
  {
  }
  return 3;
  }
  }
  if(!SW4)
  {
  delayma(10);
  if(!SW4)
  {
  while(!SW4)
  {
  }
  return 4;
  }
  }
  return 0;
   }

程序没完呀,头文件没包含呀。

看来一下图,P0口应该是上啦呀!就是接Vcc

上拉不行,试过了,价格上拉电阻,就变成了2端都是高电压,下拉电阻刚好。

具体是什么问题?而且程序能弄完整吗

支持一下
不错的资料

现在主要就是独立按键循环扫描的程序自己搞不清,不过刚又研究了一会,又尝试自己自己写了下,打算晚上试试,程序还没有写完,还要接着改。谢谢关心。

我感觉我快疯了,这个程序早上运行正常,流水灯正常,现在再测就不行了,大家帮我看看哪里不对。
  #include <reg52.h>
  sbit SW1 = P1^2;
  sbit SW2 = P1^3;
  sbit SW3 = P1^4;
  sbit SW4 = P1^5;
  sbit LED1 = P0^0;
  sbit LED2 = P0^1;
  sbit LED3 = P0^2;
  void main ()
  {        unsigned char cnt = 0;
        unsigned int i=0;
                while(SW1==0)
        {
                P0 = ~(0x01 <<cnt);           //循环测试正确,流水灯正确
                for(i=0; i<30000; i++);
                cnt++;
                if(cnt>=3)
                {
                        cnt = 0;
                }
                }
  
   
   
  }

我是来打酱油的,学习学习

//其实这个实验可以用1个按键就可以解决问题了
//有问题加qq:1334577922备注一下“夜孤影”
#include"reg51.h"
#define uint unsigned int
#define uchar unsigned char
sfr P1M0=0x92;
sfr P1M1=0x91;
sfr P2M0=0x96;
sfr P2M1=0x95;
sbit SW1 = P2^0;
//sbit SW2 = P1^3;
//sbit SW3 = P1^4;
//sbit SW4 = P1^5;
sbit LED1 = P1^0;
sbit LED2 = P1^1;
sbit LED3 = P1^2;
void delay(uint time)
{
        uchar i;
        for(;time>0;time--)
         {
                for(i=0;i<125;i++);
         }
}


void liushuideng(void)
{
        LED1 =0;
        delay(1000);
        LED2 =0;
        delay(1000);
        LED3 =0;
        delay(1000);
        LED1 =1;
        delay(1000);
        LED2 =1;
        delay(1000);
        LED3 =1;
        delay(1000);
}
void main()
{
        unsigned char j;
        P1M0=0xff;
        P1M1=0;
        P2M0=0xff;
        P2M1=0;       
        while(1)
         {
                if(SW1 == 0)
                 {
                        delay(200);
                        if(SW1 == 0)
                         {
                                j++;
                                if(j==5)j=1;
                         }
                 }
                if(j==1)
                 {
                        liushuideng();
                        delay(1000);
                        delay(1000);
                 }
               
                if(j==2)
                 {
                        LED1=0;
                        LED2=1;
                        LED3=1;
                        delay(1000);
                        delay(1000);
                  }
                if(j==3)
                 {
                        LED1=1;
                        LED2=0;
                        LED3=1;
                        delay(1000);
                        delay(1000);
                 }
                if(j==4)
                 {
                        LED3=0;
                        LED1=1;
                        LED2=1;
                        delay(1000);
                        delay(1000);
                 }
         }
}

表示你这不是流水灯,你这是按一下,3个灯依次亮一下。跟我的不太一样。

可以同过延时解决那个问题,并不是3个灯依次亮一下,而是循环点亮

我试过了,把延时时间加大,就差不多可以了

,刚试过了确实是流水灯,但是在我的单片机电路里好像做不出来我要的效果,我决定把四个按键都做成呼吸灯的效果,不要流水灯了,通过PWM来实现。我先试试。

if(num == 1)
{
    switch(status1)                   //  #define  status1 0
    {
        case 0:   
                      P0 = ~(0x01 <<cnt);
                      DelayTime++
                      while(DelayTime >= const_time_level)   //#define const_time_level 1000 延时时间到
                      {
                            status1 = 1;
                            DelayTime = 0;
                      }
                      break;
        case 1:
                      cnt++;
                      if(cnt > 3)
                      {
                          cnt = 0;
                      }
                      break;
        defualt:
                      break;
    }
}

参考 http://bbs.elecfans.com/jishu_406259_1_1.html
swith并行任务处理

哦哦,第一次看到谢谢,我去收藏下。

第二个问题应该是你没有理解好编译器的问题,你的那种写法不规范,编译器应该没有人那么智能,所以,那种写法通过C编译器编译后,就不能实现你想要的功能了。

你说的我知道了,所以我推到了我的写法,重新写了程序,在9楼可以看到,但是后来又出现了无法跳出while(1)的问题。谢谢指点。

上一篇:新手求解
下一篇:无源蜂鸣器怎么发声

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top