原创 电子模拟闹钟

2011-3-11 14:49 2632 10 10 分类: MCU/ 嵌入式

大四了,快毕业了,以前玩了2年的单片机,但做过的东西很少写文档,有些写了一点点,下面就贴出来。 这是大一下学期做的,参加学院的一个比赛。

 

a.功能简介:

 

   该闹钟可以上电后,可以通过按键调整时间,并且每当一个按键按下时蜂鸣器都会发出滴答响。调整时间是由两个按键完成,其中一个调整小时,一个调整分钟,秒钟则由软件完成,上电后自动走时。另有一个按键用来作为菜单的,通过菜单可以下翻选择闹钟调时和走时调时以及是否开启闹钟等的切换。本闹钟每秒钟走时你可以选择你是否需要伴有滴答声,其控制为一个拨打开关。

其具体使用方法如下:

1.      走时:通过模式设定键set键选择走时。四位数码管分别显示小时,分钟。第五位数码管显示秒钟,0~9显示6次分钟进1,并有声音。

2.      走时调整:通过模式设定键选择走时调整,按下hour键对走时的时进行显示调整,按下min键对走时的分显示进行调整。

3.      闹时调整:通过模式设定键选择闹时调整,按下hour键对闹时的时进行显示调整,按下min键对闹时的分显示进行调整。

4.      闹钟启停设定:通过模式设定键set选择闹钟启停开关,按下min键第四位小数点点亮,闹钟功能开启;按下hour键第三位小数点熄灭,闹钟功能关闭。

考虑到用本闹钟来作为早上起床的“呼叫”,当你开启了闹钟功能后,定好了时间后,到了闹时时间如果你起来关掉它,它过两分钟又开始呼叫你,连续四次,就不信你这么喜欢睡懒觉,呵呵…. 

b.硬件接法:

 

该作品的全部控制单元是由51单片机完成的,一共用了五位数码管,分别显示时间的时分和秒的各位,其控制位从左到右为P0^3,P0^4,P0^5,P0^6,P0^7.令采用三个按键辅助软件进行调节,其控制位分别为P3^4,P3^5,P3^6.(具体功能见程序清单。

c.作品有待改进之处:

1.  为方便需要可以多设置几个闹钟,并且闹铃可以用来自蜂鸣器产生的乐曲。

2. 该硬件可以继续将菜单加一位来显示年月日和星期

 

d.全部程序清单如下:

 

#include"reg51.h"

#define uchar unsigned char

#define uint unsigned int

sbit P3_7=P3^7;

sbit P3_6=P3^6;

sbit P3_5=P3^5;

sbit P3_4=P3^4;

sbit P0_0=P0^0;

sbit P0_2=P0^2;

sbit P0_3=P0^3;

sbit P0_4=P0^4;

sbit P0_5=P0^5;

sbit P0_6=P0^6;

sbit P2_7=P2^7;

char code  monthday[12] = {31,29,31,30,31,30,31,31,30,31,30,31};//每月最大天数

char DATA_7SEG[10]={0xC0,0xF9,0xA4,0xB0,0x99,

                    0x92,0x82,0xf8,0x80,0x90,};/*0~9的数码管段码*/

char RDATA_7SEG[10]={0xc0,0xcf,0xa4,0x86,0x8b,0x92,0x90,0xc7,0x80,0x82};//倒置的那位数码管的0~9断码

char DATA_7SEG1[10]={0x40,0x79,0x24,0x30,0x19,

                    0x12,0x02,0x78,0x00,0x10,};//带小数点的数码管的0~9的断码

uchar hour=0,min=0,sec=0; /*时、分、秒单元清零*/

uchar deda=0; /*5mS计数单元清零*/

uchar t_hour=0,t_min=0; /*闹时时、分单元清零*/

bit d_05s=0; /*0.5秒标志*/

bit o_f=0; /*闹时启/停标志*/

uchar set=0; /*模式设定标志*/

uchar m=0;

uchar flag=0; /*RAM掉电标志*/

void delay(uint k); /*延时子函数*/

void conv(); /*走时单元转换*/

void p_out(); /*判别闹时到否子函数*/

void dirve(); /*走时时间输出驱动子函数*/

void t_dirve(); /*闹时时间输出驱动子函数*/

void daytime_drive();

/*闹时启/停子函数*/

void time1_of()

{  uchar m;

   if(P3_6==0)delay(1);

   if(P3_6==0)

{P0_0=0;

      delay(5);

      P0_0=1;o_f=1;

         }       //P3_6键按下闹钟功能打开,且有按键音,以下相同

   for(m=0;m<30;m++)//该循环是防止按键已经按下而来不及显示

   {

    t_dirve();/*闹时时间输出驱动子函数*/

    P2=DATA_7SEG[t_min/10];//显示分钟

    P0=0xdf;

    delay(1);

    if(P0_5==0)

      {  if(o_f==1)

         P2_7=0;}

         else P2_7=1;

         delay(1);

      }//显示分钟后的小数点,如果闹钟功能启动了的话

if(P3_5==0)delay(1);

if(P3_5==0)

   {P0_0=0;

    delay(5);

    P0_0=1;

       o_f=0;

   }    //P3_5键按下闹钟功能关闭

for(m=0;m<30;m++)//该循环是防止按键已经按下却来不及显示

{    t_dirve();/*闹时时间输出驱动子函数*/

     P2=DATA_7SEG[t_min/10];

     P0=0xdf;delay(1);

    if(P0_5==0)

    {

         if(o_f==1)

      P2_7=0;

      else P2_7=1;

       }

      delay(1);

    }

}//不显示分钟后的小数点,如果闹钟功能关闭了的话

/*走时函数*/

void time()

{

conv(); /*走时单元转换*/

dirve(); /*走时时间输出驱动子函数*/

p_out(); /*判别闹时到否子函数*/

}

/*定时器T0 5mS初始化*/

void init_timer()

{

TMOD=0x01;//选择定时计数器第二种计数方式

TH0=(65535-4990)/256;//赋值为定时4990us,考虑到执行C代码语句要相应的时间

TL0=(65535-4990)%256;

IE=0x82;//所有的中断打开

TR0=1;//定时计数器T0打开

}

/*P3_4扫描按键子函数*/

void scan_key()

{

  delay(1);

  if(P3_4==0){P0_0=0;

      delay(5);

      P0_0=1;

      set++;}

  if(set>=5)set=0;

  if(set==1)flag=0x55;//来电显示的标志

  F0:if(P3_4==0)

     goto F0; /*按键未释放,在此等候*/

}

/*延时子函数*/

void delay(uchar k)

{

uint i,j;

for(i=0;i<k;i++)

 for(j=0;j<121;j++)

       ;     

}

/*5mS定时中断服务子函数*/

void zd(void) interrupt 1

{

   TH0=(65535-4990)/256;//定时计数器初始化

   TL0=(65535-4990)%256;

   deda++;//每隔5msdata加一

 

}

/*调整走时时间*/

 

void time_adj()

{  uchar m;

   if(P3_5==0)delay(1);//P3_5调时钟的小时位

    if(P3_5==0){P0_0=0;

    delay(5);

    P0_0=1;

   

    hour++; }//每按一下,小时位加一

    if(hour==24)hour=0;//时钟进位

    for(m=0;m<30;m++)/该循环是防止按键已经按下确来不及显示

 

       {

        dirve();

        if(P0_4==0)P2_7=0;

        else P2_7=1;//时钟与分钟之间用小数点隔开

        delay(1);

           }

 if(P3_6==0)delay(1);//P3_6调分钟,每按一下分钟加一

    if(P3_6==0){P0_0=0;

      delay(5);

      P0_0=1;

      min++;}

    if(min==60)min=0;//分钟进位

    for(m=0;m<30;m++)/该循环是防止按键已经按下确来不及显示

 

       {

        dirve();

        if(P0_4==0)P2_7=0;

        else P2_7=1; //时钟与分钟之间用小数点隔开

        delay(1);

    }

}

   {

    daytime_dirve();

    }

}

/*调整闹时时间*/

void time1_adj()

{   uchar m;

    if(P3_5==0)delay(1);

    if(P3_5==0){P0_0=0;

      delay(5);

      P0_0=1;

      t_hour++;}//P3_5按下,闹钟小时位加一

    if(t_hour==24)t_hour=0;//小时位进一

    for(m=0;m<30;m++)

    {

    t_dirve();//显示闹时时间

    }

if(P3_6==0)delay(1);

if(P3_6==0){P0_0=0;

       delay(5);

       P0_0=1;

       t_min++;}//P3_6按下,闹钟分时位加一

if(t_min==60)t_min=0;//分钟进位

for(m=0;m<30;m++)

   {

    t_dirve();//显示闹时时间

    }

}

/*时、分、秒单元及走时单元转换*/

void conv()

{

    if(deda<=100)d_05s=0;//计时没到0.5秒

    else d_05s=1;//计时已到0.5秒

    if(deda>=200){sec++;P0_0=0;delay(2);P0_0=1;deda=0;}//超过一秒,秒位进一,并且蜂鸣器滴滴响一下

    if(sec==60){min++;sec=0;}//秒钟近位

    if(min==60){hour++;min=0;}// 分钟进位

    if(hour==24){hour=0;}//一天已过

}

uchar delays(uchar k)//延时函数

{uchar i,j;

 for(i=0;i<k;i++)

    for(j=0;j<40;j++);

}

/*走时时间输出驱动子函数*/

void dirve()

{                             //数码管动态扫描

   P2=DATA_7SEG[hour/10];P0=0xf7;delay(1);//显示时位

   P2=DATA_7SEG1[hour%10];P0=0xef;delay(1);

   P2=DATA_7SEG[min/10];P0=0xdf;delay(1);//显示分位

   P2=DATA_7SEG[min%10];P0=0xbf;delay(1);

if(o_f==1){if(P0_6==0)P2_7=0;else P2_7=1;delay(1);}//闹钟功能开启,则分位后显示小数点

    P2=RDATA_7SEG[sec%10];P0=0x7f;delay(1);//显示秒位

}

/*闹时时间输出驱动子函数*/

void t_dirve()

{

    P2=DATA_7SEG[t_hour/10];P0=0xf7;delay(1); //显示闹时时位

    P2=DATA_7SEG1[t_hour%10];P0=0xef;delay(1);

    P2=DATA_7SEG[t_min/10];P0=0xdf;delay(1); //显示闹时分位

    P2=DATA_7SEG[t_min%10];P0=0xbf;delay(1);

    if(P0_6==0)P2_7=0;else P2_7=1;delay(1); //分位后一直显示小数点

    P2=RDATA_7SEG[sec%10];P0=0x7f;delay(1); //秒钟照样一直工作

}

/*判别闹时到否子函数*/

void p_out()

{

static int  i=0;

char m=count;

if(o_f==1)//在闹钟功能开启的前提下

{

if(t_hour==hour)

{if(t_min==min)//时间与定时的一样,秒钟除外

       {i++;

         P0_0=~P0_0;delay(80);//则蜂鸣器振荡响了一分钟

       }

}

    else P0_0=1;//一分钟过去后自动关闭

       if(i==1)//有三次闹铃时间,如果你很懒的话,则每隔2分钟就被吵,呵呵

       {if(t_hour==hour)

           {if(t_min==min-2)//时间与定时的少两分钟,秒钟除外

            {i++;

            P0_0=~P0_0;delay(80);//则蜂鸣器振荡响了一分钟

            }

           }

        }

       else P0_0=1;//一分钟过去后自动关闭

       if(i==2)

     {if(t_hour==hour)

           {if(t_min==min-4)//时间与定时少四分钟的一样,秒钟除外

            {i++;

            P0_0=~P0_0;delay(80);//则蜂鸣器振荡响了一分钟

            }

           }

        }

       if(i==3)

     {if(t_hour==hour)

           {if(t_min==min-6)//时间与定时的一样,秒钟除外

            {i++;

            P0_0=~P0_0;delay(80);//则蜂鸣器振荡响了一分钟

            }

           }

        }

       else P0_0=1;//一分钟过去后自动关闭

       else P0_0=1;//一分钟过去后自动关闭

          i++;

          if(i==4)

          i=0;

}

}/*主函数*/

void main()

{

    init_timer(); /*定时器T0初始化*/

    while(1) /*无限循环*/

    {

       if(P3_4==0)scan_key(); /*有按键,调用按键扫描子函数*/

    switch(set) /*根据set键值散转*/

        {

    case 0:time();break; /*走时时间程序*/

       case 1:time1_adj();break; /*闹时时间调整*/

        case 2:time_adj();break; /*走时时间调整*/

        case 3:time1_of();break; /*启/停闹时*/

    case 4:daytime_adj();break; /*启/停闹时*/

    default:break; /*其它退出*/

       }

if(flag!=0x55) /*判断掉电标志*/

    {for(m=0;m<200;m++) /*点亮12点的字样*/

        {

       P2=0xf9;P0=0xf7;delay(1);

       P2=0x24;P0=0xef;delay(1);

       P2=0xc0;P0=0xdf;delay(1);

        P2=0xc0;P0=0xbf;delay(1);

    P2=RDATA_7SEG[sec%10];P0=0x7f;delay(1);//并伴有较长时间的滴答声

    }

    P2=0xff;P0=0x80;delay(400); /*熄灭12点的字样*/

    }

    }

}

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
10
关闭 站长推荐上一条 /3 下一条