找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 9970|回复: 5
收起左侧

51单片机电子日历(可调整 带温度)DS1302时钟+12864LCD显示

  [复制链接]
ID:220429 发表于 2017-7-27 15:30 | 显示全部楼层 |阅读模式
可按照程序接线
51单片机显示时间(可调整)(DS1302时钟+12864LCD显示)

仿真原理图如下:

仿真

仿真


单片机源程序如下:
  1. /****************************************/
  2. /*        带温度显示的电子日历                */
  3. /****************************************/

  4. #include<reg51.h>
  5. #include<intrins.h>
  6. #include<string.h>
  7. #define uchar unsigned char
  8. #define uint unsigned int
  9. sbit DQ=P2^7;
  10. sbit CS1=P2^1;    //定义选择芯片左半屏信号
  11. sbit CS2=P2^2;    //定义选择芯片右半屏信号
  12. sbit DI=P2^5;     //定义选择显示类型
  13. sbit RW=P2^4;     //定义读写信号
  14. sbit E=P2^3;      //定义数据锁存信号
  15. sbit IO=P1^0;          //DS1302数据线
  16. sbit CLK=P1^1;          //DS1302时钟线
  17. sbit RST=P1^2;          //DS1302复位线
  18. sbit s1=P3^0;
  19. sbit s2=P3^1;
  20. sbit s3=P3^2;                 
  21. uchar Time_Buffer[7]; //日期缓存,0-6依次为秒、分、时、日、月、周日、年
  22. uint Temp,Temp1;
  23. bit Temp_Flag;
  24. uchar s1num;
  25. uchar flag_year=0,flag_moon=0,flag_day=0,flag_hour=0,flag_min=0,flag_sec=0,flag_week=0;
  26. uchar tempa;
  27. uchar t0_num;
  28. void delayms(uint xms);
  29. void Write_1302(uchar addr,uchar dat);
  30. void keyscan();
  31. void time_adj();

  32. /*--年,月,日,星期,时,分,秒,汉字点阵(16*16)--*/
  33. uchar code Date_Time_Words[]=
  34. {
  35. 0x40,0x20,0x10,0x0C,0xE3,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0x02,0x00,0x00,//年
  36. 0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x04,0x04,0x00,
  37. 0x00,0x00,0x00,0x00,0x00,0xFF,0x11,0x11,0x11,0x11,0x11,0xFF,0x00,0x00,0x00,0x00,//月
  38. 0x00,0x40,0x20,0x10,0x0C,0x03,0x01,0x01,0x01,0x21,0x41,0x3F,0x00,0x00,0x00,0x00,
  39. 0x00,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,0x00,0x00,//日
  40. 0x00,0x00,0x00,0x3F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x3F,0x00,0x00,0x00,0x00,
  41. 0x00,0x00,0x00,0xBE,0x2A,0x2A,0x2A,0xEA,0x2A,0x2A,0x2A,0x2A,0x3E,0x00,0x00,0x00,//星
  42. 0x00,0x48,0x46,0x41,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x49,0x49,0x41,0x40,0x00,
  43. 0x00,0x04,0xFF,0x54,0x54,0x54,0xFF,0x04,0x00,0xFE,0x22,0x22,0x22,0xFE,0x00,0x00,//期
  44. 0x42,0x22,0x1B,0x02,0x02,0x0A,0x33,0x62,0x18,0x07,0x02,0x22,0x42,0x3F,0x00,0x00,
  45. 0x00,0xFC,0x44,0x44,0x44,0xFC,0x10,0x90,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x00,//时
  46. 0x00,0x07,0x04,0x04,0x04,0x07,0x00,0x00,0x03,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,
  47. 0x80,0x40,0x20,0x98,0x87,0x82,0x80,0x80,0x83,0x84,0x98,0x30,0x60,0xC0,0x40,0x00,//分
  48. 0x00,0x80,0x40,0x20,0x10,0x0F,0x00,0x00,0x20,0x40,0x3F,0x00,0x00,0x00,0x00,0x00,
  49. 0x12,0x12,0xD2,0xFE,0x91,0x11,0xC0,0x38,0x10,0x00,0xFF,0x00,0x08,0x10,0x60,0x00,//秒
  50. 0x04,0x03,0x00,0xFF,0x00,0x83,0x80,0x40,0x40,0x20,0x23,0x10,0x08,0x04,0x03,0x00
  51. } ;
  52. //星期几的汉字点阵
  53. uchar code Weekday_Words[]=
  54. {
  55. 0x00,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,0x00,0x00,//日
  56. 0x00,0x00,0x00,0x3F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x3F,0x00,0x00,0x00,0x00,
  57. 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0x80,0x00,//一
  58. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  59. 0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x04,0x00,0x00,0x00,//二
  60. 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x18,0x10,0x00,
  61. 0x00,0x04,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x04,0x00,0x00,//三
  62. 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,
  63. 0x00,0xFE,0x02,0x02,0x02,0xFE,0x02,0x02,0xFE,0x02,0x02,0x02,0x02,0xFE,0x00,0x00,//四
  64. 0x00,0x7F,0x28,0x24,0x23,0x20,0x20,0x20,0x21,0x22,0x22,0x22,0x22,0x7F,0x00,0x00,
  65. 0x00,0x02,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0xC2,0x82,0x02,0x00,0x00,0x00,//五
  66. 0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x30,0x20,0x00,
  67. 0x10,0x10,0x10,0x10,0x10,0x91,0x12,0x1E,0x94,0x10,0x10,0x10,0x10,0x10,0x10,0x00,//六
  68. 0x00,0x40,0x20,0x10,0x0C,0x03,0x01,0x00,0x00,0x01,0x02,0x0C,0x78,0x30,0x00,0x00
  69. };

  70. //温度显示汉字点阵
  71. uchar code Templt[]=
  72. {
  73. 0x10,0x22,0x64,0x0C,0x80,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0xFF,0x02,0x00,0x00,//温
  74. 0x04,0x04,0xFE,0x01,0x40,0x7E,0x42,0x42,0x7E,0x42,0x7E,0x42,0x42,0x7E,0x40,0x00,
  75. 0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0xA5,0xA6,0xA4,0xFC,0x24,0x34,0x26,0x04,0x00,//度
  76. 0x40,0x20,0x9F,0x80,0x42,0x42,0x26,0x2A,0x12,0x2A,0x26,0x42,0x40,0xC0,0x40,0x00,
  77. 0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//:
  78. 0x00,0x00,0x00,0x00,0x31,0x7B,0x7B,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  79. 0x00,0x02,0x05,0xE2,0x18,0x04,0x02,0x02,0x02,0x02,0x02,0x02,0x04,0x1E,0x00,0x00,//℃
  80. 0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x18,0x00,0x00

  81. };

  82. //半角数字点阵
  83. uchar code Digits[]=
  84. {
  85. 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0
  86. 0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1
  87. 0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2
  88. 0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3
  89. 0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4
  90. 0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5
  91. 0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6
  92. 0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7
  93. 0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8
  94. 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9
  95. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//.
  96. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00        //' '
  97. };

  98. /*--屏幕显示--*/
  99. void left()//左半屏显示
  100. {
  101. CS1=1;
  102. CS2=0;
  103. }
  104. void right()//右半屏显示
  105. {
  106. CS1=0;
  107. CS2=1;
  108. }

  109. /*--判断LCD是否繁忙--*/
  110. void LCD_Check_Busy()
  111. {        
  112. do
  113. {
  114. E=0;
  115. DI=0;
  116. RW=1;
  117. P0=0xff;
  118. E=1;
  119. _nop_();
  120. E=0;
  121. }
  122. while(P0&0x80);//P0.7口
  123. }

  124. /*--向LCD发送命令--*/
  125. void LCD_Write_Command(uchar c)
  126. {
  127.         LCD_Check_Busy();
  128.         P0=0xFF ;
  129. RW=0;
  130. DI=0;
  131.         P0=c ;
  132.          E=1;
  133. E=0;
  134. }

  135. /*--向LCD发送数据--*/
  136. void LCD_Write_Date(uchar d)
  137. {
  138.         LCD_Check_Busy();
  139.         P0=0xFF ;
  140. RW=0;
  141. DI=1;
  142. E=1;
  143. _nop_();
  144.         P0=d ;
  145.          E=0;
  146. _nop_();
  147. }

  148. /*--设置初始页--*/
  149. void page_first(uchar p)
  150. {
  151. uchar i=p;
  152. p=i|0xb8;
  153. LCD_Check_Busy();
  154.          LCD_Write_Command(p);
  155. }

  156. /*--设置初始列--*/
  157. void col_first(uchar c)
  158. {
  159.         uchar i=c;
  160.         c=i|0x40;
  161.         LCD_Check_Busy();
  162.         LCD_Write_Command(c);
  163. }

  164. /*--任意位置显示汉字--*/
  165. void Display_Word(uchar page,uchar col,uchar*s)
  166. {
  167.         uchar i,j;
  168.         page_first(page);//上半部
  169.         col_first(col);
  170.          for(i=0;i<16;i++)
  171.         {
  172.                 LCD_Write_Date(*s);
  173. s++;
  174.         }
  175.         page_first(page+1);//下半部
  176.         col_first(col);
  177.         for(j=0;j<16;j++)
  178.         {
  179.                 LCD_Write_Date(*s);
  180.                 s++;
  181.         }
  182. }

  183. /*--任意位置显示字符--*/
  184. void Display_Char(uchar page,uchar col,uchar*s)
  185. {
  186.         uchar i,j;
  187.         page_first(page);//上半部
  188.         col_first(col);
  189.          for(i=0;i<8;i++)
  190.         {
  191.                 LCD_Write_Date(*s);
  192. s++;
  193.         }
  194.         page_first(page+1);//下半部
  195.         col_first(col);
  196.         for(j=0;j<8;j++)
  197.         {
  198.                 LCD_Write_Date(*s);
  199.                 s++;
  200.         }
  201. }

  202. /*--初始化LCD --*/
  203. void LCD_initialize()
  204. {
  205.         CS1=1;
  206.     CS2=1;
  207.         LCD_Write_Command(0x38); //8位形式,2行字符
  208.         LCD_Write_Command(0x0F); //开显示
  209.         LCD_Write_Command(0x01); //清屏
  210.         LCD_Write_Command(0x06); //画面不动光标右移
  211.         LCD_Write_Command(0xC0);//设置起始行
  212. }

  213. /*--向DS1302写入一字节--*/
  214. void Write_A_Byte_To_1302(uchar x)
  215. {
  216.          uchar i;
  217.         for(i=0;i<8;i++)
  218.         {
  219.                  IO=x&0x01; CLK=1;CLK=0;x>>=1;
  220.         }
  221. }
  222. /*--从DS1302读取一字节--*/
  223. uchar Receive_A_Byte_From_1302()
  224. {
  225.          uchar i,b=0x00;
  226.         for(i=0;i<8;i++)
  227.         {
  228.                  b |= _crol_((uchar)IO,i);
  229.                 CLK=1;CLK=0;
  230.         }
  231.         return b/16*10+b%16;
  232. }

  233. /*--从DS1302指定位置读数据--*/
  234. uchar Read_1302(uchar addr)
  235. {
  236.          uchar dat;
  237.         RST = 0;CLK=0;RST=1;
  238.            Write_A_Byte_To_1302(addr);
  239.         dat = Receive_A_Byte_From_1302();
  240.            CLK=1;RST=0;
  241.         return dat;
  242. }

  243. /*--向DS1302某地址写入数据--*/
  244. void Write_1302(uchar addr,uchar dat)
  245. {
  246.          CLK=0; RST=0;
  247.          Write_A_Byte_To_1302(addr);
  248.          Write_A_Byte_To_1302(dat);
  249.          CLK=0;RST=0;
  250. }

  251. /*--读取当前日期时间--*/
  252. void Get_Time()
  253. {
  254.         uchar i;
  255.         for(i=0;i<7;i++)
  256.         {
  257.                 Time_Buffer[i]=Read_1302(0x81+2*i);
  258.         }
  259. }

  260. /*--定时器0每秒刷新LCD显示--*/
  261. void T0_INT() interrupt 1
  262. {
  263.         TH0=(65536-50000)/256;
  264.            TL0=(65536-50000)%256;
  265.         t0_num++;
  266.     left();//显示左半屏
  267.         if(flag_year==0)         
  268.          {
  269.           Display_Char(0,16,Digits+ Time_Buffer [6]/10*16);//显示年的十位数,占8列
  270.           Display_Char(0,24,Digits+ Time_Buffer [6]%10*16); //显示年的个位数,占8列
  271.          }
  272.         else
  273.          {
  274.           if(t0_num<=5)
  275.            {
  276.                 Display_Char(0,16,Digits+ Time_Buffer [6]/10*16);//显示年的十位数,占8列
  277.             Display_Char(0,24,Digits+ Time_Buffer [6]%10*16); //显示年的个位数,占8列
  278.            }
  279.           if(t0_num>5&&t0_num<=10)
  280.            {
  281.                 if(t0_num==10)t0_num=0;
  282.                 Display_Char(0,16,Digits+ Digits[11]/10*16);//显示年的十位数,占8列
  283.             Display_Char(0,24,Digits+ Digits[11]%10*16); //显示年的个位数,占8列
  284.            }
  285.          }
  286.         Display_Char(0,48,Digits+ Time_Buffer [4]/10*16); //显示月的十位数,占8列
  287.         Display_Char(0,56,Digits+ Time_Buffer [4]%10*16); //显示月的个位数,占8列
  288.         right();//显示右半屏
  289.         Display_Char(0,80,Digits+ Time_Buffer [3]/10*16); //显示日的十位数,占8列
  290.         Display_Char(0,88,Digits+ Time_Buffer [3]%10*16); //显示日的个位数,占8列
  291.         left();//显示左半屏
  292.         Display_Char(2,16,Digits+ Time_Buffer [2]/10*16); //显示时的十位数,占8列
  293.         Display_Char(2,24,Digits+ Time_Buffer [2]%10*16); //显示时的个位数,占8列
  294.         left();//显示左半屏
  295.         Display_Char(2,48,Digits+ Time_Buffer [1]/10*16); //显示分的十位数,占8列
  296.         Display_Char(2,56,Digits+ Time_Buffer [1]%10*16); //显示分的个位数,占8列
  297.         right();//显示右半屏,秒显示在右半屏部分
  298.         Display_Char(2,80,Digits+ Time_Buffer [0]/10*16); //显示秒的十位数,占8列
  299.         Display_Char(2,88,Digits+ Time_Buffer [0]%10*16); //显示秒的个位数,占8列
  300.         right();//显示右半屏
  301.         Display_Word(4,64,Weekday_Words+( Time_Buffer [5]-1)*32);//显示周日,占16列        
  302.         left();//显示左半屏,温度
  303.         Display_Char(6,48,Digits+ Temp1/100*16); //显示温度十位数,占8列
  304.         Display_Char(6,56,Digits+ Temp1%100/10*16); //显示温度个位数,占8列
  305.     right();//显示右半屏
  306.         Display_Char(6,64,Digits+ 10*16); //显示温度小数点,占8列
  307.         Display_Char(6,72,Digits+ Temp%10*16); //显示温度十分位数,占8列
  308. }

  309. /*--定时器0初始化程序--*/
  310. void Time0_initialize()
  311. {
  312.         EA=1;//开总中断
  313.         ET0=1;//开定时/计数器0中断
  314.         TMOD=0x01;//设置工作方式1
  315.         TH0=(65536-50000)/256;//放入计数初值
  316.         TL0=(65536-50000)%256;//放入计数初值
  317.         TR0=1;//开定时/计数器0
  318. }

  319. /*--显示固定汉字:年月日 ,星期,时分秒*/
  320. void Display()
  321. {
  322.         left();//左半屏显示
  323.         Display_Char(0,0,Digits+2*16);//显示2
  324.         Display_Char(0,8,Digits);//显示0
  325.         /*--显示固定汉字:年月日 ,星期,时分秒*/
  326.         Display_Word(0,32,Date_Time_Words+0*32);        //"年"字的显示
  327.         right();//右半屏显示
  328.         Display_Word(0,64,Date_Time_Words+1*32);        //"月"字的显示
  329.         Display_Word(0,96,Date_Time_Words+2*32);        //"日"字的显示
  330.     left();//左半屏显示
  331.     Display_Word(2,32,Date_Time_Words+5*32);    //"时"字的显示
  332.         right();//右半屏显示
  333.         Display_Word(2,64,Date_Time_Words+6*32);    //"分"字的显示
  334.         Display_Word(2,96,Date_Time_Words+7*32);    //"秒"字的显示,秒显示在右半屏
  335.         left();//左半屏显示
  336.         Display_Word(4,32,Date_Time_Words+3*32);     //"星"字的显示
  337.         Display_Word(4,48,Date_Time_Words+4*32);    //"期"字的显示
  338.         left();//左半屏显示
  339.     Display_Word(6,0,Templt+0*32);    //"温"字的显示
  340.         Display_Word(6,16,Templt+1*32);    //"度"字的显示
  341.         Display_Word(6,32,Templt+2*32);    //":"字的显示
  342.         right();//右半屏显示
  343.         Display_Word(6,80,Templt+3*32);     //"℃"字的显示
  344. }


  345. void delayms(uint xms)
  346. {
  347.   uint y;
  348.   while(xms--)for(y=110;y>0;y--);
  349. }
  350. //us级延时函数
  351. void Delayus(uchar xus)//晶振为12MHz,延时时间为2i+5 us
  352. {
  353.         while(--xus);
  354. }

  355. //初始化DS18B20函数
  356. bit Init_DS18B20(void)
  357. {
  358.         bit x;
  359.         DQ=1;
  360.         DQ=0;
  361.         Delayus(250);
  362.         DQ=1;
  363.         Delayus(20);
  364.         if(!DQ) x=0;
  365.         else x=1;
  366.         Delayus(250);
  367.         DQ=1;
  368.         return x;
  369. }

  370. //读DS18B20函数
  371. uchar Read_DS18B20(void)
  372. {
  373.         uchar i=0,Dat=0;
  374.         for(i=0;i<8;i++)
  375.         {
  376.                 DQ=1;
  377.                 DQ=0;
  378.                 Dat>>=1;
  379.                 DQ=1;
  380.                 if(DQ) Dat |= 0x80;
  381.                 DQ=1;
  382.                 Delayus(30);
  383.         }
  384.         return Dat;
  385. }


  386. //写DS18B20函数
  387. void Write_DS18B20(uchar Dat)
  388. {
  389.         uchar i=0;
  390.         for(i=0;i<8;i++)//循环8次,写入一个字节
  391.         {
  392.                 DQ=1;//未发送前的状态
  393.                 Dat >>= 1;//将要传送的最低位放入CY
  394.                 DQ=0;//将总线拉低,产生写时序
  395.                 DQ=CY;//将要传送的位状态送到总线上
  396.                 Delayus(30);//延时50us,即保持总线状态,待DS18B20采样
  397.                 DQ=1;//恢复期,总线置1
  398.         }
  399. }

  400. //取温度函数
  401. void GetTemp(void)//获取温度函数
  402. {
  403.         uchar a=0,b=0;
  404.         TR0=0;//关闭定时器,防止定时器中断干扰DS18B20
  405.         
  406. ……………………

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

所有资料51hei提供下载:
51单片机显示时间(可调整)(DS1302时钟 12864LCD显示).docx (61.09 KB, 下载次数: 202)

评分

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

查看全部评分

回复

使用道具 举报

ID:189697 发表于 2017-8-3 18:53 | 显示全部楼层
好巧啊  我也有一个这样的程序
回复

使用道具 举报

ID:609509 发表于 2019-9-9 15:37 | 显示全部楼层
不错啊 很有条理
回复

使用道具 举报

ID:781187 发表于 2020-6-17 10:37 | 显示全部楼层
在仿真图上12864不显示怎么回事
回复

使用道具 举报

ID:812792 发表于 2020-8-10 11:00 | 显示全部楼层
请问您的程序包括键入的程序么
回复

使用道具 举报

ID:780721 发表于 2020-12-2 18:28 | 显示全部楼层
程序有问题
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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