搜索
bottom↓
回复: 36

单片机通过按键切换程序

[复制链接]

出0入0汤圆

发表于 2011-11-3 12:59:36 | 显示全部楼层 |阅读模式
我想编写一个按键控制流水灯花样的程序,不是单键的,而是按某一个键出现一种花样,按另一个键又出现另外一种花样。我编写的老是出不来效果。请知道的朋友帮下忙,谢了!

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

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2011-11-3 13:23:16 | 显示全部楼层
你确定按键可用否!??

出0入8汤圆

发表于 2011-11-3 13:58:36 | 显示全部楼层
uchar System_Mode;

if(Key==...)
   System_Mode=1;
if(Key==...)
   System_Mode=2;
.
.
.

switch(System_Mode)
    {
       case 1:
          Function1();
          break;
       case 2:
          Function2();
          break;
       .
       .
       .
       default:
          break;
    }

出0入0汤圆

发表于 2011-11-3 14:02:00 | 显示全部楼层
这个最好用中断。

出0入0汤圆

发表于 2011-11-3 14:51:34 | 显示全部楼层
假设按键按下为低电平
if(key1==0)
{
   while(key1==0);//弹起后执行
   {
     按键1需要执行的功能;
   }
}
if(key2==0)
{
   while(key2==0);//弹起后执行
   {
     按键2需要执行的功能;
   }
}

这个不需要消抖,我经常这样写

出0入50汤圆

发表于 2011-11-3 15:02:13 | 显示全部楼层
排除1楼问题后,2楼的方式很不错,小小状态机。

lz最好把你的程序贴出来

出0入0汤圆

 楼主| 发表于 2011-11-3 17:46:41 | 显示全部楼层
/*部分代码*/
#include<reg51.h>
#define unit unsigned int
#define uchar unsigned char//&ordm;ê&para;¨&Ograve;&aring;
#include<intrins.h>
sbit key1=P2^0;
sbit key2=P2^1;
void delayms(unit);
void vary1();
void vary2();
void main ()
{
  

  while(1)
  {       
          if(key1==0)
{
   while(key1==0);//&micro;&macr;&AElig;&eth;&ordm;ó&Ouml;&acute;&ETH;&ETH;
   {
     vary1();
   }
}
if(key2==0)
{
   while(key2==0);//&micro;&macr;&AElig;&eth;&ordm;ó&Ouml;&acute;&ETH;&ETH;
   {
     vary2();
   }
}


  /*if(s1==0&&s2==1){vary1();}  

  
  if(s2==0&&s1==1){vary2();}          */

  }
}

出0入0汤圆

 楼主| 发表于 2011-11-3 17:49:57 | 显示全部楼层

(原文件名:11_副本.jpg)

出0入0汤圆

发表于 2011-11-3 17:51:09 | 显示全部楼层
回复【5楼】span42 狂奔的蜗牛
-----------------------------------------------------------------------

蜗牛老乡

出0入0汤圆

 楼主| 发表于 2011-11-3 17:52:03 | 显示全部楼层
回复【4楼】xielong4183 梦灭
-----------------------------------------------------------------------

谢谢你的回复,可是我编了之后和原来情况一样。按某个键后有一种花样,但是换另一个键就不能切换。

出0入0汤圆

发表于 2011-11-3 18:41:41 | 显示全部楼层
回复【9楼】zengdz
-----------------------------------------------------------------------

你的程序不对,一旦按键进入某个“花样”就在里面死循环了,还怎么切换。

好的方法是用中断。但既然你不想用,可以在用于点亮LED的延时程序里加上按键检测。


#define unit unsigned int
#define uchar unsigned char
#include<reg51.h>
#include<intrins.h>

sbit key1=P2^0;
sbit key2=P2^1;

uchar key_Value;   //键值

void delayms(unit);
void vary1();
void vary2();

void main ()
{  
   while(1)
   {
      switch(key_Value)
      {
        case 1: vary1();
                break;
        case 2: vary2();
                break;
        default:break;  
      }
   }
}

void delayms(unit)
{
   ……
   if(!key1)key_Value=1;
   if(!key2)key_Value=2;
}

出0入0汤圆

 楼主| 发表于 2011-11-3 18:47:20 | 显示全部楼层
回复【10楼】BXAK
-----------------------------------------------------------------------

对呀,请问应该怎么改呢

出0入0汤圆

 楼主| 发表于 2011-11-3 18:49:07 | 显示全部楼层
回复【10楼】BXAK
-----------------------------------------------------------------------

uchar System_Mode;

if(key1==0)  
   System_Mode=1;
if(key2==0)  
   System_Mode=2;


switch(System_Mode)
    {
       case 1:
          vary1();
          break;
       case 2:
          vary2();
          break;

       default:
          break;
    }

  就算用switch case好像也没用

出0入0汤圆

发表于 2011-11-3 18:55:21 | 显示全部楼层
回复【12楼】zengdz
-----------------------------------------------------------------------

汗,还没写完你就看到了。刚写完你再看看10楼。

还有,你最好把完整的程序贴出来,不然不方便大家找出问题,

也不知道你的vary1();vary2();函数里面是不是有死循环。

出0入0汤圆

发表于 2011-11-3 19:07:47 | 显示全部楼层
按你的思路应该是这样才行,花样不能在key内做,不然会只有做刚按完键那一次而已。

void main ()
{  
while(1)
{
   if(key1==0)  
  {  
   while(key1==0);
   s1=0;
   s2=1;
  }  
  if(key2==0)  
  {  
   while(key2==0);
   s1=1;
   s2=0;
  }  

  if(s1==0&&s2==1){vary1();}   
   
  if(s2==0&&s1==1){vary2();}

}
}

出0入0汤圆

 楼主| 发表于 2011-11-3 19:15:36 | 显示全部楼层
回复【13楼】BXAK
-----------------------------------------------------------------------

呵呵,一直在线等呢。你说的点亮LED的延时程序里加上按键检测。貌似还是没效果。我把程序都贴出来吧。

#include<reg51.h>
#define unit unsigned int
#define uchar unsigned char//宏定义
uchar System_Mode;
#include<intrins.h>
sbit key1=P2^0;
sbit key2=P2^1;
void delayms(unit);
void vary1();
void vary2();
void main ()
{
  
  while(1)
  {
       
switch(System_Mode)
    {
       case 1:
          vary1();
          break;
       case 2:
          vary2();
          break;

       default:
          break;
    }
   }

  
  
}
void delayms(unit ms)
  {
  unit i,j;
   for(i=ms;i>0;i--)
       for(j=110;j>0;j--);
           if(!key1)System_Mode=1;
       if(!key2)System_Mode=2;

  }

void vary1()
  {

unit a;//定义循环用变量
uchar code table[]={
0xff,//全灭
0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,//依次逐个点亮
0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00,//依次逐个叠加
0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,//依次逐个递减
0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00,//依次逐个叠加
0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,//依次逐个递减
0x7e,0xbd,0xdb,0xe7,0xe7,0xdb,0xbd,0x7e,//两边靠拢后分开
0x7e,0x3c,0x18,0x00,0x00,0x18,0x3c,0x7e,//两边叠加后递减
0x7e,0xbd,0xdb,0xe7,0xe7,0xdb,0xbd,0x7e,//两边靠拢后分开
0x7e,0x3c,0x18,0x00,0x00,0x18,0x3c,0x7e,//两边叠加后递减
0x00,//全亮
};//定义循环用数据表格


   {
        
         a=0;//给a赋初值
         while(1)//while循环
         {
               P1=table[a];//将a所在的table中的值赋给P1口
               delayms(150);//1S延时子程序
               a++;//a的值加一
               if(a==74)//测试a是否等于42
               a=0;//给a赋值   
         }
    }

}

void vary2()
{
uchar aa;
aa=0xfe;
while(1)
   {
     P1=aa;
     delayms(150);
     aa=_crol_(aa,1);     
   }
}

出0入0汤圆

 楼主| 发表于 2011-11-3 19:23:51 | 显示全部楼层
我把程序都贴上了,通过各位的回复至今还未达到效果,可能是子函数有问题吧,因为我的子函数是由一个独立函数改来的。只是想练习按键的控制,找了两个花样想加进去。

出0入0汤圆

发表于 2011-11-3 19:24:09 | 显示全部楼层
回覆【15楼】zengdz
-----------------------------------------------------------------------
汗,这里要加跳出,不然永远不会切换

         a=0;//给a赋初值
         while(1)//while循环
         {
               P1=table[a];//将a所在的table中的值赋给P1口
               delayms(150);//1S延时子程序
               a++;//a的值加一
               if(a==74)//测试a是否等于42  
               a=0;//给a赋值   
>>>            if(System_Mode!=1) break;
         }
    }  

}

void vary2()
{
uchar aa;
aa=0xfe;
while(1)
   {
     P1=aa;
     delayms(150);
     aa=_crol_(aa,1);      
>>>  if(System_Mode!=2) break;
   }
}

出0入0汤圆

发表于 2011-11-3 19:55:06 | 显示全部楼层
void func0(void);//定义第1种流水灯花样;
void func1(void);//定义第2种流水灯花样;
void func2(void);//定义第3种流水灯花样;
void func3(void);//定义第4种流水灯花样;
void func4(void);//定义第5种流水灯花样;
void func5(void);//定义第6种流水灯花样;
void func6(void);//定义第7种流水灯花样;
void func7(void);//定义第8种流水灯花样;
void (*pAfunc[8])(void)={func0,func1,func2,func3,func4,func5,func6,func7};

int main(void)
{
        unsigned char i;
        while(1)
        {
        if(KEY_PUSHDOWN==GetKeyValue())++i;
        pAfunc[i&0x08]();
    }          
}

出0入0汤圆

发表于 2011-11-3 19:56:58 | 显示全部楼层
上面这个是一个比较简洁的实现方式。可以参考一下。

出0入0汤圆

发表于 2011-11-3 20:12:45 | 显示全部楼层
初学者不用这么麻烦吧 没理解会打击积极性的 你还是先理解怎么切换状态 理解了再把按键里面的delay换成状态机看看
1个键都能循环切换 何况多个键
/*上电LED处于灭状态,按1次开关,快闪1秒4次;按2次慢闪1秒2次;按3次常亮;按4次灭;功能循环 */
#include<reg51.h>
sbit LED1=P1^2;
sbit LED2=P1^6;
sbit KEY=P3^7;
unsigned int time;
unsigned char program;
void Delayms(unsigned int ms)
{
  unsigned int i=1000;
  for(;ms>0;ms--)
    for(i=500;i>0;i--);

}
void t0()interrupt 1 using 1
{
     if(program==0)//mie
     {
          LED1=LED2=1;   
     }
     else if(program==1)//KUAI
     {
          time++; //10ms加1
          if(time>25) //250ms
          {
               time=0;
               LED1=LED2=!LED1;
          }   
     }
     else if(program==2)//man
     {
          time++;
          if(time>50)
          {
               time=0;
               LED1=LED2=!LED1;
          }
   
     }
     else if(program==3)//liang
     {
          LED1=LED2=0;
     }

     TH0=216;//TH0=(65536-10240)/256 10ms中断1次
}
void main()
{
     bit keyflag=0;
     TMOD=0X01;
     TR0=1;
     ET0=1;
     EA=1;
     while(1)
     {
          if((KEY==0)&&(keyflag)==0)
          {
               Delayms(10);
               if(program<3)program++;
               else program=0;
               keyflag=1;      
          }
          else if(KEY)
          {
               keyflag=0;
               Delayms(10);
          }  
     }
}

出0入0汤圆

发表于 2011-11-3 20:36:17 | 显示全部楼层
按17楼说的应该可以了

出0入0汤圆

发表于 2011-11-3 20:47:45 | 显示全部楼层
呵呵~~ 二楼的方法很好

出0入0汤圆

 楼主| 发表于 2011-11-3 21:03:22 | 显示全部楼层
回复【17楼】kolinking
-----------------------------------------------------------------------

谢了,不太会处理全局关系,各位多包涵呀,呵呵

出0入0汤圆

 楼主| 发表于 2011-11-3 21:26:07 | 显示全部楼层
回复【22楼】52171314 一世孤云
-----------------------------------------------------------------------

我也是南昌的耶

出0入0汤圆

 楼主| 发表于 2011-11-3 21:47:39 | 显示全部楼层
这是我成功后的完整程序,谢谢各位的建议,特别是kolinking的建议,不过你的那句语句也有问题,改后程序如下:

#include<reg51.h>
#define unit unsigned int
#define uchar unsigned char//宏定义
#include<intrins.h>
sbit key1=P2^0;
sbit key2=P2^1;
void delayms(unit);
void vary1();
void vary2();
void main ()
{
      
  while(1)
  {
uchar System_Mode;

if(key1==0)  
   System_Mode=1;
if(key2==0)  
   System_Mode=2;


switch(System_Mode)
    {
       case 1:
          vary1();
          break;
       case 2:
          vary2();
          break;      
       default:
          break;
    }


   }

  
  
}
void delayms(unit ms)
  {
  unit i,j;
   for(i=ms;i>0;i--)
       for(j=110;j>0;j--);
          

  }

void vary1()
  {

unit a;//定义循环用变量
uchar code table[]={
0xff,//全灭
0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,//依次逐个点亮
0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00,//依次逐个叠加
0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,//依次逐个递减
0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00,//依次逐个叠加
0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,//依次逐个递减
0x7e,0xbd,0xdb,0xe7,0xe7,0xdb,0xbd,0x7e,//两边靠拢后分开
0x7e,0x3c,0x18,0x00,0x00,0x18,0x3c,0x7e,//两边叠加后递减
0x7e,0xbd,0xdb,0xe7,0xe7,0xdb,0xbd,0x7e,//两边靠拢后分开
0x7e,0x3c,0x18,0x00,0x00,0x18,0x3c,0x7e,//两边叠加后递减
0x00,//全亮
};//定义循环用数据表格


   {
        
         a=0;//给a赋初值
         while(1)//while循环
         {
               P1=table[a];//将a所在的table中的值赋给P1口
               delayms(150);//1S延时子程序
               a++;//a的值加一
               if(a==74)//测试a是否等于42
               a=0;//给a赋值
                           if(key2==0) break;   
         }
    }

}

void vary2()
{
uchar aa;
aa=0xfe;
while(1)
   {
     P1=aa;
     delayms(150);
     aa=_crol_(aa,1);
         if(key1==0) break;
     
   }
}

出0入0汤圆

发表于 2011-11-3 21:55:40 | 显示全部楼层
来学习

出0入0汤圆

发表于 2011-11-3 22:57:36 | 显示全部楼层
回复【25楼】zengdz
-----------------------------------------------------------------------

我就说嘛,不把完成的程序帖出来,大家也不好找原因,贴出来一看神马都明白了……

出0入0汤圆

发表于 2011-11-4 10:48:07 | 显示全部楼层
用了状态机还用delay? 时间还很长 LZ可以改进下程序放中断写 消除delay。。。

出0入0汤圆

 楼主| 发表于 2011-11-4 12:20:47 | 显示全部楼层
回复【28楼】yao1
-----------------------------------------------------------------------

嗯,谢谢你的建议,还没考虑过中断,以后试试

出0入143汤圆

发表于 2011-11-6 01:28:17 | 显示全部楼层
看了几遍了,还是顶一下。

出0入0汤圆

发表于 2011-11-7 19:43:45 | 显示全部楼层
这个好说啊  你设定一个变量来存按键的值  每按一下按键这个值加一  然后利用SWITCH语句来进行选择  就会出不同的效果啦~~

出0入0汤圆

发表于 2011-11-9 17:03:57 | 显示全部楼层
回复【18楼】badboy007  
-----------------------------------------------------------------------

有问题,      pAfunc[i&0x08](); i自加对它有什么影响啊0x07吧?

出0入0汤圆

发表于 2012-4-3 09:59:20 来自手机 | 显示全部楼层
xielong4183 发表于 2011-11-3 14:51  假设按键按下为低电平  if(key1==0)  {

这个感觉不错!

出0入0汤圆

发表于 2020-7-18 17:38:24 来自手机 | 显示全部楼层
看看            

出0入0汤圆

发表于 2020-7-22 00:07:36 | 显示全部楼层
这个讨论受益匪浅,谢谢

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-3-29 23:30

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

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