跪求AT89C51设计一个万年历系统,能够用按键修改各值,具有闹铃功能,能显示阴阳历,最好附有仿真图,谢谢

2024-12-20 09:35:52
推荐回答(1个)
回答1:

  程序太长了 只能发一部分 你给邮箱号给我 我发给你
  /*============================================================
  使用1602液晶显示DS1302+c51时钟 这个程序是我以前写的多功能闹钟,也可以用来做万年历
  =============================================================*/

  //#include
  #include
  #include
  #include < intrins.h >
  #define delayNOP() ; {_nop_() ;_nop_() ;_nop_() ;_nop_() ;} ;
  ////////////LCD1602定义引脚//////////////////
  sbit LCM_RW=P2^6;
  sbit LCM_RS=P2^5;
  sbit LCM_E=P2^7;
  #define LCM_Data P0
  #define Busy 0x80 //用于检测LCM状态字中的Busy标识
  sbit LED=P2^0; //背光灯输出
  ////////////////////////////////////////////////////////////////////

  #define uchar unsigned char
  sbit ACC0=ACC^0;
  sbit ACC7=ACC^7;

  /////DS1302引脚定义////////////////////////////
  sbit T_CLK=P1^0;
  sbit T_IO =P1^1;
  sbit T_RST=P1^2;
  //////////////////////////////////////////////////

  ////////按键定义/////////////////////////////
  sbit system=P3^2; //模式
  sbit TimerUp=P3^3; //时间加
  sbit TimerDown=P3^4; //时间减
  sbit Speaker=P3^2; //蜂鸣器
  /////////////////////////////////////////////////

  void Set(uchar,uchar); //根据选择调整相应项目
  void RTInputByte(uchar); //输入 1Byte */
  uchar RTOutputByte(void); //输出 1Byte */
  void W1302(uchar, uchar); //向DS1302写入一个字节
  uchar R1302(uchar); //从DS1302读出一个字节
  void Set1302(uchar * ); //设置时间
  void KeySound(); //按键音
  void ClockSound(); //闹铃蜂鸣声

  uchar id,msec,model,LedTime,d;
  bit a,b; //闪烁标志位

  uchar inittime[7]={0x00,0x10,0x19,0x29,0x03,0x04,0x06}; //初始化后设置为:06年3月//29日星期3 19点10分0秒
  void Out_LCM(void); //显示屏幕
  void model0(void); //显示输出
  void model1(void);
  void model2(void);
  void model3(void);
  void model4(void);
  void model5(void);
  void model6(void);

  void id_case1_key(); //项目调整
  void Modset(); //模式键处理

  void WriteDataLCM(uchar WDLCM); //LCD写数据函数
  void WriteCommandLCM(uchar WCLCM,BuysC);//LCD写命令函数
  uchar ReadStatusLCM(void);
  void LCMInit(void);//LCD初始化函数
  void OutputInformation(uchar X, uchar Y, uchar DData);
  void DisplayListChar(uchar X, uchar Y, uchar code *DData);

  void Delay5Ms(void);
  void Delay400Ms(void);
  void systemsetup(void); //进入系统设置

  uchar code systemp[]={"System.setup"}; //字符串输出(系统设定)
  uchar code TIMER[]={"Time"}; //字符串输出(时间)
  uchar code DATE[]={"Date"}; //字符串输出(日期)
  uchar code alarmclock[]={"alarm"}; //字符串输出(闹铃)
  uchar code lamp[]={"Lamp"}; //字符串输出(背光灯)
  uchar code reset[]={"Reset"}; //字符串输出(时间归零)
  uchar code exit[]={"Exit"}; //字符串输出(退出)
  uchar code set[]={"Set"}; //字符串输出(设置)
  uchar code sec[]={"sec"}; //字符串输出(秒)
  uchar code ClockSet[]={"ClockSet"}; //字符串输出(闹铃设置)
  uchar code ClockOn[]={"ON"}; //字符串输出(ON)
  uchar code ClockOff[]={"OFF"}; //字符串输出(OFF)

  void timesetup(void); //时间设置
  void datesetup(void); //日期设置
  void alarmclockset(void); //闹铃设置
  void lampsetup(void); //背光灯设置
  void timereset(void); //时间清零

  /*******************************************************************/
  void delay1(int ms)
  {
  unsigned char y ;
  while(ms--)
  {
  for(y = 0 ; y<250 ; y++)
  {
  _nop_() ;
  _nop_() ;
  _nop_() ;
  _nop_() ;
  }
  }
  }

  void main(void)
  {
  Speaker=1; //关闭蜂鸣器
  LED=0; //打开LED ,低电平有效,外接9012驱动
  Delay400Ms(); //启动等待,等LCM讲入工作状态
  Delay400Ms();
  LCMInit(); //LCM初始化
  TMOD=0x01; //16位定时
  TH0=0x3c; //50ms
  TL0=0xb0;
  EA=1;
  TR0=1;
  ET0=1;

  while(1)
  {
  if(TimerDown==0) //左移键按下后把背光灯打开
  {
  Delay5Ms();
  if(TimerDown==0)
  {
  KeySound(); //蜂鸣声
  LED=0; //打开背光灯
  LedTime=R1302(0xc1)/16*10+R1302(0xc1)%16;//取出背光灯时间并转换为十进制数
  }
  }
  b=1; //模式键是否动作标志。为1时不动作,为0时动作。
  Modset(); //调用模式键处理程序判断按键是否按下。
  if(b==0)
  {
  KeySound(); //蜂鸣声
  LED=0; //打开背光灯
  systemsetup(); //进入系统设置模式
  LedTime=R1302(0xc1)/16*10+R1302(0xc1)%16; //取出背光灯时间并转换为十进制数
  }
  if((LED==0)&&LedTime==0) //延时间是否到
  LED=1; //关闭背光灯
  if(R1302(0xc3)==1) //闹铃是否打开,0xc3为读闹铃寄存器地址。
  {if((R1302(0x85)==R1302(0xc5))&&(R1302(0x83)==R1302(0xc7))) //判断闹铃时间是否到,
  ClockSound(); //发出闹铃蜂鸣声,无按键动作蜂鸣一分钟。
  }
  model0(); //输出显示屏幕
  }
  }

  void KeySound() //按键音
  {
  Speaker=0; //开蜂鸣声
  Delay5Ms();
  Speaker=1; //关蜂鸣声
  }
  void ClockSound() //闹铃蜂鸣声
  {
  if(a==0)
  {
  Speaker=0; //开蜂鸣声
  Delay5Ms();
  Delay5Ms();
  Delay5Ms();
  Speaker=1; //关蜂鸣声
  }
  }

  void Modset() //模式键处理
  {
  if(system==0)
  {
  Delay5Ms();
  if(system==0)
  {
  while(system==0);
  KeySound(); //蜂鸣声
  a=0;msec=0;b=0; //a、msec为闪烁标志,按键有动作时清零,不闪烁。
  } //b为模式键确认动作。其它程判断b是否为零时来确定模式键是否动作。
  }
  }

  void systemsetup(void) //系统设置
  {
  model=1;
  while(model!=0)
  {
  Out_LCM();
  if (TimerUp==0) //设置项目左移
  {Delay5Ms();
  if(TimerUp==0)
  {
  a=0;msec=0;KeySound();//蜂鸣声
  if(model--==1) //6种系统设置项目
  model=6;
  }
  while(TimerUp==0);
  }
  if (TimerDown==0) //设置项目右移
  {
  Delay5Ms();
  if(TimerDown==0)
  {a=0;msec=0;KeySound();//蜂鸣声
  if(model++==6)
  model=1;
  }
  while(TimerDown==0);
  }
  b=1; //模式键是否动作标志。为1时不动作,为0时动作。
  Modset(); //调用模式键处理程序判断按键是否按下。
  if(b==0)
  {
  KeySound(); //蜂鸣声
  switch(model) //进入进个项目设置
  {
  case 1:
  timesetup(); break; //时间设置
  case 2:
  datesetup();break; //日期设置
  case 3:
  alarmclockset();break;//闹铃设置
  case 4:
  lampsetup();break; //背光灯设置
  case 5:
  timereset();break; //时间清零
  case 6:
  model=0;break; //退出系统设置
  }
  }
  }
  }

  void timesetup() //时间调整
  {
  id=6;
  while(model==1) //model为1时进入时间调整
  {
  b=1;
  Modset();
  if(b==0)
  {KeySound(); //蜂鸣声
  if(id++==9) //6..9为时分秒调。 .
  id=6;
  }
  id_case1_key(); //调用按键处理
  Out_LCM(); //显示输出
  }
  }
  void datesetup() //对日期进行调整
  {
  id=1;
  while(model==2) //model为2时进入日期调整
  {b=1;
  Modset(); //模式键是否动作
  if(b==0)
  {KeySound(); //蜂鸣声
  if(id++==5) //1..5为年月日星期 exit
  id=1;
  }
  id_case1_key(); //日期调整
  Out_LCM(); //显示输出
  }
  }
  void alarmclockset(void) //闹铃调整
  {id=12;
  while(model==3) //进入闹铃设置
  {b=1;
  Modset(); //模式键是否动作
  if(b==0)
  {KeySound(); //蜂鸣声
  if(R1302(0xc3)%16==0)
  {id=0;model++;} //0xc2为闹铃开关寄存器。当为关时按下模式键时将退出闹铃设置,当开时进入闹铃时间设置

  else if(id++==15) //12..15为闹铃开关和时间设置 exit
  id=12;
  }
  id_case1_key(); //调整
  Out_LCM(); //显示输出
  }
  }

  void lampsetup(void) //背光灯时间设置
  {id=10; //背光灯存储空间DS1302(0xc0)
  while(model==4) //model为3时进入背光灯调整
  {b=1;
  Modset(); //模式键是否动作
  if(b==0)
  {KeySound(); //蜂鸣声
  if(id++==11) //10为背光灯 exit
  id=10;
  }
  id_case1_key();
  Out_LCM(); //显示输出
  }

  }
  void timereset() //时间清零
  {
  Set1302(inittime); //清时间
  W1302(0x90,0xa5); //打开充电二级管 一个二级管串联一个2K电阻
  model++;
  }
  //对相应的项目进行加、减调整。
  void id_case1_key() //按键处理
  {
  if (TimerUp==0) //增加
  {
  Delay5Ms();
  if(TimerUp==0)
  {a=0;msec=0;KeySound(); //蜂鸣声
  if((id==9)||(id==5)||(id==11)||(id==15)) //当ID为9、5时按下加、减键将退出调整
  { model++; //退出时间、日期设置
  id=0;
  }
  else
  Set(id,1);
  }
  while(TimerUp==0);
  }
  if (TimerDown==0) //减少
  {
  Delay5Ms();
  if(TimerDown==0)
  {a=0;msec=0;KeySound(); //蜂鸣声
  if((id==9)||(id==5)||(id==11)||(id==15)) //当ID为9、5时按下加、减键将退出调整
  { model++; //退出时间、日期设置
  id=0;
  }
  else
  Set(id,0); //调用DS1302写入函数
  }
  while(TimerDown==0);
  }
  }

  void timer_1(void) interrupt 1 //中断入口,闪烁
  {
  TH0=0x3c; //50ms定时
  TL0=0xb0;
  if(msec++==10) //500ms
  {
  msec=0;
  a=~a; //闪烁标志反转
  if(a==0) //1秒后背光时间减一秒。
  LedTime--;
  }
  }

  //根据选择调整相应项目并写入DS1302
  void Set(uchar sel,uchar sel_1)
  {
  uchar address,item;
  uchar max,min;
  if(sel==1) {address=0x8c; max=99;min=0;} //年
  if(sel==2) {address=0x88; max=12;min=1;} //月
  if(sel==3) {address=0x86; max=31;min=1;} //日
  if(sel==4) {address=0x8a; max=7; min=1;} //星期
  if(sel==6) {address=0x84; max=23;min=0;} //小时
  if(sel==7) {address=0x82; max=59;min=0;} //分钟
  if(sel==8) {address=0x80; max=59;min=0;} //秒
  if(sel==10) {address=0xc0; max=59;min=0;} //背光时间,最长1分钟
  if(sel==12) {address=0xc2; max=1;min=0;} //闹铃开关寄存器
  if(sel==13) {address=0xc4; max=23;min=0;} //闹铃时寄存器
  if(sel==14) {address=0xc6; max=59;min=0;} //闹铃分寄存器

  item=R1302(address+1)/16*10+R1302(address+1)%16;
  if (sel_1==0) item++; else item--;
  if(item>max) item=min;
  if(item
  W1302(0x8e,0x00); //允许写操作
  W1302(address,item/10*16+item%10); //写入DS1302 //转成BCD码
  W1302(0x8e,0x80); //写保护,禁止写操作
  }

  //屏幕显示
  void Out_LCM(void)
  {
  switch(model)
  {
  case 0: model0(); break;
  case 1: model1(); break;
  case 2: model2(); break; //在不同的条件下显示不同的字符
  case 3: model3(); break;
  case 4: model4(); break;
  case 5: model5(); break;
  case 6: model6(); break;
  }
  }

  /***********************model为零时第一行显示时间,不为零时显示system setup******/
  void model0()
  {
  DisplayListChar(0,0,TIMER); //显示固定字符串(Time)
  OutputInformation(13,0,0x20); //不显示
  OutputInformation(4,0,0x20); //不显示
  OutputInformation(4,1,0x20); //不显示
  OutputInformation(15,1,0x20); //不显示
  OutputInformation(7,1,0x2f); //显示固定字符 "/"
  OutputInformation(10,1,0x2f); //显示固定字符 "/"
  OutputInformation(13,1,0x2f); //显示固定字符 "/"
  DisplayListChar(0,1,DATE); //显示固定字符串Date(日期)
  if(a==1) //冒号闪烁
  {OutputInformation(7,0,0x3a); OutputInformation(10,0,0x3a);}
  else
  {OutputInformation(7,0,0x20); OutputInformation(10,0,0x20);}

  /*******************model为零时第二行显示日期,不为零显示设置项目*******/

  OutputInformation(5,1,R1302(0x8d)/16+0x30); //显示年,十进制数字加上0x30便
  //是ASCII码对应的字符
  OutputInformation(6,1,R1302(0x8d)%16+0x30);

  OutputInformation(8,1,R1302(0x89)/16+0x30); //显示月
  OutputInformation(9,1,R1302(0x89)%16+0x30);

  OutputInformation(11,1,R1302(0x87)/16+0x30); //显示日
  OutputInformation(12,1,R1302(0x87)%16+0x30);

  OutputInformation(14,1,R1302(0x8b)%16+0x30); //显示星期

  OutputInformation(5,0,R1302(0x85)/16+0x30); //显示小时
  OutputInformation(6,0,R1302(0x85)%16+0x30);

  OutputInformation(8,0,R1302(0x83)/16+0x30); //显示分钟
  OutputInformation(9,0,R1302(0x83)%16+0x30);

  OutputInformation(11,0,R1302(0x81)/16+0x30); //显示秒
  OutputInformation(12,0,R1302(0x81)%16+0x30);
  }

  /*************************model不为零时显示系统设置***********************************/

  //model为1时time闪烁,按下模式键后进入时间调整
  void model1()
  /*************************************判断ID的值来显示项目***********************/
  { OutputInformation(0,0,0x20); //不显示
  OutputInformation(1,0,0x20);
  DisplayListChar(2,0,systemp); //第一行显示system setup
  if(id==0) //为0时显示TIME date lalcak
  {OutputInformation(9,1,0x20); //不显示
  OutputInformation(4,1,0x20); //不显示
  OutputInformation(15,1,0x20); //不显示
  DisplayListChar(5,1,DATE); //显示date
  DisplayListChar(10,1,alarmclock);//显示clock

  if(a==1)
  {OutputInformation(0,1,0x20); //不显示
  OutputInformation(1,1,0x20); //不显示
  OutputInformation(2,1,0x20); //不显示
  OutputInformation(3,1,0x20); //不显示
  }
  else
  DisplayListChar(0,1,TIMER); //显示time
  }
  else
  { //id不为零进入时间调整项目
  OutputInformation(3,1,0x3a); //显示固定字符 ":"
  OutputInformation(6,1,0x3a); //显示固定字符 ":"
  OutputInformation(9,1,0x20); //不显示
  OutputInformation(10,1,0x20); //不显示
  OutputInformation(0,1,0x20); //不显示
  /****************************时显示闪烁控制********************/
  if((id==6)&&(a==1)) //id为6时时闪烁
  {
  OutputInformation(1,1,0x20); //不显示
  OutputInformation(2,1,0x20); //不显示
  }
  else
  {OutputInformation(1,1,R1302(0x85)/16+0x30); //显示时
  OutputInformation(2,1,R1302(0x85)%16+0x30);
  }
  /******************************分显示闪烁控制********************/
  if((id==7)&&(a==1)) //id为7时分闪烁
  {
  OutputInformation(4,1,0x20); //不显示
  OutputInformation(5,1,0x20); //不显示
  }
  else
  {OutputInformation(4,1,R1302(0x83)/16+0x30); //显示分
  OutputInformation(5,1,R1302(0x83)%16+0x30);
  }
  /******************************秒显示闪烁控制********************/
  if((id==8)&&(a==1)) //id为8时秒闪烁
  {
  OutputInformation(7,1,0x20); //不显示
  OutputInformation(8,1,0x20); //不显示
  }
  else
  {OutputInformation(7,1,R1302(0x81)/16+0x30); //显示秒
  OutputInformation(8,1,R1302(0x81)%16+0x30);
  }
  /*******************************Exit显示闪烁控制********************/

  if((id==9)&&(a==1)) //id为9时exit闪烁
  {OutputInformation(11,1,0x20); //不显示
  OutputInformation(12,1,0x20); //不显示
  OutputInformation(13,1,0x20); //不显示
  OutputInformation(14,1,0x20); //不显示
  }
  else
  DisplayListChar(11,1,exit); //显示exit
  }
  }
  /***************************************modelo为2时date闪烁***********************************************/
  void model2()
  {
  if(id==0)
  {OutputInformation(9,1,0x20); //不显示
  OutputInformation(4,1,0x20); //不显示
  OutputInformation(15,1,0x20); //不显示
  DisplayListChar(0,1,TIMER); //显示time
  DisplayListChar(10,1,alarmclock); //显示clock
  if(a==1)
  {OutputInformation(5,1,0x20); //不显示
  OutputInformation(6,1,0x20); //不显示
  OutputInformation(7,1,0x20); //不显示
  OutputInformation(8,1,0x20); //不显示
  }

  else
  DisplayListChar(5,1,DATE); //显示date
  }
  /*****************************************************************************************************/
  //id不为零时、进入日期调整
  /*****************************************************************************************************/
  else
  { OutputInformation(0,1,0x20); //不显示
  OutputInformation(11,1,0x20); //不显示
  OutputInformation(3,1,0x2f); //显示固定字符 "/"
  OutputInformation(6,1,0x2f); //显示固定字符 "/"
  OutputInformation(9,1,0x2f); //显示固定字符 "/"
  /****************************年显示闪烁控制********************/
  if((id==1)&&(a==1)) //id为1时年闪烁
  {
  OutputInformation(1,1,0x20); //不显示
  OutputInformation(2,1,0x20); //不显示
  }
  else
  {OutputInformation(1,1,R1302(0x8d)/16+0x30); //显示年
  OutputInformation(2,1,R1302(0x8d)%16+0x30);
  }
  /***************************月闪烁控制************************/
  if((id==2)&&(a==1)) //id为2时月闪烁
  {
  OutputInformation(4,1,0x20); //不显示
  OutputInformation(5,1,0x20); //不显示
  }
  else
  {OutputInformation(4,1,R1302(0x89)/16+0x30); //显示月
  OutputInformation(5,1,R1302(0x89)%16+0x30);
  }
  /***************************日闪烁控制************************/
  if((id==3)&&(a==1)) //id为3日闪烁
  {
  OutputInformation(7,1,0x20); //不显示
  OutputInformation(8,1,0x20); //不显示
  }
  else
  {OutputInformation(7,1,R1302(0x87)/16+0x30); //显示日
  OutputInformation(8,1,R1302(0x87)%16+0x30);
  }
  /***************************星期闪烁控制*********************************/
  if((id==4)&&(a==1)) //id为4时星期闪烁
  {
  OutputInformation(10,1,0x20); //不显示
  }
  else
  {OutputInformation(10,1,R1302(0x8b)%16+0x30); //显示星期
  }
  /**************************exit闪烁控制*********************************/
  if((id==5)&&(a==1)) //id为5时exit闪烁
  { OutputInformation(12,1,0x20); //不显示
  OutputInformation(13,1,0x20); //不显示
  OutputInformation(14,1,0x20); //不显示
  OutputInformation(15,1,0x20); //不显示
  }
  else
  DisplayListChar(12,1,exit); //显示exit
  }
  }
  /*********************************************************************************/

  /*model为3时进入闹铃项目

  /**********************************************************************************/
  void model3()
  {
  if(id==0)
  {OutputInformation(9,1,0x20); //不显示
  OutputInformation(4,1,0x20); //不显示
  OutputInformation(15,1,0x20); //不显示
  DisplayListChar(0,1,TIMER); //显示time
  DisplayListChar(5,1,DATE); //显示date
  if(a==1)
  { OutputInformation(10,1,0x20); //不显示
  OutputInformation(11,1,0x20); //不显示
  OutputInformation(12,1,0x20); //不显示
  OutputInformation(13,1,0x20); //不显示
  OutputInformation(14,1,0x20);
  }
  else
  DisplayListChar(10,1,alarmclock); //显示cloak
  }

  /**************************id不为零进入闹铃设置显示********************/
  else
  {if(id==12) //闹铃开关显示
  {DisplayListChar(0,1,ClockSet); //显示ClockSet
  OutputInformation(8,1,0x20);
  OutputInformation(13,1,0x20);
  OutputInformation(14,1,0x20);