热卖开发板:
  • 51单片机开发板
  • USB开发板
  • AVR单片机开发板
  • 纯软件打造的时钟

      1、程序特点:针对“计时”和“动态扫描”分别用到了两个定时器。本来键盘扫描也想用定时器做防抖来着,结果干扰动态扫描,只好作罢。

      2、实现功能:计时,闹钟。调节时间和闹钟时,对应的显示位会闪烁。有闹钟开关界面。按调节键可以止闹。

      计时精度没有仔细调校,存在一定的误差。

      /***********************************************************************************
      名称:纯软件时钟 
      版本:V1.0
      作者:zjzj007
      时间:2008/10/28
      联系方式:zjzj1973@sina.com

      1、程序特点:针对“计时”和“动态扫描”分别用到了两个定时器。本来键盘扫描也想用定时器做防抖来着,结果干扰动态扫描,只好作罢。

      2、实现功能:计时,闹钟。调节时间和闹钟时,对应的位会闪烁。有闹钟开关界面。按调节键可以止闹。

      3、时间设置说明:
      按K1键1次进入设置分钟界面,按k4键时间加,按K2键时间减
      按K1键2次进入设置小时界面,按k4键时间加,按K2键时间减

      闹钟设置说明:
      按K1键3次进入闹钟分钟设置,按k4键时间加,按K2键时间减
      按K1键4次进入闹钟小时设置,按k4键时间加,按K2键时间减
      按K1键5次进入闹钟开关设置,按k4键闹钟开,按K2键闹钟关

       

      ************************************************************************************/

       

       


      #include "reg52.h"
      #define uchar unsigned char
      #define uint unsigned int

      uchar reg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x88,0xbf,0xc0,0xc8,0x8e};//段码
      //   0 ,1, 2, 3, 4, 5, 6, 7, 8, 9, 隐码, A,-, O, N, F  //
      uchar dis[8]={0,0,0,0};  //显示位缓冲
      //uchar set[4]; 
      uchar t=0,shi=0,fen=0,miao=0,key=0,num,n,j,z,zz,i;
      uchar fen_a=30,shi_a=06,a_stop=0;

      sbit beep=P1^7;  //蜂鸣器引脚

      uchar a_flag;    //闹钟标志位

       

      void delay(uint t)  //延时函数
      {  
       while(t--)
               {
          for(j=0;j<125;j++)
                    {}  
            }
      }

      void ring()  //震铃函数
      {  
          {if(t>10)
          {
         
       beep=!beep; 
          for(z=0;z<50;z++)
            {} 
          }
          }
        
      }

       


      void set_alarm(uchar n)  //闹钟时间设置
      {
          switch(n)
       {
        case 3: //K1键按下3次
        {  
         if(key==0x24)  //k4键按下
         {
             fen_a++;  //分钟加1
          if(fen_a==60)fen_a=0;
             }  
          else if(key==0x28)//k2键按下
          { 
                  
             if(fen_a==0)fen_a=60;
                fen_a--;  //分钟减1
             }
          }  
        break;
        case 4:
        {
             if(key==0x24)
             {
               shi_a++;  //小时加1
            if(shi_a==24)shi_a=0;
           
          }  
          else if(key==0x28)
          {
            shi_a--;   //小时减1
               if(shi_a==0)shi_a=24;    
              
          }
        }
        break;

       }//switch  
       
       
      }

       

       

       

      void timer2(void) interrupt 5 //时钟计时中断(TIMER2)
      {  
          TF2=0;  //清中断标志位
          t++;    //到50MS就加1
          if(t==20)  //1S
        {
              t=0;
           miao++;    //时间进位
           if(miao==60) 
        {
                 miao=0;
           fen++;
           if(fen==60)
           {
                    fen=0;
           shi++;
           if(shi==24)
           {
                    shi=0;
           }
         }
         }
              
        }

      void display(uchar i)  //动态扫描函数
      {
          switch (i)  // 四位数码管轮流显示
          {
          case 0:
          P1=0xfe;
          break;
          case 1:
          P1=0xfd;
          break;
          case 2:
          P1=0xfb;
          break;
          case 3:
          P1=0xf7;
          break;
          } 
           dis[2]=fen/10;   // 分钟的十位送显
        dis[3]=fen%10;   //分钟的个位送显
              dis[0]=shi/10;   //小时的十位送显
        dis[1]=shi%10;   //小时的个位送显

        if(n==0)  //无键按下
           {   
                   if((i==1)&&(t<10))//小时的个位数码管的小数点半秒闪动1次,作为秒显示
             {
                   P0=(reg[dis[i]])&0x7f;  //加小数点
                }  
                else
             {
                      P0=reg[dis[i]];
                   }
               }         
              else if(n==1)//K1按一次
              {
                if((i==2)|(i==3))  //分钟位闪动
             {
                   if(t<10)P0=(reg[dis[i]]); 
                      else {P0=reg[10];}
                }
                else P0=(reg[dis[i]]);
             
              }
              else if(n==2)//K1按二次
              {

                   if((i==1)|(i==0))  //小时位闪动
                   {
                   if(t<10)P0=(reg[dis[i]]);
                      else {P0=reg[10];}                            
                   }     
                   else P0=(reg[dis[i]]);
              }

              else if(n==3)//K1按三次
              {   
         dis[2]=fen_a/10;  //闹钟小时,分钟送显
         dis[3]=fen_a%10;
               dis[0]=shi_a/10;
         dis[1]=shi_a%10;

                   if((i==2)|(i==3)) 
                   {
           
                   if(t<10)//分钟位隔0.5秒闪烁一次
          {
            if(i==3)P0=(reg[dis[i]]&0x7f);//在分钟的个位显示小数点(小数点定义为闹钟标识)
                        else P0=reg[dis[i]];
          }
             else
             {
            if(i==3)P0=(reg[10]&0x7f);
                        else P0=reg[10];
             }  
                                      
                   }     
                   else P0=(reg[dis[i]]);
               }
           else if(n==4)//K1按四次
              {   
         dis[2]=fen_a/10;    //闹钟小时,分钟送显
         dis[3]=fen_a%10;
               dis[0]=shi_a/10;
         dis[1]=shi_a%10;

                   if((i==1)|(i==0))  //闹钟小时位闪动
                   {
                   if(t<10)P0=(reg[dis[i]]);
                      else {P0=reg[10];}                            
                   }     
                   else       
          {
          if(i==3)P0=(reg[dis[i]]&0x7f);//在分钟的个位显示小数点
                      else P0=reg[dis[i]];
          }   
             }
             
               else if(n==5)  //闹钟开闭状态显示, 默认值关A-OFF 
            { 
                   if(!num)  // 按下3键,即NUM=0,显示A-OFF  按下2键,NUM=1,显示A-ON
             {   
              a_flag=0;             //闹钟标志位,a_flag=0为off
              if(i<2)P0=reg[i+11];  
              else
                    {     
                 if(t<10)
                       {
                    if(i==2)P0=reg[i+11];
                 else  P0=reg[i+12]; //在各位显示F
                 
              }
           
              else P0=reg[10];
                          
                 }
           }
                 else
                 { 
              a_flag=1;//闹钟标志位,a_flag=1为on
              if(i<2)P0=reg[i+11]; //  //闹钟开状态显示,A-ON
              else
                    {  
                 if(t<10)
                       
                 P0=reg[i+11];
              else P0=reg[10];
                          
                 }    
                     }
            }


      }

      void timer1() interrupt 3  //动态扫描中断 每位40ms
      {
          uchar i;
          TH1=(65536-40000)/256;
          TL1=(65536-40000)%256;
          display(i);   //调用显示函数
       i++;
       if(i>3)i=0;  // 位   
      }


      uchar keyscan()   //键扫
      {   uchar scancode,tempcode;
       
       P2=0xf0;

        if((P2&0xf0)!=0xf0)
          {

          delay(20);  

             if((P2&0xf0)!=0xf0)
             { 
             scancode=0xfe;
             while((scancode&0x10)!=0)
          {    P2=scancode;
               if((P2&0xf0)!=0xf0)
               {
              tempcode=((P2&0xf0)|0x0f);
                       while((P2&0xf0)!=0xf0);    
           return ((~scancode)+(~tempcode));
            }    
               else scancode=((scancode<<1)|0x01);
             
          }//while
          } //if
       }//if
          else return 0 ;

      }


      void setjia()  //进入时间调整子程序,进行加1操作
      {
        
          if(n==1)
          {
            fen++;
            if(fen==60)fen=0;
        
        
          }  
       else if(n==2)
       { shi++;
            if(shi==24)shi=0;  
       
          }
       
      }

      void setjian()  //进入时间调整子程序,进行减1操作
      {
        
          if(n==1)
          {
           
         if(fen==0)fen=60;
         fen--;
          }  
       else if(n==2)
       {
            if(shi==0)shi=24;    
            shi--;
          }
       
      }

       


      void main()
      {       
             

               TMOD=0x01;  //定时器1工作在计时方式1
         T2CON=0;    //定时器2工作在自加载模式
      //       TH0=(65536-60000)/256;
      //   TL0=(65536-60000)%256;
               RCAP2H=(65536-45900)/256;  //定时器2初值
               RCAP2L=(65536-45900)%256;
               TH1=(65536-40000)/256;     //定时器1初值
         TL1=(65536-40000)%256;  
              
         IP=0x20;   //设定TIMER2优先级最高
        
         ET1=1;  //开计时器1中断
         ET2=1;  //开计时器2中断
         EA=1;   //开总中断
        
               TR1=1;   //开始计时
               TR2=1;   //开始计时

            while(1)  //大循环
            {    
             key=keyscan();    //把键值读出来
             switch(key)       //键值识别语句
          {
               case 0x18:   //k1键,为功能设置键
             
            n++;         //有键按下就加1
            if(n>5)n=0;  //按键超过5次,就清零
               break;
                     case 0x24:   //k4--加号键
               num=1;       //供开关闹钟显示的标志位 A-ON
            setjia();    //进入时间调整子程序,进行加1操作
            break;    
               case 0x28:   //k2--减号键
               num=0;       //供开关闹钟显示的标志位 A-OFF
                     setjian();   //进入时间调整子程序,进行减1操作
               break;
      /*             case 0x14://k3
               num=4;
               break;    
               case 0x21://k5
               num=5;
               break;
                     case 0x22://k6
               num=6;
               break;    
               case 0x11://k7
               num=7;
               break;
                     case 0x12://k8
               num=8;
               break;*/     

         }


      if((n==3)|(n==4)) //当K1键值累计到3或4次后,系统进入闹钟设置状态,分别设置闹钟的分或时
         {
            set_alarm(n);  //调用闹钟设置
        }

              if(shi_a==shi)    //比较小时位
        {
                  if(fen_a==fen)  //比较分钟位
            {    
             if(a_flag&&!a_stop)ring();  //检测闹钟标志位和止闹按键
                if(key){a_stop++;}   //  有按键按下,A_STOP就加1
            }
              }
              else a_stop=0; //退出时按键值清零
            }//while
             

      }

       

       

       

    声明:CEPARK已尽力确保内容的准确性,但因业务发展和技术服务的需要,有关内容可能会根据实际情况随时更新或者修改,恕不另行通知,不便之处敬请谅解!
      商城推荐
      社区指南
    CEPARK电子园-电子工程师自己的网络家园!
      迷你博客,轻松完成日志发布,管理相册;展示个性自我
      兴趣小组,热点话题,加入您感兴趣的话题讨论小组,一起交流吧
      最新资讯,热门话题与好友一起分享信息,他评论感兴趣的话题
      实名认证,真实交友,还可以轻松快捷的了解好友动态
      邀请您身边的好友,朋友,同事一起加入欢乐圈