zoukankan      html  css  js  c++  java
  • 独立按键控制跑马灯的启动和暂停----在上一例的基础上

    #include "REG52.H"
    #define const_voice_short 40 //蜂鸣器短叫的时间
    #define const_key_time1 20  //按键去抖动延时的时间
    #define const_key_time2 20  //按键去抖动延时的时间
    #define const_key_time3 20  //按键去抖动延时的时间
    #define const_key_time4 20  //按键去抖动延时的时间
    void initial_myself();
    void initial_peripheral();
    void delay_short(unsigned int uiDelayShort);
    void delay_long(unsigned int uiDelayLong);
    void led_flicker_09_16(); //第9个至第16个LED跑马灯程序,逐个亮且每次只能亮一个
    void hc595_drive(unsigned char ucLedStatusTemp16_09);
    void led_updata(); //LED更新函数
    void T0_time(); //定时中断函数
    void key_service(); //按键服务应用程序
    void key_scan(); //按键扫描程序
    sbit hc595_sh_dr=P3^6;  //上升沿时,数据寄存器数据移位
    sbit hc595_st_dr=P3^5;  //上升沿时移位寄存器的数据进入数据寄存器,下降沿时数据不变。当移位结束后,会产生一个正脉冲,用于更新显示数据。 
    sbit hc595_ds_dr=P3^4;  //串行数据输入端,级联的话接上一级的Q7
    sbit beep_dr=P1^5;
    sbit key_sr1=P0^0;
    sbit key_sr2=P0^1;
    sbit key_sr3=P0^2;
    sbit key_sr4=P0^3;
    sbit key_gnd_dr=P0^4;
    unsigned char ucKeySec=0; //被触发的按键编号
    unsigned int uiKeyTimeCnt1=0; //按键去抖动延时计数器
    unsigned char ucKeyLock1=0;  //按键触发后自锁的变量标志
    unsigned int uiKeyTimeCnt2=0; //按键去抖动延时计数器
    unsigned char ucKeyLock2=0;  //按键触发后自锁的变量标志
    unsigned int uiKeyTimeCnt3=0; //按键去抖动延时计数器
    unsigned char ucKeyLock3=0;  //按键触发后自锁的变量标志
    unsigned int uiKeyTimeCnt4=0; //按键去抖动延时计数器
    unsigned char ucKeyLock4=0;  //按键触发后自锁的变量标志
    unsigned int uiVoiceCnt=0;  //蜂鸣器鸣叫的持续时间计数器
    unsigned char ucLed_dr1=0; //代表16个灯的亮灭状态,0灭,1亮
    unsigned char ucLed_dr2=0;
    unsigned char ucLed_dr3=0;
    unsigned char ucLed_dr4=0;
    unsigned char ucLed_dr5=0;
    unsigned char ucLed_dr6=0;
    unsigned char ucLed_dr7=0;
    unsigned char ucLed_dr8=0;
    unsigned char ucLed_dr9=0; 
    unsigned char ucLed_dr10=0;
    unsigned char ucLed_dr11=0;
    unsigned char ucLed_dr12=0;
    unsigned char ucLed_dr13=0;
    unsigned char ucLed_dr14=0;
    unsigned char ucLed_dr15=0;
    unsigned char ucLed_dr16=0;
    unsigned char ucLed_updata=0; //刷新变量。每次更改LED灯的状态都要更新一次
    unsigned char ucLedStep_09_16=0; //第9个至第16个LED跑马灯的步骤变量
    unsigned int uiTimeCnt_09_16=0;  //第9个至第16个LED跑马灯的统计定时中断次数的延时计数器
    unsigned char ucLedStatus16_09=0; //代表底层74HC595输出状态的中间变量
    unsigned char ucLedDirFlag=0;  //方向变量,把按键与跑马灯关联起来的核心变量,0代表正方向,1代表反方向
    unsigned int uiSetTimeLevel_09_16=300; //速度变量,此数值越大速度越慢,此数值越小速度越快
    unsigned char ucLedStartFlag=1;  //启动和暂停的变量,0代表暂停,1代表启动
    void main()
    {
     initial_myself();
     delay_long(100);
     initial_peripheral();
     while(1)
     {
      led_flicker_09_16(); //第二路独立运行的任务,第9个至第16个LED跑马灯程序,逐个亮且每次只能亮一个 
      led_updata(); //LED更新函数
      key_service(); //按键服务的应用程序
     }
    }
    void key_scan()  //按键扫描函数,放在定时中断里
    {
     if(key_sr1==1) //IO是高电平,说明按键没有被按下,这时要及时清除一些标志位
     {
      ucKeyLock1=0; //按键自锁标志清零
      uiKeyTimeCnt1=0; //按键去抖动计数器清零,防止电压波动引起的误按
     }
     else if(key_sr1==0) //有按键按下,且是第一次按下
     {
      uiKeyTimeCnt1++; //累加定时中断次数
      if(uiKeyTimeCnt1>const_key_time1)
      {
       uiKeyTimeCnt1=0;
       ucKeyLock1=1;  //自锁按键置位,防止一直触发
       ucKeySec=1;   //触发1号按键
      }
     }
     
     if(key_sr2==1) //IO是高电平,说明按键没有被按下,这时要及时清除一些标志位
     {
      ucKeyLock2=0; //按键自锁标志清零
      uiKeyTimeCnt2=0; //按键去抖动计数器清零,防止电压波动引起的误按
     }
     else if(key_sr2==0) //有按键按下,且是第一次按下
     {
      uiKeyTimeCnt2++; //累加定时中断次数
      if(uiKeyTimeCnt2>const_key_time2)
      {
       uiKeyTimeCnt2=0;
       ucKeyLock2=1;  //自锁按键置位,防止一直触发
       ucKeySec=2;   //触发2号按键
      }
     }
     
     if(key_sr3==1) //IO是高电平,说明按键没有被按下,这时要及时清除一些标志位
     {
      ucKeyLock3=0; //按键自锁标志清零
      uiKeyTimeCnt3=0; //按键去抖动计数器清零,防止电压波动引起的误按
     }
     else if(key_sr3==0) //有按键按下,且是第一次按下
     {
      uiKeyTimeCnt3++; //累加定时中断次数
      if(uiKeyTimeCnt3>const_key_time3)
      {
       uiKeyTimeCnt3=0;
       ucKeyLock3=1;  //自锁按键置位,防止一直触发
       ucKeySec=3;   //触发3号按键
      }
     }
     
     if(key_sr4==1) //IO是高电平,说明按键没有被按下,这时要及时清除一些标志位
     {
      ucKeyLock4=0; //按键自锁标志清零
      uiKeyTimeCnt4=0; //按键去抖动计数器清零,防止电压波动引起的误按
     }
     else if(key_sr4==0) //有按键按下,且是第一次按下
     {
      uiKeyTimeCnt4++; //累加定时中断次数
      if(uiKeyTimeCnt4>const_key_time4)
      {
       uiKeyTimeCnt4=0;
       ucKeyLock4=1;  //自锁按键置位,防止一直触发
       ucKeySec=4;   //触发4号按键
      }
     }
    }
    void key_service() //按键服务应用程序
    {
     switch(ucKeySec) //按键服务状态切换
     {
      case 1:  //改变跑马灯方向的按键  
       if(ucLedDirFlag==0) //通过中间变量改变跑马灯的方向
        ucLedDirFlag=1; 
       else
        ucLedDirFlag=0; 
       
       uiVoiceCnt=const_voice_short; //按键声音触发,嘀一声就停
       ucKeySec=0;  //响应按键服务应用后,按键编号清零,避免一直触发
       break;
       
      case 2:  //加速按键
       uiSetTimeLevel_09_16=uiSetTimeLevel_09_16-10;
       if(uiSetTimeLevel_09_16<50)  //速度最快限定在50
        uiSetTimeLevel_09_16=50;
       
       uiVoiceCnt=const_voice_short; //按键声音触发,嘀一声就停
       ucKeySec=0;  //响应按键服务应用后,按键编号清零,避免一直触发
       break;
       
      case 3:  //减速按键
       uiSetTimeLevel_09_16=uiSetTimeLevel_09_16+10;
       if(uiSetTimeLevel_09_16>550)  //速度最慢限定在550
        uiSetTimeLevel_09_16=550;
       
       uiVoiceCnt=const_voice_short; //按键声音触发,嘀一声就停
       ucKeySec=0;  //响应按键服务应用后,按键编号清零,避免一直触发
       break; 
       
      case 4:  //启动和暂停按键
       if(ucLedStartFlag==1) //启动和暂停两种状态循环切换
        ucLedStartFlag=0;
       else
        ucLedStartFlag=1;
       
       uiVoiceCnt=const_voice_short; //按键声音触发,嘀一声就停
       ucKeySec=0;  //响应按键服务应用后,按键编号清零,避免一直触发
       break;
     }
    }
    void led_updata() //LED更新函数
    {
     if(ucLed_updata==1)
     {
      ucLed_updata=0;  //及时清零,避免一直更新
      if(ucLed_dr9==1)
       ucLedStatus16_09=ucLedStatus16_09&0xfe;    //确保第1位为0  亮
      else
       ucLedStatus16_09=ucLedStatus16_09|0x01;  //确保第1位为1 灭
     
      if(ucLed_dr10==1)
       ucLedStatus16_09=ucLedStatus16_09&0xfd;   
      else
       ucLedStatus16_09=ucLedStatus16_09|0x02; 
     
      if(ucLed_dr11==1)
       ucLedStatus16_09=ucLedStatus16_09&0xfb;   
      else
       ucLedStatus16_09=ucLedStatus16_09|0x04;
     
      if(ucLed_dr12==1)
       ucLedStatus16_09=ucLedStatus16_09&0xf7;   
      else
       ucLedStatus16_09=ucLedStatus16_09|0x08;
     
      if(ucLed_dr13==1)
       ucLedStatus16_09=ucLedStatus16_09&0xef;   
      else
       ucLedStatus16_09=ucLedStatus16_09|0x10;
     
      if(ucLed_dr14==1)
       ucLedStatus16_09=ucLedStatus16_09&0xdf;   
      else
       ucLedStatus16_09=ucLedStatus16_09|0x20;
     
      if(ucLed_dr15==1)
       ucLedStatus16_09=ucLedStatus16_09&0xbf;   
      else
       ucLedStatus16_09=ucLedStatus16_09|0x40;
     
      if(ucLed_dr16==1)
       ucLedStatus16_09=ucLedStatus16_09&0x7f;   
      else
       ucLedStatus16_09=ucLedStatus16_09|0x80;
     
      hc595_drive(ucLedStatus16_09);  //74HC595底层驱动程序
     }
    }
    void hc595_drive(unsigned char ucLedStatusTemp16_09)
    {
     unsigned char i;
     unsigned char ucTempData;
     hc595_sh_dr=0;
     hc595_st_dr=0;
     
     ucTempData=ucLedStatusTemp16_09; //先送高8位
     for(i=0;i<8;i++)
     {
      if(ucTempData>=0x80) //更新一次数据,移一次位
       hc595_ds_dr=1;//串行数据输入,如果是多片联级的话,更新一次,输入一次数据。(我的单片机只用了一个74HC595芯片)
      else
       hc595_ds_dr=0;
     
      hc595_sh_dr=0;
      delay_short(15);
      hc595_sh_dr=1;//SH引脚的上升沿把数据送入寄存器
      delay_short(15);
     
      ucTempData=ucTempData<<1;//左移一位
     }
     
     hc595_st_dr=0;
     delay_short(15);
     hc595_st_dr=1;  //ST引脚负责把寄存器的数据更新输出到74HC595的输出引脚上并且锁存起来。上升沿时更新显示数据。
     delay_short(15);
     
     hc595_sh_dr=0; //拉低,抗干扰就增强
     hc595_st_dr=0;
     hc595_ds_dr=0;
    }
    /*switch状态机,进行程序切换*/
    void led_flicker_09_16() //第1个至第8个LED跑马灯程序,逐个灭且每次只能灭一个
    {
     if(ucLedStartFlag==1)  //变量1代表启动
     {
      switch(ucLedStep_09_16)
      {
       case 0:
        if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16)  //LED灯延时时间到
        {
         uiTimeCnt_09_16=0;  //时间计数器清零
         
         if(ucLedDirFlag==0) //正方向
         {
          ucLed_dr16=0;  //第16个灯亮
          ucLed_dr9=1;  //第9个灯灭
          ucLed_updata=1;  //更新显示 ,找到led_updata函数,进行更新显示
          ucLedStep_09_16=1; //切换到下一个步骤
         }
         else    //反方向
         {
          ucLed_dr16=0;  //第16个灯亮
          ucLed_dr15=1;  //第15个灯灭
          ucLed_updata=1;  //更新显示
          ucLedStep_09_16=7; //切换到上一个步骤
         }
        }
        break;
        
       case 1:
        if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16)
        {
         uiTimeCnt_09_16=0;
         
         if(ucLedDirFlag==0)
         {
          ucLed_dr9=0;  //第9个灯亮
          ucLed_dr10=1;  //第10个灭
          ucLed_updata=1;
          ucLedStep_09_16=2;
         }
         else
         {
          ucLed_dr9=0;  //第9个灯亮
          ucLed_dr16=1;  //第16个灭
          ucLed_updata=1;
          ucLedStep_09_16=0;
         }
        }
        break;
        
       case 2:
        if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16)
        {
         uiTimeCnt_09_16=0;
         
         if(ucLedDirFlag==0)
         {
          ucLed_dr10=0;  //第10个灯亮
          ucLed_dr11=1;  //第11个灭
          ucLed_updata=1;
          ucLedStep_09_16=3;
         }
         else
         {
          ucLed_dr10=0;  //第10个灯亮
          ucLed_dr9=1;  //第9个灭
          ucLed_updata=1;
          ucLedStep_09_16=1;
         }
        }
        break;
     
       case 3:
        if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16)
        {
         uiTimeCnt_09_16=0;
         
         if(ucLedDirFlag==0)
         {
          ucLed_dr11=0;  //第11个灯亮
          ucLed_dr12=1;  //第12个灭
          ucLed_updata=1;
          ucLedStep_09_16=4;
         }
         else
         {
          ucLed_dr11=0;  //第11个灯亮
          ucLed_dr10=1;  //第10个灭
          ucLed_updata=1;
          ucLedStep_09_16=2;
         }
        }
        break;
     
       case 4:
        if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16)
        {
         uiTimeCnt_09_16=0;
         
         if(ucLedDirFlag==0)
         {
          ucLed_dr12=0;  //第12个灯亮
          ucLed_dr13=1;  //第13个灭
          ucLed_updata=1;
          ucLedStep_09_16=5;
         }
         else
         {
          ucLed_dr12=0;  //第12个灯亮
          ucLed_dr11=1;  //第11个灭
          ucLed_updata=1;
          ucLedStep_09_16=3;
         }
        }
        break;
     
       case 5:
        if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16)
        {
         uiTimeCnt_09_16=0;
         
         if(ucLedDirFlag==0)
         {
          ucLed_dr13=0;  //第13个灯亮
          ucLed_dr14=1;  //第14个灭
          ucLed_updata=1;
          ucLedStep_09_16=6;
         }
         else
         {
          ucLed_dr13=0;  //第13个灯亮
          ucLed_dr12=1;  //第12个灭
          ucLed_updata=1;
          ucLedStep_09_16=4;
         }
        }
        break;
     
       case 6:
        if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16)
        {
         uiTimeCnt_09_16=0;
         
         if(ucLedDirFlag==0)
         {
          ucLed_dr14=0;  //第14个灯亮
          ucLed_dr15=1;  //第15个灭
          ucLed_updata=1;
          ucLedStep_09_16=7;
         }
         else
         {
          ucLed_dr14=0;  //第14个灯亮
          ucLed_dr13=1;  //第13个灭
          ucLed_updata=1;
          ucLedStep_09_16=5;
         }
        }
        break;
     
       case 7:
        if(uiTimeCnt_09_16>=uiSetTimeLevel_09_16)
        {
         uiTimeCnt_09_16=0;
         
         if(ucLedDirFlag==0)
         {
          ucLed_dr15=0;  //第15个灯亮
          ucLed_dr16=1;  //第16个灭
          ucLed_updata=1;
          ucLedStep_09_16=0;
         }
         else
         {
          ucLed_dr15=0;  //第15个灯亮
          ucLed_dr14=1;  //第14个灭
          ucLed_updata=1;
          ucLedStep_09_16=6;
         }
        }
        break;
      }
     }
    }
    void T0_time() interrupt 1
    {
     TF0=0; //清除中断标志
     TR0=0; //关中断
      
     if(uiTimeCnt_09_16<0xffff) //设定这个条件,防止uiTimeCnt超范围
     {
      if(ucLedStartFlag==1) //1代表启动
       uiTimeCnt_09_16++; 
     } 
     key_scan();
     if(uiVoiceCnt!=0)
     {
      uiVoiceCnt--;
      beep_dr=0;  //PNP三极管控制,低电平开始鸣叫
     }
     else
     {
      ;
      beep_dr=1; 
     }  
      
     TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f
     TL0=0x2f;
     TR0=1; //开中断 
    }
    void delay_short(unsigned int uiDelayShort)
    {
     unsigned int i;
     for(i=0;i<uiDelayShort;i++)
      ;
    }
    void delay_long(unsigned int uiDelayLong)
    {
     unsigned int i;
     unsigned int j;
     for(i=0;i<uiDelayLong;i++)
      for(j=0;j<500;j++)
       ;
    }
    void initial_myself() //第一区  初始化单片机
    {
     key_gnd_dr=0;
     beep_dr=1;
     
     TMOD=0x01;  //设置定时器0工作方式为1
     TH0=0xf8;
     TL0=0x2f;
    }
    void initial_peripheral()
    {
     EA=1; //开总中断
     ET0=1; //允许定时中断
     TR0=1; //启动定时中断
    }
     
  • 相关阅读:
    Representation Data in OpenCascade BRep
    Render OpenCascade Geometry Surfaces in OpenSceneGraph
    Render OpenCascade Geometry Curves in OpenSceneGraph
    OpenCascade Shape Representation in OpenSceneGraph
    Geometry Surface of OpenCascade BRep
    Geometry Curve of OpenCascade BRep
    Tyvj2017清北冬令营入学测试
    Spfa算法模板
    洛谷1016 旅行家的预算
    洛谷1290 欧几里得的游戏
  • 原文地址:https://www.cnblogs.com/TheFly/p/12073416.html
Copyright © 2011-2022 走看看