找回密码
 立即注册

QQ登录

只需一步,快速开始

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

刚学单片机DIY个12864红外遥控时钟万年历

  [复制链接]
跳转到指定楼层
楼主
刚学单片机DIY个12864红外遥控时钟万年历
包含 单片机源代码和烧录固件  AD9原理图 PCB图


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




单片机源程序如下:
  1. /*---------------------------------------------------------------------------
  2.         李春林的智能时钟程序
  3.         单 片 机:STC89C52RC
  4.         晶    振:11.0592MHz
  5.         时钟芯片:DS1302
  6.         液 晶 屏:12864-ST7920
  7.         功能描述: 大数字显示时间;能显示农历、温度和设置闹铃;有整点报时功能
  8.                           红外遥控和按键都能设置时间和闹钟
  9.         说          明:LCD12864使用并口连接方式,PSB、RST接高电平
  10.         修改日志:无

  11. ------------------------------------------------------------------------------*/

  12. /*-------------------------------头文件---------------------------------------*/
  13. #include <reg52.h>
  14. #include <intrins.h>
  15. #include "LCD12864.h"
  16. #include "DS1302.h"
  17. #include "DS18B20.h"
  18. #include "nongli.h"
  19. #include "displaytime.h"
  20. #include "zt.h"
  21. #include "bell.h"
  22. #include "HW.H"
  23. #include "delay.h"

  24. #define uint  unsigned int
  25. #define uchar unsigned char

  26. /*--------------------定义按键-----------------------------------------------*/
  27. sbit K1  = P1^0; //K1-设置
  28. sbit K2  = P1^1; //K2-确认、返回
  29. sbit K3  = P1^2; //K3-加
  30. sbit K4  = P1^3; //K4-减
  31. //sbit K5  = P1^4; //按键K5-闹钟的打开与关闭 在"hw.h"中定义

  32. /*---------------------函数声明------------------------------*/             
  33. void ds_w0(void);
  34. void ds_w(void);
  35. void Conver_week(bit c,uchar year,uchar month,uchar day);
  36. /*-----------------------------定义全局变量------------------------------*/
  37. bit  w=0;    //调时标志位

  38. unsigned char yy,mo,dd,xq,hh,mm,ss,month_moon,day_moon,week,tiangan,dizhi,moontemp1,moontemp2;//定义时间映射全局变量(专用寄存器)
  39. signed char address,item,item0,max,mini;
  40. unsigned char clk_ala[2]={0x00,0x00};//闹钟数据存放初,始值为00:00
  41. unsigned char hour,minute,time;//用于闹铃的设置



  42. /*-----------------------------日期、时间设置函数-----------------------------*/

  43. void tiaozheng(void){
  44.         yy = read_clock(0x8d);//调用1302时钟数据中的年数据,从地址0x8d中
  45.         mo = read_clock(0x89);//调用1302时钟数据中的月数据,从地址0x89中
  46.         dd = read_clock(0x87);//从1302芯片中读取日数据,从地址0x87中
  47.         week = read_clock(0x8b);//从1302芯片中读取星期数据,从地址0x8b中
  48.         //----------------------------------
  49.         lcm_w_test(0,0x80);
  50.         lcm_w_word("20");//显示内容字符20
  51.         lcm_w_test(1,(yy/16)+0x30);//函数参数1,代表本行写数据,YY/16+0X30得出年十位数字的显示码地址,送显示       
  52.         lcm_w_test(1,yy%16+0x30);//函数
  53.         lcm_w_word("年");
  54.         //----------------------------------
  55.         lcm_w_test(1,(mo/16)+0x30);
  56.         lcm_w_test(1,mo%16+0x30);//与16取余数,得到月份的个位数,加0x30得到该数字的液晶内定显示码送显示
  57.         lcm_w_word("月");//调用字符显示函数,显示文字 月
  58.         //----------------------------------
  59. /*
  60.         lcm_w_test(0,0x88);//第一个参数0,表示本行写入LCM的是指令,指定显示位置88H(第三行左端)
  61.         lcm_w_word("星期");//调用字符显示函数,显示文字 星期
  62.         lcm_w_test(1,mo%16+0x30);//与16取余数,得到月份的个位数,加0x30得到该数字的液晶内定显示码送显示
  63. */
  64.         //----------------------------------
  65.         lcm_w_test(1,(dd/16)+0x30);
  66.         lcm_w_test(1,dd%16+0x30);//第一个1参数,表示本行写数据,日数据与16取余得个位数,加0x30得到显示码
  67.         lcm_w_word("日");//显示字符 日
  68.         //----------------------------------
  69.         if(read_clock(0x85) != hh){//如果程序中的小时与1302芯片中的不同,
  70.                 hh = read_clock(0x85);//刷新程序中的小时数据
  71.         }
  72.         lcm_w_test(0,0x91);//第一个参数0,表示本行写入LCM的是指令,指定显示位置88H(第三行左端)
  73.         lcm_w_test(1,(hh/16)+0x30);//显示十位
  74.         lcm_w_test(1,hh%16+0x30);//显示个位
  75.         lcm_w_word("时");
  76.         //----------------------------------
  77.         if(read_clock(0x83) != mm){//如果1302芯片中的分钟数据与程序中的分钟变量不相等               
  78.                 mm = read_clock(0x83);//刷新程序中的分钟数据
  79.         }
  80.         lcm_w_test(1,(mm/16)+0x30);//向液晶写数据,显示分钟的十位数
  81.         lcm_w_test(1,mm%16+0x30);//向液晶写数据,显示分钟的个位数
  82.         lcm_w_word("分");
  83.         //----------------------------------
  84.         if(read_clock(0x81) != ss){//如果1302芯片中的分钟数据与程序中的秒钟变量不相等(0x81为读秒数据0x80为写秒数据)               
  85.                 ss = read_clock(0x81);//刷新程序中的秒钟数据
  86.         }
  87.         lcm_w_test(1,(ss/16)+0x30);//向液晶写数据,显示分钟的十位数
  88.         lcm_w_test(1,ss%16+0x30);//向液晶写数据,显示分钟的个位数
  89.         lcm_w_word("秒");

  90. //////////////////////////////////////////////////////////////////////
  91.         //=========显示闹钟的设置时间===================       
  92.        
  93.         hour=clk_ala[0];        //取出上一次的闹钟小时值
  94.         minute=clk_ala[1];         //取出上一次的闹钟分钟值
  95.        
  96.         lcm_w_test(0,0x88);
  97.         lcm_w_word("闹钟---");
  98.         //----------------------------       
  99.         lcm_w_test(1,(hour/10)+0x30);//显示小时十位
  100.         lcm_w_test(1,(hour%10)+0x30);//显示小时个位
  101.         //----------------------------
  102.           lcm_w_word(":");
  103.         //----------------------------
  104.         lcm_w_test(1,(minute/10)+0x30);//显示分钟的十位
  105.         lcm_w_test(1,(minute%10)+0x30);//显示分钟的个位
  106.         //----------------------------
  107.         lcm_w_word("----");


  108. /////////////////////////////////////////////////////////////////////////

  109. }
  110. /*****************************************************************************/
  111. //被调数据加一或减一,并检查数据范围,写入1302指定地址保存
  112. void ds_w(void)
  113. {
  114.         item0=time;
  115.         item=((read_clock(address+1))/16)*10 + (read_clock(address+1))%16;//时间的调整
  116.         if(K3 == 0||key_add==1){//如果按动上调键
  117.          item++;//数加 1  
  118.         }
  119.         if(K4 == 0||key_minish==1){//如果按动下调键
  120.            item--;//数减 1
  121.         }
  122.         if(item>max)  item=mini;//查看数值是否在有效范围之内   
  123.         if(item<mini) item=max;//如果数值小于最小值,则自动等于最大值           
  124.         write_clock(0x8e,0x00);//允许写1302芯片操作
  125.         write_clock(address,(item/10)*16+item%10);//转换成16进制写入1302
  126.         write_clock(0x8e,0x80);//写保护,禁止写操作
  127. }

  128. /********************************************************************/
  129. //===============闹钟时间的加减设置======================
  130. void ds_w0(void)
  131. {
  132.   item0=time;

  133.   if(K3 == 0||key_add==1){//如果按动上调键
  134.         item0++;//数加 1
  135.         }
  136.   if(K4 == 0||key_minish==1){//如果按动下调键
  137.         item0--;//数减 1
  138.         }
  139.   if(item0>max) item0=mini;//查看数值是否在有效范围之内
  140.   if(item0<mini)item0=max;//如果数值小于最小值,则自动等于最大值
  141.   time=item0;//调整后的时间重新赋值给time(time为hour或minute),这步很重要,没有将无法更新闹钟数据
  142. }


  143. /**********************************************************************************************************/
  144. //调整时间子函数,设置键、数据范围、上调加一,下调减一功能。
  145. void Set_time(unsigned char sel){ //根据选择调整的相应项目加1并写入DS1302,函数参数是按动设置键的次数
  146.   
  147.         write_com(0x30); write_com(0x06);

  148.         lcm_w_test(0,0x98);//第一参数0表示本行写入指令,指定下面行的 调整 显示起始位置为9AH
  149.         lcm_w_word(">>调整>>    <<<<");//调用字符显示函数,显示 调整字样
  150.   
  151. /*        if(sel==8)  {lcm_w_word("星期");address=0x8a; max=7;mini=1;          
  152.      tiaozheng();
  153.      ds_w();
  154.      tiaozheng();
  155.           }
  156. */
  157. //================================================================
  158.         lcm_w_test(0,0x9c);
  159.         if(sel==7)  {lcm_w_word("闹钟分"); time=minute;max=59;mini=0;        
  160.          tiaozheng();//显示调整前的内容
  161.      ds_w0();//设置闹钟
  162.          clk_ala[1]=time;//把更新后的分钟数据重新保存
  163.      tiaozheng();//显示调整后的内容
  164.           }//按动8次显示 调整闹钟的分钟部分
  165.         if(sel==6)  {lcm_w_word("闹钟时");time=hour; max=23;mini=0;
  166.      tiaozheng();
  167.      ds_w0();
  168.          clk_ala[0]=time;//把更新后的小时数据重新保存
  169.      tiaozheng();
  170.           }//按动7次显示 调整闹钟的小时部分
  171. //================================================================

  172.         if(sel==5)  {lcm_w_word("秒钟");address=0x80; max=59;mini=0;          
  173.         tiaozheng();  //调用日期、时间调整函数
  174.            ds_w();                  //被调数据加一或减一函数
  175.            tiaozheng();
  176.    
  177.         }        //秒6,按动6次显示 调整秒钟   
  178.                 //并指定秒钟数据写入1302芯片的写入地址是0x80,秒钟数据的最大值是59,最小值是0

  179.         if(sel==4)  {lcm_w_word("分钟");address=0x82; max=59;mini=0;
  180.            tiaozheng();
  181.            ds_w();
  182.            tiaozheng();
  183.   
  184.         }        //分钟5,按动5次显示 调整分钟
  185.                 //并指定分钟数据写入1302芯片的地址是0x82,分钟数据的最大值是59,最小值是0

  186.         if(sel==3)  {lcm_w_word("小时");address=0x84; max=23;mini=0;
  187.   
  188.             tiaozheng();
  189.            ds_w();
  190.            tiaozheng();
  191.   
  192.         }        //小时4,按动4次显示 调整小时
  193.                 //规定小时数据写入1302芯片的位置是0x84,小时数据最大值23,最小值是0
  194.   

  195.         if(sel==2)  {lcm_w_word("日期");address=0x86;
  196.                 mo = read_clock(0x89);//读月数据
  197.                 moontemp1=mo/16;
  198.                 moontemp2=mo%16;
  199.                 mo=moontemp1*10+moontemp2;//转换成10进制月份数据

  200.       yy = read_clock(0x8d);//读年数据
  201.       moontemp1=yy/16;
  202.                 moontemp2=yy%16;
  203.                 yy=moontemp1*10+moontemp2;//转换成10进制年份数据

  204.       if(mo==2&&yy%4!=0){max=28;mini=1;}//平年2月28天
  205.                 if(mo==2&&yy%4==0){max=29;mini=1;}//闰年2月29天
  206.                 if(mo==1||mo==3||mo==5||mo==7||mo==8||mo==10||mo==12){max=31;mini=1;}//31天的月份
  207.                 if(mo==4||mo==6||mo==9||mo==11){max=30;mini=1;}//30天的月份
  208.                 tiaozheng();
  209.                 ds_w();
  210.                 tiaozheng(); //调用日期、时间调整函数

  211.   }        //日3,按动3次显示 调整日期
  212.                 //规定日期数据写入1302的位置地址是0x86,日期最大值31,最小值是1



  213.   if(sel==1)  {lcm_w_word("月份");address=0x88; max=12;mini=1;
  214.      tiaozheng();
  215.      ds_w();
  216.      tiaozheng();
  217.   
  218.    }        //月2,按动2次显示 调整月份
  219.                 //规定月份写入1302的位置地址是0x88,月份最大值12,最小值1


  220.   if(sel==0)  {lcm_w_word("年份");address=0x8c; max=99; mini=0;
  221.          tiaozheng();
  222.      ds_w();                //被调数据加一或减一函数
  223.      tiaozheng();        //调用日期、时间调整函数

  224.    }        //年1,按动1次显示 调整年份,
  225.                 //规定年份写入1302的地址是0x8c,年份的最大值99,最小值0

  226. }

  227. /*********************************************************************
  228. **********************************************************************
  229. **************             主函数                                  ****************
  230. **********************************************************************
  231. /********************************************************************/
  232. void main()
  233. {       
  234.         unsigned char e=0,f=0,tmp,i;                     

  235.     IE = 0x81;    //允许总中断中断,使能 INT0 外部中断
  236.     TCON = 0x01;  //触发方式为脉冲负边沿触发   
  237.     IRIN=1;       //IO口初始化
  238.     BEEP=1;
  239.         K1=1;K2=1;K3=1;K4=1;
  240.        
  241.        
  242.         Init_1302();                //时钟芯片初始化
  243.         lcm_init();                        //液晶初始化
  244.         welcome0();  //调用欢迎信息1
  245.         DelayM(2000);//延时
  246.         //welcome();DelayM(1000);  //调用欢迎信息2                
  247.         lcm_clr();            //清屏
  248.         Clean_12864_GDRAM();         //清屏
  249.         while(1)
  250.         {


  251.                 if (w == 0)                  //正常走时
  252.                 {
  253.                         displaydate();         //显示日期
  254.                         displaynl();         //显示农历
  255.                         displaytime();         //显示时间
  256.                         read_temp();         //读取温度
  257.                         ds1820disp();          //显示温度
  258.                         displayxq();         //显示星期
  259.                                
  260.                 //=================以下是闹钟的相关处理===================
  261.                        
  262.                         if(ala_flag==1){//闹钟标志位               
  263.                         set1616pic(6,1,0,2);} //显示"闹钟图标"               
  264.                     else{                                                                               
  265.                         set1616pic(6,1,0,3);}//关闭"闹钟图标"显示

  266.                         //----------------------------------------
  267.                         tmp=read_clock(0x85);//取出1302小时
  268.                         i = tmp/16;
  269.                         tmp = tmp&0x0f;
  270.                         tmp = tmp + i*10;
  271.                         if(clk_ala[0]==tmp)//与闹钟设定的小时值相同
  272.                                 {
  273.                                 tmp=read_clock(0x83);//取出1302分钟
  274.                                 i = tmp/16;
  275.                                 tmp = tmp&0x0f;
  276.                                 tmp = tmp + i*10;
  277.                                         if(clk_ala[1]==tmp)//与闹钟设定的分钟值相同
  278.                                           {
  279.                                                 if(ala_flag==1)//闹钟打开
  280.                                                   {
  281.                                                         alarmbeep();//闹铃声响1分钟后自动关闭,
  282.                                                         DelayM(200);//控制闹钟响的间隔即频率
  283.                                                    }
  284.                                                 else BEEP=1;//关闭蜂鸣器
  285.                                            }
  286.                                          else BEEP=1;//关闭蜂鸣器
  287.                                 }
  288.                         //==============闹钟处理结束=======================
  289.                 }       
  290.                 else {} //========否则启动调时=========================
  291.          
  292.      
  293. /*---------------按键及红外遥控设置时间------------------------------*/               
  294.                 if (K1 == 0||key_manue==1)         
  295.                 {                 
  296.                        
  297.                         DelayM(8);                       //按键消抖
  298. /*当是调时状态 本键用于调整下一项---------------------------------------------------*/               
  299.                         if((K1 == 0 && w == 1)||(key_manue==1&&w==1))      //
  300.                         {
  301.                                        
  302.                                 e++;
  303.                                 if (e >= 8 ) {e = 0;}
  304.                              while(! K1 );            //等待键松开
  305.                           key_manue=0;
  306.                                 Set_time(e); beep();          //调整                               
  307.                         }
  308. /*当是正常状态时就进入调时状态---------------------------------------------------*/               
  309.                         if((K1 == 0 && w == 0)||(key_manue==1&&w==0))  //
  310.                         {       
  311.                                 key_manue=0;
  312.                                 lcm_clr();            
  313.                                 Clean_12864_GDRAM();   //清屏
  314.                                 w=1;                       //进入调时
  315.                                 Set_time(e);beep();
  316.                         }
  317.                            while(K1 == 0);            //等待键松开
  318.                 }
  319. /*当在调时状态时就退出调时---------------------------------------------------*/               
  320.                 if (K2 == 0||key_ok==1)                   //
  321.                 {        beep();
  322.                         DelayM(8);
  323.                         if((K2 == 0 && w == 1)||(key_ok==1&&w==1))
  324.                         {                       
  325.                                 w = 0;                       //退出调时
  326.                                 e = 0;                           //"下一项"计数器清0                                                               
  327.                         }
  328.                         if((K2 == 0 && w == 0)||(key_ok==1&&w==0))
  329.                         {
  330.                                 lcm_clr(); Clean_12864_GDRAM();
  331.                                 write_com(0x30); write_com(0x06);
  332.                                 welcome();       
  333.                                 while(K2 == 0); //按下K2是显示欢迎信息
  334.                                 DelayM(500);key_ok=0;//红外"OK"按键按下时显示0.5秒钟的欢迎界面2                                 
  335.                         }
  336.                         lcm_clr(); Clean_12864_GDRAM();
  337. ……………………

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

所有资料51hei提供下载:
万年历01ok.zip (841.17 KB, 下载次数: 265)




评分

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

查看全部评分

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

使用道具 举报

沙发
ID:312815 发表于 2018-6-28 23:26 | 只看该作者
感谢分享;正需要这个
回复

使用道具 举报

板凳
ID:260833 发表于 2018-6-29 20:07 | 只看该作者
为什么我的老是显示一会儿就不显示
回复

使用道具 举报

地板
ID:380389 发表于 2018-7-29 10:20 来自手机 | 只看该作者
很好,很实用,收藏了
回复

使用道具 举报

5#
ID:367948 发表于 2018-7-31 09:22 | 只看该作者
感谢楼主分享资料,正在学习
回复

使用道具 举报

6#
ID:380389 发表于 2018-7-31 14:38 来自手机 | 只看该作者
感谢分享,字体好看
回复

使用道具 举报

7#
ID:363686 发表于 2018-8-10 06:58 | 只看该作者
学习贴,收藏了,谢谢分享&#128591;
回复

使用道具 举报

8#
ID:324871 发表于 2018-8-10 11:06 | 只看该作者
对这个12864显示大字体不太懂,想参考一下。
回复

使用道具 举报

9#
ID:372098 发表于 2019-3-25 12:00 | 只看该作者
好东西,刚好想做一个
回复

使用道具 举报

10#
ID:404374 发表于 2019-4-4 08:54 | 只看该作者
下载了,时间显示不出来啊
回复

使用道具 举报

11#
ID:508635 发表于 2019-4-10 12:06 | 只看该作者
怎么才能下载呢,金币不足好难受啊
回复

使用道具 举报

12#
ID:404374 发表于 2019-5-9 20:12 | 只看该作者
闹钟不能用是为什么那个大佬知道?
回复

使用道具 举报

13#
ID:404374 发表于 2019-5-9 20:13 | 只看该作者
xsj1877578806 发表于 2018-7-29 10:20
很好,很实用,收藏了

闹钟可以用吗
回复

使用道具 举报

14#
ID:550025 发表于 2019-5-29 11:38 | 只看该作者
感谢分享;正需要这个
回复

使用道具 举报

15#
ID:543653 发表于 2019-5-29 20:28 | 只看该作者
楼主刚学都做这么好啊,真是厉害!
回复

使用道具 举报

16#
ID:323741 发表于 2019-5-30 16:06 | 只看该作者
大字体怎么显示?求教
回复

使用道具 举报

17#
ID:551975 发表于 2019-6-2 13:44 | 只看该作者
可以给封装吗
回复

使用道具 举报

18#
ID:544558 发表于 2019-6-2 21:03 | 只看该作者
请问KEY的封装是什么呀
回复

使用道具 举报

19#
ID:343165 发表于 2019-6-2 23:04 | 只看该作者
这个按键是什么型号的?
回复

使用道具 举报

20#
ID:111376 发表于 2019-12-30 20:41 | 只看该作者
测试效果很好,太好了,感谢分享
回复

使用道具 举报

21#
ID:620287 发表于 2019-12-31 07:49 来自手机 | 只看该作者
Mahdi_51 发表于 2019-4-10 12:06
怎么才能下载呢,金币不足好难受啊

金币可以通过你手上现有的单片机类的资料,在此网站共享出来就可以获取
回复

使用道具 举报

22#
ID:641703 发表于 2020-6-3 16:03 | 只看该作者

感谢分享;正需要这个
回复

使用道具 举报

23#
ID:768919 发表于 2020-6-3 22:18 | 只看该作者
正需要这个
回复

使用道具 举报

24#
ID:171297 发表于 2021-11-28 18:54 | 只看该作者
温度显示不动!
回复

使用道具 举报

25#
ID:242298 发表于 2022-2-12 06:28 | 只看该作者
温度显示不动!
求解答@
回复

使用道具 举报

26#
ID:59830 发表于 2022-2-12 20:32 | 只看该作者
看见显示UI图片,觉得挺好看呢. 看一下代码.
回复

使用道具 举报

27#
ID:149988 发表于 2022-2-19 08:34 | 只看该作者
您好,程序中有计算农历部分吗?谢谢
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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