找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3588|回复: 7
收起左侧

用stc15w101单片机写的按键单击双击长按程序,怎么加上休眠功能?

[复制链接]
ID:60656 发表于 2019-1-24 22:44 | 显示全部楼层 |阅读模式
#include <STC15F2K60S2.H>
#include"intrins.h"
sbit key=P3^5;
sbit LED=P3^4;
unsigned char L,value,time,num;
bit S,flag;
void  delay_ms(unsigned char         z)
{
        unsigned int x,y;
        for(x=z; x>0; x--)
                for(y=848; y>0; y--);
}
void HY()
{ if(!S)
    {
                 switch(L)
                        {
                         case 0: LED=1;break;
                         case 1: LED=0;delay_ms(2);LED=1;delay_ms(8);break;
                         case 2: LED=0;delay_ms(4);LED=1;delay_ms(6);break;
                         case 3: LED=0;delay_ms(6);LED=1;delay_ms(4);break;
                         case 4: LED=0;break;
                        }
         }
if(S)
   {
         switch(L)
                 {
                         case 0: LED=1;break;
                         case 1: LED=0;delay_ms(45);LED=1;delay_ms(255);break;
                         case 2: LED=0;delay_ms(80);LED=1;delay_ms(220);break;
                         case 3: LED=0;delay_ms(150);LED=1;delay_ms(150);break;
                         case 4: LED=0;delay_ms(10);LED=1;delay_ms(90);break;
                 }
   }
}

void Timer0Init(void)                //12.000MHz
{
        AUXR &= 0x7F;
        TMOD &= 0xF0;
        TL0 = 0x00;
        TH0 = 0xEE;
        TF0 = 0;
        TR0 = 1;
        EA = 1;
        ET0 = 1;
}
unsigned char getkey()
{         
         static unsigned char lp=0;
          switch(lp)
                {
                case 0:
                         if(!key)lp++;
                         else if(flag)
                                   {
                                        if(++time>50)
                                          {
                                           value=1;
                                           time=0,
                                           flag=0;
                                           }
                                        }
                        break;
                        case 1:if(!key)lp++;else lp=0;break;
                        case 2:
                             if(key)
                                   {
                                    lp++;
                                    if(flag)
                                      {
                                       value=2;
                                       flag=0;
                                      }
                                     else flag=1;
                                    }
                                  else if(++num>250)
                                {
                                         flag=0;
                                         value=3;
                                         lp++;
                                        }
                                        break;
                        case 3:if(key){lp=0;num=0;time=0;}break;
                  }
return value;
}        

main()
   {
                LED=1;
          L=0;S=0;flag=0;value=0;         
    Timer0Init();
          while(1)
   {  

        HY();         
   }
}
         
void timer()interrupt 1
{
switch(getkey())
           {  
           case 1:         
                 L++;
                             value=0;        
                              if(L>4) L=1;
                       break;
           case 2: S=~S;L=1;value=0;break;
           case 3: L=0;value=0; break;
          }
}


回复

使用道具 举报

ID:415064 发表于 2019-1-25 10:12 | 显示全部楼层
休眠?操作时来个中断
回复

使用道具 举报

ID:60656 发表于 2019-1-25 12:23 | 显示全部楼层
wojiaoguogai 发表于 2019-1-25 10:12
休眠?操作时来个中断

现在我碰到的问题是, 想要上电唤醒后也要响应功能,按键处理不好, 我加入休眠和中断唤醒后, 第一次上电后单击按键,会直接跳到第2个功能上(就L=2了), 不断电后续再循环休眠唤醒视乎正常 。
回复

使用道具 举报

ID:123289 发表于 2019-1-25 13:02 | 显示全部楼层
一个主循环的末端可以安排进入“休眠”。
在它的下一条指令,安排跳转向主循环入口(C语言自动完成)
这个每次主循环结束时都会休眠,而循环的连续则是由中断打破休眠后完成的。

评分

参与人数 1黑币 +50 收起 理由
admin + 50 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:60656 发表于 2019-1-25 21:55 | 显示全部楼层
yzwzfyz 发表于 2019-1-25 13:02
一个主循环的末端可以安排进入“休眠”。
在它的下一条指令,安排跳转向主循环入口(C语言自动完成)
这 ...

#include <STC15F2K60S2.H>
#include"intrins.h"
sbit key=P3^5;
sbit LED=P3^4;
unsigned char L,value,time,num;
bit S,flag,d;
void  delay_ms(unsigned char         z)
{
        unsigned int x,y;
        for(x=z; x>0; x--)
                for(y=848; y>0; y--);
}
void HY()
{ if(!S)
    {
                 switch(L)
                        {
                         case 0: LED=1;break;
                         case 1: LED=0;delay_ms(2);LED=1;delay_ms(8);break;
                         case 2: LED=0;delay_ms(4);LED=1;delay_ms(6);break;
                         case 3: LED=0;delay_ms(6);LED=1;delay_ms(4);break;
                         case 4: LED=0;break;
                        }
         }
if(S)
   {
         switch(L)
                 {
                         case 0: LED=1;break;
                         case 1: LED=0;delay_ms(45);LED=1;delay_ms(255);break;
                         case 2: LED=0;delay_ms(80);LED=1;delay_ms(220);break;
                         case 3: LED=0;delay_ms(150);LED=1;delay_ms(150);break;
                         case 4: LED=0;delay_ms(10);LED=1;delay_ms(90);break;
                 }
   }
}

void Timer0Init(void)                //5毫秒@12.000MHz
{
        AUXR &= 0x7F;                //定时器时钟12T模式
        TMOD &= 0xF0;                //设置定时器模式
        TL0 = 0x00;                //设置定时初值
        TH0 = 0xEE;                //设置定时初值
        TF0 = 0;                //清除TF0标志
        TR0 = 1;                //定时器0开始计时
        EA = 1;
        ET0 = 1;
}
unsigned char getkey()
{         
         static unsigned char lp=0;
          switch(lp)
                {
                case 0:
                         if(!key)lp++;
                         else if(flag)
                                   {
                                        if(++time>50)
                                          {
                                           value=1;           //单击
                                           time=0,
                                           flag=0;
                                           }
                                        }
                        break;
                        case 1:if(!key)lp++;else lp=0;break; //        消抖动
                        case 2:
                             if(key)
                                   {
                                    lp++;
                                    if(flag)
                                      {
                                       value=2;                 //连击
                                       flag=0;
                                      }
                                     else flag=1;
                                    }
                                  else if(++num>250)
                                {
                                         flag=0;
                                         value=3;                  //长按
                                         lp++;
                                        }
                                        break;
                        case 3:if(key){lp=0;num=0;time=0;}break;
                  }
return value;
}       

main()
   {
                LED=1;
          L=0;S=0;flag=0;value=0,d=0;         
    Timer0Init();
          while(1)
   {  
         if(d==0&&key==1)
           {
                 LED=1;        
     ET0 = 0;
           INT_CLKO |= 0x20;              //INT3 Enable
                 PCON = 0x02;             //MCU进入掉电模式
                 _nop_();
                 _nop_();
                 _nop_();
                 _nop_();                  
           }
        HY();         
   }
}
         
void timer()interrupt 1
{
switch(getkey())
           {  
           case 1:        
                 L++;
                             value=0;       
                              if(L>4) L=1;
                       break;
           case 2: S=~S;L=1;value=0;break;
           case 3: L=0;value=0;d=0; break;
          }
}

void INT3_int (void) interrupt 11
{       
         INT_CLKO &= 0xDF;
         delay_ms(30);
   if(key==0)
          {d=1;
     L=1;       
           ET0 = 1;
         }
}
回复

使用道具 举报

ID:60656 发表于 2019-1-25 22:04 | 显示全部楼层
yzwzfyz 发表于 2019-1-25 13:02
一个主循环的末端可以安排进入“休眠”。
在它的下一条指令,安排跳转向主循环入口(C语言自动完成)
这 ...

谢谢你的提示, 修改后的程序可休眠,但是按键口外部中断唤醒后 我处理不好, 按键这个地方有问题,上电后进入休眠,第一次按按键 功能直接跳第2档(L1 初始化是0,中断唤醒判断按键有效 L=1,推出出中断,开定时器中断),相当于L=2了,这个时候如果长按在休眠,不掉电 在单击启 有不连跳 ,搞不明白 请教一下这里怎么改。想来几天了搞不定,帮忙指点一下
回复

使用道具 举报

ID:123289 发表于 2019-1-26 08:19 | 显示全部楼层
你的编程逻辑构思上存在问题:一时说不清,给你一个任务,如果你能完成,则会有很大的进步。
任务:
不许任何地方用硬延时(例如程序中的:delay_ms()),用中断的方式来做。
硬延时:占用CPU时间,特别是中断服务程序中还使用,是件很糟糕的事,初学者都在做这个事。估计老师水平差,不教学生如何正确处理延时。或者学生也懒,硬延也时简单,就一直用了。

评分

参与人数 1黑币 +10 收起 理由
zxq9781 + 10 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:60656 发表于 2019-1-26 19:14 | 显示全部楼层
yzwzfyz 发表于 2019-1-26 08:19
你的编程逻辑构思上存在问题:一时说不清,给你一个任务,如果你能完成,则会有很大的进步。
任务:
不许 ...

谢谢你的指点,我基础差,有爱好自学,谢谢你的经验
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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