微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 按键控制流水灯

按键控制流水灯

时间:10-02 整理:3721RD 点击:
利用一个按键控制流水灯的移位C语言程序怎样写,求指导

你不会是要我们帮你整个程序都写出来吧

你不是这样吧,这样伸手,随便搜索一下都有吧

这话说的,就只要那个开关控制的那段程序,我现在写出来了
所以不用找了

肯定不是啊,就主要实现的那一点啊,再说了又不是很多好吧

想问一下你的按键检测程序是不是这种模式:if(key == 0)
{
    delay_ms(20);
    while(!key);
}
这个由于引入了延时,延时期间,单片机什么事情都没做,浪费CPU,你应该要让单片机实现延时功能,确又能在延时期间做一些其他事情,再一个是实现按键短按与长按。

楼上为什么不选择定时呢?

利用定时器怎么说?如果说利用外部中断,让按键成为脉冲触发,这个确实应该是可以的,但是我现在问题是线路固定好了,只能用单片机的P0口来完成,没想到好的触发,我现在想到的一个程序是
void main()
{ P2=0xfe;
  num=P2;
  while(1)
{
        while(P0==0xff);
         btn=P0;
         if(btn==0xfe)
         {
           num=_crol_(num,1);
           delay(300);
           P2=num;
         }
         if(btn==0xfd)
         {
                 num=_cror_(num,1);
                 delay(300);
                P2=num;
         }
  }
}
这段程序能实现效果,靠的延时,但是总感觉不好一样

按键是弹性按键,按下后弹起,不分长按还是短按,楼下有我想到的一些程序,也是靠延时,能实现效果,但是感觉不咋好,这里有个更好的给你看看,我看的不清楚#include <reg51.h>#include <intrins.h>
unsigned char scan_key();
void proc_key(unsigned char key_v);
void delayms(unsigned char ms);
sbit        K1 = P0^0;        //对应按钮K1
sbit        K2 = P0^1;        //对应按钮K2
main()
{
        unsigned char key_s,key_v;
        key_v = 0x03;
        P2 = 0xfe;
        while(1)
        {
                key_s = scan_key();
                if(key_s != key_v)
                {
                        delayms(10);
                        key_s = scan_key();
                        if(key_s != key_v)
                        {       
                                key_v = key_s;
                                proc_key(key_v);                                       
                        }
                }
        }       
}
unsigned char scan_key()
{
        unsigned char key_s;
        key_s = 0x00;
        key_s |= K2;
        key_s <<= 1;
        key_s |= K1;
        return key_s;               
}
void proc_key(unsigned char key_v)
{
        if((key_v & 0x01) == 0)
        {
                P2 = _cror_(P2,1);
        }
        else if((key_v & 0x02) == 0)
        {
                P2 = _crol_(P2, 1);
        }
}
void delayms(unsigned char ms)                // 延时子程序
{                                               
        unsigned char i;
        while(ms--)
        {
                for(i = 0; i < 120; i++);
        }
}

下面是我写的程序,你参考一下,你那个程序感觉可读性不是很强
#include <reg52.h>
/*按键程序,不采用任何空循环延时*/
sbit K1 = P0^0;
sbit K2 = P0^1;
unsigned char KeyValue = 0;                //按键键值
unsigned char KeyShortDown = 0;        //按键短按
unsigned char KeyLongDown = 0;        //按键长按
unsigned char KeyUpFlag = 0;
unsigned int KeyDownTime=0;        //按键按下时间
void Time0Init(void);                        //定时器0初始化
unsigned char GetKeyValue(void);
unsigned char IsKeyUp(void);        //有按键松手
void main(void)
{
        Time0Init();
        P0 = 0xff;
        while(1)
        {
                if(KeyUpFlag == 1)//有按键松手
                {       
                        KeyUpFlag = 0;
                        KeyDownTime=0;
                        switch (KeyValue)
                        {
                                case 1:
                                        if(KeyShortDown == 1)        P1 ^= 0x01;
                                        if(KeyLongDown == 1)        P1 ^= 0x02;
                                        KeyShortDown = 0;
                                        KeyLongDown = 0;
                                break;
                                case 2:
                                        if(KeyShortDown == 1)        P1 ^= 0x04;
                                        if(KeyLongDown == 1)        P1 ^= 0x08;
                                        KeyShortDown = 0;
                                        KeyLongDown = 0;
                                       
                                break;
                                default:break;
                        }
                }
        }
}
void Time0Init(void)
{
        TMOD |= 0x01;        //定时器0方式1
        TH0 = 0x8A;
        TL0 =0xCF;                //定时器0定时30ms
        ET0 = 1;
        TR0 = 1;
        EA = 1;
}
unsigned char GetKeyValue(void)
{
        if(0 == K1)return 1;
        if(0 == K2)return 2;
        return 0;                        //若没有按键按下则返回0
}
unsigned char IsKeyUp(void)
{
        if((K1 == 1)&&(K2 == 1))return 1;
        else return 0;
}
void Time0(void) interrupt 1
{
        unsigned char TempValue;
        TH0 = 0x8A;
        TL0 = 0xCF;                //定时器0定时30ms
        TempValue = GetKeyValue();   //这里引入TempValue变量是因为松开手时GetKeyValue返回0,
                                                       //若直接KeyValue=GetKeyValue那么松手时KeyValue=0了
        if(TempValue != 0)
        {
                KeyValue = TempValue;
                KeyDownTime++;               
        }
        if(KeyDownTime > 1)                //30ms 去抖动
        {
                if(0 != IsKeyUp())                //有按键松手
                {       
                        KeyUpFlag = 1;
                        if(KeyDownTime < 20)        KeyShortDown = 1;        //按键短按
                        if(KeyDownTime >= 20)        KeyLongDown = 1;        //按键长按
                }
        }
}

你可以参考一下我写的程序,也可以对比一下吧。在你的程序中执行一次按键检测程序总时间有20ms左右吧,20ms中有90%的时间是空出来什么都没做的,这个时间我指的是执行这些语句所需要的时间。再看看我的程序吧,执行定时器中断中所有程序算200us左右吧,在主函数中也算200us左右吧,执行一次按键程序所需语句时间为400us左右吧,其他时间CPU自由扩展,按键一直按下对其他程序没什么影响,因为中断程序时间太短了

首先非常感谢你这么认真为我回答问题,你写的很不错,但是我感觉有点繁琐点了,我主要就是用一个按键直接控制一个灯的亮灭,按键连到P0^0,LED接在P2^0,如果说用到外部中断,那就非常简答,现在不能用这个,你说的我的程序可读性不高,那应该是8楼的吧,但是9楼的程序可读性应该是很好的,你不妨看下九楼的程序。非常感谢你的回答

e ,不好意思,我可能看错了点,是控制流水灯的实现,用两个开关

不用谢啊,写程序要多积累点东西,到网上多找点好资料,c语言方面看一下《c与指针》《c缺陷与陷阱》,还有一点是程序风格很重要,我所说的可读性是指变量名和函数名的命名规则,比如不能用aa,bb,cc,dd这样的方式来命名,几个月后可能自己都看不到自己的程序了,另外一个我推荐的是不要使用延时是因为在大的项目中不方便,会带来很多的麻烦。另外推荐使用状态机编程,这样程序执行会更加好,可读性和可靠性高,调试非常方便

这个貌似很简单的

觉得简单就写出来撒

恩,多谢,受教了                                 

加头文件<intrins.h>,用里面的函数_crol_(,)或者_crol_( , )就行了

不好意思还有一个是_cror_( , )

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

网站地图

Top