原创 【小雨的成长】最基本的数码管显示时钟

2009-4-17 16:17 2606 5 5 分类: MCU/ 嵌入式

这3天都在为这个时钟忙。。 终于写好了。。
因为水平有限,所以大部分编程技巧都是借用zjzj007在论坛发的那个纯软件时钟。


   下面就来说说我的时钟。
/***********************************
软件名称:数码管显示时钟
版本:V1.0
作者:hnrain
完成时间:2008/12/7
功能描述:完成基本的时钟功能。24小时制
有三个按键分别为set键K1,调整加键K2,调整减键K3。
按一次set键,进入分设置.分钟位闪烁,此时按k2分钟加,按k3分钟减。
第二次按set键,进入时设置.时钟位闪烁,此时按k2分钟加,按k3分钟减。
第三次按set键,退出,显示为调整后的时间。
************************************/


呵呵。。这算是最简单的时钟了。。。我将陆续改写其他版本。程序内部有较详细的说明。


   这一次我将结合我的时钟讲时钟算法,也就是编程思路。


时钟也就是让秒分达到60时,时达到24时自动加1,进位。通过按键让其进入特定的函数执行程序进行相应操作。
我的时钟程序中用到的函数:
delay(uchar i)
void timer1() interrupt 3
void display(uchar seg_count)
void timer0() interruption 1
uchar keyscan()
void setadd()
void setdec()
void main()
主要的执行过程:没有按键时。始终执行主程序判断按键情况,并通过两个中断自动的进行时间加,和显示。有按键时跳到相应的按键程序执行。


我们写的每个函数都要用到执行,要么是被其他函数调用,要么自动执行。

uchar keyscan()
void setadd()
void setdec()
delay(uchar i)
void display(uchar seg_count)
就是被其他函数调用执行。

void main()
void timer1() interrupt 3
void timer0() interruption 1
就是被自动执行的!!


  算法就是这样。具体的编写技巧。就要看大家的编写程序了。。这方面我也是菜鸟刚学。。
这几天通过分析,编程学到很多东西1!
   呵呵。。。


我希望和大家一起共同学习,进步。。



下面是代码,可以下载压缩包.
/***********************************
软件名称:数码管显示时钟
版本:V1.0
作者:hnrain
完成时间:2008/12/7
功能描述:完成基本的时钟功能。24小时制
有三个按键分别为set键K1,调整加键K2,调整减键K3。
按一次set键,进入分设置.分钟位闪烁,此时按k2分钟加,按k3分钟减。
第二次按set键,进入时设置.时钟位闪烁,此时按k2分钟加,按k3分钟减。
第三次按set键,退出,显示为调整后的时间。
************************************/


#include "reg51.h"
#define uchar unsigned char
#define uint  unsigned int
uchar reg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
//  分别是0,1,2,3,4,5,6,7,8,9,消隐
uchar dis[4]={0};
uchar miao="0",fen=30,shi=12,key_count,t=0,seg_count=0,key=0;
/********************
函数名:delay(uchar i)
函数功能:消除键盘抖动,被uchar keyscan()函数调用
调用变量:局部变量j
********************/
void delay(uchar i)
{  
    uchar j;
while(i--)
      {
     for(j=0;j<200;j++);
    }
}


/**************************************
函数名:void timer1() interrupt 3
函数功能:定时计数中断 ,时间进位
调到变量:全局变量t
***************************************/
void timer1() interrupt 3
{
    TF1=0;
TH1=((65536-45900)/256);
TL1=((65536-45900)%256); //因为是采用方式1,这里是重新装载数据
t++;
while(t==20)   //定时器1定时50MS,中断20次就是1S
       { 
       t="0";
    miao++;
    if(miao==60)
         {
        miao="0";
        fen++;
    
        if(fen==60)
          {
        fen="0";
        shi++;
         
       if(shi==24)
          {
           shi="0";
        }
       }//fen
     }//miao
     }
  
}
/******************************
函数名:void display(uchar seg_count)
函数功能:将时钟数据送到数码管中显示。对数码管进行扫描,判断按键情况并做出是否闪动的操作!
调用函数:被void timer0() interrupt 1函数调用。
**********************************/
void display(uchar i)
{        
switch(i)
     {
    case 0:  P1=0xfe;     //通过seg_count函数的值判断选通那个数码管          
    break;
   
    case 1:  P1=0xfd;          
    break;
    case 2:  P1=0xfb;          
    break;
    case 3:  P1=0xf7;          
    break;
    default: break; 
  }
   dis[0]=shi/10;  //将需要显示的数据放到数组中缓存。
   dis[1]=shi%10;
   dis[2]=fen/10;
   dis[3]=fen%10;  
      if(key_count==0)   //没有按键时,让第二个数码管的小数点每半秒闪动一次。
         {
        if((seg_count==1)&&(t<10))
        P0=(reg[dis[seg_count]]&0x7f);
     else P0=reg[dis[seg_count]];
   }
 
  else if(key_count==1)  //set键按了一次,让分钟位闪烁
         {
        if(seg_count==3|seg_count==2)
       {
         if(t<10) P0=reg[dis[seg_count]];
        else P0=reg[10];  //让数码管灭,就输出0xff
     }
     else {
             P0=reg[dis[seg_count]];
       }
       
     }
 
    else if(key_count==2) //set键按了两次,让时钟位闪烁
         {
        if(seg_count==0|seg_count==1)
       {
         if(t<10) P0=reg[dis[seg_count]];
        else P0=reg[10];
     }
     else {
             P0=reg[dis[seg_count]];
       }
       
     }
 
}


/*****************************
函数名:void timer0() interruption 1
函数功能:数码管动态扫描中断,让数码管显示现在的时间
所用变量:seg_count,调用void display(uchar seg_count)
******************************/
void timer0() interrupt 1
{
  
   TF0=0;
   TH0=((65536-5000)/256);
   TL0=((65536-5000)%256); //定时器重装载。
   display(seg_count);
   seg_count++;      
   if(seg_count>3)seg_count=0;   //当按键数大于3时清零


/*******************************
函数名:uchar keyscan()
函数功能:对键盘进行扫描,确定那个按键有用。
所用变量:局部变量 scancode,tempcode。
************************************/
uchar keyscan()
{   uchar scancode,tempcode;


P2=0xf0;
  if((P2&0xf0)!=0xf0)     //仅仅是判断是否有按键按下,有则P2口数据会变化,往下执行。
    {
    delay(20);        //调延时防抖动
       if((P2&0xf0)!=0xf0)    //再判断是否有按键按下,防止误操作
       { 
       scancode="0xfe";    //将P2.0口至0其他位至1
       while((scancode&0x10)!=0)    //判断是否P2.4为0.
    {    P2=scancode;
         if((P2&0xf0)!=0xf0)   //判断是否有按键按下。。有的话P2.4,P2.5至少有一个为0
         {
        tempcode=((P2&0xf0)|0x0f);   //得出到底是那个高位键按下。如果是P2.4则P2.4为0,其他位为1
                 while((P2&0xf0)!=0xf0);    
     return ((~scancode)+(~tempcode));  //通过列,行得出到底是那个键按下。
      }    
         else scancode=((scancode<<1)|0x01);   //通过左移,不断的扫描低4位。
       
    }//while
    } //if
}//if
    else return 0 ;  //没按键则返回0
}
/***********************************
函数名:void setadd()
函数功能:调节时钟,对其进行加功能
所用函数: 被主函数调用
*************************************/
void setadd()
{
  if(key_count==1)
      {
     fen++;
   if(fen==60)fen=0;
   }
  else if(key_count==2)
         {
     shi++;
     if(shi==24)shi=0;
   }
}
/****************************
函数名:void setdec()
函数功能:调节时钟,对其进行减功能
所用函数:被主函数调用
****************************/
void setdec()
{
      
  if(key_count==1)
      {    
   if(fen==0)fen=60;    //这两行可以改成这样。if(fen)fen--; else fen="59";
   fen--;
   }
  else if(key_count==2)
         {    
     if(shi==0)shi=24; //不能写成这样shi--;  if(shi==0)shi=24; 避免出现0减一的情况。减了就会出错。
     shi--;
   }
}


/********************
函数名:void main()
函数功能:初始化程序,不断的对是键盘进行扫描
所用函数:
***********************/
void main()
{
            TMOD="0x11";
      TH1=((65536-45900)/256);
         TL1=((65536-45900)%256);
   TH0=((65536-5000)/256);
            TL0=((65536-5000)%256);
   EA="1";
   ET0=1;
   ET1=1;
   IP="0x08";
   TR0=1;
   TR1=1;
   while(1)
{    key="keyscan"();
   switch(key)       //键值识别语句
    {
         case 0x18:   //k1键,为set设置键 ,数据由keyscan函数返回。      
      key_count++;         //有键按下就加1
      if(key_count>2)key_count=0;  //按键超过2次,就清零
         break;
               case 0x24:   //加号键
      setadd();    //进入时间调整子程序,进行加1操作
      break;    
         case 0x28:   //减号键
               setdec();   //进入时间调整子程序,进行减1操作
         break;
   
   }


    }
}

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
5
关闭 站长推荐上一条 /3 下一条