找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 12686|回复: 33
收起左侧

分享51电子时钟,LCD1602显示,DS1302,DS18B20

  [复制链接]
ID:101749 发表于 2016-1-27 16:11 | 显示全部楼层 |阅读模式
单片机:STC89C52RC            时钟芯片:DS1302
测温元件:DS18B20            显示元件:LCD1602
信息保持:STC单片机内部EEPROM
作者:BrightBell             时间:2016年1月初
邮箱:brightbell@qq.com

备注:
1.DS1302没有第二电源,掉电不走时,误差 < 1s/5天
2.时间、背光开关时间、蜂鸣器整点报时时间、LCD背光亮度、
  按键音皆可设置
3.长按KEY0马上开/关LCD背光,长按KEY1进入系统设置界面,
  长按KEY2进入时间设置界面
4.每3秒读取一次DS18B20温度
5.每一小时更新一次EEPROM中的时间信息,重新设置时间后马
  上更新
6.进行一次系统设置后,马上更新EEPROM中的系统设置信息,
  下次启动时会先加载
正.jpg

反.jpg

视频:


部分源文件预览:(完整版可从附件下载)
  1. #ifndef _DS1302_H_
  2. #define _DS1302_H_


  3. void DS1302ByteWrite(unsigned char dat)  //向DS1302写入一个字节
  4. {
  5.   unsigned char mask;       
  6.         for(mask=0x01; mask!=0; mask<<=1)  //低位在先
  7.         {
  8.           if((mask&dat) != 0)
  9.                         DS1302IO = 1;
  10.                 else
  11.                         DS1302IO = 0;
  12.                 DS1302CK = 1;
  13.           DS1302CK = 0;
  14.         }
  15.         DS1302IO = 1;
  16. }

  17. unsigned char DS1302ByteRead(void)  //从DS1302读取一个字节
  18. {
  19.   unsigned char mask;
  20.         unsigned char dat = 0;
  21.         for(mask=0x01; mask!=0; mask<<=1)
  22.         {
  23.           if(DS1302IO != 0)
  24.                         dat |= mask;
  25.                 DS1302CK = 1;
  26.                 DS1302CK = 0;
  27.         }
  28.         return dat;
  29. }

  30. void DS1302SingleWrite(unsigned char reg, unsigned char dat)  //写入DS1302的某一寄存器
  31. {
  32.   DS1302CE = 1;
  33.         DS1302ByteWrite((reg<<1)|0x80);
  34.         DS1302ByteWrite(dat);
  35.         DS1302CE = 0;
  36. }

  37. unsigned char DS1302SingleRead(unsigned char reg)   //读取DS1302的某一寄存器
  38. {
  39.   unsigned char dat;
  40.         DS1302CE = 1;
  41.         DS1302ByteWrite((reg<<1)|0x81);
  42.         dat = DS1302ByteRead();
  43.         DS1302CE = 0;
  44.         return dat;
  45. }

  46. void DS1302BurstWrite(unsigned char *dat) //Brust模式写入时间信息
  47. {
  48.   unsigned char i;
  49.         DS1302CE = 1;
  50.         DS1302ByteWrite(0xBE);
  51.         for(i=0; i<8; i++)
  52.         {
  53.           DS1302ByteWrite(dat[i]);
  54.         }
  55.         DS1302CE = 0;
  56. }

  57. void DS1302BurstRead(unsigned char *dat)    //Brust模式读出时间信息
  58. {
  59.   unsigned char i;
  60.         DS1302CE = 1;
  61.         DS1302ByteWrite(0xBF);
  62.         for(i=0; i<8; i++)
  63.         {
  64.           dat[i] = DS1302ByteRead();
  65.         }
  66.         DS1302CE = 0;
  67. }

  68. //欲写入的是十进制的时间信息,不是BCD码,已进行转换
  69. struct TIME Bcd1302ToDec(struct TIME *time)
  70. {
  71.   struct TIME dectime;
  72.   dectime.year = (time->year >> 4) * 10;
  73.         dectime.year = (time->year & 0x0F) + dectime.year;
  74.         dectime.mon = (time->mon >> 4) * 10;
  75.         dectime.mon = (time->mon & 0x0F) + dectime.mon;
  76.         dectime.day = (time->day >> 4) * 10;
  77.         dectime.day = (time->day & 0x0F) + dectime.day;
  78.   dectime.hour = (time->hour >> 4) * 10;
  79.         dectime.hour = (time->hour & 0x0F) + dectime.hour;
  80.         dectime.min = (time->min >> 4) * 10;
  81.         dectime.min = (time->min & 0x0F) + dectime.min;
  82.         dectime.sec = (time->sec >> 4) * 10;
  83.         dectime.sec = (time->sec & 0x0F) + dectime.sec;
  84.        
  85.         dectime.week = time->week & 0x0F;
  86.        
  87.         return dectime;
  88. }

  89. //获取到的是十进制的时间信息,不是BCD码,获取后已进行转换
  90. void GetRealTime(struct TIME *time)  //获取时间信息,并保存在时间结构体中
  91. {
  92.   unsigned char buf[8];
  93.         struct TIME temp;
  94.         DS1302BurstRead(buf);
  95.         temp.year = buf[6];
  96.         temp.mon = buf[4];
  97.         temp.day = buf[3];
  98.         temp.hour = buf[2];
  99.         temp.min = buf[1];
  100.         temp.sec = buf[0];
  101.         temp.week = buf[5];
  102.        
  103.         *time = Bcd1302ToDec(&temp);  //将BCD码转为十进制
  104. }

  105. struct TIME DecToBcd1302(struct TIME *time)
  106. {
  107.   struct TIME bcdtime;
  108.   bcdtime.year = (time->year / 10 % 10) * 16;
  109.         bcdtime.year = (time->year % 10) + bcdtime.year;
  110.         bcdtime.mon = (time->mon / 10 % 10) * 16;
  111.         bcdtime.mon = (time->mon % 10) + bcdtime.mon;
  112.         bcdtime.day = (time->day / 10 % 10) * 16;
  113.         bcdtime.day = (time->day % 10) + bcdtime.day;
  114.   bcdtime.hour = (time->hour / 10 % 10) * 16;
  115.         bcdtime.hour = (time->hour % 10) + bcdtime.hour;
  116.         bcdtime.min = (time->min / 10 % 10) * 16;
  117.         bcdtime.min = (time->min % 10) + bcdtime.min;
  118.         bcdtime.sec = (time->sec / 10 % 10) * 16;
  119.         bcdtime.sec = (time->sec % 10) + bcdtime.sec;
  120.        
  121.         bcdtime.week = time->week % 10;
  122.        
  123.         return bcdtime;
  124. }

  125. void SetRealTime(struct TIME *time)  //通过时间结构体设置时间
  126. {
  127.   unsigned char buf[8];
  128.         struct TIME temp;
  129.         temp = DecToBcd1302(time);
  130.         buf[7] = 0;
  131.         buf[6] = temp.year;
  132.         buf[5] = temp.week;
  133.         buf[4] = temp.mon;
  134.         buf[3] = temp.day;
  135.         buf[2] = temp.hour;
  136.         buf[1] = temp.min;
  137.         buf[0] = temp.sec;
  138.         DS1302BurstWrite(buf);
  139. }

  140. void InitDS1302(void)  //初始化DS1302
  141. {
  142.   unsigned char dat;
  143.         struct TIME eepromtime;
  144.         DS1302CE = 0;
  145.         DS1302CK = 0;
  146.         dat = DS1302SingleRead(0);
  147.         if((dat & 0x80) != 0)  //检测时间在掉电时是否停止过,停1走0,如果停过就从新写入初始化时间
  148.         {
  149.           GetE2promTime(&eepromtime);  //停止过,获取EEPROM里的时间
  150.                 DS1302SingleWrite(7, 0x00);  //撤销保护
  151.                 SetRealTime(&eepromtime);
  152.         }
  153.        
  154.         lcdShowStr(0, 0, "20  -  -");
  155.         lcdShowStr(3, 1, ":  :");
  156. }

  157. void lcdShowWeek(unsigned char x, unsigned char y, unsigned char week)
  158. {
  159.   unsigned char str[5];
  160.         lcdShowStr(x-4, y, "week");
  161.         str[0] = week % 10 + '0';
  162.         str[1] = '\0';
  163.         lcdShowStr(x, y, str);
  164. }

  165. void RefreshTime(struct TIME *time)
  166. {
  167.         static unsigned char dayBF = 88;
  168.         if(dayBF != time->day)  //日期发生变化,更新年月日周
  169.         {
  170.                 lcdShowNum(2, 0, time->year);
  171.                 lcdShowNum(5, 0, time->mon);
  172.                 lcdShowNum(8, 0, time->day);
  173.                 lcdShowWeek(15,0, time->week);
  174.                 dayBF = time->day;
  175.         }
  176.         lcdShowNum(1, 1, time->hour);
  177.         lcdShowNum(4, 1, time->min);
  178.         lcdShowNum(7, 1, time->sec);
  179. }

  180. void HourlyWork(struct TIME *time)  //小时事件
  181. {
  182.   static char hourBF = 88;
  183.         static char lightlevelBF = 3;
  184.   if(time->hour != hourBF)    //时有变
  185.   {               
  186.                 if(time->hour==lcdlighton)  //判断是否有背光开关
  187.                 {
  188.                   lcdlight = 0;
  189.                         if(lightlevelBF != 0)
  190.                     lcdlightlevel = lightlevelBF;
  191.                         else
  192.                                 lcdlightlevel = 4;
  193.                 }
  194.                 else if(time->hour==lcdlightoff)  //判断是否有背光开关
  195.                 {
  196.                   lcdlight = 1;
  197.                   lightlevelBF = lcdlightlevel;
  198.                         lcdlightlevel = 0;
  199.                 }
  200.                
  201.                 if((time->hour>=ZDBSbegin)&&(time->hour<=ZDBSend))
  202.                 {
  203.                         if(hourlybuzz != 0)  //整点报时开
  204.                           flagZD = 1;
  205.                 }
  206.                
  207.                 SaveTimeToE2prom(time);  //每小时更新EEPROM里的时间信息
  208.                
  209.                 hourBF = time->hour;  //更新备份值
  210.         }
  211. }

  212. void LedWaterShow()    //流水灯效果
  213. {
  214.   static unsigned char ledshow = 0x01;
  215.         static bit dir = 0;
  216.         ledDB = ledshow;
  217.         if(dir == 0)
  218.         {
  219.           ledshow = ledshow << 1;
  220.                 if(ledshow == 0x00)
  221.                 {
  222.                         dir = 1;
  223.                         ledshow = 0x40;
  224.                 }
  225.         }
  226.         else
  227.         {
  228.           ledshow = ledshow >> 1;
  229.                 if(ledshow == 0x00)
  230.                 {
  231.                   dir = 0;
  232.                         ledshow = 0x02;
  233.                 }
  234.         }
  235. }

  236. /*******************************************************************************
  237.         补偿值计算方法:当X秒后时间慢Y秒,则:实减=X/当前值;应减=实减-Y; 补偿值=X/应减
  238. ********************************************************************************/
  239. void TimeBuChang(struct TIME *time)
  240. {
  241.         static char flagBC = 0;
  242.         static unsigned int BCcnt = 0;
  243.         static struct TIME BCtime;
  244.         if(flagBC != 0)
  245.         {
  246.           flagBC = 0;
  247.                 SetRealTime(&BCtime);  //写入上一秒时间,相当于减一秒
  248.         }
  249.        
  250.         BCcnt++;
  251.         if(BCcnt > secBuChang)   //每X秒减1秒  
  252.         {
  253.                 timemenu = 88;   //禁止时间更新
  254.           BCcnt = 0;
  255.                 BCtime = *time;  //备份上一秒时间
  256.                 flagBC = 1;
  257.                 timemenu = 0;   //开时间更新
  258.         }
  259. }

  260. void UpdateTime()
  261. {
  262.   static unsigned char secBF = 88;
  263.         static unsigned int ds18b20cnt = 0;
  264.   struct TIME buftime;   //从DS1302中读取出来的值
  265.         GetRealTime(&buftime);
  266.         if(buftime.sec != secBF)
  267.         {
  268.                 RefreshTime(&buftime);
  269.                 secBF = buftime.sec;
  270.           
  271.                 ds18b20cnt++;
  272.                 if(ds18b20cnt > GetTempSpace)
  273.                 {
  274.                   ds18b20cnt = 0;
  275.                         RefreshTemp();
  276.                 }
  277.                
  278.                 HourlyWork(&buftime);
  279.                 LedWaterShow();
  280.                
  281.                 TimeBuChang(&buftime);   //时间补偿
  282.         }
  283. }

  284. void RefreshTimeNow()
  285. {
  286.   struct TIME buftime;
  287.         GetRealTime(&buftime);
  288.         lcdShowStr(0, 0, "20  -  -");
  289.         lcdShowStr(3, 1, ":  :");
  290.         lcdShowNum(2, 0, buftime.year);
  291.         lcdShowNum(5, 0, buftime.mon);
  292.         lcdShowNum(8, 0, buftime.day);
  293.         lcdShowNum(1, 1, buftime.hour);
  294.         lcdShowNum(4, 1, buftime.min);
  295.         lcdShowNum(7, 1, buftime.sec);
  296.         lcdShowWeek(15,0, buftime.week);
  297.         if(hourlybuzz != 0)
  298.                 lcdShowImage(0, 1, image0, 0);
  299.         else
  300.                 lcdShowStr(0, 1, " ");
  301.         lcdShowImage(15, 1, image1, 1);
  302. }

  303. #endif
复制代码
网盘下载:
游客,本帖隐藏的内容需要积分高于 1 才可浏览,您当前积分为 0



【BrightBell】基于51单片机的电子时钟.rar

969.98 KB, 下载次数: 326, 下载积分: 黑币 -5

评分

参与人数 3黑币 +60 收起 理由
郑港华 + 5 很给力!
月光 + 5 很给力!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:23303 发表于 2016-3-7 10:11 | 显示全部楼层
下来学习一下,谢谢!
回复

使用道具 举报

ID:109342 发表于 2016-4-12 12:45 | 显示全部楼层
看不过来了都
回复

使用道具 举报

ID:109342 发表于 2016-4-12 12:46 | 显示全部楼层
电子时钟带有闹铃功能吗?
回复

使用道具 举报

ID:114669 发表于 2016-5-21 19:12 | 显示全部楼层
谢谢分享。。。。。。。。。。。。。。。。。。。。
回复

使用道具 举报

ID:101749 发表于 2016-5-22 12:39 | 显示全部楼层
故国神游1 发表于 2016-4-12 12:46
电子时钟带有闹铃功能吗?

没有呢,不打算加进去了,用手机
回复

使用道具 举报

ID:122542 发表于 2016-5-22 12:44 | 显示全部楼层
学习学习
回复

使用道具 举报

ID:122542 发表于 2016-5-22 12:45 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:124675 发表于 2016-6-3 16:39 | 显示全部楼层

谢谢分享。。。。。。。。。
回复

使用道具 举报

ID:137004 发表于 2016-8-17 22:23 | 显示全部楼层
为什么我在5110上不能同时显示
回复

使用道具 举报

ID:127122 发表于 2016-8-18 00:16 | 显示全部楼层
支持一下               .
回复

使用道具 举报

ID:99938 发表于 2016-8-28 14:07 | 显示全部楼层
不管用
回复

使用道具 举报

ID:140922 发表于 2016-9-29 23:16 来自手机 | 显示全部楼层
厉害了…
回复

使用道具 举报

ID:106598 发表于 2016-10-31 22:11 | 显示全部楼层
为什么按键不能调节呢
回复

使用道具 举报

ID:146145 发表于 2016-11-26 17:16 | 显示全部楼层
这个是全部的程序么?
回复

使用道具 举报

ID:146145 发表于 2016-11-30 18:41 | 显示全部楼层

RE: 分享51电子时钟,LCD1602显示,DS1302,DS18B20

楼主  ds18b02的这个程序 仿真的时候可以用吗  在proteus中不显示啊
回复

使用道具 举报

ID:155617 发表于 2016-12-23 23:54 | 显示全部楼层
lz这个不错,另外加上自动亮度控制更好
回复

使用道具 举报

ID:155617 发表于 2017-1-7 08:50 来自手机 | 显示全部楼层
嘟嘟嘟 发表于 2016-11-30 18:41
楼主  ds18b02的这个程序 仿真的时候可以用吗  在proteus中不显示啊

我去仿真试一下
回复

使用道具 举报

ID:153685 发表于 2017-1-10 22:34 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:89286 发表于 2017-1-21 11:30 | 显示全部楼层
thanks for sharing
回复

使用道具 举报

ID:153681 发表于 2017-4-4 13:17 | 显示全部楼层
兄弟,逗我呢,资料里就那么点程序
回复

使用道具 举报

ID:187675 发表于 2017-6-27 08:44 | 显示全部楼层
百度分享的东东失效

本贴分享的附件,无法通过仿真

楼主能提供完整的资料学习一下吗?


谢谢


zg@jslskj.com

回复

使用道具 举报

ID:167272 发表于 2017-8-11 10:14 | 显示全部楼层
下载的附件,程序不全。。。
回复

使用道具 举报

ID:101749 发表于 2017-8-21 10:54 | 显示全部楼层
MyClock_V2.0F EEPROM.zip (102.89 KB, 下载次数: 45)
回复

使用道具 举报

ID:242098 发表于 2017-10-23 19:52 来自手机 | 显示全部楼层
分享取消了
回复

使用道具 举报

ID:197331 发表于 2017-11-23 21:17 | 显示全部楼层
不错,值得学习。
回复

使用道具 举报

ID:170645 发表于 2018-4-22 14:48 | 显示全部楼层
收藏学习
回复

使用道具 举报

ID:360792 发表于 2018-6-28 15:24 | 显示全部楼层
楼主有能网盘分享一下吗
回复

使用道具 举报

ID:89134 发表于 2018-12-12 18:41 | 显示全部楼层
基于51单片机的电子时钟Ok
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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