找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2825|回复: 13
收起左侧

新手求助单片机按键问题

[复制链接]
ID:738970 发表于 2020-5-1 16:31 | 显示全部楼层 |阅读模式
200黑币
求助 我写了控制LED闪烁和常亮的程序, 写到这里 后面就不会写了。
我的按键是 K1  K2  当K1按下LED闪烁,再按下LED常亮,
我这里的K1按键是我想要的,我不知道怎么让单片机上电后LED灯全部熄灭的。能不能让K1按下2秒后关闭所有
LED灯。K2按下 单片机停止工作  K1按键按下也不要工作。帮忙修改下谢谢。下面是我写的程序 我是新手刚刚开始学习。






#include <AT89X52.H>
unsigned char n = 0;
sbit k1 = P1^0;
sbit k2 = P1^1;
sbit led = P0^0;
sbit led1 = P0^1;
sbit led2 = P0^2;
sbit led3 = P0^3;
sbit led4 = P0^4;
void delay()
{
    unsigned int  i, j;
    for(i = 0; i < 100; i++)   for(j = 0; j < 150; j++);
}
void readkey(void)
{
    unsigned char  i, j;
    if(!k1)  {
      for(i = 0; i < 10; i++)
        for(j = 0; j < 120; j++);  //延时消抖
      if(!k1)  {
        while(!k1);  //等待按键释放
        n++;
        n %= 2;       //n = 0~0
      }
    }
}
main()
{
    while(1)  {
      switch(n)    {
      case 1: led = 0;led1 = 0;led2 = 0;led3 = 0;led4 = 0; readkey(); break;      //长亮
      case 0: led1 = 0; led2 = 0; led3 = 0; led4 = 0; delay(); readkey(); led=~led; //快速闪烁
      }
    }
}

回复

使用道具 举报

ID:742494 发表于 2020-5-1 20:24 | 显示全部楼层
首先建议楼主的问题可以描述得更准确些。
我整理如下,请看下是不是你想要的?
按键输入 K1,K2
按键K1功能1:控制LED灯闪烁和常亮切换。  
                     这个就你现在的代码,自己进行优化调试。
按键K1功能2:“让K1按下2秒后关闭所有”,这点和功能1是矛盾的,应删除,直接改为上电初始化全灭。
                     解决方法是:1)增加1个void init(void)程序,将LED关掉。
                     2)在MAIN入口处先运行init();程序。 这样开机就可以先执行关LED操作。
按键K2功能:单片机停止工作,包括K1的按键功能也停止。
                   解决方法是,在循环中增加检测K2的操作,检测到K2后,执行while(1);直接进入死循环,这样就停止所有功能了。如果想要再按一次K2退出循环,可以在检测到K2后,执行{灭灯,while(K2);};这样一检测到K2,就退出循环,K1的功能又能再次使用。
                以上是思路,按照这个思路肯定可以实现你要的功能,代码还是自己写吧。
回复

使用道具 举报

ID:369312 发表于 2020-5-1 20:54 | 显示全部楼层
#include <AT89X52.H>
unsigned char n = 0;
sbit k1 = P1^0;
sbit k2 = P1^1;
sbit led = P0^0;
sbit led1 = P0^1;
sbit led2 = P0^2;
sbit led3 = P0^3;
sbit led4 = P0^4;
unsigned char flag = 0;
void delay()
{
    unsigned int  i, j;
    for(i = 0; i < 100; i++)   for(j = 0; j < 150; j++);
}
void readkey(void)
{
    unsigned char  i, j;
    if(!k1)  {
      for(i = 0; i < 10; i++)
        for(j = 0; j < 120; j++);  //延时消抖
      if(!k1)      {
        while(!k1);  //等待按键释放
        n++;
        n %= 2;       //n = 0~0
      }
    }
    if(!k2)  {
      for(i = 0; i < 100; i++)
         for(j = 0; j < 250; j++)
              delay();
    //粗略延时2S
      if(!k2)      {
        while(!k2);  //等待按键释放
            flag=!flag;//标志位取反
      }
    }
}
main()
{
led = 1;led1 = 1;led2 = 1;led3 = 1;led4 = 1;//关灯
    while(1)  {
readkey();
if(!flag)   // flag为0则key1正常工作,为1则停止工作
{
      switch(n)    {
      case 1: led = 0; break;      //长亮
      case 0: delay();  led=~led; break; //快速闪烁
      }
}
    }
}
试试看,行不行
回复

使用道具 举报

ID:413383 发表于 2020-5-1 22:11 | 显示全部楼层
真不知想表达什么
回复

使用道具 举报

ID:592807 发表于 2020-5-1 22:59 | 显示全部楼层


看着你功能描述,看着你的代码,完全不知道你要干嘛,如果你要K2按下后单片机停止工作,那你只要将K2放到电源处就好了你要开机后所有灯熄灭,就要在开始处while(1)之前将IO口低电平
要精确延时2秒就去网上搜定时器延时函数
另外你的按键扫描也一团糟
switch函数没有结尾
led =~ led;是什么东西


#include <AT89X52.H>


unsigned char n = 0;//按键功能标志为
sbit k1 = P1^0;//按键 1,k1 =1,表示按下
sbit k2 = P1^1;//按键2,k2 =1,表示按下
sbit led = P0^0;//led1 = 0灯亮
sbit led1 = P0^1;
sbit led2 = P0^2;
sbit led3 = P0^3;
sbit led4 = P0^4;
/*
  延时函数
  这里用的不是精确的定时器函数,
  精度不高,但是也够你用了

*/
void delay(unsigned int ums)
{
    unsigned int  i, j;

    for(i = 0;i < ums;i++)
    {
      for(j= 0; j< 200; j++) ;  //这里是两个分开循环200 和 102,没有嵌套

      for(j = 0; j < 102; j++); //这里是两个分开循环200 和 102,没有嵌套
    }
}

/*
按键扫描
排除同时按下两个按键的情况
n = 0 K2首次按下,或者刚开机状态,k1失效,灯全灭
n = 1 K2第二次按下状态灯闪烁
n = 2  K1按下,可以不停按下k1切换n = 1=2状态
*/
void readkey(void)
{
    unsigned char  i, j;

  if(!k2)//检测k2是否按下过
{
   delay(50);         //延时消抖,50ms-200ms不能太长,不能太短
  if(!k2)               //延时消抖
  {
    while(!k2);        //等待按键弹起,
    if(n == 0)n=1;
    else n=0;
  }
  else if(!k1)//检测k1是否按下,用else if,别用if
  {
     delay(50);         //延时消抖,50ms-200ms不能太长,不能太短
    if(!k1)               //延时消抖
    {
      while(!k1);        //等待按键弹起,
      if(n == 1)n=2;
      else if n=0
   }     

  }


}



}
main()
{
     led = 0;
   led1 = 0;
   led2 = 0;
   led3 = 0;
   led4 = 0;

    while(1)
    {
      readkey();
      switch(n)  
      {
      case 0:  led = 1;led1 = 1;led2 = 1;led3 = 1;led4 = 1; break;  //全灭   
      case 1:if(led == 0)led=1;else led = 0;break;//闪烁
      case 2: delay(500);delay(500);delay(500);delay(500);//延时2S
                 led=0;led1=0;led2=0;led3=0;led4=0;//全亮
                  break;
      default:break;//switch函结尾
      }
    }
}







回复

使用道具 举报

ID:371233 发表于 2020-5-2 08:08 | 显示全部楼层
Proteus8.9 仿真STM32407ZGT6系列003_Keys的u8 ReadKey(u16 IoBit)按键要有防抖延时。
#define Oppsit(A) (A!=0)?0:1
u8 i, k=1, t=0;
u8 str[8][17]={  "红灯亮!!!...\r\n",
                                        "红亮灭!!!...\r\n",
                                        "黄灯亮!!!...\r\n",
                                        "黄亮灭!!!...\r\n",
                                        "绿灯亮!!!...\r\n",
                                        "绿亮灭!!!...\r\n",
                                        "灯闪亮!!!...\r\n",
                                        "灯闪灭!!!...\r\n",
                   };
u8 ReadKey(u16 IoBit){
       if(0==GPIO_ReadInputDataBit(GPIOC,IoBit)){
              return 0;
       }
    else{
              delay_us(10);
              if(1==GPIO_ReadInputDataBit(GPIOC,IoBit)) {
                     return1;
              }
              else{
                     return0;
              }
       }
}
int main (void)
{
       NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
       delay_init(168);    //初始化延时函数
       uart_init(9600);     //串口初始化
       LED_Init();                           //初始化LED端口
       KEY_Init();                                //按键初始化        
       while(1)
       {
                     if(1==ReadKey(0x0020))k=0;
                     if(1==k){
                            for(t=0;t<16;t++){
                                   USART_SendData(USART1,(u16) str[6][t]);
                                   while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
                            }
                            for(i=0;  i<6; i++){
                                          PCout((i/2+1))=Oppsit((i%2));
                                          for(t=0;t<16;t++){
                                                 USART_SendData(USART1,(u16) str[ i][t]);
                                                 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
                                          }
                                          delay_ms(500);
                            }
                     }
                     else{
                            for(t=0;t<16;t++){
                                   USART_SendData(USART1,(u16) str[7][t]);
                                   while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
                            }
                            while(1!=ReadKey(0x0010));
                            k=1;
                            delay_ms(50);
                     }
       }
}
回复

使用道具 举报

ID:452950 发表于 2020-5-2 10:33 | 显示全部楼层
本帖最后由 xxpp2011 于 2020-5-2 12:25 编辑

//根据你的描述,LED接的应该是高电平亮,所以开始可以给P0低电平,k1按下交替控制LED闪烁和常亮两种状态,k2为自锁开关控制电源就好了。
#include <REG52.H>
sbit k1 = P1^0;unsigned char n=0;
void delay(uint ms){
        unsigned char i=100,j;
        for(;ms;ms--)
        {
                while(--i)
                {
                        j=10;
                        while(--j);
                }
        }
}

main()
{
   P0=0;
   if(k1=0)
    {
     while(1)  
     {
       while(!(n%2))
       {
        P0=1;
        delay(30);
        P0=0;
        delay(30);
        if(k1=0)n++;      
        }
       while(n%2)
       {
        P0=1;
       if(k1=0)n++;      
       }
     }
}}






回复

使用道具 举报

ID:738970 发表于 2020-5-2 11:11 | 显示全部楼层
黄youhui 发表于 2020-5-1 22:59
看着你功能描述,看着你的代码,完全不知道你要干嘛,如果你要K2按下后单片机停止工作,那你只要将K2放 ...

else if n=0  错误
回复

使用道具 举报

ID:738970 发表于 2020-5-2 11:22 | 显示全部楼层
黄youhui 发表于 2020-5-1 22:59
看着你功能描述,看着你的代码,完全不知道你要干嘛,如果你要K2按下后单片机停止工作,那你只要将K2放 ...

我是新手上面代码我都是开视频学的。有点乱不好意思。其实我就2个LED灯。LED 和LED1,我想用一个按键控制不同状态。就像 k1 按一下 led闪烁 led1常亮。再按一下led常亮 led1也是常亮,再按一下循环。长按2秒k1 跟按下K2同样 关闭 led 和led1.不好意思 我是新手
回复

使用道具 举报

ID:738970 发表于 2020-5-2 11:54 | 显示全部楼层
tcdzyq 发表于 2020-5-1 20:24
首先建议楼主的问题可以描述得更准确些。
我整理如下,请看下是不是你想要的?
按键输入 K1,K2

我新手 只能看视频教程所以你跟我说我不会写。我的要求应该不是很难,上电灯是灭的,按一下k1 led闪烁led1常亮 再按 led常亮led1常亮。k1按键循环这两个功能。需要关闭时长按k1    2秒关闭。k2按一下就关闭。就是因为不会写才来求助的。会写就不求助了。

#include <AT89X52.H>
unsigned char n = 0;

sbit k1 = P1^0;
sbit k2 = P1^1;
sbit led = P0^0;
sbit led1 = P0^1;


void delay()
{
    unsigned int  i, j;
    for(i = 0; i < 110; i++)   for(j = 0; j < 220; j++);
}

void readkey(void)
{
    unsigned char  i, j;
    if(!k1)  {
      for(i = 0; i < 10; i++)
        for(j = 0; j < 120; j++);  //延时消抖
      if(!k1)  {
        while(!k1);  //等待按键释放
        n++;
        n %= 3;       //n = 0~3
      }
    }
}
void main()
{     
      while(1)  {
      switch(n)    {
      case 2: led = 1;led1 = 1; readkey(); break;      //熄灭
          case 1: led = 0;led1 = 0; readkey(); break;      //长亮
          case 0: led1 = 0; delay(); readkey(); led = ~led; //快速闪烁
      }
    }
}
回复

使用道具 举报

ID:738970 发表于 2020-5-2 11:54 | 显示全部楼层
hulilanyua 发表于 2020-5-1 22:11
真不知想表达什么

我新手 只能看视频教程所以你跟我说我不会写。我的要求应该不是很难,上电灯是灭的,按一下k1 led闪烁led1常亮 再按 led常亮led1常亮。k1按键循环这两个功能。需要关闭时长按k1    2秒关闭。k2按一下就关闭。就是因为不会写才来求助的。会写就不求助了。

#include <AT89X52.H>
unsigned char n = 0;

sbit k1 = P1^0;
sbit k2 = P1^1;
sbit led = P0^0;
sbit led1 = P0^1;


void delay()
{
    unsigned int  i, j;
    for(i = 0; i < 110; i++)   for(j = 0; j < 220; j++);
}

void readkey(void)
{
    unsigned char  i, j;
    if(!k1)  {
      for(i = 0; i < 10; i++)
        for(j = 0; j < 120; j++);  //延时消抖
      if(!k1)  {
        while(!k1);  //等待按键释放
        n++;
        n %= 3;       //n = 0~3
      }
    }
}
void main()
{     
      while(1)  {
      switch(n)    {
      case 2: led = 1;led1 = 1; readkey(); break;      //熄灭
          case 1: led = 0;led1 = 0; readkey(); break;      //长亮
          case 0: led1 = 0; delay(); readkey(); led = ~led; //快速闪烁
      }
    }
}
回复

使用道具 举报

ID:738970 发表于 2020-5-2 11:55 | 显示全部楼层
黄youhui 发表于 2020-5-1 22:59
看着你功能描述,看着你的代码,完全不知道你要干嘛,如果你要K2按下后单片机停止工作,那你只要将K2放 ...

我新手 只能看视频教程所以你跟我说我不会写。我的要求应该不是很难,上电灯是灭的,按一下k1 led闪烁led1常亮 再按 led常亮led1常亮。k1按键循环这两个功能。需要关闭时长按k1    2秒关闭。k2按一下就关闭。
你给我的代码是错的。

#include <AT89X52.H>
unsigned char n = 0;

sbit k1 = P1^0;
sbit k2 = P1^1;
sbit led = P0^0;
sbit led1 = P0^1;


void delay()
{
    unsigned int  i, j;
    for(i = 0; i < 110; i++)   for(j = 0; j < 220; j++);
}

void readkey(void)
{
    unsigned char  i, j;
    if(!k1)  {
      for(i = 0; i < 10; i++)
        for(j = 0; j < 120; j++);  //延时消抖
      if(!k1)  {
        while(!k1);  //等待按键释放
        n++;
        n %= 3;       //n = 0~3
      }
    }
}
void main()
{     
      while(1)  {
      switch(n)    {
      case 2: led = 1;led1 = 1; readkey(); break;      //熄灭
          case 1: led = 0;led1 = 0; readkey(); break;      //长亮
          case 0: led1 = 0; delay(); readkey(); led = ~led; //快速闪烁
      }
    }
}
回复

使用道具 举报

ID:738970 发表于 2020-5-2 11:56 | 显示全部楼层
kaillen 发表于 2020-5-2 08:08
Proteus8.9 仿真STM32407ZGT6系列003_Keys的u8 ReadKey(u16 IoBit)按键要有防抖延时。
#define Oppsit(A)  ...

我新手 只能看视频教程所以你跟我说我不会写。我的要求应该不是很难,上电灯是灭的,按一下k1 led闪烁led1常亮 再按 led常亮led1常亮。k1按键循环这两个功能。需要关闭时长按k1    2秒关闭。k2按一下就关闭。
你给我的代码51单片机可以用吗?

#include <AT89X52.H>
unsigned char n = 0;

sbit k1 = P1^0;
sbit k2 = P1^1;
sbit led = P0^0;
sbit led1 = P0^1;


void delay()
{
    unsigned int  i, j;
    for(i = 0; i < 110; i++)   for(j = 0; j < 220; j++);
}

void readkey(void)
{
    unsigned char  i, j;
    if(!k1)  {
      for(i = 0; i < 10; i++)
        for(j = 0; j < 120; j++);  //延时消抖
      if(!k1)  {
        while(!k1);  //等待按键释放
        n++;
        n %= 3;       //n = 0~3
      }
    }
}
void main()
{     
      while(1)  {
      switch(n)    {
      case 2: led = 1;led1 = 1; readkey(); break;      //熄灭
          case 1: led = 0;led1 = 0; readkey(); break;      //长亮
          case 0: led1 = 0; delay(); readkey(); led = ~led; //快速闪烁
      }
    }
}
回复

使用道具 举报

ID:592807 发表于 2020-5-2 20:06 | 显示全部楼层
haolong155 发表于 2020-5-2 11:55
我新手 只能看视频教程所以你跟我说我不会写。我的要求应该不是很难,上电灯是灭的,按一下k1 led闪烁led ...

我没用keil打代码,用的是论坛手打的代码,出错了,也不报错的,所以要你自己改错,这很关键,写代码基本都是复制粘贴大佬或者别人写好的代码,再手动改错。
吧else if换成if。另外你那个长安两秒的判断要在 while(!k1);  //等待按键释放   要在这里判断是否超过2秒
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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