找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2070|回复: 5
收起左侧

单片机多个独立按键控制不同功能的led灯,检测按键部分好像出了问题,求解

[复制链接]
ID:764941 发表于 2020-10-4 17:00 | 显示全部楼层 |阅读模式
单片机源程序如下:
  1. #include<reg52.h>

  2. #define uchar unsigned char
  3. #define uint unsigned int

  4. void delayMS(uint x);
  5. void KeyProcess(uchar Key);
  6. uchar GetKey();


  7. //延时函数
  8. void delayMS(uint x)
  9. {
  10.     uchar i;

  11. while (x--)
  12. for(i=0;i<120; i++) ;
  13. }

  14. //检测按键

  15. uchar GetKey()

  16. {

  17. uchar k;

  18. if(P1==0xFF)
  19. return 0;

  20. delayMS(10);

  21. switch (P1)

  22. {

  23. case 0xF7: k=1;break;

  24. case 0xFB: k=2;break;

  25. case 0xFD: k=3;break;

  26. case 0xFE: k=4;break;

  27. default: k=0;

  28. }

  29. while (P1 != 0xFF);//等待释放按键(释放按键时退出循环)

  30. return k;
  31. }
  32. //键盘按键处理


  33. void KeyProcess(uchar Key)

  34. {

  35. switch (Key)

  36. {

  37. case 1://led灯全部点亮

  38. P0=0x00;
  39. break;

  40. case 2://以流水灯形式点亮
  41. P0=0x7f;
  42. while(1)
  43. P0>>=1;
  44. break;
  45. case 3: //led灯进行闪烁
  46. if(Key==3)
  47. {
  48. P0=0x00;
  49. delayMS(100);
  50. P0=0xff;
  51. delayMS(100);
  52. }
  53. while(Key!=3);
  54. break;
  55. case 4://全部关闭
  56. P0=0xff;
  57. break;
  58. }

  59. }
  60. //主程序

  61. //--------------------------------------------------------------------

  62. void main()

  63. {

  64. uchar Key;

  65. P0=P1=0xFF;

  66. while(1)

  67. {

  68. Key=GetKey();

  69. if(Key!=0)  KeyProcess(Key);

  70. }

  71. }
复制代码

proteus仿真图

proteus仿真图

用上面程序的hex文件后,按了按键没反应,将检测按键直接删去后有一点反应,但达不到预期效果。


回复

使用道具 举报

ID:89515 发表于 2020-10-5 12:54 来自手机 | 显示全部楼层
你的按键接的高四位吧?按键2,3的功能有逻辑问题。
回复

使用道具 举报

ID:275826 发表于 2020-10-6 09:56 | 显示全部楼层
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define Kport  P3
#define Ledport  P1
uchar code table0[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//LED从低位往高位移
unsigned char kscancnt;        //记录进入中断的次数,满一个周期清零

void timer0_init();                        //定时器0初始化
void delayMS(uint x);           //延时函数
void KeyProcess(uchar Key);         //按键处理函数
bit flag;
uchar knum;
uint F3cnt,F2cnt,Pwmcnt,T0cnt;
uchar temp=0xff,temp1;
uchar sh_cnt;
//延时函数
void delayMS(uint x)
{
    uchar i;

   while (x--)
      for(i=0;i<120; i++) ;
}
/***************************************************
*                                定时器0初始化子函数
*                        工作方式2,每1000us中断一次
****************************************************/
void timer0_init(void)
{
        TMOD = 0x01;                //采用定时器0,工作方式2,
        TH0 = (65536-1000)/256;                         //定时器设置,每隔20us发起一次中断。
        TL0 = (65536-1000)%256;         
        ET0 = 1;                        //开定时器0中断
        EA = 1;                                 //开总中断
        TR0 = 1;                        //打开定时器
}

//检测按键

uchar GetKey(uchar kscancnt)

{  
   uchar ktmp;
   if(kscancnt==0)
         {
          temp=(Kport&0xf0)>>4;
          ktmp=~temp &(temp1);
          if(ktmp)knum=ktmp;
          temp1=temp;
         }
   return knum;

}

//键盘按键处理

void KeyProcess(uchar Key)
  {
   
   switch (Key)
        {
           case 1:Ledport=0x00;                        
                       break;
               
           case 2:if(F2cnt==200){sh_cnt=++sh_cnt%8;F2cnt=0;}
                          Ledport=table0[sh_cnt];
                      break;
           case 4:if(T0cnt==300)
                    {F3cnt=F3cnt+10;T0cnt=0;}
                          if(F3cnt==130){F3cnt=0;flag=!flag;}
                  Pwmcnt=++Pwmcnt%100;

                          if(flag)
                            {if(Pwmcnt>F3cnt)Ledport=0x00;else Ledport=0xff;}
                          else
                            {if(Pwmcnt>F3cnt)Ledport=0xff;else Ledport=0x00;}
                  break;

           case 8:Ledport=0xff; //全部关闭
                          break;

        }

}

/***************************************************
*               中断服务子函数
*****************************************************/
void time0(void) interrupt 1
{
    TH0 = (65536-1000)/256;                         //定时器设置,每隔20us发起一次中断。
    TL0 = (65536-1000)%256;  
        kscancnt=++ kscancnt%10;
        if(knum==2)         {F2cnt++; }
    if(knum==4)         {T0cnt++; }
}


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

void main(void)

{  
        uchar Key;
        P0=P1=0xFF;
        timer0_init();
        while(1)
                   {
                 Key=GetKey(kscancnt);
                 KeyProcess(Key);
               
                }
}
先把程序理解
回复

使用道具 举报

ID:332444 发表于 2020-10-6 09:58 | 显示全部楼层
按键释放后主程序再次调用按键就被赋值0,因此,思路需重新考虑。
回复

使用道具 举报

ID:275826 发表于 2020-10-6 09:58 | 显示全部楼层
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define Kport  P3
#define Ledport  P1
uchar code table0[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//LED从低位往高位移
unsigned char kscancnt;        //记录进入中断的次数,满一个周期清零

void timer0_init();                        //定时器0初始化
void delayMS(uint x);           //延时函数
void KeyProcess(uchar Key);         //按键处理函数
bit flag;
uchar knum;
uint F3cnt,F2cnt,Pwmcnt,T0cnt;
uchar temp=0xff,temp1;
uchar sh_cnt;
//延时函数
void delayMS(uint x)
{
    uchar i;

   while (x--)
      for(i=0;i<120; i++) ;
}
/***************************************************
*                                定时器0初始化子函数
*                        工作方式2,每1000us中断一次
****************************************************/
void timer0_init(void)
{
        TMOD = 0x01;                //采用定时器0,工作方式2,
        TH0 = (65536-1000)/256;                         //定时器设置,每隔20us发起一次中断。
        TL0 = (65536-1000)%256;         
        ET0 = 1;                        //开定时器0中断
        EA = 1;                                 //开总中断
        TR0 = 1;                        //打开定时器
}

//检测按键

uchar GetKey(uchar kscancnt)

{  
   uchar ktmp;
   if(kscancnt==0)
         {
          temp=(Kport&0xf0)>>4;
          ktmp=~temp &(temp1);
          if(ktmp)knum=ktmp;
          temp1=temp;
         }
   return knum;

}

//键盘按键处理

void KeyProcess(uchar Key)
  {
   
   switch (Key)
        {
           case 1:Ledport=0x00;                        
                       break;
               
           case 2:if(F2cnt==200){sh_cnt=++sh_cnt%8;F2cnt=0;}
                          Ledport=table0[sh_cnt];
                      break;
           case 4:if(T0cnt==300)
                    {F3cnt=F3cnt+10;T0cnt=0;}
                          if(F3cnt==130){F3cnt=0;flag=!flag;}
                  Pwmcnt=++Pwmcnt%100;

                          if(flag)
                            {if(Pwmcnt>F3cnt)Ledport=0x00;else Ledport=0xff;}
                          else
                            {if(Pwmcnt>F3cnt)Ledport=0xff;else Ledport=0x00;}
                  break;

           case 8:Ledport=0xff; //全部关闭
                          break;

        }

}

/***************************************************
*               中断服务子函数
*****************************************************/
void time0(void) interrupt 1
{
    TH0 = (65536-1000)/256;                         //定时器设置,每隔20us发起一次中断。
    TL0 = (65536-1000)%256;  
        kscancnt=++ kscancnt%10;
        if(knum==2)         {F2cnt++; }
    if(knum==4)         {T0cnt++; }
}


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

void main(void)

{  
        uchar Key;
        P0=P1=0xFF;
        timer0_init();
        while(1)
                   {
                 Key=GetKey(kscancnt);
                 KeyProcess(Key);
               
                }
}
回复

使用道具 举报

ID:827243 发表于 2020-10-9 18:53 | 显示全部楼层
晕死, 按键高4位, 你判断低4位,错了。

switch (P1)

{

case 0xF7: k=1;break;

case 0xFB: k=2;break;

case 0xFD: k=3;break;

case 0xFE: k=4;break;

default: k=0;

}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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