基于AT89C51单片机的 LCD闹钟

 

#include<reg52.h>
#define uchar unsigned char 
#define uint unsigned int
#define KEY_IO P3
#define LCD_IO P0
//以下是C调低音的音频宏定义
#define L1  262    //将"L1"宏定义为低音"1"的频率262Hz 时间是1/262=3826/2 us  取半周期
#define L2  286    //将"L2"宏定义为低音"2"的频率286Hz
#define L3  311    //将"L3"宏定义为低音"3"的频率311Hz
#define L4  349    //将"L4"宏定义为低音"4"的频率349Hz
#define L5  392    //将"L5"宏定义为低音"5"的频率392Hz
#define L6  440    //将"l_a"宏定义为低音"6"的频率440Hz
#define L7  494    //将"L7"宏定义为低音"7"的频率494Hz
//以下是C调中音的音频宏定义
#define Z1    523     //将"Z1"宏定义为中音"1"的频率523Hz
#define Z2    587     //将"Z2"宏定义为中音"2"的频率587Hz
#define Z3  659     //将"Z3"宏定义为中音"3"的频率659Hz
#define Z4    698     //将"Z4"宏定义为中音"4"的频率698Hz
#define Z5    784     //将"Z5"宏定义为中音"5"的频率784Hz
#define Z6    880     //将"Z6"宏定义为中音"6"的频率880Hz
#define Z7    987     //将"Z7"宏定义为中音"7"的频率523H      
//以下是C调高音的音频宏定义
#define H1  1046    //将"H1"宏定义为高音"1"的频率1046Hz
#define H2  1174    //将"H2"宏定义为高音"2"的频率1174Hz
#define H3  1318    //将"H3"宏定义为高音"3"的频率1318Hz
#define H4  1396    //将"H4"宏定义为高音"4"的频率1396Hz
#define H5  1567    //将"H5"宏定义为高音"5"的频率1567Hz
#define H6  1760    //将"H6"宏定义为高音"6"的频率1760Hz
#define H7  1975    //将"H7"宏定义为高音"7"的频率1975Hz




sbit k4=P3^3;
sbit sound=P1^6;    //蜂鸣器
unsigned int C;     //储存定时器的定时常数






sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
sbit LED = P2^4;




void music(void);






unsigned char u,t;
bit new_s, modify = 0;
char t0, sec = 40, min = 29, hour = 6;
char code LCD_line1[] = "HAPPY   EVEDAY";
char code LCD_line2[] = "Timer: 00:00:00 ";
char Timer_buf[] = "23:59:50";
//---------------------------------------------------
void delay(uint z)
{
    uint  x, y;
    for(x = z; x > 0; x--)  for(y = 100; y > 0; y--);
}
void delay1()               
   {
     unsigned char i,j;
 for(i=0;i<100;i++)
   for(j=0;j<250;j++)
    ;
   }
//---------------------------------------------------
void W_LCD_Com(uchar com)      //写指令
{
    LCD_RS = 0;  LCD_IO = com; // LCD_RS和R/W都为低电平时,写入指令
    LCD_EN = 1;  delay(5); LCD_EN = 0; //用EN输入一个高脉冲 
}
//---------------------------------------------------
void W_LCD_Dat(uchar dat)      //写数据
{
    LCD_RS = 1;  LCD_IO = dat; // LCD_RS为高、R/W为低时,写入数据
    LCD_EN = 1;  delay(5); LCD_EN = 0; //用EN输入一个高脉冲 
}
//---------------------------------------------------
void W_LCD_STR(uchar *s)       //写字符串
{
    while(*s)  W_LCD_Dat(*s++);
}
//---------------------------------------------------
void W_BUFF(void)              //填写显示缓冲区
{
    Timer_buf[7] = sec % 10 + 48;/*秒除以10,并取余数*/ Timer_buf[6] = sec / 10 + 48; /*秒除以10,并取整数*/       
    Timer_buf[4] = min % 10 + 48;                       Timer_buf[3] = min / 10 + 48;
    Timer_buf[1] = hour % 10 + 48;                      Timer_buf[0] = hour / 10 + 48;
    W_LCD_Com(0xc0 + 7); W_LCD_STR(Timer_buf);
}
//---------------------------------------------------
uchar read_key(void)  //按键 判断
{
    uchar  x1, x2;
    KEY_IO = 255;
    x1 = KEY_IO; //  if (new_s) { 
    if (x1 != 255) { //  new_s = 0;    sec++;  sec %= 60;
      delay(100);   //  if(!sec)  {   min++;  min %= 60;
      x2 = KEY_IO;  //       if(!min)  { hour++; hour %= 24;}
      if (x1 != x2)  return 255; //  }
      while(x2 != 255) x2 = KEY_IO;    //  W_BUFF(); 
      if      (x1 == 0x7f)  return 0;
      else if (x1 == 0xbf)  return 1;
      else if (x1 == 0xdf)  return 2;  
      else if (x1 == 0xef)  return 3;
     
    }
    return 255;
}
//---------------------------------------------------
void Init()
{
    LCD_RW = 0;
    W_LCD_Com(0x38); delay(50); 
    W_LCD_Com(0x0c);
    W_LCD_Com(0x06);
    W_LCD_Com(0x01);
    W_LCD_Com(0x80); W_LCD_STR(LCD_line1);
    W_LCD_Com(0xC0); W_LCD_STR(LCD_line2);
    TMOD = 0x01;   //T0定时方式1   16位
    TH0 = 0x4c; 
   
      ET0 = 1;
    TR0 = 1;       //启动T0
        
 


    EA = 1;
}


//-----------------------------------------------------------
void music(void)
  {
   
//以下是《天空之城》简谱 //每行对应一小节音符
   unsigned  int code f[]={ Z6,Z7,/**/H1,Z7,H1,H3,/**/Z7,Z3,Z3,   /**/Z6,Z5,Z6,H1,/**/Z5,Z3,Z3,   /**/Z4,Z3,Z4,H1, 
                               Z3,H1,H1,H1,/**/Z7,Z4,Z4,Z7,/**/Z7,Z6,Z7,   /**/H1,Z7,H1,H3,/**/Z7,Z3,Z3,   /**/Z6,Z5,Z6,H1,
                                Z5,      Z3,/**/Z4,H1,Z7,H1,/**/H2,H2,H2,H1,/**/H1,Z6,Z7,Z5,/**/Z6,H1,H2,   /**/H3,H2,H3,H5,
           H2,Z5,Z5,   /**/H1,Z7,H1,H3,/**/H3,         /**/Z6,H1,Z7,H2,/**/H1,Z5,Z5,   /**/H4,H3,H2,H1,
           H3,         /**/Z3,H3,      /**/H6,H5,H5,   /**/H3,H2,H1,H1,/**/H2,H1,H2,H5,/**/H3,H3,
           H6,H5,      /**/H3,H2,H1,H1,/**/H2,H1,H2,Z7,/**/Z6,Z6,Z7,   /**/Z6,       
0xff }; //以0xff作为音符的结束标志
//以下是简谱中每个音符的节拍
//"4"对应4个延时单位,"2"对应2个延时单位,"1"对应1个延时单位 
unsigned char code JP[ ]={     4,4,  /**/12,4,8,8,   /**/20,4,4,     /**/12,4,8,8,   /**/20,4,4,     /**/12,4,4,12,
  20,4,4,4,   /**/12,4,8,8,   /**/20,4,4,     /**/12,4,8,8,   /**/20,4,4,     /**/12,4,8,8,
32,      4, /**/8,4,6,8,    /**/4,4,4,16,   /**/8,4,6,8,    /**/24,4,4,     /**/12,4,8,8,
24,4,4,     /**/4,4,8,8,    /**/32, /**/4,8,8,6,    /**/12,4,16,    /**/8,8,8,8,
30,         /**/20,8,       /**/16,8,8,     /**/4,4,16,8,   /**/8,4,4,8,    /**/20,8,
16,16,      /**/4,20,8,     /**/8,4,4,8,    /**/20,4,4,     /**/32,
};
  EA=1;         //开总中断
  ET1=1;        //定时器T1中断允许
  TMOD &= 0x0f;
       TMOD |= 0x00;    // 使用定时器T1的模式1(13位计数器)
  TR1=1;
  while(1)       //无限循环
{
u=0;   //从第1个音符f[0]开始播放
     while(f[u]!=0xff)            //只要没有读到结束标志就继续播放
  {
              C=460830/f[u];   //
              TH1=(8192-C)/32;   //可证明这是13位计数器TH0高8位的赋初值方法   5
              TL1=(8192-C)%32;   //可证明这是13位计数器TL0低5位的赋初值方法
              TR1=1;             //启动定时器T0
for(t=0;t<JP[u];t++)  //控制节拍数
                  delay1();          //延时1个节拍单位
 TR1=0;               //关闭定时器T1
    u++; //播放下一个音符
if(k4==0) //暂停按键 
{ delay(2);
  if(k4==0)  
{
ET1=0; //  关      允许T1,相当于关音乐
}  
break;

ET1=1;  //为了不影响第二次播放音乐,再  开 允许T1
  }   
sound=0;

  break;
}











//---------------------------------------------------
void main()
{


    uchar Key;
    Init();
    while(1)  
{
//-------------------------------
      
//-------------------------------
        if (!sec && min==1  && hour==0) 
{ //整点报时 //  可以自己定闹钟
           music();
}
      
//-------------------------------
      Key = read_key();  //读出按键
      switch(Key) 
 {      //分别处理四个按键
      case  0: modify = 1; break;
      case  1: if(modify) {min++;  min %= 60;  W_BUFF(); break;}
      case  2: if(modify) {hour++; hour %= 24; W_BUFF(); break;}
      case  3: modify = 0; break;
    }
 }
}
//---------------------------------------------------










void timer0(void) interrupt 1  //T0中断函数, 50ms执行一次   T0中断等级是1  注意
{


    TH0 = 0x4c; 
    t0++; t0 %= 20;   //20, 一秒钟
    if(t0 == 0)  {new_s = 1; LED = ~LED;}




if (new_s) 
 { //如果出现了新的一秒, 修改时间
        new_s = 0;    sec++;  sec %= 60;
        if(!sec)     // 如果SEC为零,说明满了60秒,  进入下一步
{   min++;  min %= 60;  
          if(!min)   // 如果MIN为零,说明满了60分钟,进入下一步
 { hour++; hour %= 24;
 }   
        }
        W_BUFF();  //写显示
    if(modify)  LED = 0;
}
}










 void Time1(void ) interrupt 3   //T1定时器的中断等级要注意  是3
  {
    sound=!sound;      //将P3.7引脚输出电平取反,形成方波  
    TH1=(8192-C)/32;   //可证明这是13位计数器TH0高8位的赋初值方法
    TL1=(8192-C)%32;   //可证明这是13位计数器TL0低5位的赋初值方法 
  }


 

  • 9
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值