找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5199|回复: 0
收起左侧

基于51单片机液晶万年历设计(源码+AD原理图)

[复制链接]
ID:72940 发表于 2019-1-21 19:50 | 显示全部楼层 |阅读模式
       电子万年历是一种非常广泛日常计时工具,给人们的带来了很大的方便,在社会上越来越流行。 它可以对年、月、日、时、分、秒进行计时,采用直观的数字显示,可以同时显示年月日时分秒和温度等信息,还有时间校准、闹钟等功能。该电子万年历主要采用STC89C52单片机作为主控核心,用DS1302时钟芯片作为时钟、液晶12864显示屏显示。STC89C52单片机是由宏晶公司推出的,功耗小,电压可选用4~6V电压供电;DS1302时钟芯片是美国DALLAS公司推出的具有细电流充电功能的低功耗实时时钟芯片,它可以对年、月、日、星期、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小;数字显示是采用的12864液晶显示屏来显示,可以同时显示年、月、日、星期、时、分、秒和温度等信息。此外,该电子万年历还具有时间校准等功能
1.        系统总体功能
    本设计采用的是宏晶公司的STC89C52单片机为核心,通过单片机与时钟芯片DS1302通信来对时间的读写,保证时钟时间的稳定性,并带有内部电源模块,使系统断电时时钟数据不会丢失,以DS18B20温度感应芯片作为温度电路的核心,向单片机发出获取到的温度数据,并通过LCD1602将时间、显示出来,并可以通过按键调整时间日期和闹钟时间
2.        总体电路图
    20181219221654961.jpg
3.        程序设计
(1)        LCD1602驱动程序
  1. sbit rs                = P2^0;
  2. sbit rw                = P2^1;
  3. sbit e          = P2^2;
  4. #define lcddata P0
  5. sbit busy=P0^7;   //lcd busy bit
  6. void wr_d_lcd(uchar content);
  7. void wr_i_lcd(uchar content);
  8. void clrram_lcd (void);
  9. void init_lcd(void);
  10. void busy_lcd(void);
  11. void rev_row_lcd(uchar row);
  12. void rev_co_lcd(uchar row,uchar col,uchar mode);
  13. void clr_lcd(void);
  14. void wr_co_lcd(uchar row,uchar col,uchar lcddata1,uchar lcddtta2);
  15. void wr_row_lcd(uchar row,char *p);
  16. //**********************************
  17. //液晶初始化
  18. //**********************************
  19. void init_lcd(void)
  20. {
  21.         wr_i_lcd(0x06);  /*光标的移动方向*/
  22.         wr_i_lcd(0x0c);  /*开显示,关游标*/
  23. }
  24. //***********************************
  25. //填充液晶DDRAM全为空格
  26. //**********************************
  27. void clrram_lcd (void)
  28. {
  29.         wr_i_lcd(0x30);
  30.         wr_i_lcd(0x01);
  31. }
  32. //***********************************
  33. //对液晶写数据
  34. //content为要写入的数据
  35. //***********************************
  36. void wr_d_lcd(uchar content)
  37. {
  38.         busy_lcd();
  39.         rs=1;
  40.     rw=0;
  41.         lcddata=content;
  42.         e=1;
  43.         ;
  44.         e=0;
  45. }
  46. //********************************
  47. //对液晶写指令
  48. //content为要写入的指令代码
  49. //*****************************
  50. void wr_i_lcd(uchar content)
  51. {
  52.         busy_lcd();
  53.         rs=0;
  54.     rw=0;
  55.         lcddata=content;
  56.         e=1;
  57.         ;
  58.         e=0;
  59. }
  60. //********************************
  61. //液晶检测忙状态
  62. //在写入之前必须执行
  63. //********************************
  64. void busy_lcd(void)
  65. {
  66.   lcddata=0xff;
  67.   rs=0;
  68.   rw=1;
  69.   e =1;
  70.   while(busy==1);
  71.   e =0;
  72. }
  73. //********************************
  74. //指定要显示字符的坐标
  75. //*******************************
  76. void gotoxy(unsigned char y, unsigned char x)
  77. {
  78.         if(y==1)
  79.                 wr_i_lcd(0x80|x);
  80.         if(y==2)
  81.         wr_i_lcd(0x90|x);
  82.         if(y==3)
  83.                 wr_i_lcd((0x80|x)+8);
  84.         if(y==4)
  85.         wr_i_lcd((0x90|x)+8);
  86. }
  87. //**********************************
  88. //液晶显示字符串程序
  89. //**********************************
  90. void print(uchar *str)
  91. {
  92.         while(*str!='\0')
  93.         {
  94.                 wr_d_lcd(*str);
  95.                 str++;
  96.         }
  97. }

  98. //***************************************
  99. //液晶显示主程序模块
  100. //***************************************
  101. void show_time()   
  102. {
  103.   DS1302_GetTime(&CurrentTime);  //获取时钟芯片的时间数据
  104.   TimeToStr(&CurrentTime);       //时间数据转换液晶字符
  105.   DateToStr(&CurrentTime);       //日期数据转换液晶字符
  106.   ReadTemp();                    //开启温度采集程序
  107.   temp_to_str();                 //温度数据转换成液晶字符
  108.   gotoxy(4,0);
  109.   print("温度");
  110.   gotoxy(4,2);                  //液晶字符显示位置
  111.   print(TempBuffer);             //显示温度
  112.   gotoxy(4,6);
  113.   print("℃");
  114.   gotoxy(3,0);
  115.   print("时间:");
  116.   gotoxy(3,3);
  117.   print(CurrentTime.TimeString); //显示时间
  118.   gotoxy(2,3);
  119.   print(CurrentTime.DateString); //显示日期
  120.   gotoxy(2,0);
  121.   print("星期");
  122.   gotoxy(2,2);
  123.   print(week_value);             //显示星期
  124.   gotoxy(1,1);
  125.   print("【万年历】");
  126.   mdelay(500);                 //扫描延时
  127. }
复制代码
(2)        DS1302驱动程序

  1. //***********************************
  2. //DS1302时钟部分子程序模块
  3. //***********************************
  4. typedef struct __SYSTEMTIME__
  5. {
  6.         uchar Second;
  7.         uchar Minute;
  8.         uchar Hour;
  9.         uchar Week;
  10.         uchar Day;
  11.         uchar Month;
  12.         uchar  Year;
  13.         uchar DateString[11];
  14.         uchar TimeString[9];
  15. }SYSTEMTIME;        //定义的时间类型
  16. SYSTEMTIME CurrentTime;


  17. #define AM(X)        X
  18. #define PM(X)        (X+12)                      // 转成24小时制
  19. #define DS1302_SECOND        0x80          //时钟芯片的寄存器位置,存放时间
  20. #define DS1302_MINUTE        0x82
  21. #define DS1302_HOUR                0x84
  22. #define DS1302_WEEK                0x8A
  23. #define DS1302_DAY                0x86
  24. #define DS1302_MONTH        0x88
  25. #define DS1302_YEAR                0x8C
  26. //**********************************
  27. //实时时钟写入一字节(内部函数)
  28. //**********************************
  29. void DS1302InputByte(uchar d)         
  30. {
  31.     uchar i;
  32.     ACC = d;
  33.     for(i=8; i>0; i--)
  34.     {
  35.         DS1302_IO = ACC0;                   //相当于汇编中的 RRC
  36.         DS1302_CLK = 1;
  37.         DS1302_CLK = 0;
  38.         ACC = ACC >> 1;
  39.     }
  40. }
  41. //*************************************
  42. //实时时钟读取一字节(内部函数)
  43. //*************************************
  44. uchar DS1302OutputByte(void)         
  45. {
  46.     uchar i;
  47.     for(i=8; i>0; i--)
  48.     {
  49.         ACC = ACC >>1;                                 //相当于汇编中的 RRC
  50.         ACC7 = DS1302_IO;
  51.         DS1302_CLK = 1;
  52.         DS1302_CLK = 0;
  53.     }
  54.     return(ACC);
  55. }
  56. //**************************************
  57. //ucAddr: DS1302地址, ucData: 要写的数据
  58. //**************************************
  59. void Write1302(uchar ucAddr, uchar ucDa)        
  60. {
  61.     DS1302_RST = 0;
  62.     DS1302_CLK = 0;
  63.     DS1302_RST = 1;
  64.     DS1302InputByte(ucAddr);               // 地址,命令
  65.     DS1302InputByte(ucDa);               // 写1Byte数据
  66.     DS1302_CLK = 1;
  67.     DS1302_RST = 0;
  68. }
  69. //**************************************
  70. //读取DS1302某地址的数据
  71. //**************************************
  72. uchar Read1302(uchar ucAddr)        
  73. {
  74.     uchar ucData;
  75.     DS1302_RST = 0;
  76.     DS1302_CLK = 0;
  77.     DS1302_RST = 1;
  78.     DS1302InputByte(ucAddr|0x01);        // 地址,命令
  79.     ucData = DS1302OutputByte();         // 读1Byte数据
  80.     DS1302_CLK = 1;
  81.     DS1302_RST = 0;
  82.     return(ucData);
  83. }

  84. //******************************************
  85. //获取时钟芯片的时钟数据到自定义的结构型数组
  86. //******************************************
  87. void DS1302_GetTime(SYSTEMTIME *Time)  
  88. {
  89.         uchar ReadValue;
  90.         ReadValue = Read1302(DS1302_SECOND);
  91.         Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//转换为相应的10进制数
  92.         ReadValue = Read1302(DS1302_MINUTE);
  93.         Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
  94.         ReadValue = Read1302(DS1302_HOUR);
  95.         Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
  96.         ReadValue = Read1302(DS1302_DAY);
  97.         Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);        
  98.         ReadValue = Read1302(DS1302_WEEK);
  99.         Time->Week = ((ReadValue&0x10)>>4)*10 + (ReadValue&0x0F);
  100.         ReadValue = Read1302(DS1302_MONTH);
  101.         Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
  102.         ReadValue = Read1302(DS1302_YEAR);
  103.         Time->Year = ((ReadValue&0xf0)>>4)*10 + (ReadValue&0x0F);        
  104. }
  105. //******************************************
  106. //将时间年,月,日,星期数据转换成液
  107. //晶显示字符串,放到数组里DateString[]
  108. //******************************************
  109. void DateToStr(SYSTEMTIME *Time)   
  110. {   
  111.    uchar tab[ ]={0XD2,0XBB,0XB6,0XFE,0XC8,0XFD,0XCB,0XC4,0XCE,0XE5,0XC1,0XF9,0XC8,0XD5};
  112.    if(hide_year<2)          //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22
  113.     {                              
  114.           Time->DateString[0] = '2';
  115.           Time->DateString[1] = '0';         
  116.           Time->DateString[2] = Time->Year/10 + '0';
  117.           Time->DateString[3] = Time->Year%10 + '0';
  118.         }
  119.           else
  120.             {
  121.               Time->DateString[0] = ' ';
  122.               Time->DateString[1] = ' ';                 
  123.               Time->DateString[2] = ' ';
  124.               Time->DateString[3] = ' ';
  125.                 }
  126.     Time->DateString[4]='-';
  127.         if(hide_month<2)
  128.         {
  129.           Time->DateString[5] = Time->Month/10 + '0';
  130.           Time->DateString[6] = Time->Month%10 + '0';
  131.         }
  132.           else
  133.           {
  134.             Time->DateString[5] = ' ';
  135.             Time->DateString[6] = ' ';
  136.           }
  137.     Time->DateString[7]='-';
  138.         if(hide_day<2)
  139.         {
  140.           Time->DateString[8] = Time->Day/10 + '0';
  141.           Time->DateString[9] = Time->Day%10 + '0';
  142.         }
  143.           else
  144.           {
  145.             Time->DateString[8] = ' ';
  146.             Time->DateString[9] = ' ';            
  147.           }
  148.         if(hide_week<2)
  149.         {
  150.           week_value[0] =tab[2*(Time->Week%10)-2];  //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示
  151.           week_value[1] =tab[2*(Time->Week%10)-1];
  152.         }
  153.           else
  154.           {
  155.             week_value[0] = ' ';
  156.                 week_value[1]=' ';
  157.           }
  158.           week_value[2] = '\0';

  159.         Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判断结束字符
  160. }
  161. //******************************************
  162. //将时,分,秒数据转换成液晶
  163. //显示字符放到数组 TimeString[]
  164. //*****************************************
  165. void TimeToStr(SYSTEMTIME *Time)
  166. {   if(hide_hour<2)
  167.     {
  168.           Time->TimeString[0] = Time->Hour/10 + '0';
  169.           Time->TimeString[1] = Time->Hour%10 + '0';
  170.         }
  171.           else
  172.             {
  173.               Time->TimeString[0] = ' ';
  174.               Time->TimeString[1] = ' ';
  175.                 }
  176.         Time->TimeString[2] = ':';
  177.     if(hide_min<2)
  178.         {
  179.           Time->TimeString[3] = Time->Minute/10 + '0';
  180.           Time->TimeString[4] = Time->Minute%10 + '0';
  181.         }
  182.           else
  183.             {
  184.               Time->TimeString[3] = ' ';
  185.               Time->TimeString[4] = ' ';
  186.                }
  187.         Time->TimeString[5] = ':';
  188.     if(hide_sec<2)
  189.     {
  190.           Time->TimeString[6] = Time->Second/10 + '0';
  191.           Time->TimeString[7] = Time->Second%10 + '0';
  192.     }
  193.       else
  194.        {
  195.          Time->TimeString[6] = ' ';
  196.              Time->TimeString[7] = ' ';
  197.        }
  198.         Time->TimeString[8] = '\0';
  199. }

  200. //******************************
  201. //时钟芯片初始化
  202. //******************************
  203. void Initial_DS1302(void)   
  204. {   
  205.         uchar Second=Read1302(DS1302_SECOND);
  206.         if(Second&0x80)              //判断时钟芯片是否关闭         
  207.     {
  208.         Write1302(0x8e,0x00); //写入允许
  209.         Write1302(0x8c,0x07); //以下写入初始化时间 日期:07/07/25.星期: 3. 时间: 23:59:55
  210.         Write1302(0x88,0x07);
  211.         Write1302(0x86,0x25);
  212.         Write1302(0x8a,0x07);
  213.         Write1302(0x84,0x23);
  214.         Write1302(0x82,0x59);
  215.         Write1302(0x80,0x55);
  216.         Write1302(0x8e,0x80); //禁止写入
  217.         }

  218. }
复制代码
(3)DS18B20驱动程序

  1. /***********ds18b20子程序*************************/

  2. /***********ds18b20延迟子函数(晶振12MHz )*******/

  3. void delay_18B20(unsigned int i)
  4. {
  5.         while(i--);
  6. }

  7. /**********ds18b20初始化函数**********************/

  8. void Init_DS18B20(void)
  9. {
  10.          unsigned char x=0;
  11.          DQ = 1;          //DQ复位
  12.          delay_18B20(8);  //稍做延时
  13.          DQ = 0;          //单片机将DQ拉低
  14.          delay_18B20(40); //精确延时 大于 480us
  15.          DQ = 1;          //拉高总线
  16.          delay_18B20(7);
  17.          x=DQ;            //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
  18.          delay_18B20(10);
  19. }

  20. /***********ds18b20读一个字节**************/  

  21. uchar ReadOneChar(void)
  22. {
  23.         uchar i=0;
  24.         uchar dat = 0;
  25.         for (i=8;i>0;i--)
  26.          {
  27.                   DQ = 0; // 给脉冲信号
  28.                   dat>>=1;
  29.                   DQ = 1; // 给脉冲信号
  30.                   if(DQ)
  31.                   dat|=0x80;
  32.                   delay_18B20(4);
  33.          }
  34.          return(dat);
  35. }

  36. /*************ds18b20写一个字节****************/  

  37. void WriteOneChar(uchar dat)
  38. {
  39.          uchar i=0;
  40.          for (i=8; i>0; i--)
  41.          {
  42.                   DQ = 0;
  43.                  DQ = dat&0x01;
  44.             delay_18B20(5);
  45.                  DQ = 1;
  46.             dat>>=1;
  47. }
  48. }

  49. /**************读取ds18b20当前温度************/

  50. void ReadTemp(void)
  51. {
  52.         uchar a=0;
  53.         uchar b=0;
  54.         uchar t;

  55.         Init_DS18B20();
  56.         WriteOneChar(0xCC);            // 跳过读序号列号的操作
  57.         WriteOneChar(0x44);         // 启动温度转换

  58.         delay_18B20(100);       // this message is wery important

  59.         Init_DS18B20();
  60.         WriteOneChar(0xCC);         //跳过读序号列号的操作
  61.         WriteOneChar(0xBE);         //读取温度寄存器等(共可读9个寄存器) 前两个就是温度

  62.         delay_18B20(50);

  63.         a=ReadOneChar();            //读取温度值低位
  64.         b=ReadOneChar();                   //读取温度值高位
  65.         t=b&0xf8;
  66.         if(t)
  67.         {
  68.           TempBuffer[0]=':';
  69.           TempBuffer[1]='-';
  70.             temp_value=b<<4;
  71.           temp_value+=(a&0xf0)>>4;  
  72.           temp_value=~temp_value+1;
  73.           temp1_value=~a&0x0f;
  74.         }
  75.         else
  76.         {  
  77.         temp_value=b<<4;
  78.         temp_value+=(a&0xf0)>>4;
  79.                  temp1_value=a&0x0f;
  80.             TempBuffer[0]=':';
  81.             TempBuffer[1]=temp_value/100+'0';  //百位
  82.        if(TempBuffer[1]=='1')
  83.        {
  84.             TempBuffer[1]='1';
  85.        }
  86.        else
  87.        {
  88.            TempBuffer[1]=' ';
  89.        }
  90.     }
  91. }
  92. void temp_to_str()   //温度数据转换成液晶字符显示
  93. {               

  94.   TempBuffer[2]=temp_value%100/10+'0';  //十位
  95.   TempBuffer[3]=temp_value%10+'0';  //个位
  96.   TempBuffer[4]='.';
  97.   TempBuffer[5]=temp1_value*625/1000%10+'0';
  98.   TempBuffer[6]=temp1_value*625/100%10+'0';
  99.   TempBuffer[7]=temp1_value*625/10%10+'0';
  100.   //TempBuffer[8]=temp1_value*625%10+'0';
  101.   TempBuffer[8]='\0';
  102. }
  103. //**********************************************
  104. //延时子程序模块
  105. //**********************************************
  106. void mdelay(uint delay)
  107. {        uint i;
  108.          for(;delay>0;delay--)
  109.                    {for(i=0;i<80;i++) //1ms延时.
  110.                        {;}
  111.                    }
  112. }
复制代码
(4)        按键驱动程序

  1. //************************************
  2. //跳出调整模式,返回默认显示
  3. //************************************
  4. void outkey()                    
  5. { uchar Second;
  6.   if(out==0)         
  7.   { mdelay(5);
  8.         count=0;
  9.         hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0;
  10.         Second=Read1302(DS1302_SECOND);
  11.     Write1302(0x8e,0x00); //写入允许
  12.         Write1302(0x80,Second&0x7f);
  13.         Write1302(0x8E,0x80);          //禁止写入
  14.         done=0;           
  15.   }
  16. }
  17. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  18. //*************************
  19. //升序按键
  20. //*************************
  21. void Upkey()
  22. {           
  23.                 Up=1;
  24.                     if(Up==0)
  25.                           {
  26.                                    mdelay(5);
  27.                                        switch(count)
  28.                                           {case 1:
  29.                                   temp=Read1302(DS1302_SECOND);  //读取秒数
  30.                                                                   temp=((temp&0x70)>>4)*10 + (temp&0x0F);
  31.                                                                   temp=temp+1;  //秒数加1
  32.                                   up_flag=1;    //数据调整后更新标志
  33.                                                                   if((temp)>59)   //超过59秒,清零
  34.                                   temp=0;        
  35.                                                                     temp=temp/10*16+temp%10;
  36.                                                                   break;
  37.                                            case 2:
  38.                                   temp=Read1302(DS1302_MINUTE);  //读取分数
  39.                                                                   temp=((temp&0x70)>>4)*10 + (temp&0x0F);
  40.                                                                   temp=temp+1;  //分数加1
  41.                                   up_flag=1;
  42.                                                                   if(temp>59)          //超过59分,清零
  43.                                                                   temp=0;
  44.                                                                   temp=temp/10*16+temp%10;
  45.                                                                   break;
  46.                                            case 3:
  47.                                   temp=Read1302(DS1302_HOUR);  //读取小时数
  48.                                                                   temp=((temp&0x70)>>4)*10 + (temp&0x0F);
  49.                                                                   temp=temp+1;  //小时数加1
  50.                                   up_flag=1;
  51.                                                                   if(temp>23)   //超过23小时,清零
  52.                                                                   temp=0;
  53.                                                                   temp=temp/10*16+temp%10;
  54.                                                                   break;
  55.                                            case 4:
  56.                                   temp=Read1302(DS1302_WEEK);  //读取星期数
  57.                                                                   temp=((temp&0x70)>>4)*10 + (temp&0x0F);
  58.                                                                   temp=temp+1;  //星期数加1
  59.                                   up_flag=1;
  60.                                                                   if(temp>7)  
  61.                                                                   temp=1;
  62.                                                                   temp=temp/10*16+temp%10;
  63.                                                                   break;
  64.                                            case 5:
  65.                                   temp=Read1302(DS1302_DAY);  //读取日数
  66.                                                                   temp=((temp&0x70)>>4)*10 + (temp&0x0F);
  67.                                                                   temp=temp+1;  //日数加1
  68.                                   up_flag=1;
  69.                                                                   if(temp>31)
  70.                                                                   temp=1;
  71.                                                                   temp=temp/10*16+temp%10;
  72.                                                                   break;
  73.                                            case 6:
  74.                                   temp=Read1302(DS1302_MONTH);  //读取月数
  75.                                                                   temp=((temp&0x70)>>4)*10 + (temp&0x0F);
  76.                                                                   temp=temp+1;  //月数加1
  77.                                   up_flag=1;
  78.                                                                   if(temp>12)
  79.                                                                   temp=1;
  80.                                                                   temp=temp/10*16+temp%10;
  81.                                                                   break;
  82.                                            case 7:
  83.                                   temp=Read1302(DS1302_YEAR);  //读取年数
  84.                                                                   temp=((temp&0xf0)>>4)*10 + (temp&0x0F);
  85.                                                                   temp=temp+1;  //年数加1
  86.                                   up_flag=1;
  87.                                                                   if(temp>99)
  88.                                                                   temp=0;
  89.                                                                   temp=temp/10*16+temp%10;
  90.                                                                   break;
  91.                                                default:break;
  92.                                           }
  93.                                           
  94.                                  //  while(Up==0);
  95.                                   }
  96. }

  97. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  98. //************************
  99. //降序按键
  100. //************************
  101. void Downkey()
  102. {            
  103.                 Down=1;
  104.             if(Down==0)
  105.                           {
  106.                                    mdelay(5);
  107.                                      switch(count)
  108.                                           {case 1:
  109.                                   temp=Read1302(DS1302_SECOND);  //读取秒数
  110.                                                                   temp=((temp&0x70)>>4)*10 + (temp&0x0F);
  111.                                                                   temp=temp-1;                                                    //秒数减1
  112.                                   down_flag=1;       //数据调整后更新标志
  113.                                                                   if(temp==-1)     //小于0秒,返回59秒
  114.                                                                   temp=59;
  115.                                                                   temp=temp/10*16+temp%10;
  116.                                                                   break;
  117.                                            case 2:
  118.                                   temp=Read1302(DS1302_MINUTE);  //读取分数
  119.                                                                   temp=((temp&0x70)>>4)*10 + (temp&0x0F);
  120.                                                                   temp=temp-1;  //分数减1
  121.                                   down_flag=1;
  122.                                                                   if(temp==-1)
  123.                                                                   temp=59;      //小于0秒,返回59秒
  124.                                                                   temp=temp/10*16+temp%10;
  125.                                                                   break;
  126.                                            case 3:
  127.                                   temp=Read1302(DS1302_HOUR);  //读取小时数
  128.                                                                   temp=((temp&0x70)>>4)*10 + (temp&0x0F);
  129.                                                                   temp=temp-1;  //小时数减1
  130.                                   down_flag=1;
  131.                                                                   if(temp==-1)
  132.                                                                   temp=23;
  133.                                                                   temp=temp/10*16+temp%10;
  134.                                                                   break;
  135.                                            case 4:
  136.                                   temp=Read1302(DS1302_WEEK);  //读取星期数;
  137.                                                                   temp=((temp&0x70)>>4)*10 + (temp&0x0F);
  138.                                                                   temp=temp-1;  //星期数减1
  139.                                   down_flag=1;
  140.                                                                   if(temp==0)
  141.                                                                   temp=7;
  142.                                                                   temp=temp/10*16+temp%10;
  143.                                                                   break;
  144.                                            case 5:
  145.                                   temp=Read1302(DS1302_DAY);  //读取日数
  146.                                                                   temp=((temp&0x70)>>4)*10 + (temp&0x0F);
  147.                                                                   temp=temp-1;  //日数减1
  148.                                   down_flag=1;
  149.                                                                   if(temp==0)
  150.                                                                   temp=31;
  151.                                                                   temp=temp/10*16+temp%10;
  152.                                                                   break;
  153.                                            case 6:
  154.                                   temp=Read1302(DS1302_MONTH);  //读取月数
  155.                                                                   temp=((temp&0x70)>>4)*10 + (temp&0x0F);
  156.                                                                   temp=temp-1;  //月数减1
  157.                                   down_flag=1;
  158.                                                                   if(temp==0)
  159.                                                                   temp=12;
  160.                                                                   temp=temp/10*16+temp%10;
  161.                                                                   break;
  162.                                            case 7:
  163.                                   temp=Read1302(DS1302_YEAR);  //读取年数
  164.                                                                   temp=((temp&0xf0)>>4)*10 + (temp&0x0F);
  165.                                                                   temp=temp-1;  //年数减1
  166.                                   down_flag=1;
  167.                                                                   if(temp==-1)
  168.                                                                   temp=99;
  169.                                                                   temp=temp/10*16+temp%10;
  170.                                                                   break;
  171.                                               default:break;
  172.                                          }
  173.                                          
  174.                                  //  while(Down==0);
  175.                                   }
  176. }

  177. //**************************
  178. //模式选择按键
  179. //**************************
  180. void Setkey()
  181. {
  182.                 Set=1;
  183.                 if(Set==0)
  184.             {
  185.            mdelay(5);
  186.            count=count+1;         //Setkey按一次,count就加1
  187.                    done=1;                         //进入调整模式
  188.            while(Set==0);
  189.                  }

  190. }

  191. //*************************
  192. //按键功能执行
  193. //*************************
  194. void keydone()
  195. {        
  196.                 uchar Second;
  197.                 /* if(flag==0)    //关闭时钟,停止计时
  198.          { Write1302(0x8e,0x00); //写入允许
  199.            temp=Read1302(0x80);
  200.            Write1302(0x80,temp|0x80);
  201.                Write1302(0x8e,0x80); //禁止写入
  202.            flag=1;
  203.          }*/
  204.          Setkey();                                            //扫描模式切换按键
  205.                  switch(count)
  206.                  {
  207.                          case 1:do                                                //count=1,调整秒
  208.                        {
  209.                    outkey();                           //扫描跳出按钮
  210.                                    Upkey();                //扫描加按钮
  211.                                    Downkey();              //扫描减按钮
  212.                                    if(up_flag==1||down_flag==1)  //数据更新,重新写入新的数据
  213.                                    {
  214.                                      Write1302(0x8e,0x00); //写入允许
  215.                                      Write1302(0x80,temp); //写入新的秒数
  216.                                      Write1302(0x8e,0x80); //禁止写入
  217.                                      up_flag=0;
  218.                                      down_flag=0;
  219.                                   }
  220.                      if(Down!=0&&Up!=0)
  221.                      {
  222.                                                 hide_sec++;
  223.                                         if(hide_sec>3)
  224.                                         hide_sec=0;
  225.                      }
  226.                                          else hide_sec=0;
  227.                                          show_time();         //液晶显示数据
  228.                                   }while(count==2);break;  
  229.                   case 2:do                                                //count=2,调整分
  230.                           {
  231.                                    hide_sec=0;
  232.                                    outkey();
  233.                                    Upkey();
  234.                                    Downkey();
  235.                                    if(temp>0x60)
  236.                                      temp=0;
  237.                                    if(up_flag==1||down_flag==1)
  238.                                    {
  239.                                      Write1302(0x8e,0x00); //写入允许
  240.                                      Write1302(0x82,temp); //写入新的分数
  241.                                      Write1302(0x8e,0x80); //禁止写入
  242.                                      up_flag=0;
  243.                                      down_flag=0;
  244.                                   }
  245.                      if(Down!=0&&Up!=0)
  246.                      {
  247.                                                 hide_min++;
  248.                                         if(hide_min>3)
  249.                                         hide_min=0;
  250.                      }
  251.                                          else hide_min=0;
  252.                                          show_time();
  253.                                   }while(count==3);break;
  254.                   case 3:do                                                //count=3,调整小时
  255.                           {
  256.                    hide_min=0;
  257.                                    outkey();
  258.                                    Upkey();
  259.                                    Downkey();
  260.                                    if(up_flag==1||down_flag==1)
  261.                                    {
  262.                                       Write1302(0x8e,0x00); //写入允许
  263.                                       Write1302(0x84,temp); //写入新的小时数
  264.                                       Write1302(0x8e,0x80); //禁止写入
  265.                                       up_flag=0;
  266.                                       down_flag=0;
  267.                                    }
  268.                       if(Down!=0&&Up!=0)
  269.                      {
  270.                                                 hide_hour++;
  271.                                         if(hide_hour>3)
  272.                                         hide_hour=0;
  273.                      }
  274.                                          else  hide_hour=0;
  275.                                           show_time();
  276.                                   }while(count==4);break;
  277.                   case 4:do                                                //count=4,调整星期
  278.                           {
  279.                    hide_hour=0;
  280.                                    outkey();
  281.                                    Upkey();
  282.                                    Downkey();
  283.                                    if(up_flag==1||down_flag==1)
  284.                                    {
  285.                                      Write1302(0x8e,0x00); //写入允许
  286.                                      Write1302(0x8a,temp); //写入新的星期数
  287.                                      Write1302(0x8e,0x80); //禁止写入
  288.                                      up_flag=0;
  289.                                      down_flag=0;
  290.                                    }
  291.                      if(Down!=0&&Up!=0)
  292.                      {
  293.                                            hide_week++;
  294.                                        if(hide_week>3)
  295.                                        hide_week=0;
  296.                      }
  297.                                          else hide_week=0;
  298.                                          show_time();
  299.                                   }while(count==5);break;
  300.                   case 5:do                                                //count=5,调整日
  301.                           {
  302.                                    hide_week=0;
  303.                                    outkey();
  304.                                    Upkey();
  305.                                    Downkey();
  306.                                    if(up_flag==1||down_flag==1)
  307.                                    {
  308.                                      Write1302(0x8e,0x00); //写入允许
  309.                                      Write1302(0x86,temp); //写入新的日数
  310.                                      Write1302(0x8e,0x80); //禁止写入
  311.                                      up_flag=0;
  312.                                      down_flag=0;
  313.                                    }
  314.                      if(Down!=0&&Up!=0)
  315.                                      {
  316.                                                 hide_day++;
  317.                                         if(hide_day>3)
  318.                                         hide_day=0;
  319.                                          }
  320.                                     else hide_day=0;
  321.                      show_time();
  322.                                   }while(count==6);break;
  323.                   case 6:do                                                //count=6,调整月
  324.                           {
  325.                    hide_day=0;
  326.                                    outkey();
  327.                                    Upkey();
  328.                                    Downkey();
  329.                                    if(up_flag==1||down_flag==1)
  330.                                    {
  331.                                       Write1302(0x8e,0x00); //写入允许
  332.                                       Write1302(0x88,temp); //写入新的月数
  333.                                       Write1302(0x8e,0x80); //禁止写入
  334.                                       up_flag=0;
  335.                                       down_flag=0;
  336.                                    }
  337.                      if(Down!=0&&Up!=0)
  338.                                      {
  339.                                                  hide_month++;
  340.                                          if(hide_month>3)
  341.                                          hide_month=0;
  342.                                          }
  343.                                         else hide_month=0;
  344.                      show_time();
  345.                                   }while(count==7);break;
  346.                   case 7:do                                                //count=7,调整年
  347.                           {
  348.                    hide_month=0;
  349.                                    outkey();
  350.                                    Upkey();
  351.                                    Downkey();
  352.                                    if(up_flag==1||down_flag==1)
  353.                                    {
  354.                                       Write1302(0x8e,0x00); //写入允许
  355.                                       Write1302(0x8c,temp); //写入新的年数
  356.                                       Write1302(0x8e,0x80); //禁止写入
  357.                                       up_flag=0;
  358.                                       down_flag=0;
  359.                                   }
  360.                       if(Down!=0&&Up!=0)
  361.                                       {
  362.                                                   hide_year++;
  363.                                          if(hide_year>3)
  364.                                          hide_year=0;
  365.                       }
  366.                                           else hide_year=0;
  367.                       show_time();
  368.                                   }while(count==8);break;
  369.                   case 8: count=0;hide_year=0;  //count8, 跳出调整模式,返回默认显示状态
  370.                       Second=Read1302(DS1302_SECOND);
  371.                   Write1302(0x8e,0x00); //写入允许
  372.                       Write1302(0x80,Second&0x7f);
  373.                       Write1302(0x8E,0x80);          //禁止写入
  374.                                   done=0;
  375.                   break; //count=7,开启中断,标志位置0并退出
  376.                   default:break;

  377.                  }

  378. }
复制代码
(5)        主程序

  1. main()
  2. {
  3.   //  flag=1;           //时钟停止标志
  4.         init_lcd();
  5.         clrram_lcd();
  6.         Init_DS18B20( ) ;      //DS18B20初始化
  7.         Initial_DS1302(); //时钟芯片初始化
  8.         up_flag=0;
  9.         down_flag=0;
  10.         done=0;           //进入默认液晶显示
  11.         while(1)
  12.         {   
  13.         while(done==1)
  14.           keydone();    //进入调整模式
  15.                 while(done==0)
  16.              {  
  17.             show_time();                //液晶显示数据
  18.            // flag=0;                  
  19.                       Setkey();                                 //扫描各功能键
  20.                  }               
  21.         }
  22. }
复制代码

20181219221654961.jpg

51单片机的万年历.rar

275.49 KB, 下载次数: 40, 下载积分: 黑币 -5

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表