zengdz 发表于 2011-11-3 12:59:36

单片机通过按键切换程序

我想编写一个按键控制流水灯花样的程序,不是单键的,而是按某一个键出现一种花样,按另一个键又出现另外一种花样。我编写的老是出不来效果。请知道的朋友帮下忙,谢了!

shi_90 发表于 2011-11-3 13:23:16

你确定按键可用否!??

jingwaner 发表于 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;
    }

.titrwh 发表于 2011-11-3 14:02:00

这个最好用中断。

xielong4183 发表于 2011-11-3 14:51:34

假设按键按下为低电平
if(key1==0)
{
   while(key1==0);//弹起后执行
   {
   按键1需要执行的功能;
   }
}
if(key2==0)
{
   while(key2==0);//弹起后执行
   {
   按键2需要执行的功能;
   }
}

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

span42 发表于 2011-11-3 15:02:13

排除1楼问题后,2楼的方式很不错,小小状态机。

lz最好把你的程序贴出来

zengdz 发表于 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();}        */

}
}

zengdz 发表于 2011-11-3 17:49:57

http://cache.amobbs.com/bbs_upload782111/files_47/ourdev_691400IL74G4.jpg
(原文件名:11_副本.jpg)

.titrwh 发表于 2011-11-3 17:51:09

回复【5楼】span42 狂奔的蜗牛
-----------------------------------------------------------------------

蜗牛老乡

zengdz 发表于 2011-11-3 17:52:03

回复【4楼】xielong4183 梦灭
-----------------------------------------------------------------------

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

BXAK 发表于 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;
}

zengdz 发表于 2011-11-3 18:47:20

回复【10楼】BXAK
-----------------------------------------------------------------------

对呀,请问应该怎么改呢

zengdz 发表于 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好像也没用

BXAK 发表于 2011-11-3 18:55:21

回复【12楼】zengdz
-----------------------------------------------------------------------

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

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

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

kolinking 发表于 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();}

}
}

zengdz 发表于 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所在的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);   
   }
}

zengdz 发表于 2011-11-3 19:23:51

我把程序都贴上了,通过各位的回复至今还未达到效果,可能是子函数有问题吧,因为我的子函数是由一个独立函数改来的。只是想练习按键的控制,找了两个花样想加进去。

kolinking 发表于 2011-11-3 19:24:09

回覆【15楼】zengdz
-----------------------------------------------------------------------
汗,这里要加跳出,不然永远不会切换

         a=0;//给a赋初值
         while(1)//while循环
         {
               P1=table;//将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;
   }
}

badboy007 发表于 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)(void)={func0,func1,func2,func3,func4,func5,func6,func7};

int main(void)
{
      unsigned char i;
        while(1)
        {
      if(KEY_PUSHDOWN==GetKeyValue())++i;
      pAfunc();
    }          
}

badboy007 发表于 2011-11-3 19:56:58

上面这个是一个比较简洁的实现方式。可以参考一下。

yao1 发表于 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);
          }
   }
}

xiaobendan 发表于 2011-11-3 20:36:17

按17楼说的应该可以了

52171314 发表于 2011-11-3 20:47:45

呵呵~~ 二楼的方法很好

zengdz 发表于 2011-11-3 21:03:22

回复【17楼】kolinking
-----------------------------------------------------------------------

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

zengdz 发表于 2011-11-3 21:26:07

回复【22楼】52171314 一世孤云
-----------------------------------------------------------------------

我也是南昌的耶

zengdz 发表于 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所在的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;
   
   }
}

badodo 发表于 2011-11-3 21:55:40

来学习

BXAK 发表于 2011-11-3 22:57:36

回复【25楼】zengdz
-----------------------------------------------------------------------

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

yao1 发表于 2011-11-4 10:48:07

用了状态机还用delay? 时间还很长 LZ可以改进下程序放中断写 消除delay。。。

zengdz 发表于 2011-11-4 12:20:47

回复【28楼】yao1
-----------------------------------------------------------------------

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

XIE2099 发表于 2011-11-6 01:28:17

看了几遍了,还是顶一下。

lxl359909575 发表于 2011-11-7 19:43:45

这个好说啊你设定一个变量来存按键的值每按一下按键这个值加一然后利用SWITCH语句来进行选择就会出不同的效果啦~~

swallowpig 发表于 2011-11-9 17:03:57

回复【18楼】badboy007
-----------------------------------------------------------------------

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

rickly_hzy 发表于 2012-4-3 09:59:20

xielong4183 发表于 2011-11-3 14:51假设按键按下为低电平if(key1==0){

这个感觉不错!

liaozh79 发表于 2020-7-18 17:38:24

看看            

lijianxing 发表于 2020-7-22 00:07:36

这个讨论受益匪浅,谢谢

lijianxing 发表于 2020-8-30 14:29:56

一步一步地把帖子看完,受教了,一个问题引来了很多解决办法,长见识了
页: [1]
查看完整版本: 单片机通过按键切换程序