找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5847|回复: 10
收起左侧

带两个闹钟的LCD1602屏小型单片机万年历制作

  [复制链接]
ID:88481 发表于 2018-7-27 20:03 | 显示全部楼层 |阅读模式
本设计中,在按键处理方面,下了不少功夫,虽然只有三个按键,不同状态下,实现不同的功能.
为了节省用电,设计背景灯有按键铵下才亮,延时5秒后灭.长按K1进入设置状态,按K2移位,K3数字加.依次设置年月日,星期,时分秒,闹钟1,闹钟2.
在走时状态下,按K2显示闹钟1,按K3显示闹钟2,延时5秒后返回走时.在显示闹钟状态下,按K1,开关闹钟,显示"*"为开.走时状态下显示"%"为只有一个闹钟开,显示"@"为两个闹钟开.在闹钟响铃时,按任意键关闭声音.

制作出来的原理图如下:
1532689260920.jpg IMG_20180725_214417.jpg IMG_20180724_101645.jpg

Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
IMG_20180727_191855.jpg

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
IMG_20180727_191906.jpg

单片机源程序如下:
  1. #include "Lcd1602.h"
  2. #include "KEY.h"
  3. #include "DS18B20.h"
  4. #include "DS1302.h"

  5. uchar T0RH,T0RL;
  6. bit flag1s = 1;                         //1秒标志
  7. bit flag200ms = 1;                 //200毫秒标志
  8. bit beeonoff1=0,beeonoff2=0;         //闹钟1,2开关标志
  9. bit beeon = 0;                                         //峰鸣开关
  10. uchar keybee = 0;                //按键闹钟1,2切换
  11. uchar hourbee1=0x08,minbee1=0x00,hourbee2=0x13,minbee2=0x30;          //闹钟1,2存放值
  12. uchar flag = 0;                //闹钟显示时间
  13. uchar pos = 0;                 //设置时间引索
  14. sint buftemp;                //温度暂存

  15. struct  sTime {
  16.         uchar year;
  17.         uchar mon;
  18.         uchar day;
  19.         uchar hour;
  20.         uchar min;
  21.         uchar sec;
  22.         uchar week;
  23.   };
  24. struct sTime buftime;

  25. void ConfigTimer0(uchar ms);
  26. void ShowTemp();
  27. void RefrTime();

  28. void main()
  29. {
  30.         bit reg = 0;
  31.         uchar bufsec = 0xaa;
  32.        
  33.         EA = 1;
  34.         ConfigTimer0(2);
  35.         LcdInit();
  36.         DS1302Init();
  37.         Start18B20();
  38.         GainTime(&buftime);
  39.         RefrTime();
  40.         while(1)
  41.         {
  42.                 KeyDriver();
  43.                 if (!pos)
  44.                 {
  45.                         if (flag200ms)
  46.                         {
  47.                                 flag200ms = 0;
  48.                                 GainTime(&buftime);
  49.                                 if (bufsec != buftime.sec)
  50.                                 {
  51.                                         RefrTime();
  52.                                         bufsec = buftime.sec;               
  53.                                 }
  54.                                 if (((hourbee1==buftime.hour) && (minbee1==buftime.min) && beeonoff1) || (hourbee2==buftime.hour) && (minbee2==buftime.min) && beeonoff2)
  55.                                 {
  56.                                         beeon = 1;
  57.                                 }
  58.                                 else
  59.                                 {
  60.                                         beeon = 0;
  61.                                 }
  62.                         }  
  63.                         if (flag1s )
  64.                         {
  65.                                 flag1s = 0;
  66.                                 reg = Get18B20Temp(&buftemp);
  67.                                 if (reg)
  68.                                 {
  69.                                         ShowTemp();          
  70.                                 }
  71.                                 Start18B20();                 
  72.                         }               
  73.                 }               
  74.         }       
  75. }

  76. void ShowTemp()                         //温度显示
  77. {
  78.         schar i = 0;
  79.         uchar len=0;
  80.         uchar tempint,tempdec;           //温度整数部分,小数部分存放
  81.         uchar buf[4],str[6];

  82.         tempint = (buftemp>>4) & 0x7f;                //取出整数部分
  83.         tempdec = buftemp & 0x0f;                        //取出小数部分
  84.         do {
  85.                 buf[i++] = tempint%10;          
  86.                 tempint = tempint/10;
  87.           }while (tempint > 0);       
  88.         if (i < 2)
  89.         {
  90.                 str[len++] = ' ';
  91.         }         
  92.         while (i-- > 0)
  93.         {
  94.                 str[len++] = buf[i] + '0';       
  95.         }                                                                           
  96.         str[len++] = '.';
  97.         str[len++] = (tempdec*10/16) +'0';
  98.        
  99.         str[len] = '\0';                                          
  100.         LcdShowStr(11,1,str);         
  101. }                                         

  102. void NumToStr(uchar x,uchar y, uchar *str)                 //数据转换字符
  103. {
  104.         uchar buf[3];

  105.         buf[0] = (*str>>4) + '0';
  106.         buf[1] = (*str&0x0f) + '0';
  107.         buf[2] = '\0';
  108.         LcdShowStr(x,y,buf);
  109. }

  110. void RefrTime()                                                  //刷新时间
  111. {
  112.         NumToStr(2,0,&buftime.year);
  113.         NumToStr(5,0,&buftime.mon);
  114.         NumToStr(8,0,&buftime.day);
  115.         LcdShowStr(15,0,&buftime.week);       
  116.         if  (((flag>0) && (keybee ==1)) || ((pos>=14) && (pos<=17)))        //闹钟1显示       
  117.         {
  118.                 NumToStr(2,1,&hourbee1);
  119.                 NumToStr(5,1,&minbee1);
  120.                 LcdShowStr(8,1,"-1");
  121.         }
  122.         else if (((flag>0) && (keybee ==2)) || ((pos>=18) && (pos<=21)))         //闹钟2显示
  123.         {
  124.                 NumToStr(2,1,&hourbee2);
  125.                 NumToStr(5,1,&minbee2);
  126.                 LcdShowStr(8,1,"-2");
  127.         }
  128.         else
  129.         {
  130.                 NumToStr(2,1,&buftime.hour);
  131.                 NumToStr(5,1,&buftime.min);
  132.                 NumToStr(8,1,&buftime.sec);
  133.                 if (beeonoff1 && beeonoff2)                                  //如果两个闹钟开,则显示"@"
  134.                         LcdShowStr(0,1,"@");
  135.                 else if (!beeonoff1 && !beeonoff2)                  //如果两个闹钟关,则不显示,
  136.                         LcdShowStr(0,1," ");
  137.                 else
  138.                         LcdShowStr(0,1,"%");                                  //如果其中一个闹钟开,则显示"%"
  139.         }                                                                               
  140. }

  141. void BeeOnroOff()                        //闹钟开关时显示
  142. {
  143.         if (keybee == 1)                //闹钟1开关
  144.         {
  145.                 beeonoff1 = ~beeonoff1;
  146.                 if (beeonoff1)
  147.                 {
  148.                         LcdShowStr(0,1,"*");                         //显示"*",表示闹钟开
  149.                 }
  150.                 else
  151.                 {
  152.                         LcdShowStr(0,1," ");
  153.                 }
  154.         }
  155.         else if (keybee == 2)         //闹钟2开关
  156.         {
  157.                 beeonoff2 = ~beeonoff2;       
  158.                 if (beeonoff1 || beeonoff2)
  159.                 {
  160.                         LcdShowStr(0,1,"*");       
  161.                 }
  162.                 else
  163.                 {
  164.                         LcdShowStr(0,1," ");
  165.                 }
  166.         }        
  167. }

  168. void CurPosit()                                                           //光标位置,设置修改的位置
  169. {
  170.         switch(pos)
  171.         {
  172.                 case 1: LcdSetCort(2,0); break;                //日期
  173.                 case 2: LcdSetCort(3,0); break;
  174.                 case 3: LcdSetCort(5,0); break;
  175.                 case 4: LcdSetCort(6,0); break;
  176.                 case 5: LcdSetCort(8,0); break;
  177.                 case 6: LcdSetCort(9,0); break;                 
  178.                 case 7: LcdSetCort(15,0); break;         //星期
  179.                 case 8: LcdSetCort(2,1); break;                 //时间
  180.                 case 9: LcdSetCort(3,1); break;
  181.                 case 10: LcdSetCort(5,1); break;
  182.                 case 11: LcdSetCort(6,1); break;
  183.                 case 12: LcdSetCort(8,1); break;
  184.                 case 13: LcdSetCort(9,1); break;
  185.                 case 14: LcdSetCort(2,1); break;          //闹钟1
  186.                 case 15: LcdSetCort(3,1); break;
  187.                 case 16: LcdSetCort(5,1); break;
  188.                 case 17: LcdSetCort(6,1); break;
  189.                 case 18: LcdSetCort(2,1); break;           //闹钟2
  190.                 case 19: LcdSetCort(3,1); break;
  191.                 case 20: LcdSetCort(5,1); break;
  192.                 case 21: LcdSetCort(6,1); break;
  193.                 default:        break;                       
  194.         }       
  195. }

  196. void RightShift()                          //向右移动
  197. {
  198.         if (pos != 0)
  199.         {
  200.                 if (pos < 21)
  201.                         pos++;
  202.                 else
  203.                         pos = 1;
  204.                 if ((pos==14) || (pos==18) || (pos==1))
  205.                         RefrTime();
  206.                 CurPosit();
  207.         }
  208. }

  209. uchar IncBcdHigh(uchar dat, uchar n)           //高位加
  210. {
  211.         if ((dat&0xf0) < (n<<4))
  212.                 dat += 0x10;
  213.         else
  214.                 dat &= 0x0f;
  215.         return dat;
  216. }

  217. uchar IncBcdLow(uchar dat, uchar n)                   //低位加
  218. {
  219.         if ((dat&0x0f) < n)
  220.                 dat += 0x01;
  221.         else
  222.                 dat &= 0xf0;
  223.         return dat;
  224. }

  225. uchar IncBcdWeek(uchar dat, uchar n)                //星期加
  226. {
  227.         if ((dat&0x0f) < n)
  228.                 dat += 0x01;
  229.         else
  230.                 dat = 1;
  231.         return dat;
  232. }

  233. void IncSetTime()                 //向上(加)
  234. {
  235.         switch (pos)
  236.         {
  237.                 case 1: buftime.year = IncBcdHigh(buftime.year,9); break;
  238.                 case 2: buftime.year = IncBcdLow(buftime.year,9); break;
  239.                 case 3: buftime.mon = IncBcdHigh(buftime.mon,1); break;
  240.                 case 4: buftime.mon = IncBcdLow(buftime.mon,9); break;
  241.                 case 5: buftime.day = IncBcdHigh(buftime.day,3); break;
  242.                 case 6: buftime.day = IncBcdLow(buftime.day,9); break;
  243.                 case 7: buftime.week = IncBcdWeek(buftime.week,7); break;
  244.                 case 8: buftime.hour = IncBcdHigh(buftime.hour,2); break;
  245.                 case 9: buftime.hour = IncBcdLow(buftime.hour,9); break;
  246.                 case 10: buftime.min = IncBcdHigh(buftime.min,5); break;
  247.                 case 11: buftime.min = IncBcdLow(buftime.min,9); break;
  248.                 case 12: buftime.sec = IncBcdHigh(buftime.sec,5); break;
  249.                 case 13: buftime.sec = IncBcdLow(buftime.sec,9); break;

  250.                 case 14: hourbee1 = IncBcdHigh(hourbee1,2); break;
  251.                 case 15: hourbee1 = IncBcdLow(hourbee1,9); break;
  252.                 case 16: minbee1 = IncBcdHigh(minbee1,5); break;
  253.                 case 17: minbee1 = IncBcdLow(minbee1,9); break;

  254.                 case 18: hourbee2 = IncBcdHigh(hourbee2,2); break;
  255.                 case 19: hourbee2 = IncBcdLow(hourbee2,9); break;
  256.                 case 20: minbee2 = IncBcdHigh(minbee2,5); break;
  257.                 case 21: minbee2 = IncBcdLow(minbee2,9); break;
  258.                 default: break;
  259.         }
  260.         RefrTime();
  261.         CurPosit();       
  262. }

  263. void EntertimeSet()                        //进入时间设置
  264. {
  265.         pos = 21;
  266.         RightShift();
  267.         LcdCoorTwin();                //光标闪动
  268. }

  269. void KeyAction(uchar cod,bit set)                          //按键动作
  270. {
  271.         switch(cod)
  272.         {
  273.                 case 0: if (!set)       
  274.                                 {
  275.                                         if (flag > 0)                        //闹钟延时显示状态下,则可以设置闹钟开关
  276.                                                 BeeOnroOff();
  277.                                         pos = 0;
  278.                                         SetTime(&buftime);
  279.                                         LcdClsCur();                 //光标闪动清除
  280.                                 }
  281.                                 else                                          //进入设置
  282.                                 {
  283.                                         flag = 0;                          //延时显示时间清零                                       
  284.                                         EntertimeSet();
  285.                                 }
  286.                                         break;
  287.                 case 1: if (!set && (pos==0))                        //非设置状态,显示闹钟1
  288.                                 {
  289.                                         keybee = 1;
  290.                                         flag = 3;                                        //延时6秒计算
  291.                                         if (beeonoff1)
  292.                                         {
  293.                                                 LcdShowStr(0,1,"*");         //显示闹钟标志
  294.                                         }
  295.                                         else
  296.                                         {
  297.                                                 LcdShowStr(0,1," ");
  298.                                         }
  299.                                         RefrTime();       
  300.                                 }
  301.                                 else if (pos!=0)                                 //设置状态,数字移动
  302.                                 {
  303.                                         RightShift();                               
  304.                                 }                       
  305.                                         break;
  306.                 case 2: if (!set && (pos==0))                        //非设置状态,显示闹钟2
  307.                                 {
  308.                                         keybee = 2;
  309.                                         flag = 3;                                         //延时6秒计算
  310.                                         if (beeonoff2)
  311.                                         {
  312.                                                 LcdShowStr(0,1,"*");           //显示闹钟标志
  313.                                         }
  314.                                         else
  315.                                         {
  316.                                                 LcdShowStr(0,1," ");
  317.                                         }
  318.                                         RefrTime();       
  319.                                 }
  320.                                 else if (pos!=0)                           //设置状态,数字加
  321.                                 {
  322.                                         IncSetTime();
  323.                                 }                               
  324.                                           break;
  325.         }       
  326. }

  327. void LedLigh(bit ledt)                                  //背影灯开启
  328. {
  329.         static bit ledflag = 0;
  330.         static uint ledcou=0;

  331.         if (ledt)
  332.         {
  333.                 ledflag = 1;
  334.                 ledcou = 3000;
  335.                 LED = 0;
  336.         }
  337.         if (ledflag)
  338.         {               
  339.                 if (ledcou > 0)
  340.                 {
  341.                         ledcou--;
  342.                 }
  343.                 else
  344.                 {
  345.                         ledflag = 0;
  346.                         LED = 1;       
  347.                 }
  348.         }
  349. }

  350. void AlarmClock(bit on, bit beet)                //闹钟发声         on 闹钟触发开关,beet为按键暂时关
  351. {
  352.         static bit off = 0;
  353.         static uchar alcou=0;

  354.         if (on)
  355.         {
  356.                 if (beet)
  357.                         off = 1;
  358.                 if (!off)
  359.                 {               
  360.                         alcou++;
  361.                         if (alcou == 255)
  362.                         {
  363.                         alcou = 0;
  364.                         }
  365.                         if (alcou > 150)
  366.                         {
  367.                                 BEE = ~BEE;
  368.                         }
  369.                 }
  370.                 else
  371.                 {
  372.                         BEE = 1;
  373.                 }       
  374.         }
  375.         else
  376.         {
  377. ……………………

  378. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
0.png
所有资料51hei提供下载:
自制小型万年历.zip (440.2 KB, 下载次数: 148)

评分

参与人数 2黑币 +55 收起 理由
不负时光~田 + 5 绝世好帖!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:367440 发表于 2018-7-29 18:36 | 显示全部楼层
大神,膜拜
回复

使用道具 举报

ID:307566 发表于 2018-9-8 20:09 | 显示全部楼层
和我想做的差不多,就等下下来实践一下
回复

使用道具 举报

ID:457329 发表于 2018-12-31 13:30 | 显示全部楼层
老哥,我下载下来修改,发现好多.C文件不知道怎么修改,求教
回复

使用道具 举报

ID:154310 发表于 2018-12-31 22:38 | 显示全部楼层
太厉害了,求指导呀。。。。
回复

使用道具 举报

ID:133790 发表于 2019-1-2 11:39 | 显示全部楼层
这个帖子不错,自从自己开始自己自学单片机,从来都没有系统的学习过。多谢了。
回复

使用道具 举报

ID:479216 发表于 2019-2-22 11:02 来自手机 | 显示全部楼层
谢谢楼主,正准备做个这种的。
回复

使用道具 举报

ID:517951 发表于 2020-11-15 14:10 | 显示全部楼层
谢谢楼主分享,,51hei有你更精彩!!
回复

使用道具 举报

ID:336670 发表于 2023-1-31 12:24 | 显示全部楼层
谢谢楼主分享,,51hei有你更精彩!!
回复

使用道具 举报

ID:1026113 发表于 2023-2-6 16:36 | 显示全部楼层
老哥怎么没有复位
回复

使用道具 举报

ID:824664 发表于 2023-3-12 23:37 | 显示全部楼层
正在学习的内容,非常感谢!!!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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