找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8696|回复: 13
打印 上一主题 下一主题
收起左侧

12864万年历(单片机毕业设计可参考)

  [复制链接]
跳转到指定楼层
楼主
它可以对年、月、日、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小。对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、时、分、秒和温度等信息,还具有时间校准等功能。该电路采用AT89C51单片机作为核心,DS1302时钟芯片作为时钟数据的时间,用DS18b20Z作为温度传感器,降低单片机芯片内部资源的消耗,功耗小,工作电压5V。阿阳工作室
一、 设计要求:
1、系统要控制准确无误;
2、可以调整万年历时间;
3、可以设置闹钟
4、用12864显示时间,温度;
5、分析电路的工作原理和工作过程。
QQ1137035271

实物图:


单片机源程序如下:
  1. #include <reg52.h>                 //调用单片机头文件
  2. #define uchar unsigned char  //无符号字符型 宏定义        变量范围0~255
  3. #define uint  unsigned int         //无符号整型 宏定义        变量范围0~65535
  4. #include "nongli.h"

  5. uchar code shuzi[]="0123456789ABCDEF";
  6. char  code shuzi_c[]="0123456789ABCDEF";//uchar xdata dat_12864[64][16];

  7. sbit rs=P0^2;         //寄存器选择信号 H:数据寄存器          L:指令寄存器
  8. sbit rw=P0^1;         //寄存器选择信号 H:数据寄存器          L:指令寄存器
  9. sbit e =P0^0;         //片选信号   下降沿触发
  10. sbit LCD12864_PSB=P0^3;

  11. sbit beep = P3^7;        //蜂鸣器IO口

  12. sbit dq   = P3^2;          //18b20 IO口的定义
  13. uint temperature ;    //温度变量


  14. bit flag_200ms = 1;
  15. uchar menu_1;
  16. uchar flag_clock_en;        //闹钟标志位
  17. uchar open1;        //闹钟开标志位
  18. uchar flag_c_en;
  19. bit flag_100ms;

  20. uchar n_nian,n_yue,n_ri;

  21. /********************************************************************
  22. * 名称 : delay_1ms()
  23. * 功能 : 延时1ms函数
  24. * 输入 : q
  25. * 输出 : 无
  26. ***********************************************************************/
  27. void delay_1ms(uint q)
  28. {
  29.         uint i,j;
  30.         for(i=0;i<q;i++)
  31.                 for(j=0;j<115;j++);
  32. }


  33. #include "ds1302.h"


  34. /*********************定时器0、定时器1初始化******************/
  35. void time0_init()         
  36. {                                         
  37.         EA  = 1;                   //开总中断
  38.         TMOD = 0X11;          //定时器0、定时器1工作方式1
  39.         ET0 = 1;                  //开定时器0中断
  40.         TR0 = 1;                  //允许定时器0定时
  41. }
  42.                                                    
  43.                                           
  44. /************ 延时函数  *****************/
  45. void delay_uint(uint z)
  46. {
  47.    while(z--);
  48. }

  49. /***************交换函数 高位变低位 低位变高位*****************/
  50. uchar change_dat(uchar dat)
  51. {
  52.         uchar i,value;
  53.         for(i=0;i<8;i++)
  54.         {        
  55.                 value <<= 1;
  56.                 if((dat & 0x01) == 0x01)
  57.                         value |= 0x01;
  58.                 dat >>= 1;        
  59.         }
  60.         return value;
  61. }

  62. /************ 写命令函数  *****************/
  63. void write_com(uchar com)
  64. {

  65.    P2=com;//change_dat(com);
  66.    rw=0;
  67.    rs=0;
  68.    delay_uint(25);
  69.    e=1;
  70.    delay_uint(50);
  71.    e=0;
  72. }
  73. /************ 写数据函数  *****************/
  74. void write_dat(uchar dat)
  75. {

  76.    P2=dat;//change_dat(dat);;
  77.    rw=0;
  78.    rs=1;
  79.    delay_uint(25);
  80.    e=1;
  81.    delay_uint(50);
  82.    e=0;
  83. }

  84. /**********************************************************
  85. *函数名: addr_12864
  86. *功能:写地址
  87. *说明:写汉字时要写个地址
  88. *输入:无
  89. *返回:无
  90. **********************************************************/
  91. void addr_12864(uchar hang,uchar lie)          //地址转换
  92. {
  93.         uchar address;
  94.         switch(hang)
  95.         {
  96.                 case 1: address=0x80 + lie ;
  97.                                 break;
  98.                 case 2: address=0x90 + lie ;
  99.                                 break;
  100.                 case 3: address=0x88 + lie ;
  101.                                 break;
  102.                 case 4: address=0x98 + lie ;
  103.                                 break;
  104.                 default :
  105.                                 break;
  106.         }        
  107.         write_com(address);
  108. }

  109. /**********************************************************
  110. *函数名: write_shu16
  111. *功能:在12864上显示16进制数据
  112. *说明:
  113. *输入:无
  114. *返回:无
  115. **********************************************************/
  116. void write_shu16(uchar hang,uchar lie,uchar dat)
  117. {
  118.         addr_12864(hang,lie);          //地址转换        
  119.         write_dat(shuzi[dat/16]);        
  120.         write_dat(shuzi[dat%16]);        
  121. }

  122. /**********************************************************
  123. *函数名: write_string
  124. *功能:在12864上显示字符数据
  125. *说明:
  126. *输入:无
  127. *返回:无
  128. **********************************************************/

  129. void write_string(uchar hang,uchar lie,uchar *p)
  130. {
  131.         addr_12864(hang,lie);          //地址转换
  132.         while(*p != '\0')
  133.         {
  134.                 write_dat(*p);
  135.                 p++;
  136.                 delay_uint(50);
  137.         }
  138. }


  139. /*****************控制光标函数********************/
  140. void write_guanbiao(uchar hang,uchar lie,uchar date)
  141. {               
  142.         addr_12864(hang,lie);         
  143.         if(date == 1)
  144.                 write_com(0x0f);     //显示光标并且闪烁        
  145.         else
  146.                 write_com(0xc0);   //关闭光标
  147. }         


  148. /************12864液晶初始化函数*****************/
  149. void init_12864()
  150. {
  151.         LCD12864_PSB=1;   //串口模式
  152.    write_com(0x30);
  153.    write_com(0x0c);
  154.    write_com(0x01);
  155. }

  156. /*------------------------清除12864------------------------------*/
  157. void clear_12864()
  158. {
  159.         write_string(1,0,"                ");        //1行        
  160.         write_string(2,0,"                ");        //2行        
  161.         write_string(3,0,"                ");        //3行        
  162.         write_string(4,0,"                ");        //4行        
  163. }


  164. /************初始化显示*****************/
  165. void init_12864_dis()
  166. {
  167.         write_string(1,0,"液晶多功能台历");
  168.         write_string(2,0,"阳历2000年00月00");
  169.         write_string(3,0,"农历00-00 星期  ");
  170.         write_string(4,0," 00:00:00 00.0℃");
  171.         write_guanbiao(1,1,0);
  172. }

  173. /************初始化设置显示*****************/
  174. void init_12864_set1()
  175. {
  176.         clear_12864();
  177.         write_string(1,0,"2015年00月00日  ");
  178.         write_string(2,0,"  00时00分00秒  ");
  179.         write_string(3,0,"设置  星期01    ");
  180.         write_string(4,0,"闹钟开  00时00分");
  181.         if(open1 == 1)
  182.                 write_string(4,2,"开");
  183.         else
  184.                 write_string(4,2,"关");
  185.         write_guanbiao(1,1,1);
  186. }

  187. /***********************18b20初始化函数*****************************/
  188. void init_18b20()
  189. {
  190.         bit q;
  191.         dq = 1;                                //把总线拿高
  192.         delay_uint(1);            //15us
  193.         dq = 0;                                //给复位脉冲
  194.         delay_uint(80);                //750us
  195.         dq = 1;                                //把总线拿高 等待
  196.         delay_uint(10);                //110us
  197.         q = dq;                                //读取18b20初始化信号
  198.         delay_uint(20);                //200us
  199.         dq = 1;                                //把总线拿高 释放总线
  200. }

  201. /*************写18b20内的数据***************/
  202. void write_18b20(uchar dat)
  203. {
  204.         uchar i;
  205.         for(i=0;i<8;i++)
  206.         {                                         //写数据是低位开始
  207.                 dq = 0;                         //把总线拿低写时间隙开始
  208.                 dq = dat & 0x01; //向18b20总线写数据了
  209.                 delay_uint(5);         // 60us
  210.                 dq = 1;                         //释放总线
  211.                 dat >>= 1;
  212.         }        
  213. }

  214. /*************读取18b20内的数据***************/
  215. uchar read_18b20()
  216. {
  217.         uchar i,value;
  218.         for(i=0;i<8;i++)
  219.         {
  220.                 dq = 0;                         //把总线拿低读时间隙开始
  221.                 value >>= 1;         //读数据是低位开始
  222.                 dq = 1;                         //释放总线
  223.                 if(dq == 1)                 //开始读写数据
  224.                         value |= 0x80;
  225.                 delay_uint(5);         //60us        读一个时间隙最少要保持60us的时间
  226.         }
  227.         return value;                 //返回数据
  228. }

  229. /*************读取温度的值 读出来的是小数***************/
  230. uint read_temp()
  231. {
  232.         uint value;
  233.         uchar low;                           //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
  234.         init_18b20();                   //初始化18b20
  235.         write_18b20(0xcc);           //跳过64位ROM
  236.         write_18b20(0x44);           //启动一次温度转换命令
  237.         delay_uint(50);                   //500us

  238.         init_18b20();                   //初始化18b20
  239.         
  240.         write_18b20(0xcc);           //跳过64位ROM
  241.         write_18b20(0xbe);           //发出读取暂存器命令
  242.         
  243.         EA = 0;
  244.         low = read_18b20();           //读温度低字节
  245.         value = read_18b20();  //读温度高字节
  246.         EA = 1;
  247.         value <<= 8;                   //把温度的高位左移8位
  248.         value |= low;                   //把读出的温度低位放到value的低八位中
  249.         value *= 0.625;               //转换到温度值 小数
  250.         return value;                   //返回读出的温度 带小数
  251. }


  252. /******************时间芯片显示函数**********************/           
  253. void ds1302_dis()
  254. {
  255.         uchar miao_1;
  256.         if(menu_1 == 0)
  257.         {
  258.                 read_time();
  259.                 if(miao_1 != miao)
  260.                 {
  261.                         miao_1 = miao;
  262.                         Conversion(0,nian,yue,ri);        //农历转换                                    
  263.                         n_nian = year_moon ;
  264.                         n_yue  = month_moon ;
  265.                         n_ri   = day_moon ;
  266.                         write_shu16(2,3,nian);           //显示年
  267.                         write_shu16(2,5,yue);           //显示月
  268.                         write_shu16(2,7,ri);           //显示日
  269.                         write_shu16(3,7,week);           //显示星期
  270.                         
  271.                         addr_12864(3,2);          //地址转换        
  272.                         write_dat(shuzi[n_yue/16]);        
  273.                         write_dat(shuzi[n_yue%16]);        
  274.                         write_dat('-');        
  275.                         write_dat(shuzi[n_ri/16]);        
  276.                         write_dat(shuzi[n_ri%16]);        
  277.                                        
  278.                         addr_12864(4,0);          //地址转换
  279.                         write_dat(' ');               
  280.                         write_dat(shuzi[shi/16]);        
  281.                         write_dat(shuzi[shi%16]);        
  282.                         write_dat(':');        
  283.                         write_dat(shuzi[fen/16]);        
  284.                         write_dat(shuzi[fen%16]);        
  285.                         write_dat(':');        
  286.                         write_dat(shuzi[miao/16]);        
  287.                         write_dat(shuzi[miao%16]);        

  288.                         write_dat(' ');        
  289.                         write_dat(shuzi[temperature/100%10]);        
  290.                         write_dat(shuzi[temperature/10%10]);        
  291.                         write_dat('.');        
  292.                         write_dat(shuzi[temperature%10]);        


  293.                 }
  294.         }
  295. }



  296. /********************独立按键程序*****************/
  297. uchar key_can;         //按键值

  298. void key()         //独立按键程序
  299. {
  300.         static uchar key_new;
  301.         key_can = 20;                   //按键值还原
  302.         P3 |= 0x78;                     //对应的按键IO口输出为1
  303.         if((P3 & 0x78) != 0x78)                //按键按下
  304.         {
  305.                 delay_1ms(1);                     //按键消抖动
  306.                 if(((P3 & 0x78) != 0x78) && (key_new == 1))
  307.                 {                                                //确认是按键按下
  308.                         key_new = 0;
  309.                         switch(P3 & 0x78)
  310.                         {
  311.                                 case 0x70:  key_can = 1;  break;         //得到按键值
  312.                                 case 0x68:  key_can = 2;  break;         //得到按键值
  313.                                 case 0x58:  key_can = 3;  break;         //得到按键值
  314.                                 case 0x38:  key_can = 4;  break;         //得到按键值
  315.                         }
  316. //                        write_sfm2(1,0,key_can);                                 //显示按键值
  317.                 }                        
  318.         }
  319.         else
  320.                 key_new = 1;        
  321. }

  322. /**********************设置函数************************/
  323. void key_with()
  324. {
  325.         if(key_can == 4)   //退出键
  326.         {
  327.                 init_12864();
  328.                 init_12864_dis();
  329.                 flag_200ms = 1;
  330.                 menu_1 = 0;
  331.         }
  332.         if(key_can == 1)        //设置键
  333.         {
  334.                 menu_1 ++;
  335.                 flag_200ms = 1;
  336.                 if(menu_1 == 1)
  337.                         init_12864_set1();
  338.                 if(menu_1 > 10)
  339.                         menu_1 = 1;
  340.         }
  341.         if(menu_1 != 0)
  342.         {
  343.                 if(menu_1 == 1)                  //设置年
  344.                 {
  345.                         if(key_can == 2)        //加
  346.                                 set_ds1302time(1,&nian,0x99);               
  347.                         if(key_can == 3)        //减         
  348.                                 set_ds1302time(0,&nian,0x99);        
  349.                 }
  350.                 if(menu_1 == 2)                  //设置月
  351.                 {
  352.                         if(key_can == 2)        //加
  353.                                 set_ds1302time(1,&yue,0x13);               
  354.                         if(key_can == 3)        //减         
  355.                                 set_ds1302time(0,&yue,0x13);        
  356.                 }
  357.                 if(menu_1 == 3)                  //设置日
  358.                 {
  359.                         if(key_can == 2)        //加
  360.                                 set_ds1302time(1,&ri,0x32);               
  361.                         if(key_can == 3)        //减         
  362.                                 set_ds1302time(0,&ri,0x32);        
  363.                 }
  364.                 if(menu_1 == 4)                  //设置时
  365.                 {
  366.                         if(key_can == 2)        //加
  367.                                 set_ds1302time(1,&shi,0x24);               
  368.                         if(key_can == 3)        //减         
  369.                                 set_ds1302time(0,&shi,0x24);        
  370.                 }
  371.                 if(menu_1 == 5)                  //设置分
  372.                 {
  373.                         if(key_can == 2)        //加
  374.                                 set_ds1302time(1,&fen,0x60);               
  375.                         if(key_can == 3)        //减         
  376.                                 set_ds1302time(0,&fen,0x60);        
  377.                 }
  378.                 if(menu_1 == 6)                  //设置秒
  379.                 {
  380.                         if(key_can == 2)        //加
  381.                                 set_ds1302time(1,&miao,0x60);               
  382.                         if(key_can == 3)        //减         
  383.                                 set_ds1302time(0,&miao,0x60);        
  384.                 }
  385.                 if(menu_1 == 7)                  //设置星期
  386.                 {
  387.                         if(key_can == 2)        //加
  388.                                 set_ds1302time(1,&week,0x8);               
  389.                         if(key_can == 3)        //减         
  390.                                 set_ds1302time(0,&week,0x8);        
  391.                 }
  392.                 if(menu_1 == 8)                  //设置闹钟时
  393.                 {
  394.                         if(key_can == 2)        //加
  395.                                 set_ds1302time(1,&shi1,0x24);               
  396.                         if(key_can == 3)        //减         
  397.                                 set_ds1302time(0,&shi1,0x24);        
  398.                         clock1_save();
  399.                 }
  400.                 if(menu_1 == 9)                  //设置闹钟分
  401.                 {
  402.                         if(key_can == 2)        //加
  403.                                 set_ds1302time(1,&fen1,0x60);               
  404.                         if(key_can == 3)        //减         
  405.                                 set_ds1302time(0,&fen1,0x60);
  406.                         clock1_save();        
  407.                 }
  408.                 if(menu_1 == 10)                  //设置闹钟分
  409.                 {
  410.                         if((key_can == 2) || (key_can == 3))        //加
  411.                                 open1 ++;
  412.                         if(open1 >= 2)
  413.                                 open1 = 0;
  414.                         if(open1 == 1)
  415.                                 write_string(4,2,"开");
  416.                         else
  417.                                 write_string(4,2,"关");        
  418.                         clock1_save();        
  419.                 }
  420.                 write_shu16(1,1,nian);           //显示年
  421.                 write_shu16(1,3,yue);           //显示月
  422.                 write_shu16(1,5,ri);           //显示日
  423.                 write_shu16(2,1,shi);           //显示时
  424.                 write_shu16(2,3,fen);           //显示分
  425.                 write_shu16(2,5,miao);           //显示秒
  426.                 write_shu16(3,5,week);           //显示星期                                       
  427.                 write_shu16(4,4,shi1);           //显示时钟
  428.                 write_shu16(4,6,fen1);           //显示分钟
  429.                 switch(menu_1)           // 光标显示
  430.                 {
  431.                         case 1:  write_guanbiao(1,1,1);  break;
  432.                         case 2:  write_guanbiao(1,3,1);  break;
  433.                         case 3:  write_guanbiao(1,5,1);  break;
  434.                         case 4:  write_guanbiao(2,1,1);  break;
  435.                         case 5:  write_guanbiao(2,3,1);  break;
  436.                         case 6:  write_guanbiao(2,5,1);  break;
  437.                         case 7:  write_guanbiao(3,5,1);  break;
  438.                         case 8:  write_guanbiao(4,4,1);  break;
  439.                         case 9:  write_guanbiao(4,6,1);  break;
  440.                         case 10: write_guanbiao(4,2,1);  break;
  441.                 }
  442.                 write_time();           //把时间写进去
  443.         }                        
  444. }

  445. /*************闹钟报警函数***************/
  446. void menu_dis()
  447. {
  448.         if(menu_1 == 0)
  449.         if(open1 == 1)        //如果闹钟打开
  450.         {
  451.                 if((fen == fen1) && (shi == shi1) && (miao == 0))
  452.                 {               
  453.                         flag_clock_en = 1;        //有报警 打开蜂鸣器响的标志位                                
  454.                 }               
  455.                 if(flag_clock_en == 1)        //闹钟以被打开
  456.                 {        
  457.                         beep = ~beep;           //蜂鸣器叫3秒
  458.                 }
  459.         }        
  460. }


  461. ……………………

  462. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码


所有资料51hei提供下载:
参考资料.rar (180.82 KB, 下载次数: 247)


评分

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

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:339506 发表于 2018-5-28 16:23 | 只看该作者
值得参考
回复

使用道具 举报

板凳
ID:339506 发表于 2018-5-28 16:25 | 只看该作者
哈哈,值得学习一下。。
回复

使用道具 举报

地板
ID:380985 发表于 2018-10-17 08:27 来自触屏版 | 只看该作者
别下载了,没有代码
回复

使用道具 举报

5#
ID:106063 发表于 2018-10-25 20:24 | 只看该作者
谢谢分享
回复

使用道具 举报

6#
ID:408839 发表于 2018-11-17 18:08 | 只看该作者
PSB=1是并口,整个程序也都不完整。
回复

使用道具 举报

7#
ID:400807 发表于 2018-11-18 22:08 | 只看该作者
值得好好学习一下
回复

使用道具 举报

8#
ID:428919 发表于 2018-11-18 22:27 | 只看该作者
很经典的demo。
回复

使用道具 举报

9#
ID:428947 发表于 2018-11-19 00:07 来自触屏版 | 只看该作者
大神,灰常感谢
回复

使用道具 举报

10#
ID:442877 发表于 2018-12-9 21:11 | 只看该作者
谢谢分享
回复

使用道具 举报

11#
ID:412461 发表于 2018-12-17 09:11 | 只看该作者
没有仿真,没有电路图,只有程序
回复

使用道具 举报

12#
ID:312128 发表于 2019-4-2 22:04 | 只看该作者
谢谢分享
回复

使用道具 举报

13#
ID:323774 发表于 2019-7-9 15:15 | 只看该作者
都不全
下次给你们个全的
回复

使用道具 举报

14#
ID:590697 发表于 2019-7-26 10:55 | 只看该作者
这个太强了,新手过来学习
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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