找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于51单片机的多功能电子时钟设计

[复制链接]
跳转到指定楼层
楼主
ID:890502 发表于 2021-8-10 21:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include <reg52.h>
  2. #include <intrins.h>

  3. #define uchar unsigned char        // 以后unsigned char就可以用uchar代替
  4. #define uint  unsigned int        // 以后unsigned int 就可以用uint 代替

  5. sfr ISP_DATA  = 0xe2;                // 数据寄存器
  6. sfr ISP_ADDRH = 0xe3;                // 地址寄存器高八位
  7. sfr ISP_ADDRL = 0xe4;                // 地址寄存器低八位
  8. sfr ISP_CMD   = 0xe5;                // 命令寄存器
  9. sfr ISP_TRIG  = 0xe6;                // 命令触发寄存器
  10. sfr ISP_CONTR = 0xe7;                // 命令寄存器

  11. sbit LcdRs_P    = P2^7;               // 1602液晶的RS管脚      
  12. sbit LcdRw_P   = P2^6;               // 1602液晶的RW管脚
  13. sbit LcdEn_P   = P2^5;               // 1602液晶的EN管脚
  14. sbit RST_P     = P1^3;                        // 时钟芯片DS1302的RST管脚
  15. sbit SDA_P     = P1^2;                        // 时钟芯片DS1302的SDA管脚
  16. sbit SCK_P     = P1^1;                        // 时钟芯片DS1302的SCK管脚
  17. sbit KeySet_P   = P3^2;                        // 设置时间按键
  18. sbit KeyClock_P = P3^3;                        // 设置闹钟按键
  19. sbit KeyDown_P  = P3^4;                // 减按键
  20. sbit KeyUp_P    = P3^5;                // 加按键
  21. sbit Buzzer_P   = P2^0;                        // 蜂鸣器
  22. sbit DQ         = P1^0;                // DS18B20传感器的引脚定义

  23. uchar TimeBuff[7]={17,9,1,6,18,30,40};          // 时间数组,默认2017年9月1日,星期五,18:30:40
  24. // TimeBuff[0] 代表年份,范围00-99
  25. // TimeBuff[1] 代表月份,范围1-12
  26. // TimeBuff[2] 代表日期,范围1-31
  27. // TimeBuff[3] 代表星期,范围1-7,1是星期天,2是星期一... ...
  28. // TimeBuff[4] 代表小时,范围00-23
  29. // TimeBuff[5] 代表分钟,范围00-59
  30. // TimeBuff[6] 代表秒钟,范围00-59

  31. uchar Clock_Hour;                                        // 闹钟的小时
  32. uchar Clock_Minute;                                // 闹钟的分钟
  33. uchar Clock_Swt;                                        // 闹钟的开关
  34. uchar Buzzer_Flag=0;                                // 蜂鸣器工作标志


  35. /*********************************************************/
  36. // 单片机内部EEPROM不使能
  37. /*********************************************************/
  38. void ISP_Disable()
  39. {
  40.         ISP_CONTR = 0;
  41.         ISP_ADDRH = 0;
  42.         ISP_ADDRL = 0;
  43. }

  44. /*********************************************************/
  45. // 从单片机内部EEPROM读一个字节,从0x2000地址开始
  46. /*********************************************************/
  47. unsigned char EEPROM_Read(unsigned int add)
  48. {
  49.         ISP_DATA  = 0x00;
  50.         ISP_CONTR = 0x83;
  51.         ISP_CMD   = 0x01;
  52.         ISP_ADDRH = (unsigned char)(add>>8);
  53.         ISP_ADDRL = (unsigned char)(add&0xff);
  54.         // 对STC89C51系列来说,每次要写入0x46,再写入0xB9,ISP/IAP才会生效
  55.         ISP_TRIG  = 0x46;          
  56.         ISP_TRIG  = 0xB9;
  57.         _nop_();
  58.         ISP_Disable();
  59.         return (ISP_DATA);
  60. }

  61. /*********************************************************/
  62. // 往单片机内部EEPROM写一个字节,从0x2000地址开始
  63. /*********************************************************/
  64. void EEPROM_Write(unsigned int add,unsigned char ch)
  65. {
  66.         ISP_CONTR = 0x83;
  67.         ISP_CMD   = 0x02;
  68.         ISP_ADDRH = (unsigned char)(add>>8);
  69.         ISP_ADDRL = (unsigned char)(add&0xff);
  70.         ISP_DATA  = ch;
  71.         ISP_TRIG  = 0x46;
  72.         ISP_TRIG  = 0xB9;
  73.         _nop_();
  74.         ISP_Disable();
  75. }

  76. /*********************************************************/
  77. // 擦除单片机内部EEPROM的一个扇区
  78. // 写8个扇区中随便一个的地址,便擦除该扇区,写入前要先擦除
  79. /*********************************************************/
  80. void Sector_Erase(unsigned int add)          
  81. {
  82.         ISP_CONTR = 0x83;
  83.         ISP_CMD   = 0x03;
  84.         ISP_ADDRH = (unsigned char)(add>>8);
  85.         ISP_ADDRL = (unsigned char)(add&0xff);
  86.         ISP_TRIG  = 0x46;
  87.         ISP_TRIG  = 0xB9;
  88.         _nop_();
  89.         ISP_Disable();
  90. }

  91. /*********************************************************/
  92. // 毫秒级的延时函数,time是要延时的毫秒数
  93. /*********************************************************/
  94. void DelayMs(uint time)
  95. {
  96.         uint i,j;
  97.         for(i=0;i<time;i++)
  98.                 for(j=0;j<112;j++);
  99. }

  100. /*********************************************************/
  101. // 延时15微秒
  102. /*********************************************************/
  103. void Delay15us(void)
  104. {
  105.         _nop_();
  106.         _nop_();
  107.         _nop_();
  108.         _nop_();
  109.         _nop_();
  110.         _nop_();
  111.         _nop_();
  112.         _nop_();
  113.         _nop_();
  114.         _nop_();
  115.         _nop_();
  116.         _nop_();
  117.         _nop_();
  118.         _nop_();
  119.         _nop_();
  120. }

  121. /*********************************************************/
  122. // 复位DS18B20(初始化)
  123. /*********************************************************/
  124. void DS18B20_ReSet(void)
  125. {
  126.         uchar i;
  127.         DQ=0;
  128.         i=240;
  129.         while(--i);
  130.         DQ=1;
  131.         i=30;
  132.         while(--i);
  133.         while(~DQ);
  134.         i=4;
  135.         while(--i);
  136. }

  137. /*********************************************************/
  138. // 向DS18B20写入一个字节
  139. /*********************************************************/
  140. void DS18B20_WriteByte(uchar dat)
  141. {
  142.         uchar j;
  143.         uchar btmp;
  144.        
  145.         for(j=0;j<8;j++)
  146.         {
  147.                 btmp=0x01;
  148.                 btmp=btmp<<j;
  149.                 btmp=btmp&dat;
  150.                 if(btmp>0)                // 写1
  151.                 {
  152.                         DQ=0;
  153.                         Delay15us();
  154.                         DQ=1;
  155.                         Delay15us();
  156.                         Delay15us();
  157.                         Delay15us();
  158.                         Delay15us();
  159.                 }
  160.                 else                        // 写0
  161.                 {
  162.                         DQ=0;
  163.                         Delay15us();
  164.                         Delay15us();
  165.                         Delay15us();
  166.                         Delay15us();
  167.                         DQ=1;
  168.                         Delay15us();
  169.                 }
  170.         }
  171. }

  172. /*********************************************************/
  173. // 读取温度值
  174. /*********************************************************/
  175. int DS18B20_ReadTemp(void)
  176. {
  177.         uchar j;
  178.         int b,temp=0;       

  179.         DS18B20_ReSet();                                        // 产生复位脉
  180.         DS18B20_WriteByte(0xcc);                        // 忽略ROM指令
  181.         DS18B20_WriteByte(0x44);                        // 启动温度转换指令

  182.         DS18B20_ReSet();                                        // 产生复位脉
  183.         DS18B20_WriteByte(0xcc);                        // 忽略ROM指令
  184.         DS18B20_WriteByte(0xbe);                        // 读取温度指令

  185.         for(j=0;j<16;j++)                                        // 读取温度数量
  186.         {                                               
  187.                 DQ=0;
  188.                 _nop_();
  189.                 _nop_();
  190.                 DQ=1;       
  191.                 Delay15us();
  192.                 b=DQ;
  193.                 Delay15us();
  194.                 Delay15us();
  195.                 Delay15us();
  196.                 b=b<<j;
  197.                 temp=temp|b;
  198.         }
  199.        
  200.         temp=temp*0.0625*10;                                // 合成温度值并放大10倍                                       
  201.         return (temp);                                                // 返回检测到的温度值
  202. }

  203. /*********************************************************/
  204. // 1602液晶写命令函数,cmd就是要写入的命令
  205. /*********************************************************/
  206. void LcdWriteCmd(uchar cmd)
  207. {
  208.         LcdRs_P = 0;
  209.         LcdRw_P = 0;
  210.         LcdEn_P = 0;
  211.         P0=cmd;
  212.         DelayMs(2);
  213.         LcdEn_P = 1;   
  214.         DelayMs(2);
  215.         LcdEn_P = 0;       
  216. }

  217. /*********************************************************/
  218. // 1602液晶写数据函数,dat就是要写入的数据
  219. /*********************************************************/
  220. void LcdWriteData(uchar dat)
  221. {
  222.         LcdRs_P = 1;
  223.         LcdRw_P = 0;
  224.         LcdEn_P = 0;
  225.         P0=dat;
  226.         DelayMs(2);
  227.         LcdEn_P = 1;   
  228.         DelayMs(2);
  229.         LcdEn_P = 0;
  230. }

  231. /*********************************************************/
  232. // 1602液晶初始化函数
  233. /*********************************************************/
  234. void LcdInit()
  235. {
  236.         LcdWriteCmd(0x38);        // 16*2显示,5*7点阵,8位数据口
  237.         LcdWriteCmd(0x0C);        // 开显示,不显示光标
  238.         LcdWriteCmd(0x06);        // 地址加1,当写入数据后光标右移
  239.         LcdWriteCmd(0x01);        // 清屏
  240. }

  241. /*********************************************************/
  242. // 液晶光标定位函数
  243. /*********************************************************/
  244. void LcdGotoXY(uchar line,uchar column)
  245. {
  246.         // 第一行
  247.         if(line==0)        
  248.                 LcdWriteCmd(0x80+column);
  249.         // 第二行
  250.         if(line==1)        
  251.                 LcdWriteCmd(0x80+0x40+column);
  252. }

  253. /*********************************************************/
  254. // 液晶输出字符串函数
  255. /*********************************************************/
  256. void LcdPrintStr(uchar *str)
  257. {
  258.         while(*str!='\0')
  259.                         LcdWriteData(*str++);
  260. }

  261. /*********************************************************/
  262. // 液晶显示内容的初始化
  263. /*********************************************************/
  264. void LcdShowInit()
  265. {
  266.         LcdGotoXY(0,0);
  267.         LcdPrintStr("20  -  -        ");
  268.         LcdGotoXY(1,0);
  269.         LcdPrintStr("  :  :         C");
  270.         LcdGotoXY(1,14);                                // 温度单位摄氏度上面的圆圈符号
  271.         LcdWriteData(0xdf);       
  272. }

  273. /*********************************************************/
  274. // 液晶输出数字
  275. /*********************************************************/
  276. void LcdPrintNum(uchar num)
  277. {
  278.         LcdWriteData(num/10+48);                // 十位
  279.         LcdWriteData(num%10+48);                 // 个位
  280. }

  281. /*********************************************************/
  282. // 液晶显示星期
  283. /*********************************************************/
  284. void LcdPrintWeek(uchar week)
  285. {
  286.         switch(week)
  287.         {
  288.                 case 1: LcdPrintStr(" Sun");        break;
  289.                 case 2: LcdPrintStr(" Mon");        break;
  290.                 case 3: LcdPrintStr("Tues");        break;
  291.                 case 4: LcdPrintStr(" Wed");        break;
  292.                 case 5: LcdPrintStr("Thur");        break;
  293.                 case 6: LcdPrintStr(" Fri");        break;
  294.                 case 7: LcdPrintStr(" Sat");        break;
  295.                 default:                                        break;
  296.         }
  297. }

  298. /*********************************************************/
  299. // 刷新时间显示
  300. /*********************************************************/
  301. void FlashTime()
  302. {
  303.         LcdGotoXY(0,2);                                                // 年份
  304.         LcdPrintNum(TimeBuff[0]);
  305.         LcdGotoXY(0,5);                                                // 月份
  306.         LcdPrintNum(TimeBuff[1]);
  307.         LcdGotoXY(0,8);                                                // 日期
  308.         LcdPrintNum(TimeBuff[2]);
  309.         LcdGotoXY(1,0);                                                // 小时
  310.         LcdPrintNum(TimeBuff[4]);
  311.         LcdGotoXY(1,3);                                                // 分钟
  312.         LcdPrintNum(TimeBuff[5]);
  313.         LcdGotoXY(1,6);                                                // 秒钟
  314.         LcdPrintNum(TimeBuff[6]);
  315.         LcdGotoXY(0,12);                                                // 星期       
  316.         LcdPrintWeek(TimeBuff[3]);

  317. }

  318. /*********************************************************/
  319. // 温度值的显示
  320. /*********************************************************/
  321. void LcdPrintTemp(int temp)
  322. {
  323.         if(temp<0)                                                                                                       
  324.         {
  325.                 LcdWriteData('-');                                        // 显示负号       
  326.                 temp=0-temp;                                                // 负数转为正数       
  327.         }
  328.         else if(temp>999)                                                 // 显示百位
  329.         {
  330.                 LcdWriteData(temp/1000+0x30);
  331.         }
  332.         else
  333.         {
  334.                 LcdWriteData(' ');
  335.         }
  336.         LcdWriteData(temp%1000/100+0x30);                // 显示十位
  337.         LcdWriteData(temp%100/10+0x30);                // 显示个位
  338.         LcdWriteData('.');                                                // 显示小数点
  339.         LcdWriteData(temp%10+0x30);                        // 显示小数后一位小数
  340. }

  341. /*********************************************************/
  342. // 初始化DS1302
  343. /*********************************************************/
  344. void DS1302_Init(void)
  345. {
  346.         RST_P=0;                        // RST脚置低
  347.         SCK_P=0;                        // SCK脚置低
  348.         SDA_P=0;                        // SDA脚置低                               
  349. }

  350. /*********************************************************/
  351. // 从DS1302读出一字节数据
  352. /*********************************************************/
  353. uchar DS1302_Read_Byte(uchar addr)
  354. {
  355.         uchar i;
  356.         uchar temp;
  357.         RST_P=1;                                                               
  358.         /* 写入目标地址:addr*/
  359.         for(i=0;i<8;i++)
  360.         {     
  361.                 if(addr&0x01)
  362.                         SDA_P=1;
  363.                 else
  364.                         SDA_P=0;
  365.                 SCK_P=1;
  366.                 _nop_();
  367.                 SCK_P=0;
  368.                 _nop_();
  369.                 addr=addr>> 1;
  370.         }
  371.         /* 读出该地址的数据 */
  372.         for(i=0;i<8;i++)
  373.         {
  374.                 temp=temp>>1;
  375.                 if(SDA_P)
  376.                         temp|= 0x80;
  377.                 else
  378.                         temp&=0x7F;
  379.                 SCK_P=1;
  380.                 _nop_();
  381.                 SCK_P=0;
  382.                 _nop_();
  383.         }
  384.         RST_P=0;
  385.         return temp;
  386. }

  387. /*********************************************************/
  388. // 向DS1302写入一字节数据
  389. /*********************************************************/
  390. void DS1302_Write_Byte(uchar addr, uchar dat)
  391. {
  392.         uchar i;
  393.         RST_P = 1;
  394.         /* 写入目标地址:addr*/
  395.         for(i=0;i<8;i++)
  396.         {
  397.                 if(addr&0x01)
  398.                         SDA_P=1;
  399.                 else
  400.                         SDA_P=0;
  401.                 SCK_P=1;
  402.                 _nop_();
  403.                 SCK_P=0;
  404.                 _nop_();
  405.                 addr=addr>>1;
  406.         }
  407.         /* 写入数据:dat*/
  408.         for(i=0;i<8;i++)
  409.         {
  410.                 if(dat&0x01)
  411.                         SDA_P=1;
  412.                 else
  413.                         SDA_P=0;
  414.                 SCK_P=1;
  415.                 _nop_();
  416.                 SCK_P=0;
  417.                 _nop_();
  418.                 dat=dat>>1;
  419.         }
  420.         RST_P=0;                                       
  421. }

  422. /*********************************************************/
  423. // 向DS1302写入时间数据
  424. /*********************************************************/
  425. void DS1302_Write_Time()
  426. {
  427.           uchar i;
  428.         uchar temp1;
  429.         uchar temp2;

  430.         for(i=0;i<7;i++)                        // 十进制转BCD码
  431.         {
  432.                 temp1=(TimeBuff[i]/10)<<4;
  433.                 temp2=TimeBuff[i]%10;
  434.                 TimeBuff[i]=temp1+temp2;
  435.         }
  436.        
  437.         DS1302_Write_Byte(0x8E,0x00);                                        // 关闭写保护
  438.         DS1302_Write_Byte(0x80,0x80);                                        // 暂停时钟
  439.         DS1302_Write_Byte(0x8C,TimeBuff[0]);                        // 年
  440.         DS1302_Write_Byte(0x88,TimeBuff[1]);                                // 月
  441.         DS1302_Write_Byte(0x86,TimeBuff[2]);                                // 日
  442.         DS1302_Write_Byte(0x8A,TimeBuff[3]);                        // 星期
  443.         DS1302_Write_Byte(0x84,TimeBuff[4]);                                // 时
  444.         DS1302_Write_Byte(0x82,TimeBuff[5]);                                // 分
  445.         DS1302_Write_Byte(0x80,TimeBuff[6]);                                // 秒
  446.         DS1302_Write_Byte(0x80,TimeBuff[6]&0x7F);                // 运行时钟
  447.         DS1302_Write_Byte(0x8E,0x80);                                        // 打开写保护  
  448. }

  449. /*********************************************************/
  450. // 从DS1302读出时间数据
  451. /*********************************************************/
  452. void DS1302_Read_Time()  
  453. {
  454.         uchar i;

  455.         TimeBuff[0]=DS1302_Read_Byte(0x8D);                        // 年
  456.         TimeBuff[1]=DS1302_Read_Byte(0x89);                        // 月
  457.         TimeBuff[2]=DS1302_Read_Byte(0x87);                        // 日
  458.         TimeBuff[3]=DS1302_Read_Byte(0x8B);                        // 星期
  459.         TimeBuff[4]=DS1302_Read_Byte(0x85);                        // 时
  460.         TimeBuff[5]=DS1302_Read_Byte(0x83);                        // 分
  461.         TimeBuff[6]=(DS1302_Read_Byte(0x81))&0x7F;                // 秒

  462.         for(i=0;i<7;i++)                // BCD转十进制
  463.         {           
  464.                 TimeBuff[i]=(TimeBuff[i]/16)*10+TimeBuff[i]%16;
  465.         }
  466. }
  467. }

  468. /*********************************************************/
  469. // 按键扫描(设置时间)
  470. /*********************************************************/
  471. void KeyScanf1()
  472. {
  473.         if(KeySet_P==0)
  474.         {
  475.                 LcdWriteCmd(0x0f);                        // 启动光标闪烁
  476.                 LcdGotoXY(0,3);                                // 定位光标到年份闪烁
  477.                 DelayMs(10);                                        // 延时等待,消除按键按下的抖动
  478.                 while(!KeySet_P);                                // 等待按键释放
  479.                 DelayMs(10);                                        // 延时等待,消除按键松开的抖动
  480.                
  481.                 /* 调整年份 */
  482.                 while(1)
  483.                 {
  484.                         if(KeyDown_P==0)                                        // 如果减按键被下去
  485.                         {
  486.                                 if(TimeBuff[0]>0)                                // 判断年份是否大于0               
  487.                                         TimeBuff[0]--;                                // 是的话就减去1
  488.                                 LcdGotoXY(0,2);                                // 光标定位到年份的位置
  489.                                 LcdPrintNum(TimeBuff[0]);                // 刷新显示改变后的年份
  490.                                 LcdGotoXY(0,3);                                // 定位光标到年份闪烁
  491.                                 DelayMs(300);                                        // 延时0.3秒左右
  492.                         }
  493.                        
  494.                         if(KeyUp_P==0)                                        // 如果加按键被下去
  495.                         {
  496.                                 if(TimeBuff[0]<99)                                // 判断年份是否小于99
  497.                                         TimeBuff[0]++;                        // 是的话就加上1
  498.                                 LcdGotoXY(0,2);                                // 光标定位到年份的位置
  499.                                 LcdPrintNum(TimeBuff[0]);                // 刷新显示改变后的年份
  500.                                 LcdGotoXY(0,3);                                // 定位光标到年份闪烁
  501.                                 DelayMs(300);                                        // 延时0.3秒左右
  502.                         }
  503.                        
  504.                         if(KeySet_P==0)
  505.                         {
  506.                                 break;
  507.                         }
  508.                 }
  509.                
  510.                 LcdGotoXY(0,6);                                        // 定位光标到月份闪烁
  511.                 DelayMs(10);                                                // 延时等待,消除按键按下的抖动
  512.                 while(!KeySet_P);                                        // 等待按键释放
  513.                 DelayMs(10);                                                // 延时等待,消除按键松开的抖动
  514.                        
  515.                 /* 调整月份 */
  516.                 while(1)
  517.                 {
  518.                         if(KeyDown_P==0)                                        // 如果减按键被下去
  519.                         {
  520.                                 if(TimeBuff[1]>1)                                // 判断月份是否大于1               
  521.                                         TimeBuff[1]--;                                // 是的话就减去1
  522.                                 LcdGotoXY(0,5);                                // 光标定位到月份的位置
  523.                                 LcdPrintNum(TimeBuff[1]);                // 刷新显示改变后的月份
  524.                                 LcdGotoXY(0,6);                                // 定位光标到月份闪烁
  525.                                 DelayMs(300);                                        // 延时0.3秒左右
  526.                         }
  527.                        
  528.                         if(KeyUp_P==0)                                        // 如果加按键被下去
  529.                         {
  530.                                 if(TimeBuff[1]<12)                                // 判断月份是否小于12
  531.                                         TimeBuff[1]++;                        // 是的话就加上1
  532.                                 LcdGotoXY(0,5);                                // 光标定位到月份的位置
  533.                                 LcdPrintNum(TimeBuff[1]);                // 刷新显示改变后的月份
  534.                                 LcdGotoXY(0,6);                                // 定位光标到月份闪烁
  535.                                 DelayMs(300);                                        // 延时0.3秒左右
  536.                         }
  537.                        
  538.                         if(KeySet_P==0)
  539.                         {
  540.                                 break;
  541.                         }
  542.                 }
  543.                
  544.                 LcdGotoXY(0,9);                                        // 定位光标到日期闪烁
  545.                 DelayMs(10);                                                // 延时等待,消除按键按下的抖动
  546.                 while(!KeySet_P);                                        // 等待按键释放
  547.                 DelayMs(10);                                                // 延时等待,消除按键松开的抖动
  548.                
  549.                 /* 调整日期 */
  550.                 while(1)
  551.                 {
  552.                         if(KeyDown_P==0)                                        // 如果减按键被下去
  553.                         {
  554.                                 if(TimeBuff[2]>1)                                // 判断日期是否大于1               
  555.                                         TimeBuff[2]--;                                // 是的话就减去1
  556.                                 LcdGotoXY(0,8);                                // 光标定位到日期的位置
  557.                                 LcdPrintNum(TimeBuff[2]);                // 刷新显示改变后的日期
  558.                                 LcdGotoXY(0,9);                                // 定位光标到日期闪烁
  559.                                 DelayMs(300);                                        // 延时0.3秒左右
  560.                         }
  561.                        
  562.                         if(KeyUp_P==0)                                        // 如果加按键被下去
  563.                         {
  564.                                 if(TimeBuff[2]<31)                                // 判断日期是否小于31
  565.                                         TimeBuff[2]++;                        // 是的话就加上1
  566.                                 LcdGotoXY(0,8);                                // 光标定位到日期的位置
  567.                                 LcdPrintNum(TimeBuff[2]);                // 刷新显示改变后的日期
  568.                                 LcdGotoXY(0,9);                                // 定位光标到日期闪烁
  569.                                 DelayMs(300);                                        // 延时0.3秒左右
  570.                         }
  571.                        
  572.                         if(KeySet_P==0)
  573.                         {
  574.                                 break;
  575.                         }
  576.                 }
  577.                
  578.                 LcdGotoXY(0,15);                                // 定位光标到星期闪烁
  579.                 DelayMs(10);                                        // 延时等待,消除按键按下的抖动
  580.                 while(!KeySet_P);                                // 等待按键释放
  581.                 DelayMs(10);                                        // 延时等待,消除按键松开的抖动
  582.                
  583.                 /* 调整星期 */
  584.                 while(1)
  585.                 {
  586.                         if(KeyDown_P==0)                                        // 如果减按键被下去
  587.                         {
  588.                                 if(TimeBuff[3]>1)                                // 判断星期是否大于1               
  589.                                         TimeBuff[3]--;                                // 是的话就减去1
  590.                                 LcdGotoXY(0,12);                                // 光标定位到星期的位置
  591.                                 LcdPrintWeek(TimeBuff[3]);                // 刷新显示改变后的星期
  592.                                 LcdGotoXY(0,15);                                // 定位光标到星期闪烁
  593.                                 DelayMs(300);                                        // 延时0.3秒左右
  594.                         }
  595.                        
  596.                         if(KeyUp_P==0)                                        // 如果加按键被下去
  597.                         {
  598.                                 if(TimeBuff[3]<7)                                // 判断星期是否小于7
  599.                                         TimeBuff[3]++;                        // 是的话就加上1
  600.                                 LcdGotoXY(0,12);                                // 光标定位到星期的位置
  601.                                 LcdPrintWeek(TimeBuff[3]);                // 刷新显示改变后的星期
  602.                                 LcdGotoXY(0,15);                                // 定位光标到星期闪烁
  603.                                 DelayMs(300);                                        // 延时0.3秒左右
  604.                         }
  605.                        
  606.                         if(KeySet_P==0)
  607.                         {
  608.                                 break;
  609.                         }
  610.                 }

  611.                 LcdGotoXY(1,1);                                // 定位光标到小时闪烁
  612.                 DelayMs(10);                                        // 延时等待,消除按键按下的抖动
  613.                 while(!KeySet_P);                                // 等待按键释放
  614.                 DelayMs(10);                                        // 延时等待,消除按键松开的抖动
  615.                
  616.                 /* 调整小时 */
  617.                 while(1)
  618.                 {
  619.                         if(KeyDown_P==0)                                        // 如果减按键被下去
  620.                         {
  621.                                 if(TimeBuff[4]>0)                                // 判断小时是否大于0
  622.                                         TimeBuff[4]--;                                // 是的话就减去1
  623.                                 LcdGotoXY(1,0);                                // 光标定位到小时的位置
  624.                                 LcdPrintNum(TimeBuff[4]);                // 刷新显示改变后的小时
  625.                                 LcdGotoXY(1,1);                                // 定位光标到小时闪烁
  626.                                 DelayMs(300);                                        // 延时0.3秒左右
  627.                         }
  628.                        
  629.                         if(KeyUp_P==0)                                        // 如果加按键被下去
  630.                         {
  631.                                 if(TimeBuff[4]<23)                                // 判断小时是否小于23
  632.                                         TimeBuff[4]++;                        // 是的话就加上1
  633.                                 LcdGotoXY(1,0);                                // 光标定位到小时的位置
  634.                                 LcdPrintNum(TimeBuff[4]);                // 刷新显示改变后的小时
  635.                                 LcdGotoXY(1,1);                                // 定位光标到小时闪烁
  636.                                 DelayMs(300);                                        // 延时0.3秒左右
  637.                         }
  638.                        
  639.                         if(KeySet_P==0)
  640.                         {
  641.                                 break;
  642.                         }
  643.                 }
  644.                
  645.                 LcdGotoXY(1,4);                                // 定位光标到分钟闪烁
  646.                 DelayMs(10);                                        // 延时等待,消除按键按下的抖动
  647.                 while(!KeySet_P);                                // 等待按键释放
  648.                 DelayMs(10);                                        // 延时等待,消除按键松开的抖动
  649.                
  650.                 /* 调整分钟 */
  651.                 while(1)
  652.                 {
  653.                         if(KeyDown_P==0)                                        // 如果减按键被下去
  654.                         {
  655.                                 if(TimeBuff[5]>0)                                // 判断分钟是否大于0
  656.                                         TimeBuff[5]--;                                // 是的话就减去1
  657.                                 LcdGotoXY(1,3);                                // 光标定位到分钟的位置
  658.                                 LcdPrintNum(TimeBuff[5]);                // 刷新显示改变后的分钟
  659.                                 LcdGotoXY(1,4);                                // 定位光标到分钟闪烁
  660.                                 DelayMs(300);                                        // 延时0.3秒左右
  661.                         }
  662.                        
  663.                         if(KeyUp_P==0)                                        // 如果加按键被下去
  664.                         {
  665.                                 if(TimeBuff[5]<59)                                // 判断分钟是否小于59
  666.                                         TimeBuff[5]++;                        // 是的话就加上1
  667.                                 LcdGotoXY(1,3);                                // 光标定位到分钟的位置
  668.                                 LcdPrintNum(TimeBuff[5]);                // 刷新显示改变后的分钟
  669.                                 LcdGotoXY(1,4);                                // 定位光标到分钟闪烁
  670.                                 DelayMs(300);                                        // 延时0.3秒左右
  671.                         }
  672.                        
  673.                         if(KeySet_P==0)
  674.                         {
  675.                                 break;
  676.                         }
  677.                 }
  678.                
  679.                 LcdGotoXY(1,7);                                // 定位光标到秒钟闪烁
  680.                 DelayMs(10);                                        // 延时等待,消除按键按下的抖动
  681.                 while(!KeySet_P);                                // 等待按键释放
  682.                 DelayMs(10);                                        // 延时等待,消除按键松开的抖动
  683.                
  684.                 /* 调整秒钟 */
  685.                 while(1)
  686.                 {
  687.                         if(KeyDown_P==0)                                        // 如果减按键被下去
  688.                         {
  689.                                 if(TimeBuff[6]>0)                                // 判断秒钟是否大于0
  690.                                         TimeBuff[6]--;                                // 是的话就减去1
  691.                                 LcdGotoXY(1,6);                                // 光标定位到秒钟的位置
  692.                                 LcdPrintNum(TimeBuff[6]);                // 刷新显示改变后的秒钟
  693.                                 LcdGotoXY(1,7);                                // 定位光标到秒钟闪烁
  694.                                 DelayMs(300);                                        // 延时0.3秒左右
  695.                         }
  696.                        
  697.                         if(KeyUp_P==0)                                                // 如果加按键被下去
  698.                         {
  699.                                 if(TimeBuff[6]<59)                                        // 判断秒钟是否小于59
  700.                                         TimeBuff[6]++;                                // 是的话就加上1
  701.                                 LcdGotoXY(1,6);                                        // 光标定位到秒钟的位置
  702.                                 LcdPrintNum(TimeBuff[6]);                        // 刷新显示改变后的秒钟
  703.                                 LcdGotoXY(1,7);                                        // 定位光标到秒钟闪烁
  704.                                 DelayMs(300);                                                // 延时0.3秒左右
  705.                         }
  706.                        
  707.                         if(KeySet_P==0)
  708.                         {
  709.                                 break;
  710.                         }
  711.                 }
  712.                
  713.                 /* 退出前的设置 */
  714.                 LcdWriteCmd(0x0C);                        // 关闭光标闪烁
  715.                 DS1302_Write_Time();                        // 把新设置的时间值存入DS1302芯片
  716.                 DelayMs(10);                                        // 延时等待,消除按键按下的抖动
  717.                 while(!KeySet_P);                                // 等待按键释放
  718.                 DelayMs(10);                                        // 延时等待,消除按键松开的抖动
  719.         }
  720. }

  721. /*********************************************************/
  722. // 按键扫描(设置闹钟)
  723. /*********************************************************/
  724. void KeyScanf2()
  725. {
  726.         if(KeyClock_P==0)
  727.         {
  728.                 LcdGotoXY(0,0);                                                // 液晶显示为闹钟设置的界面
  729.                 LcdPrintStr("Alarm Clock Set ");
  730.                 LcdGotoXY(1,0);                               
  731.                 LcdPrintStr("     :          ");
  732.                 LcdGotoXY(1,3);                                                // 显示闹钟的小时
  733.                 LcdPrintNum(Clock_Hour);
  734.                 LcdGotoXY(1,6);                                                // 显示闹钟的分钟
  735.                 LcdPrintNum(Clock_Minute);
  736.                 LcdGotoXY(1,10);                                                // 显示闹钟状态
  737.                 if(Clock_Swt==0)
  738.                 {
  739.                         LcdPrintStr("OFF");
  740.                 }
  741.                 else
  742.                 {
  743.                         LcdPrintStr(" ON");
  744.                 }
  745.                 LcdGotoXY(1,4);                                                // 光标定位
  746.                 LcdWriteCmd(0x0f);                                        // 光标闪烁
  747.                 DelayMs(10);                                                        // 延时等待,消除按键按下的抖动
  748.                 while(!KeyClock_P);                                        // 等待按键释放
  749.                 DelayMs(10);                                                        // 延时等待,消除按键松开的抖动
  750.                
  751.                 /* 调整闹钟小时 */
  752.                 while(1)
  753.                 {
  754.                         if(KeyDown_P==0)                                        // 如果减按键被下去
  755.                         {
  756.                                 if(Clock_Hour>0)                                // 判断闹钟小时是否大于0
  757.                                         Clock_Hour--;                                // 是的话就减去1
  758.                                 LcdGotoXY(1,3);                                // 光标定位到闹钟小时的位置
  759.                                 LcdPrintNum(Clock_Hour);                // 刷新显示改变后的闹钟小时
  760.                                 LcdGotoXY(1,4);                                // 定位光标到闹钟小时闪烁
  761.                                 DelayMs(300);                                        // 延时0.3秒左右
  762.                         }
  763.                        
  764.                         if(KeyUp_P==0)                                        // 如果加按键被下去
  765.                         {
  766.                                 if(Clock_Hour<23)                                // 判断闹钟小时是否小于23
  767.                                         Clock_Hour++;                                // 是的话就加上1
  768.                                 LcdGotoXY(1,3);                                // 光标定位到闹钟小时的位置
  769.                                 LcdPrintNum(Clock_Hour);                // 刷新显示改变后的闹钟小时
  770.                                 LcdGotoXY(1,4);                                // 定位光标到闹钟小时闪烁
  771.                                 DelayMs(300);                                        // 延时0.3秒左右
  772.                         }
  773.                        
  774.                         if(KeyClock_P==0)
  775.                         {
  776.                                 break;
  777.                         }
  778.                 }
  779.                
  780.                 LcdGotoXY(1,7);                                                // 定位光标到闹钟分钟的闪烁
  781.                 DelayMs(10);                                                        // 延时等待,消除按键按下的抖动
  782.                 while(!KeyClock_P);                                        // 等待按键释放
  783.                 DelayMs(10);                                                        // 延时等待,消除按键松开的抖动
  784.                
  785.                 /* 调整分钟 */
  786.                 while(1)
  787.                 {
  788.                         if(KeyDown_P==0)                                        // 如果减按键被下去
  789.                         {
  790.                                 if(Clock_Minute>0)                                // 判断闹钟分钟是否大于0
  791.                                         Clock_Minute--;                        // 是的话就减去1
  792.                                 LcdGotoXY(1,6);                                // 光标定位到闹钟分钟的位置
  793.                                 LcdPrintNum(Clock_Minute);                // 刷新显示改变后的闹钟分钟
  794.                                 LcdGotoXY(1,7);                                // 定位光标到闹钟分钟闪烁
  795.                                 DelayMs(300);                                        // 延时0.3秒左右
  796.                         }
  797.                        
  798.                         if(KeyUp_P==0)                                        // 如果加按键被下去
  799.                         {
  800.                                 if(Clock_Minute<59)                        // 判断闹钟分钟是否小于59
  801.                                         Clock_Minute++;                        // 是的话就加上1
  802.                                 LcdGotoXY(1,6);                                // 光标定位到闹钟分钟的位置
  803.                                 LcdPrintNum(Clock_Minute);                // 刷新显示改变后的闹钟分钟
  804.                                 LcdGotoXY(1,7);                                // 定位光标到闹钟分钟闪烁
  805.                                 DelayMs(300);                                        // 延时0.3秒左右
  806.                         }
  807.                        
  808.                         if(KeyClock_P==0)
  809.                         {
  810.                                 break;
  811.                         }
  812.                 }
  813.                
  814.                 LcdGotoXY(1,12);                                                // 定位光标到闹钟开关的位置闪烁
  815.                 DelayMs(10);                                                        // 延时等待,消除按键按下的抖动
  816.                 while(!KeyClock_P);                                        // 等待按键释放
  817.                 DelayMs(10);                                                        // 延时等待,消除按键松开的抖动
  818.                
  819.                 /* 闹钟开关 */
  820.                 while(1)
  821.                 {
  822.                         if(KeyDown_P==0)                                        // 如果减按键被下去
  823.                         {
  824.                                 if(Clock_Swt==1)                                // 判断闹钟是否开启
  825.                                         Clock_Swt=0;                                // 关闭闹钟
  826.                                 LcdGotoXY(1,10);                                // 光标定位到秒钟开关的位置
  827.                                 LcdPrintStr("OFF");                                // 液晶显示“OFF”
  828.                                 LcdGotoXY(1,12);                                // 定位光标到闹钟开关的位置闪烁
  829.                                 DelayMs(300);                                        // 延时0.3秒左右
  830.                         }
  831.                        
  832.                         if(KeyUp_P==0)                                        // 如果加按键被下去
  833.                         {
  834.                                 if(Clock_Swt==0)                                // 判断闹钟是否关闭
  835.                                         Clock_Swt=1;                                // 启动闹钟
  836.                                 LcdGotoXY(1,10);                                // 光标定位到秒钟开关的位置
  837.                                 LcdPrintStr(" ON");                                // 液晶显示“ ON”
  838.                                 LcdGotoXY(1,12);                                // 定位光标到闹钟开关的位置闪烁
  839.                                 DelayMs(300);                                        // 延时0.3秒左右
  840.                         }
  841.                        
  842.                         if(KeyClock_P==0)
  843.                         {
  844.                                 break;
  845.                         }
  846.                 }
  847.                
  848.                 /* 退出前的设置 */
  849.                 LcdWriteCmd(0x0C);                        // 关闭光标闪烁
  850.                 LcdShowInit();                                        // 液晶显示内容恢复为检测界面的
  851.                 DelayMs(10);                                        // 延时等待,消除按键按下的抖动
  852.                 while(!KeyClock_P);                        // 等待按键释放
  853.                 DelayMs(10);                                        // 延时等待,消除按键松开的抖动
  854.                 Sector_Erase(0x2000);
  855.                 EEPROM_Write(0x2000,Clock_Hour);                // 往0x2000这个地址写入闹钟的小时
  856.                 EEPROM_Write(0x2001,Clock_Minute);        // 往0x2001这个地址写入闹钟的分钟
  857.                 EEPROM_Write(0x2002,Clock_Swt);                // 往0x2002这个地址写入闹钟的开关
  858.         }
  859. }


  860. /*********************************************************/
  861. // 闹钟判断
  862. /*********************************************************/
  863. void ClockJudge()
  864. {
  865.         if(Clock_Swt==1)                        // 判断闹钟的开关是否开启
  866.         {
  867. // 当前小时和分钟,和闹钟的小时和分钟是否一致
  868.                 if((Clock_Hour==TimeBuff[4])&&(Clock_Minute==TimeBuff[5]))                                {
  869.                         if(TimeBuff[6]==0)                                        // 秒数是否等于0
  870.                         {
  871.                                 Buzzer_Flag=1;                                // 开启蜂鸣器报警标志
  872.                         }
  873.                 }
  874.         }
  875.        
  876.         if(TimeBuff[6]==59)                                                        // 如果当前秒数为59秒
  877.         {
  878.                 Buzzer_Flag=0;                                                // 关闭蜂鸣器报警标志
  879.         }
  880.        
  881.         if((KeyDown_P==0)||(KeyUp_P==0))                        // 如果加按键或减按键被按下
  882.         {
  883.                 Buzzer_Flag=0;                                                // 关闭蜂鸣器报警标志
  884.         }
  885.        
  886.         if(Buzzer_Flag==1)                                                        // 如果蜂鸣器报警标志为启动
  887.         {
  888.                 Buzzer_P=0;                                                        // 启动蜂鸣器
  889.                 DelayMs(100);                                                        // 延时0.1秒
  890.                 Buzzer_P=1;                                                        // 关闭蜂鸣器
  891.                 DelayMs(100);                                                        // 延时0.1秒
  892.         }
  893. }


  894. /*********************************************************/
  895. // 主函数
  896. /*********************************************************/
  897. void main()
  898. {
  899.         int temp;                                                        // 保存温度值

  900.         LcdInit();                                                        // 执行液晶初始化       
  901.         DS1302_Init();                                                // 时钟芯片的初始化
  902.         LcdShowInit();                                                // 液晶显示内容的初始化

  903.         if(DS1302_Read_Byte(0x81)>=128)        // 判断时钟芯片是否正在运行
  904.         {
  905.                 DS1302_Write_Time();                        // 如果没有,则初始化一个时间
  906.         }

  907.         Clock_Hour=EEPROM_Read(0x2000);        // 读取0x2000这个地址的值赋给闹钟的小时变量
  908.         if(Clock_Hour>23)                                        // 如果读取到的闹钟小时值不正常,则重新赋值
  909.         {
  910.                 Clock_Hour=12;
  911.         }
  912.           Clock_Minute=EEPROM_Read(0x2001);// 读取0x2001这个地址的值赋给闹钟的分钟变量
  913.         if(Clock_Minute>59)                                // 如果读取到的闹钟分钟值不正常,则重新赋值
  914.         {
  915.                 Clock_Minute=30;
  916.         }
  917.         Clock_Swt=EEPROM_Read(0x2002);        // 读取0x2002这个地址的值赋给闹钟的开关变量
  918.         if(Clock_Swt>1)                                        // 如果读取到的闹钟开关值不正常,则重新赋值
  919.         {
  920.                 Clock_Swt=0;
  921.         }
  922. while(DS18B20_ReadTemp()==850)        // 等待温度传感器初始化完成
  923.         {
  924.                 DelayMs(10);
  925.         }

  926.         while(1)
  927.         {
  928.                 DS1302_Read_Time();                  // 获取当前时钟芯片的时间,存在数组time_buf中
  929.                 FlashTime();                                  // 刷新时间显示
  930.                 ClockJudge();                                  // 闹钟工作的判断
  931.                
  932.                 temp=DS18B20_ReadTemp();          // 读取温度
  933.                 LcdGotoXY(1,9);                          // 定位到显示温度的地方
  934.                 LcdPrintTemp(temp);                  // 显示温度

  935.                 KeyScanf1();                                  // 按键扫描(时间的设置)
  936.                 KeyScanf2();                                  // 按键扫描(闹钟的设置)
  937.                
  938.                 DelayMs(100);                                  // 延时0.1秒
  939.         }
  940. }
复制代码


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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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