找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机万年历时钟制作参考代码仿真(LCD12864+ds1302)

[复制链接]
跳转到指定楼层
楼主
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)

单片机源程序如下:
  1. /*
  2. * 万年历
  3. */

  4. #include "main.h"                         //包含头文件main.h
  5. #include "LCD.h"                        //包含头文件LCD.h
  6. #include "DS1302.h"                        //包含头文件DS1302.h
  7. #include "word.h"                        //包含头文件word.h
  8. #include "lunar_calendar.h" //包含头文件lunar_calendar.h
  9. #include "buzz.h"                        //包含头文件buzz.h

  10. #include "eeprom52.h"
  11. TIME time, tmp_time;        //时间变量
  12. ALARM alarm;                                //时间变量
  13. char a_a;
  14. bit Alarm_flag=0;                        //时间变量
  15. bit Clock_flag=0;                        //时间变量
  16. bit flag=0;                                        //时间变量

  17. sbit DQ=P3^7;   //DS18B20 pin 温度传感器引脚

  18. /******************把数据保存到单片机内部eeprom中******************/
  19. void write_eeprom()
  20. {


  21.         SectorErase(0x2c00);                          //清空
  22.         SectorErase(0x2e00);
  23.         byte_write(0x2c01,Alarm_flag);
  24.            byte_write(0x2c02,Clock_flag);
  25.         byte_write(0x2c03,alarm.hour);
  26.         byte_write(0x2c04,alarm.min);
  27.             
  28.         byte_write(0x2060,a_a);       

  29. }

  30. /******************把数据从单片机内部eeprom中读出来*****************/
  31. void read_eeprom()
  32. {
  33.         Alarm_flag=        byte_read(0x2c01);
  34.            Clock_flag=byte_read(0x2c02);
  35.         alarm.hour=byte_read(0x2c03);
  36.         alarm.min=byte_read(0x2c04);

  37.         a_a = byte_read(0x2060);

  38. }

  39. /**************开机自检eeprom初始化*****************/
  40. void init_eeprom()
  41. {
  42.         a_a = byte_read(0x2060);
  43.         if(a_a != 1)                //新的单片机初始单片机内问eeprom
  44.         {
  45.        
  46.                 a_a = 1;
  47.                 write_eeprom();           //保存数据
  48.         }       
  49. }


  50. //-----------------18B20-----------------------
  51. unsigned char L_18B20,H_18B20,zhengshu,shangwen,xiawen;  //温度用变量
  52. unsigned int fg=0,xiaoshu_a;                                                        //温度用变量
  53. //-----------------18B20----------------------


  54. void delay(uint16 n)//延时us级
  55. {
  56.         while (n--);
  57. }
  58. //************************************************************************/
  59. // 函数: LCD_Delay()
  60. // 描述: 延时t ms函数
  61. // 参数: t
  62. // 返回: 无
  63. // 备注: 11.0592MHZ       t=1延时时间约1ms
  64. // 版本:  2015/01/01      First version
  65. //************************************************************************/
  66. void Delay_nms(unsigned int t)
  67. {
  68.         unsigned int i,j;
  69.         for(i=0;i<t;i++)             //循环t次
  70.         for(j=0;j<113;j++)                 //循环113次 每次约3us
  71.         ;
  72. }
  73. /////////////////////////////////////////////////
  74. //-----------播放音乐----------------------------

  75. /////////////////////////////////////////////////
  76. /*------DS18B20------*/
  77. void delay_18B20(unsigned int i)
  78. {
  79.         while(i--);
  80. }
  81. /*DS18B20的复位脉冲 主机通过拉低单总线至少480us以产生复位脉冲
  82.   然后主机释放单总线并进入接收模式 此时单总线电平被拉高
  83.   DS18B20检测到上升沿后 延时15~60us,拉低总线60~240us产生应答脉冲  */                                               
  84. void Init_DS18B20(void)
  85. {
  86.          unsigned char x=0;
  87.          DQ = 1;          //DQ复位
  88.          delay_18B20(8);  //稍做延时
  89.          DQ = 0;          //单片机将DQ拉低
  90.          delay_18B20(80); //精确延时 大于 480us
  91.          DQ = 1;          //拉高总线
  92.          delay_18B20(14); //延时
  93.          x=DQ;            //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
  94.          delay_18B20(20); //延时
  95. }

  96. /*写时隙 主机在写1时隙向DS18B20写入1,在写0时隙向DS18B20写入0
  97.   所有写时隙至少需要60us,且在两次写时隙之间至少需要1us的恢复时间
  98.   两种写时隙均以主机拉低总线开始
  99.   产生写1时隙:主机拉低总线后,必须在15us内释放总线,由上拉电阻拉回至高电平
  100.   产生写0时隙:主机拉低总线后,必须整个时隙保持低电平 */
  101. void WriteOneChar(unsigned char dat)
  102. {
  103.         unsigned char i=0;
  104.         for (i=8; i>0; i--)//循环8次
  105.         {
  106.                   DQ = 0;                        //DQ输出0
  107.                 DQ = dat&0x01;
  108.             delay_18B20(5); //延时
  109.                 DQ = 1;         //DQ输出1
  110.             dat>>=1;        //右移位
  111. }
  112. }
  113.   
  114. /*所有读时隙至少60us 且两次独立的读时隙之间至少需要1us的恢复时间
  115.   每次读时隙由主机发起,拉低总线至少1us。
  116.   若传1,则保持总线高电平;若发送0,则拉低总线
  117.   传0时DS18B20在该时隙结束时释放总线,再拉回高电平状态,主机必须在读时隙开始后的15us内释放总线,并保持采样总线状态 */
  118. unsigned char ReadOneChar(void)
  119. {
  120.         unsigned char i=0;
  121.         unsigned char dat = 0;
  122.         for (i=8;i>0;i--)
  123.          {
  124.                   DQ = 0;                 // 给脉冲信号
  125.                   dat>>=1;      //移位
  126.                   DQ = 1;                 // 给脉冲信号
  127.                   if(DQ)       //如果DQ=1,执行下面的语句   
  128.                   dat|=0x80;
  129.                   delay_18B20(4);//延时
  130.          }
  131.         return(dat);                //返回数据
  132. }
  133.                  

  134. void read_18B20(void)
  135. {

  136.         Init_DS18B20();
  137.         WriteOneChar(0xCC);            // 跳过读序号列号的操作
  138.         WriteOneChar(0x44);         // 启动温度转换

  139.         delay_18B20(100);       // this message is wery important

  140.         Init_DS18B20();                        //初始化DS18B20
  141.         WriteOneChar(0xCC);         //跳过读序号列号的操作
  142.         WriteOneChar(0xBE);         //读取温度寄存器等(共可读9个寄存器) 前两个就是温度

  143.         delay_18B20(100);                //延时

  144.         L_18B20=ReadOneChar();        //读取低八位数据
  145.         H_18B20=ReadOneChar();        //读取高八位数据

  146.         zhengshu=L_18B20/16+H_18B20*16; //整数部分
  147.         xiaoshu_a=(L_18B20&0x0f)*10/16; //小数第一位
  148. }
  149. //------------------DS18B20---------------------
  150. /////////////////////////////////////////////////
  151. /*
  152. * 按键扫描
  153. */
  154. int8 scan_key(void)
  155. {
  156.         int8 val=-1;                  //初始化键值为-1

  157.         if (KeyIn1 == 0)                 //判断=0?有无按键按键
  158.         {
  159.                 val = 1;                         //键值=1
  160.                 while (KeyIn1 == 0); //等待按键释放
  161.         }
  162.         else if (KeyIn2 == 0)         //判断=0?有无按键按键
  163.         {
  164.                 val = 2;                        //键值=2
  165.                 while (KeyIn2 == 0);//等待按键释放
  166.         }
  167.         else if (KeyIn3 == 0)        //判断=0?有无按键按键
  168.         {
  169.                 val = 3;                        //键值=3
  170.                 while (KeyIn3 == 0);//等待按键释放
  171.         }

  172.         //if (val > 0)
  173.                 //buzzer_sound();

  174.         return val;                                //返回键值
  175. }

  176. /*
  177. * 主界面框架
  178. */
  179. void main_frame(void)
  180. {
  181.         play32(80, 2, 10); //显示数
  182.         play32(32, 2, 10); //显示数
  183.         play8(16, 0, S_xie);//显示斜线
  184.         play8(40, 0, S_xie);//显示斜线
  185. //        play8(96, 0, RH);
  186. //        play8(120, 0, S_percent);
  187.         play8(120, 6, S_du);//显示度
  188. }

  189. /*
  190. * 主界面
  191. */
  192. void main_show(bit refresh)
  193. {
  194.     uint8  lunar[2];
  195.         if (refresh)
  196.                 read_time((uint8 *)&time);// 读时间函数// 时间                                                                                          
  197.         if (refresh || (time.sec != tmp_time.sec)) // 秒更新
  198.         {
  199.                 tmp_time.sec = time.sec;                                  //读取秒数据
  200.             play8_num(104, 6,zhengshu);                           //温度显示
  201.                 play32_num(96, 2, time.sec);                        //显示秒


  202.         }
  203.         if (refresh)
  204.                 main_frame();//刷新界面
  205.         if (refresh || (time.min != tmp_time.min)) // 分更新
  206.         {
  207.                 if (!refresh)
  208.                         flag = 0;
  209.                 tmp_time.min = time.min;//读取分
  210.                 play32_num(48, 2, time.min); //显示分
  211.         }
  212.         if (refresh || (time.hour != tmp_time.hour)) // 时更新
  213.         {
  214.                 if ((!refresh)&&(Clock_flag))
  215.                         alarm_sound();
  216.                 tmp_time.hour = time.hour;                                 //读取时
  217.                 play32_num(0, 2, time.hour);                        //显示时
  218.         }
  219.         if (refresh || (time.day != tmp_time.day))  //日更新
  220.         {
  221.                 tmp_time.day = time.day;                                //读取日
  222.                 play8_num(48, 0, time.day);                                //显示日
  223.                 // 农历       
  224.                 turn_lunar_calendar(&time, lunar);
  225.                 play_lunar_calendar(0, 6, lunar[0], lunar[1]);
  226.         }
  227.         if (refresh || (time.week != tmp_time.week)) // 周更新
  228.         {
  229.                 tmp_time.week = time.week;                                //读取周
  230.                 play_week(68, 0, time.week);                        //显示周
  231.         }
  232.         if (refresh || (time.mon != tmp_time.mon))  // 月更新
  233.         {
  234.                 tmp_time.mon = time.mon;                                //读取月
  235.                 play8_num(24, 0, time.mon);                                //显示月
  236.                 // 农历       
  237.                 turn_lunar_calendar(&time, lunar);                                //转换农历月
  238.                 play_lunar_calendar(0, 6, lunar[0], lunar[1]);        //显示农历月
  239.         }

  240.         if (refresh || (time.year != tmp_time.year)) // 年更新
  241.         {
  242.                 tmp_time.year = time.year;                                        //读取年数据
  243.                 play8_num(0, 0, time.year);                                        //显示年
  244.                 // 农历       
  245.                 turn_lunar_calendar(&time, lunar);                                //转换农历年
  246.                 play_lunar_calendar(0, 6, lunar[0], lunar[1]);        //显示农历年
  247.         }
  248.        
  249. }
  250. /*
  251. * 主机界面设置
  252. */
  253. void main_set(void)
  254. {
  255.         int8 key_val, state=1;                                 //变量
  256.         play32_num(96, 2|0x80, time.sec);        //显示秒


  257.         while (1)
  258.         {        key_val = scan_key();//键盘扫描
  259.                 if (key_val == 1) // 设置
  260.                 {
  261.                         if (state >= 7)
  262.                                 state = 0;
  263.                         else
  264.                                 state++;                                //位置状态加1
  265.                         set_time((uint8 *)&time);        //设置时间
  266.                         main_show(1);                                //显示主界面

  267.                         switch (state)
  268.                         {        case 0:        set_time((uint8 *)&time); break;//设置时间
  269.                                 case 1:        play32_num(96, 2|0x80, time.sec); break;//显示秒
  270.                                 case 2:        play32_num(48, 2|0x80, time.min); break;//显示分
  271.                                 case 3:        play32_num(0, 2|0x80, time.hour); break;//显示时
  272.                                 case 4:        play_week(68, 0|0x80, time.week); break;//显示周
  273.                                 case 5:        play8_num(48, 0|0x80, time.day); break; //显示日
  274.                                 case 6:        play8_num(24, 0|0x80, time.mon); break; //显示月
  275.                                 case 7:        play8_num(0, 0|0x80, time.year); break; //显示年
  276.                
  277.                                 default: break;                //退出循环                                                  
  278.                         }
  279.                 }
  280.                 else if (key_val > 1)//按键值大于1
  281.                 {
  282.                         if (state == 1)//位置1设置秒
  283.                         {
  284.                                 if (key_val == 3)//加按下?
  285.                                         time.sec++;//秒加1
  286.                                 else
  287.                                         time.sec--; //秒减1
  288.                                 if (time.sec >= 60)
  289.                                         time.sec = 0;
  290.                                 else if (time.sec < 0)
  291.                                         time.sec = 59;      
  292.                                 play32_num(96, 2|0x80, time.sec);//显示秒
  293.                         }
  294.                         else if (state == 2)                                //位置2设置分
  295.                         {
  296.                                 if (key_val == 3)                                //加按下?
  297.                                         time.min++;                                        //加1
  298.                                 else
  299.                                         time.min--;                                        //减1
  300.                                 if (time.min >= 60)
  301.                                         time.min = 0;
  302.                                 else if (time.min < 0)
  303.                                         time.min = 59;
  304.                                 play32_num(48, 2|0x80, time.min);//显示分
  305.                         }
  306.                         else if (state == 3)                                //位置3设置时
  307.                         {                if (key_val == 3)                                //加按下?
  308.                                         time.hour++;                                //加1
  309.                                 else
  310.                                         time.hour--;                                //减1
  311.                                 if (time.hour >= 24)
  312.                                         time.hour = 0;
  313.                                 else if (time.hour < 0)
  314.                                         time.hour = 23;
  315.                                 play32_num(0, 2|0x80, time.hour);//显示时
  316.                         }
  317.                         else if (state == 4)                                //位置4设置周
  318.                         {                if (key_val == 3)                        //加按下?
  319.                                         time.week++;                                //加1
  320.                                 else
  321.                                         time.week--;                                //减1
  322.                                 if (time.week >= 8)
  323.                                         time.week = 1;
  324.                                 else if (time.week < 1)
  325.                                         time.week = 7;
  326.                                 play_week(68, 0|0x80, time.week);//显示周
  327.                         }
  328.                         else if (state == 5)//位置5设置日
  329.                         {
  330.                                 if (key_val == 3)                                //加按下?
  331.                                         time.day++;                                        //加1
  332.                                 else
  333.                                         time.day--;                                        //减1
  334.                                 if (time.day >= 32)
  335.                                         time.day = 1;
  336.                                 else if (time.day < 1)
  337.                                         time.day = 31;
  338.                                 play8_num(48, 0|0x80, time.day);//显示日
  339.                         }
  340.                         else if (state == 6)                                //位置6设置月
  341.                         {
  342.                                 if (key_val == 3)                                //加按下?
  343.                                         time.mon++;                                        //加1
  344.                                 else
  345.                                         time.mon--;                                        //减1
  346.                                 if (time.mon >= 13)
  347.                                         time.mon = 1;
  348.                                 else if (time.mon < 1)
  349.                                         time.mon = 12;
  350.                                 play8_num(24, 0|0x80, time.mon);//显示月
  351.                         }
  352.                         else if (state == 7)                                //位置7设置年
  353.                         {
  354.                                 if (key_val == 3)                                //加按下?
  355.                                         time.year++;                                //加1
  356.                                 else
  357.                                         time.year--;                                //减1
  358.                                 if (time.year >= 100)
  359.                                         time.year = 0;                                //0年
  360.                                 else if (time.year < 0)
  361.                                         time.year = 99;                                //99年
  362.                                 play8_num(0, 0|0x80, time.year);//显示年
  363.                         }
  364.                        
  365.                         else
  366.                         {
  367.                                 break;                //退出循环
  368.                         }
  369.                 }
  370.                 if (state == 0)
  371.                         break;                //退出循环
  372.         }
  373. }

  374. /*
  375. * 闹钟界面显示
  376. */
  377. void alarm_show(void)
  378. {
  379.         int8 key_val, state=1;
  380.         uint32 t=0;

  381.         play16(0, 0, nao);                        //显示 闹
  382.         play16(16, 0, zhong);                //钟
  383.         play16(32, 0, maohao);                //冒号:
  384.         if (Alarm_flag)
  385.                 play16(48, 0, kai);                //开
  386.         else
  387.                 play16(48, 0, guan);//关
  388.         play32_num(32, 2, alarm.hour);        //时
  389.         play32(64, 2, 10);                                //冒号
  390.         play32_num(80, 2, alarm.min);        //分
  391.         play16(0, 6, zheng);                        //显示 整
  392.         play16(16, 6, dian);                        //显示 点
  393.         play16(32, 6, bao);                                //显示 报
  394.         play16(48, 6, shi);                                //显示 时
  395.         play16(64, 6, maohao);                        //显示 冒号
  396.         if (Clock_flag)
  397.                 play16(80, 6, kai);                        //显示 开
  398.         else
  399.                 play16(80, 6, guan);                //显示 关       
  400.         for (t=0; t<30000; t++)
  401.         {        key_val = scan_key();                //键盘扫描 获取键值
  402.                 if (key_val > 1)                        //判断数据
  403.                         break;
  404.                 else if (key_val == 1)                //判断数据
  405.                 {
  406.                         if (Alarm_flag)
  407.                                 play16(48, 0|0x80, kai);//显示 开
  408.                         else
  409.                                 play16(48, 0|0x80, guan);//关                       
  410. ……………………

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

仿真与代码51hei附件下载:
智能时钟.zip (447.09 KB, 下载次数: 110)

评分

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

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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