基于数码管的简单时钟系统

来源:互联网 发布:方舟画质优化 编辑:程序博客网 时间:2024/05/18 01:13
  • 主要实现:能够在数码管上显示时,分,秒;
    设置闹钟(蜂鸣器);
    利用51单片机的定时器功能进行计时。
    说明:在程序的编写过程中无法实现减一的操作,没按一次减一的键总是不止一次地减一。这个问题尚未解决,详情见附录的程序部分。希望各路大神看到了能指点一二,在此不胜感激。
  • 系统仿真图:
    仿真图
  • 程序如下:
#include<reg51.h>    //头文件#define uchar unsigned char     //宏定义 之后用uchar代替unsigned char 这里指无符号字符#define uint unsigned int      //宏定义 同上 无符号整数sbit beep=P0^0;uchar dat[]={0,0,10,0,0,10,2,1};   //定义初始化显示时间数组uchar dat1[]={0,0,10,0,0,10,0,0};    //定义初始化闹钟设定值数组,本程序中闹钟只设定到分uchar dis_bit[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};   //数码管位选uchar code SEG7[11]={0xC0,/*0*/0xF9,/*1*/0xA4,/*2*/0xB0,/*3*/0x99,/*4*/0x92,/*5*/0x82,/*6*/0xF8,/*7*/                       0x80,/*8*/0x90,/*9*/0xBF,/*-*/};   //共阴极数码管字段码uchar  key_code[]= {           /*列检测时按键按下时key的可能值,通过对这些值的判断也就可以知道具体按键的位置*/   0x7e,0x7d,0x7b,0x77,        /*当列中的最高位P2.7为0时,这一列四个按键按下时(即对应行值变为0)的key的值,对应的键值为0,1,2,3*/   0xbe,0xbd,0xbb,0xb7,        /*当列中的P2.6为0时,这一列四个按键按下时(即对应行值变为0)的key的值,对应的键值为4,5,6,7*/   0xde,0xdd,0xdb,0xd7,        /*当列中的P2.5为0时,这一列四个按键按下时(即对应行值变为0)的key的值,对应的键值为8,9,A,B*/   0xee,0xed,0xeb,0xe7         /*当列中的P2.4为0时,这一列四个按键按下时(即对应行值变为0)的key的值,对应的键值为C,D,E,F*/                   };uchar code ksp[4]={0x7f,0xbf,0xdf,0xef};  //确定列的前提下(分别给每列置零)进行行检测uint tcount,t_beep;uchar flag=0;   //闹钟切换标志位,uchar flag_beep=0; //蜂鸣器响标志位,=1表示蜂鸣器响 /*flag=0,设定闹钟;flag=1,显示正常时间*/struct time{uint second;uint minute;uint hour;}time1;   //定义名为time的结构体,变量名time1uchar n,i,k;void delay(n)    //延时函数  {while(n--)    {      for(i=110;i>0;i--);    }    }  void display(void)      //数字显示{  if(flag==0)          //显示正常时间  {       for(k=0;k<8;k++)     {      P3=dis_bit[k];      P2=SEG7[dat[k]];     //p2接数码管a-g,p3接数码管1-8,控制动态扫描输出      delay(5);      P3=0X00;      }  }  if(flag==1)       //显示闹钟设定时间  {     for(k=0;k<8;k++)     {      P3=dis_bit[k];      P2=SEG7[dat1[k]];     //p2接数码管a-g,p3接数码管1-8,控制动态扫描输出      delay(5);      P3=0X00;              //消影      }  }}uchar keypad_scan(){    uchar key,temp=0;    P1=0xf0;    if(P1!=0xf0)    {       delay(10);       if(P1!=0xf0)       {              do{                 for(i=0;i<4;i++) //检测四列,按键必定在这四列之中                 {                       P1=ksp[i];     //重新给P2口赋值,此时列已经确定了                       if(P1!=ksp[i])   //某一行值变为0,P2口的值发生改变                       {                            delay(10);      //消抖,按键抖动                            key=P1;                            if(key!=ksp[i])  //再次确认四行中有某行变为0                            {                                  while(temp!=ksp[i])                                  {P1=ksp[i];temp=P1;display();}                                  return(key);    //此时的key值既包含了行值信息又包含了列值信息。                            }                        }                  }                }while(1);      }    }}uchar gotkey(){   uchar temp;   temp=keypad_scan();            for(i=0;i<16;i++)   {      if(temp==key_code[i])   //查表确定键盘号            return(i);   }} void keyscan(void)    //时间调整函数{  uchar keynum;   keynum=gotkey();   EA=0;     //中断开关。=0关中断   if(keynum==0)    //开始设定闹钟时间   {       flag=1;       TR0=0;    }   if(keynum==1)    //暂停功能触发,停止计时,便于调整时间   {       flag=0;       TR0=0;ET0=0;  //ET0为定时器T0的中断控制位。=0禁止中断;TR0运行控制位,位于TCON内部,=1定时器可能工作    }   if(keynum==2)   {         if(flag==0)    //时钟调整每次加1       {          dat[6]++;          if((dat[7]==2)&&(dat[6]>3))                 {             dat[7]=0;              dat[6]=0;           }          if(dat[6]>9)          {              dat[6]=0;             dat[7]++;             if(dat[7]>2)             {                dat[7]=0;             }          }           }       if(flag==1)   //闹钟时钟定时       {          dat1[6]++;          if((dat1[7]==2)&&(dat1[6]>3))               {             dat1[7]=0;              dat1[6]=0;          }          if(dat1[6]>9)          {              dat1[6]=0;              dat1[7]++;              if(dat1[7]>2)              {                dat1[7]=0;              }          }        }   }       if(keynum==3)   {     if(flag==0)   //分钟调整每次加一    {       dat[3]++;       if(dat[3]>=9)       {           dat[4]++;           dat[3]=0;        if(dat[4]>5)        {           dat[4]=0;        }       }     }    if(flag==1)   //闹钟分钟定时    {       dat1[3]++;       if(dat1[3]>9)       {          dat1[4]++;          dat1[3]=0;          if(dat1[4]>5)          {              dat1[4]=0;          }       }     }   }           if(keynum==4)      //暂停结束,显示正常时间;正常情况按下时无影响     {         flag=0;        TR0=1;ET0=1;          }     if(keynum==5)     {        dat1[0]=0;        dat1[1]=0;        dat1[3]=0;        dat1[4]=0;        dat1[6]=0;        dat1[7]=0;     }/*   if(keynum==6)                    {         if(flag==0)         //时钟减一       {         if(dat[6]!=0)          {  dat[6]=dat[6]-1; }         else         {            if((dat[6]==0)&&(dat[7]!=0))            {               dat[7]=dat[7]-1;               dat[6]=9;            }            else            {               dat[6]=3;               dat[7]=2;            }         }       }       if(flag==1)         //闹钟时钟减一       {         if(dat1[6]!=0)            dat1[6]=dat1[6]-1;         else         {            if((dat1[6]==0)&&(dat1[7]!=0))            {               dat1[7]=dat[7]-1;               dat1[6]=9;            }            else            {               dat1[6]=3;               dat1[7]=2;            }         }       }     }     if(keynum==7)     {        if(flag==0)        //分钟减一       {         if(dat[3]!=0)            dat[3]=dat[3]-1;         else         {            if((dat[3]==0)&&(dat[4]!=0))            {               dat[4]=dat[4]-1;               dat[3]=9;            }            else            {               dat[3]=9;               dat[4]=5;            }         }       }       if(flag==1)         //闹钟分钟减一       {         if(dat1[3]!=0)            dat1[3]=dat1[3]-1;         else         {            if((dat1[3]==0)&&(dat1[4]!=0))            {               dat1[4]=dat1[4]-1;               dat1[3]=9;            }            else            {               dat1[3]=9;               dat1[4]=5;            }         }       }     }        */    EA=1;   //中断开关,开中断}    void init(void)     //初始化函数{    TMOD = 0x11;    //TMOD特殊功能寄存器。控制两个定时器T1,T0,这里=00010001,T1T0处于工作方式1,定时开关仅由TR0控制    TH0 = 0xDB;   //预置数计时,转为十进制56319,到65536结束。计时约10ms    TL0 =0xFF;    ET0=1;     TR0=1;    tcount=0;    EA = 1;    beep=1;    t_beep=0;    flag=0;    flag_beep=0;}void main(){    init();    delay(10);    while(1)    //只要条件为真就一直循环。      {       display();       keyscan();       if((dat[7]==dat1[7])&&(dat[6]==dat1[6])&&(dat[4]==dat1[4])&&(dat[3]==dat1[3])&&(dat[1]==dat1[1])&&(dat[0]==dat1[0]))        /*以上条件同时成立*/       {             flag_beep=1;     //当正常时间到达设定时间时,将蜂鸣器响标志置为1       }       if(flag_beep)       {          if(t_beep%2==0)          { beep=0;delay(5);}          beep=1;           }      }   }void timer_0() interrupt 1 {     ET0=0;     //T0禁止中断   TR0=0;   TH0 = 0xDB;   TL0 = 0xFF;   TR0=1;   tcount++;   if(tcount==100)    //定时器是否满1秒   {        time1.second++;        t_beep++;        if(t_beep==60)       //蜂鸣器持续响60s        {           flag_beep=0;           t_beep=0;        }        tcount=0;        dat[0]=(time1.second)%10;        dat[1]=(time1.second)/10;   //显示秒        if(time1.second>59)        {              dat[0]=0;           dat[1]=0;           time1.second=0;           time1.minute++;           dat[3]=(time1.minute)%10;           dat[4]=(time1.minute)/10;   //显示分           if(time1.minute>59)           {               dat[3]=0;              dat[4]=0;              time1.minute=0;              time1.hour++;               dat[6]=time1.hour%10;     //显示小时              dat[7]=time1.hour/10;              if(time1.hour>23)              {                   dat[6]=0;                  dat[7]=0;                  time1.hour=0;                }            }        }    }   ET0=1;}

本设计相关工程文件和仿真文件见:基于数码管的简单时钟系统

1 0