找回密码
 立即注册

QQ登录

只需一步,快速开始

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

纯手工打造,51单片机智能热水器控制系统

  [复制链接]
跳转到指定楼层
楼主
本帖最后由 xiao_yp2014 于 2016-3-11 10:11 编辑

大家好!我叫肖亚平,从小热爱上了电子技术,读书时阴差阳错的选择了电子这方面的专业,学习电子技术。对于我的理解来说,学校里面学到的技术不是全部实用,但是必须有用,所以一直奋斗在前线。我对学习总结出一句话“压力不是有人努力,而是比你牛X N倍的人依然在努力

欢迎加入“单片机程序开发”交流群:425089475


/********************************************************************************************

名    称:智能热水器控制系统
功    能:
                 1、数码管显示当前北京时间。可对时间进行修改。
                  2、设定时间,到达设定的时间开始加热。
                  3、设定温度,到达设定的温度值,停止加热。
                  4、加热完毕后,蜂鸣器报警提示,温度控制在设定温度+-5度变化。(+-5度还是温度采样的精度,只是为了不让继电器平凡跳动)
                  5、DS1302备用电池电量用完时,蜂鸣器报警。并在数码管上显示E002代码
                  6、发热体好坏判别,如果坏了,蜂鸣器报警,并在数码管上显示E001代码。
                  7、没有水的情况下,不加热,并且蜂鸣器发出报警。
                  8、数码管显示6个窗口。
                       窗口1:显示当前的北京时间
                       窗口2:显示设定的时间
                       窗口3:显示设定的温度
                       窗口4:显示设定的水温
                       窗口5:显示错误代码
                       窗口6:显示开机画面
                  9、按键采用了:单击,长按,短按。最多一个按键实现三个功能。
作    者:肖亚平
创建时间:2014年11月11日
修改时间:2014年13月3日   
备    注:程序如有问题,请联系    QQ交流群:425089475        电话:15882089269             由于水平能力有限,纰漏之外,还望各位高人指出。。。。。
**************************************************************************************************/





正面



背面

热水器程序——测试.zip (123.57 KB, 下载次数: 379)    -------->源程序







智能热水器.zip (120.23 KB, 下载次数: 401)











主要器件说明:
1、STC89C52单片机作为主控芯片
2、ADC0832
  · 8位分辨率
. 逐次逼近式A/D转换器
· 双通道A/D转换;
· 输入输出电平与TTL/CMOS相兼容;
· 5V电源供电时输入电压在0~5V之间;
· 工作频率为250KHZ,转换时间为32μS;
· 一般功耗仅为15mW;
芯片接口说明:
· CS_片选使能,低电平芯片使能。
· CH0 模拟输入通道0,或作为IN+/-使用。
· CH1 模拟输入通道1,或作为IN+/-使用。
· GND 芯片参考0 电位(地)。
· DI 数据信号输入,选择通道控制。
· DO 数据信号输出,转换数据输出
· CLK 芯片时钟输入。
· Vcc/REF 电源输入及参考电压输入(复用)。
ADC0832 为8位分辨率A/D转换芯片,其最高分辨可达256级,可以适应一般的模拟量转换要求。其内部电源输入与参考电压的复用,使得芯片的模拟电压输入在0~5V之间。芯片转换时间仅为32μS,据有双数据输出可作为数据校验,以减少数据误差,转换速度快且稳定性能强。独立的芯片使能输入,使多器件挂接和处理器控制变的更加方便。通过DI 数据输入端,可以轻易的实现通道功能的选择。
单片机对ADC0832 的控制原理
正常情况下ADC0832 与单片机的接口应为4条数据线,分别是CS、CLK、DO、DI。但由于DO端与DI端在通信时并未同时有效并与单片机的接口是双向的,所以电路设计时可以将DO和DI 并联在一根数据线上使用。当ADC0832未工作时其CS输入端应为高电平,此时芯片禁用,CLK 和DO/DI 的电平可任意。当要进行A/D转换时,须先将CS使能端置于低电平并且保持低电平直到转换完全结束。此时芯片开始转换工作,同时由处理器向芯片时钟输入端CLK 输入时钟脉冲,DO/DI端则使用DI端输入通道功能选择的数据信号。在第1 个时钟脉冲的下沉之前DI端必须是高电平,表示启始信号。在第2、3个脉冲下沉之前DI端应输入2 位数据用于选择通道功能,其功能详见官方资料。
3、DS1302实时时钟芯片(用于用准确的时间


DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力。
结构DS1302的引脚排列,其中Vcc2为主电源,VCC1为后备电源。在主电源关闭的情况下,也能保持时钟的连续运行。DS1302由Vcc1或Vcc2两者中的较大者供电。当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。当Vcc2小于Vcc1时,DS1302由Vcc1供电。X1和X2是振荡源,外接32.768kHz晶振。RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据传送的方法。当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。上电运行时,在Vcc>2.0V之前,RST必须保持低电平。只有在SCLK为低电平时,才能将RST置为高电平。I/O为串行数据输入输出端(双向),后面有详细说明。SCLK为时钟输入端。 下图为DS1302的引脚功能图





     4、温度采用NTC10K热敏电阻

          10K温度阻值对应表.zip (4.14 KB, 下载次数: 134)


    5、继电器
         由于是热水器,发热体的功率比较大,所以就选用:12V、40A
         注:原理图和中的继电器驱动用的是低电平,程序中用的是高电平。
     
     6、数码管

          共阳极数码管,PNP三极管做驱动。中间两点是时间的秒,要单独用一个I/O控制。


          为什么要单独用一个I/O口控制?
          因为:中间两点闪亮一下就是1S,不可以放在P0数据端口,这样数码管要500MS才扫描一次,数码管会闪烁,所以要单独用一个I/O来控制。


         


程序如下:
  1. /********************************************************************************************
  2. 名    称:智能热水器控制系统
  3. 功    能:
  4.           1、数码管显示当前北京时间。可对时间进行修改。
  5.                   2、设定时间,到达设定的时间开始加热。
  6.                   3、设定温度,到达设定的温度值,停止加热。
  7.                   4、加热完毕后,蜂鸣器报警提示,温度控制在设定温度+-5度变化。
  8.                   5、DS1302备用电池电量用完时,蜂鸣器报警。并在数码管上显示E002代码
  9.                   6、发热体好坏判别,如果坏了,蜂鸣器报警,并在数码管上显示E001代码。
  10.                   7、没有水的情况下,不加热,并且蜂鸣器发出报警。

  11. 作    者:肖亚平
  12. 创建时间:2014年11月11日
  13. 修改时间:
  14. 备    注:
  15. **************************************************************************************************/
  16. #include<reg52.h>                                //头文件

  17. #define const_dpy_time_half  200  //数码管闪烁时间的半值
  18. #define const_dpy_time_all   400  //数码管闪烁时间的全值 一定要比const_dpy_time_half 大
  19. #define const_voice_short  40   //蜂鸣器短叫的持续时间
  20. #define const_voice_long  120 //蜂鸣器长鸣叫的时间
  21. #define const_DigTime_level 240        //小数点计时上限值
  22. #define const_KeyTime_level 30 //按键去抖动延时的时间
  23. #define const_key_time_short3  30    //短按的按键去抖动延时的时间
  24. #define const_key_time_long3   1024     //长按的按键去抖动延时的时间
  25. #define const_time_0_25s  111   //0.25秒钟的时间需要的定时中断次数
  26. #define const_time_1s     444   //1秒钟的时间需要的定时中断次数
  27. #define const_ds1302_0_5s  200   //大概0.5秒的时间
  28. #define const_ds1302_sampling_time    300   //累计主循环次数的时间,每次刷新采样时钟芯片的时间

  29. #define WRITE_SECOND    0x80    //DS1302内部的相关地址
  30. #define WRITE_MINUTE    0x82
  31. #define WRITE_HOUR      0x84
  32. #define WRITE_DATE      0x86
  33. #define WRITE_MONTH     0x88
  34. #define WRITE_YEAR      0x8C
  35. #define WRITE_CHECK     0xC2  //用来检查芯片的备用电池是否用完了的地址
  36. #define READ_CHECK      0xC3  //用来检查芯片的备用电池是否用完了的地址
  37. #define READ_SECOND     0x81
  38. #define READ_MINUTE     0x83
  39. #define READ_HOUR       0x85
  40. #define READ_DATE       0x87
  41. #define READ_MONTH      0x89
  42. #define READ_YEAR       0x8D
  43. #define WRITE_PROTECT   0x8E

  44. #define WRITE_SET_HOUR     0xC4  //用来检查芯片的备用电池是否用完了的地址
  45. #define READ_SET_HOUR      0xC5  //用来检查芯片的备用电池是否用完了的地址

  46. #define WRITE_SET_MINUTE     0xC6  //用来检查芯片的备用电池是否用完了的地址
  47. #define READ_SET_MINUTE      0xC7  //用来检查芯片的备用电池是否用完了的地址

  48. sbit SCLK_dr      =P1^0;  
  49. sbit DIO_dr_sr    =P1^1;  
  50. sbit DS1302_CE_dr =P1^2;  

  51. sbit dig1_dr =  P2^0;                        //第一位数码管位选输出
  52. sbit dig2_dr =  P2^1;                        //第二位数码管位选输出
  53. sbit dig3_dr =  P2^2;                        //第三位数码管位选输出
  54. sbit dig4_dr =  P2^3;                        //第四位数码管位选输出
  55. sbit digital_dp_dr = P2^4;                //小数点输出

  56. sbit beep_dr = P2^5;           //蜂鸣器输出
  57. sbit Key_sr1 = P3^7;                        //确认/选择键
  58. sbit Key_sr2 = P3^6;                           //上选择键        Down
  59. sbit Key_sr3 = P3^5;                        //下选择键        UP
  60. sbit relay_dr = P1^5;                        //继电器输出
  61. sbit Key_sr4 = P1^3;                        //开机按键

  62. sbit adc0832_CS_dr = P1^4;                        //adc0832的使能端口
  63. sbit adc0832_DI_sr_dr = P1^6;                        //adc0832的数据端口
  64. sbit adc0832_CLK_dr = P1^7;                //adc0832的时钟端口

  65. unsigned char ucShortTouchFlag3 = 0; //短按的自锁标志、
  66. unsigned char ucShortTouchFlag4 = 0; //短按的自锁标志

  67. unsigned char ucDigStep = 1;        //步骤变量         
  68. unsigned int uiDigTimeCnt = 0;        //小数点延时计数器
  69. unsigned char ucDigTimeLock = 0;//原子锁
  70. unsigned int uiVoiceCnt        = 0;         //蜂鸣器计数器

  71. unsigned int uiDigTemp1 = 0;        //第一位数码管显示内容
  72. unsigned int uiDigTemp2 = 0;        //第二位数码管显示内容
  73. unsigned int uiDigTemp3 = 0;        //第三位数码管显示内容
  74. unsigned int uiDigTemp4 = 0;        //第四位数码管显示内容

  75. unsigned int uiDigTemp = 0;     //计数的变量

  76. unsigned int uiKeyTimeCnt1 = 0;  //按键去抖动延时计数器
  77. unsigned char ucKeyLock1 = 0;         //按键触发后自锁的变量标志
  78. unsigned char ucKeySec = 0;                         //被触发的按键编号

  79. unsigned int uiKeyTimeCnt2 = 0;  //按键去抖动延时计数器
  80. unsigned char ucKeyLock2 = 0;         //按键触发后自锁的变量标志

  81. unsigned int uiKeyTimeCnt3 = 0;  //按键去抖动延时计数器
  82. unsigned char ucKeyLock3 = 0;         //按键触发后自锁的变量标志

  83. unsigned int uiKeyTimeCnt4 = 0;  //按键去抖动延时计数器
  84. unsigned char ucKeyLock4 = 0;         //按键触发后自锁的变量标志

  85. unsigned char ucKeyStartFlag1=0; //启动定时中断计数的开关
  86. unsigned char ucKeyStartFlag2=0; //启动定时中断计数的开关
  87. unsigned char ucKeyStartFlag3=0; //启动定时中断计数的开关
  88. unsigned char ucKeyStartFlag4=0; //启动定时中断计数的开关

  89. unsigned int uiKeyCtntyCnt1 = 0; //连续触发延时计数器累加
  90. unsigned int uiKeyCtntyCnt2 = 0;
  91. /*****************************************************************************************/

  92. unsigned char  ucVoiceLock=0;  //蜂鸣器鸣叫的原子锁

  93. unsigned char ucDigShowTemp=0; //临时中间变量
  94. unsigned char ucWd=6;  //本程序的核心变量,窗口显示变量。类似于一级菜单的变量。代表显示不同的窗口。
  95. unsigned char ucPart=0;//本程序的核心变量,局部显示变量。类似于二级菜单的变量。代表显示不同的局部。
  96. unsigned char ucWd1Update=0; //窗口1更新显示标志
  97. unsigned char ucWd2Update=1; //窗口2更新显示标志
  98. unsigned char ucWd3Update=1; //窗口3更新显示标志
  99. unsigned char ucWd4Update=1; //窗口4更新显示标志
  100. unsigned char ucWd5Update=1; //窗口5更新显示标志

  101. unsigned char ucWd1Part1Update=0;  //在窗口1中,局部1的更新显示标志
  102. unsigned char ucWd1Part2Update=0; //在窗口1中,局部2的更新显示标志

  103. unsigned char ucWd2Part1Update=0;  //在窗口2中,局部1的更新显示标志
  104. unsigned char ucWd2Part2Update=0; //在窗口2中,局部2的更新显示标志

  105. unsigned char ucWd3Part1Update=0; //在窗口3中,局部1的更新显示标志
  106. unsigned char ucWd3Part2Update=0; //在窗口3中,局部2的更新显示标志

  107. unsigned char ucWd4Part1Update = 0;        //在窗口4中,局部1的更新显示标志
  108. unsigned char ucWd4Part2Update = 0;        //在窗口4中,局部2的更新显示标志

  109. unsigned char ucWd5Part1Update = 0;        //在窗口5中,局部1的更新显示标志


  110. unsigned char ucDelayTimerLock=0; //原子锁

  111. //unsigned int  uiDelayTimer=0;
  112. unsigned char ucCheckDs1302=0;  //检查Ds1302芯片是否正常
  113. unsigned char ucDs1302Error=0; //Ds1302芯片的备用电池是否用完了的报警标志
  114. unsigned char ucDs1302Lock=0;//原子锁
  115. unsigned int  uiDs1302Cnt=0; //间歇性蜂鸣器报警的计时器
  116. unsigned char ucDpyTimeLock=0; //原子锁
  117. unsigned int  uiDpyTimeCnt=0;  //数码管的闪烁计时器,放在定时中断里不断累加
  118. unsigned char ucAutoDisplayDateLock1 = 0;  //原子锁
  119. unsigned char ucAutoDisplayDateLock2 = 0;  //原子锁

  120. unsigned char  ucHour=0;  
  121. unsigned char  ucMinute=0;  
  122. unsigned char  ucSecond=0;  

  123. unsigned char  ucHourBCD=0;  
  124. unsigned char  ucMinuteBCD=0;  
  125. unsigned char  ucSecondBCD=0;  

  126. unsigned char ucSetTimedataCnt1;
  127. unsigned char ucSetTimedataCnt2;
  128. unsigned char ucSetTimeCnt1BCD;
  129. unsigned char ucSetTimeCnt2BCD;

  130. unsigned char ucTemp1=0;  //中间过渡变量
  131. unsigned char ucTemp2=0;  //中间过渡变量
  132. unsigned char ucTemp3=0;  //中间过渡变量
  133. unsigned char ucTemp4=0;  //中间过渡变量

  134. unsigned char ucSetTimeCnt1 = 12; //设定时间变量
  135. unsigned char ucSetTimeCnt2 = 30;

  136. unsigned char ucSetTepCnt1 = 50;         //设置温度计数器

  137. unsigned char ucDigShow4;  //第4位数码管要显示的内容
  138. unsigned char ucDigShow3;  //第3位数码管要显示的内容
  139. unsigned char ucDigShow2;  //第2位数码管要显示的内容
  140. unsigned char ucDigShow1;  //第1位数码管要显示的内容

  141. unsigned int uiSampingCnt=0;   //采集Ds1302的计时器,每秒钟更新采集一次
  142. unsigned char ucStartheat = 0;  //启动加热标志位
  143. unsigned char ucAlarmPrompt = 0;//加热完毕报警提示标志位

  144. unsigned char ucAD_value_Tem = 0;//AD转换过后的温度数据
  145. unsigned char ucADC_value = 0;//AD数据
  146. unsigned char ucADC_sampling_number = 1; //开启ADC采样的标志位
  147. unsigned char ucADC_samplingCnt = 0;         //ADC采样次数变量
  148. unsigned char KeyChangeTimeFlag;
  149. unsigned char ucBootScreen = 0;  //开机标志位

  150. /************************************************************************************************/

  151. void ds1302_alarm_service(void); //ds1302出错报警
  152. void ds1302_sampling(void); //ds1302采样程序,内部每秒钟采集更新一次
  153. void Write1302 ( unsigned char addr, unsigned char dat );//修改时间的驱动
  154. void display_service(void); //显示的窗口菜单服务程序

  155. void delay_short(unsigned int uiDelayShort);
  156. void delay_long(unsigned int uiDelayLong);

  157. unsigned char Read1302 ( unsigned char addr );//读取时间的驱动
  158. unsigned char bcd_to_number(unsigned char ucBcdTemp);  //BCD转原始数值
  159. unsigned char number_to_bcd(unsigned char ucNumberTemp); //原始数值转BCD

  160. void initial_myself(void);  //第一区 初始化单片机
  161. void delay(unsigned int delay_ms);
  162. void display();
  163. void T0_time();
  164. void key_scan();
  165. void key_service();
  166. void T0_init();
  167. void TimeData_contrast();
  168. void ucAlarmPrompt_service();
  169. void ADC_sampling_service();
  170.                                                   
  171. unsigned char array[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xc6,0x86,
  172.                        0xc6,0xf6,0xf6,0xf0};

  173. const unsigned int code wendu_tab[106]=
  174. {
  175.    3274,3111,2957,2812,2674,2545,2422,2306,2196,2092, //0~9
  176.    1993,1900,1811,1728,1648,1573,1501,1433,1369,1308, //10~19
  177.    1250,1194,1142,1092,1045,1000,957,916,877,840,          //20~29
  178.    805,771,739,709,679,652,625,600,576,553,                          //30~39
  179.    531,510,490,471,453,435,418,402,387,372,                          //40~49
  180.    358,345,332,320,308,297,286,276,266,256,                          //50~59
  181.    247,238,230,222,214,207,199,193,186,180,                          //60~69
  182.    174,168,162,157,152,147,142,137,133,128,                          //70~79
  183.    124,120,116,113,109,106,102,99,96,93,                          //80~89
  184.    90,88,85,82,80,78,75,73,71,69,                                          //90~99
  185.    67,65,63,61,59,58                                                                  //100~105
  186. };

  187. /********************************************************************************************
  188. 函数名称:主程序
  189. 功    能:程序执行的入口
  190. 返 回 值:无
  191. 时    间:2014-11-11        
  192. 备    注:
  193. **************************************************************************************************/
  194. void main()
  195. {
  196.     T0_init();
  197.         initial_myself();
  198.         while(1)
  199.         {

  200.                  ds1302_alarm_service(); //ds1302出错报警
  201.                  ucAlarmPrompt_service();
  202.                  display_service(); //显示的窗口菜单服务程序
  203.                  ds1302_sampling(); //ds1302采样程序,内部每秒钟采集更新一次
  204.                  key_service();                         //按键服务函数放在主程序里
  205.                  TimeData_contrast();

  206.                 if(ucADC_sampling_number == 1)
  207.                 {
  208.                         ucADC_samplingCnt++;

  209.                         if(ucADC_samplingCnt==10)
  210.                         {
  211.                             ucADC_sampling_number = 0;
  212.                                 ucADC_samplingCnt = 0;
  213.                                 ADC_sampling_service();
  214.                             ucADC_sampling_number = 1;
  215.                         }
  216.                 }

  217.                  if(ucDigTimeLock == 0 && ucPart == 0)          //开始计数器标志
  218.                  {
  219.                     uiDigTimeCnt++;                  //计数器开始计数
  220.                  }
  221.                  else
  222.                  {
  223.                     digital_dp_dr = 1;  //关闭小数点显示
  224.                  }
  225.                  
  226.                  if(uiDigTimeCnt >= const_DigTime_level)  //计数时间到
  227.                  {
  228.                          ucDigTimeLock = 1;                                          //计数器标志位置1
  229.                          uiDigTimeCnt = 0;                                          //计数器清零
  230.                          digital_dp_dr = ~digital_dp_dr;          //小数点输出
  231.                          ucDigTimeLock = 0;                                          //计数器标志位清零,开始计数。
  232.                  }
  233.                  
  234. /********************************************************************************************
  235. 功    能:数码管闪烁计数器在外部可以关闭,不开启计时功能
  236. 时    间:2014-11-11        
  237. **************************************************************************************************/
  238.     if(ucDpyTimeLock==0) //原子锁判断
  239.         {
  240.                 uiDpyTimeCnt++;  //数码管的闪烁计时器
  241.         }


  242.         }  
  243. }         


  244. /********************************************************************************************
  245. 函数名称:按键扫描
  246. 功    能:
  247.          1、按下Key_sr1,加1,如果安下一直不松,就连续加。
  248.                  2、按下Key_sr2,加减1,如果安下一直不松,就连续减。
  249.                  3、按下Key_sr3,单击单步触发,和长按触发
  250. 返 回 值:无
  251. 时    间:2014-11-11        
  252. 备    注:按键运用了,单击,长按,连续触发的方法。
  253. **************************************************************************************************/
  254. void key_scan()
  255. {
  256.         static unsigned char KeyChangeTimeFlag3;

  257.         if(Key_sr1 == 1)                 //1号键
  258.         {
  259.            ucKeyStartFlag1 = 0;         //启动定时中断计数的开关清零
  260.            uiKeyTimeCnt1 = 0;         //按键去抖动延时计数器清零
  261.            ucKeyLock1 = 0;                  //按键触发后自锁的变量标志清零
  262.          
  263.         }
  264.         else if(ucKeyLock1 == 0)
  265.         {
  266.               ucKeyStartFlag1 = 1;                //开启计数器开关,开始计数

  267.                 if(uiKeyTimeCnt1>=const_KeyTime_level)
  268.                 {
  269.                     ucKeyStartFlag1 = 0;        //开启计数器关闭,停止计数
  270.                         ucKeyLock1 = 1;                        //自锁按键置位,避免一直触发
  271.                         uiKeyTimeCnt1 = 0;           //按键去抖动延时计数器清零
  272.                         ucKeySec = 1;                   //触发1号键
  273.                 }
  274.         }

  275.         else if(uiKeyTimeCnt1<const_time_1s)
  276.         {
  277.                  uiKeyTimeCnt1++;
  278.         }
  279.         else
  280.         {
  281.                  uiKeyCtntyCnt1++; //连续触发延时计数器累加

  282.                 if(uiKeyCtntyCnt1>const_time_0_25s)
  283.                 {
  284.                         uiKeyCtntyCnt1 = 0;
  285.                         ucKeySec = 1;                   //触发1号键
  286.                 }
  287.         }


  288.         if(Key_sr2 == 1)                 //2号键
  289.         {
  290.            ucKeyStartFlag2 = 0;         //启动定时中断计数的开关清零
  291.            uiKeyTimeCnt2 = 0;         //按键去抖动延时计数器清零
  292.            ucKeyLock2 = 0;                  //按键触发后自锁的变量标志清零
  293.         }
  294.         else if(ucKeyLock2 == 0)
  295.         {
  296.               ucKeyStartFlag2 = 1;                //开启计数器开关,开始计数

  297.                 if(uiKeyTimeCnt2>=const_KeyTime_level)
  298.                 {
  299.                     ucKeyStartFlag2 = 0;        //开启计数器关闭,停止计数
  300.                         ucKeyLock2 = 1;                        //自锁按键置位,避免一直触发
  301.                         uiKeyTimeCnt2 = 0;           //按键去抖动延时计数器清零
  302.                         ucKeySec = 2;                   //触发2号键
  303.                 }
  304.         }
  305.         else if(uiKeyTimeCnt2<const_time_1s)
  306.         {
  307.                  uiKeyTimeCnt2++;
  308.         }
  309.         else
  310.         {
  311.                  uiKeyCtntyCnt2++; //连续触发延时计数器累加

  312.                 if(uiKeyCtntyCnt2>const_time_0_25s)
  313.                 {
  314.                         uiKeyCtntyCnt2 = 0;
  315.                         ucKeySec = 2;                   //触发1号键
  316.                 }
  317.         }
  318.             
  319.         if(Key_sr3 == 1)                 //3,4号键
  320.         {
  321.            ucKeyStartFlag3 = 0;         //启动定时中断计数的开关清零
  322.            uiKeyTimeCnt3 = 0;         //按键去抖动延时计数器清零
  323.            ucKeyLock3 = 0;                  //按键触发后自锁的变量标志清零
  324.            ucShortTouchFlag3 = 0; //短按的自锁标志清零
  325.             KeyChangeTimeFlag3 = 0;
  326.         }
  327.         else if(ucKeyLock3 == 0)
  328.         {
  329.               ucKeyStartFlag3 = 1;                //开启计数器开关,开始计数

  330.                 if(ucShortTouchFlag3 == 0)
  331.                 {
  332.                         if(uiKeyTimeCnt3>=const_key_time_short3)  //短按中间间隔的时间
  333.                         {
  334.                             ucShortTouchFlag3 = 1;
  335.                                 ucKeySec = 3;                   //触发3号键
  336.                         }
  337.                 }

  338.                 if(uiKeyTimeCnt3>=const_key_time_long3&&KeyChangeTimeFlag3 == 0)
  339.                 {
  340.             KeyChangeTimeFlag3 = 1;
  341.                         ucKeySec = 17;                   //触发17号键
  342.                 }
  343.             if(uiKeyTimeCnt3>=const_key_time_long3+const_key_time_long3)
  344.                 {
  345.                     ucKeyStartFlag3 = 0;        //开启计数器关闭,停止计数
  346.                         ucKeyLock3 = 1;                        //自锁按键置位,避免一直触发
  347.                         uiKeyTimeCnt3 = 0;           //按键去抖动延时计数器清零
  348.                         ucKeySec = 18;                   //触发17号键
  349.                 }

  350.         }

  351.         if(Key_sr4 == 1)                 //1号键
  352.         {
  353.            ucKeyStartFlag4 = 0;         //启动定时中断计数的开关清零
  354.            uiKeyTimeCnt4 = 0;         //按键去抖动延时计数器清零
  355.            ucKeyLock4 = 0;                  //按键触发后自锁的变量标志清零
  356.            ucShortTouchFlag4 = 0; ///短按的自锁标志清零
  357.          
  358.         }
  359.         else if(ucKeyLock4 == 0)
  360.         {
  361.               ucKeyStartFlag4 = 1;                //开启计数器开关,开始计数

  362.                 if(ucShortTouchFlag4 == 0)
  363.                 {         
  364.                         if(uiKeyTimeCnt4>=const_KeyTime_level)
  365.                         {
  366.                                 ucShortTouchFlag4 = 1;
  367.                                 ucKeySec = 4;                   //触发4号键
  368.                         }

  369.                
  370.                 }

  371.            if(uiKeyTimeCnt4>=const_key_time_long3)
  372.            {
  373.                         ucKeyStartFlag4 = 0;        //开启计数器关闭,停止计数
  374.                         ucKeyLock4 = 1;                        //自锁按键置位,避免一直触发
  375.                         uiKeyTimeCnt4 = 0;           //按键去抖动延时计数器清零
  376.                         ucKeySec = 5;                   //触发5号键

  377.            }
  378.         }
  379. }

  380. /********************************************************************************************
  381. 函数名称:显示的窗口菜单服务程序
  382. 功    能:更新显示内容
  383. 返 回 值:无
  384. 时    间:2014-11-11        
  385. 备    注:
  386. **************************************************************************************************/

  387. void display_service(void) //显示的窗口菜单服务程序
  388. {
  389.    switch(ucWd)  //本程序的核心变量,窗口显示变量。类似于一级菜单的变量。代表显示不同的窗口。
  390.    {
  391.            case 1:   //显示时间窗口的数据  数据格式 SS FF MM 时 分 秒
  392.                 if(ucWd1Update==1)  //窗口1要全部更新显示
  393.                 {
  394.                                 ucWd1Update=0;  //及时清零标志,避免一直进来扫描
  395.                                 ucWd1Part1Update=1;  //局部时更新显示
  396.                                 ucWd1Part2Update=1;  //局部分更新显示
  397.                 }
  398.         
  399.                         if(ucWd1Part1Update==1)//局部时更新显示
  400.                         {
  401.                                 ucWd1Part1Update=0;
  402.                                 ucTemp1=ucHour/10;  //时
  403.                                 ucTemp2=ucHour%10;
  404.                                 ucDigShow1=ucTemp1; //数码管显示实际内容
  405.                                 ucDigShow2=ucTemp2;
  406.                         }
  407.         
  408.                         if(ucWd1Part2Update==1)//局部分更新显示
  409.                         {
  410.                                 ucWd1Part2Update=0;
  411.                                 ucTemp3=ucMinute/10;  //分
  412.                                 ucTemp4=ucMinute%10;
  413.                                 ucDigShow3=ucTemp3; //数码管显示实际内容
  414.                                 ucDigShow4=ucTemp4;
  415.                         }
  416.         
  417.              //数码管闪烁
  418.                 switch(ucPart)  //相当于二级菜单,根据局部变量的值,使对应的参数产生闪烁的动态效果。
  419.                         {
  420.                             case 0:  //都不闪烁
  421.                                  break;
  422.                             case 1:  //时参数闪烁
  423.                                  if(uiDpyTimeCnt==const_dpy_time_half)
  424.                                  {
  425.                                        ucDigShow1=ucTemp1; //数码管显示实际内容
  426.                                        ucDigShow2=ucTemp2;
  427.                                   }
  428.                                  else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
  429.                                  {
  430.                                                 ucDpyTimeLock=1; //原子锁加锁
  431.                                                 uiDpyTimeCnt=0;   //及时把闪烁记时器清零
  432.                                                 ucDpyTimeLock=0;  //原子锁解锁
  433.                                                 ucDigShow1=10;   //数码管显示空,什么都不显示
  434.                                                 ucDigShow2=10;
  435.                                  }
  436.                                  break;
  437.                         
  438.                             case 2:   //分参数闪烁
  439.                                  if(uiDpyTimeCnt==const_dpy_time_half)
  440.                                  {
  441.                                                 ucDigShow1=ucTemp1; //数码管显示实际内容,显示前两位,
  442.                                     ucDigShow2=ucTemp2;         //目的是上面闪烁后,数码管显示内容会清零

  443.                                                 ucDigShow3=ucTemp3; //数码管显示实际内容
  444.                                                 ucDigShow4=ucTemp4;
  445.                                  }
  446.                                  else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
  447.                                  {
  448.                                                 ucDpyTimeLock=1; //原子锁加锁
  449.                                                 uiDpyTimeCnt=0;   //及时把闪烁记时器清零
  450.                                                 ucDpyTimeLock=0;  //原子锁解锁
  451.                                                 ucDigShow3=10;   //数码管显示空,什么都不显示
  452.                                                 ucDigShow4=10;

  453.                                  }
  454.                                 break;
  455.                         }
  456.             break;

  457.                 case 2:
  458.                     if(ucWd2Update==1)  //窗口1要全部更新显示
  459.                 {
  460.                                 ucWd2Update=0;  //及时清零标志,避免一直进来扫描
  461.                                 ucWd2Part1Update=1;  //局部时更新显示
  462.                                 ucWd2Part2Update=1;  //局部分更新显示
  463.                 }

  464.                         if(ucWd2Part1Update == 1)
  465.                         {
  466.                                    ucWd2Part1Update = 0;
  467.                                 ucTemp1=ucSetTimeCnt1/10;  //时
  468.                                 ucTemp2=ucSetTimeCnt1%10;
  469.                                 ucDigShow1=ucTemp1; //数码管显示实际内容
  470.                                 ucDigShow2=ucTemp2;
  471.                         }

  472.                         if(ucWd2Part2Update == 1)
  473.                         {
  474.                                    ucWd2Part2Update = 0;
  475.                                 ucTemp3=ucSetTimeCnt2/10;  //时
  476.                                 ucTemp4=ucSetTimeCnt2%10;
  477.                                 ucDigShow3=ucTemp3; //数码管显示实际内容
  478.                                 ucDigShow4=ucTemp4;
  479.                         }

  480.                     switch(ucPart)  //相当于二级菜单,根据局部变量的值,使对应的参数产生闪烁的动态效果。
  481.                         {
  482.                             case 0:  //都不闪烁
  483.                                  break;
  484.                             case 1:  //时参数闪烁
  485.                                  if(uiDpyTimeCnt==const_dpy_time_half)
  486.                                  {
  487.                                        ucDigShow1=ucTemp1; //数码管显示实际内容
  488.                                        ucDigShow2=ucTemp2;
  489.                                   }
  490.                                  else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
  491.                                  {
  492.                                                 ucDpyTimeLock=1; //原子锁加锁
  493.                                                 uiDpyTimeCnt=0;   //及时把闪烁记时器清零
  494.                                                 ucDpyTimeLock=0;  //原子锁解锁
  495.                                                 ucDigShow1=10;   //数码管显示空,什么都不显示
  496.                                                 ucDigShow2=10;
  497.                                  }
  498.                                  break;
  499.                         
  500.                             case 2:   //分参数闪烁
  501.                                  if(uiDpyTimeCnt==const_dpy_time_half)
  502.                                  {
  503.                                                 ucDigShow1=ucTemp1; //数码管显示实际内容,这里是为了显示前两位
  504.                                     ucDigShow2=ucTemp2;         //目的是上面闪烁后,数码管显示内容会清零

  505.                                                 ucDigShow3=ucTemp3; //数码管显示实际内容
  506.                                                 ucDigShow4=ucTemp4;
  507.                                  }
  508.                                  else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
  509.                                  {
  510.                                                 ucDpyTimeLock=1; //原子锁加锁
  511.                                                 uiDpyTimeCnt=0;   //及时把闪烁记时器清零
  512.                                                 ucDpyTimeLock=0;  //原子锁解锁
  513.                                                 ucDigShow3=10;   //数码管显示空,什么都不显示
  514.                                                 ucDigShow4=10;

  515.                                  }
  516.                                 break;
  517.                         }
  518.             break;

  519.                  case 3:
  520.                        if(ucWd3Update==1)  //窗口3要全部更新显示
  521.                    {
  522.                                    ucWd3Update=0;  //及时清零标志,避免一直进来扫描
  523.                                    ucWd3Part1Update=1;  //局部时更新显示
  524.                                    ucWd3Part2Update=1;  //局部分更新显示
  525.                    }  
  526.                            
  527.                            if(ucWd3Part1Update == 1)
  528.                            {
  529.                                       ucWd3Part1Update = 0;

  530.                                    if(ucSetTepCnt1>=100)
  531.                                    {
  532.                                               ucTemp1 = ucSetTepCnt1/100;
  533.                                        ucTemp2 = ucSetTepCnt1/10%10;
  534.                                            ucTemp3 = ucSetTepCnt1%10;
  535.                                    }
  536.                                    else
  537.                                    {
  538.                                               ucTemp1 = ucSetTepCnt1/10;
  539.                                        ucTemp2 = ucSetTepCnt1%10;
  540.                                            ucTemp3 = 10;
  541.                                    }

  542.                                    ucDigShow1=ucTemp1; //数码管显示实际内容
  543.                                    ucDigShow2=ucTemp2; //数码管显示实际内容
  544.                                    ucDigShow3=ucTemp3; //数码管显示实际内容
  545.                            }

  546.                            if(ucWd3Part2Update == 1)
  547.                            {
  548.                                        ucWd3Part2Update = 0;        
  549.                                         ucDigShow4 = 11;
  550.                            }

  551.                            switch(ucPart)
  552.                            {
  553.                                 case 0:  break;
  554.                                 case 1:
  555.                                          if(uiDpyTimeCnt==const_dpy_time_half)
  556.                                          {
  557.                                                         ucDigShow1=ucTemp1; //数码管显示实际内容
  558.                                                         ucDigShow2=ucTemp2;
  559.                                          }
  560.                                          else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
  561.                                          {
  562.                                                         ucDpyTimeLock=1; //原子锁加锁
  563.                                                         uiDpyTimeCnt=0;   //及时把闪烁记时器清零
  564.                                                         ucDpyTimeLock=0;  //原子锁解锁
  565.                                                         ucDigShow1=10;   //数码管显示空,什么都不显示
  566.                                                         ucDigShow2=10;
  567.         
  568.                                          }
  569.                                                  break;

  570.                            }
  571.                            break;

  572.                 case 4:        
  573.                        if(ucWd4Update==1)  //窗口4要全部更新显示
  574.                    {
  575.                                    ucWd4Update=0;  //及时清零标志,避免一直进来扫描
  576.                                    ucWd4Part1Update=1;  //局部时更新显示
  577.                                    ucWd4Part2Update=1;  //局部分更新显示
  578.                    }  
  579.                            
  580.                            if(ucWd4Part1Update == 1)
  581.                            {
  582.                                       ucWd4Part1Update = 0;

  583.                                    if(ucAD_value_Tem>=100)
  584.                                    {
  585.                                               ucTemp1 = ucAD_value_Tem/100;
  586.                                        ucTemp2 = ucAD_value_Tem/10%10;
  587.                                            ucTemp3 = ucAD_value_Tem%10;
  588.                                    }
  589.                                    else
  590.                                    {
  591.                                               ucTemp1 = ucAD_value_Tem/10;
  592.                                        ucTemp2 = ucAD_value_Tem%10;
  593.                                            ucTemp3 = 10;
  594.                                    }

  595.                                    ucDigShow1=ucTemp1; //数码管显示实际内容
  596.                                    ucDigShow2=ucTemp2; //数码管显示实际内容
  597.                                    ucDigShow3=ucTemp3; //数码管显示实际内容
  598.                            }

  599.                            if(ucWd4Part2Update == 1)
  600.                            {
  601.                                        ucWd4Part2Update = 0;        
  602.                                         ucDigShow4 = 11;
  603.                            }
  604.                 break;

  605.                 case 5:if(ucWd5Update==1)  //窗口5要全部更新显示
  606.                    {
  607.                                    ucWd5Update=0;  //及时清零标志,避免一直进来扫描
  608.                                    ucWd5Part1Update=1;  //局部时更新显示
  609.                    }  
  610.                            
  611.                            if(ucWd5Part1Update == 1)
  612.                            {
  613. //                                      ucWd5Part1Update = 0;
  614.                   
  615.                                    ucDigShow1=ucTemp1; //数码管显示实际内容
  616.                                    ucDigShow2=ucTemp2; //数码管显示实际内容
  617.                                    ucDigShow3=ucTemp3; //数码管显示实际内容
  618.                                    ucDigShow4=ucTemp4; //数码管显示实际内容

  619.                            }
  620.                            break;

  621.                  case 6:ucDigTimeLock = 1; //不显示小数点
  622.                                 ucDigShow1=13; //数码管显示实际内容
  623.                                 ucDigShow2=14; //数码管显示实际内容
  624.                                 ucDigShow3=15; //数码管显示实际内容
  625.                                 ucDigShow4=16; //数码管显示实际内容

  626.                  break;
  627.       }
  628. }


  629. /********************************************************************************************
  630. 函数名称:按键服务程序
  631. 功    能:按键处理的事务
  632. 返 回 值:无
  633. 时    间:2014-11-11        
  634. 备    注:
  635. **************************************************************************************************/
  636. void key_service(void) //按键服务的应用程序
  637. {
  638.         switch(ucKeySec) //按键服务状态切换
  639.         {
  640.                 case 1:// 加按键  
  641.                                 switch(ucWd)  //在不同的窗口下,设置不同的参数
  642.                                 {
  643.                                 
  644.                                 case 1:switch(ucPart) //在不同的局部变量下,相当于二级菜单
  645.                                                 {
  646.                                                         case 1:  //时
  647.                                                                         ucHour++;
  648.                         
  649.                                                                         if(ucHour>23)
  650.                                                                         {
  651.                                                                                 ucHour=23;
  652.                                                                         }
  653.                                                                         ucWd1Part1Update=1;  //更新显示                                               
  654.                                                                         break;
  655.         
  656.                                                         case 2: //分
  657.                                                                         ucMinute++;
  658.                                                                         if(ucMinute>59)
  659.                                                                         {
  660.                                                                                 ucMinute=59;
  661.                                                                         }
  662.                                                                         ucWd1Part2Update=1;  //更新显示                                                      
  663.                                                                         break;
  664.                                                 }
  665.                                         break;

  666.                                  case 2:
  667.                                         switch(ucPart)
  668.                                                 {
  669.                                                         case 1:
  670.                                                               ucSetTimeCnt1++;
  671.                                                                   if(ucSetTimeCnt1>23)
  672.                                                                   {
  673.                                                                      ucSetTimeCnt1 = 23;
  674.                                                                   }

  675.                                                                   ucWd2Part1Update=1;  //更新显示
  676.                                                                  break;

  677.                                                         case 2:
  678.                                                                    ucSetTimeCnt2++;
  679.                                                                   if(ucSetTimeCnt2>59)
  680.                                                                   {
  681.                                                                      ucSetTimeCnt2 = 59;
  682.                                                                   }
  683.                                                                   ucWd2Part2Update=1;  //更新显示
  684.                                                               break;
  685.                                                 }
  686.                                  break;

  687.                                  case 3:
  688.                                        switch(ucPart)
  689.                                            {
  690.                                              
  691.                                                    case 1:
  692.                                                          ucSetTepCnt1++;
  693.                                                                  if(ucSetTepCnt1>125)
  694.                                                                  {
  695.                                                                      ucSetTepCnt1 = 125;
  696.                                                                  }
  697.                                                                  ucWd3Part1Update = 1;
  698.                                                    break;
  699.                                                    
  700.                                            }
  701.                                  break;

  702.                                 }
  703.         
  704.               ucVoiceLock=1;  //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
  705.               uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。
  706.               ucVoiceLock=0;  //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
  707.               ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  708.               break;   
  709.         
  710.         
  711.                 case 2:// 减按键  
  712.                       switch(ucWd)  //在不同的窗口下,设置不同的参数
  713.                       {
  714.                                       case 1:
  715.                                 switch(ucPart) //在不同的局部变量下,相当于二级菜单
  716.                                                 {
  717.                                                         case 1:  //时
  718.                                                                         ucHour--;
  719.                                                                         if(ucHour>23)
  720.                                                                         {
  721.                                                                                 ucHour=0;
  722.                                                                         }
  723.                                                                         ucWd1Part1Update=1;  //更新显示                                               
  724.                                                                 break;
  725.         
  726.                                                         case 2: //分
  727.                                                                         ucMinute--;
  728.                                                                         if(ucMinute>59)
  729.                                                                         {
  730.                                                                                 ucMinute=0;
  731.                                                                         }
  732.                                                                         ucWd1Part2Update=1;  //更新显示                                                      
  733.                                                                         break;
  734.                                                         }
  735.                                 break;
  736.                                    case 2:
  737.                                 switch(ucPart) //在不同的局部变量下,相当于二级菜单
  738.                                                 {
  739.                                                         case 1:  //时
  740.                                                                         ucSetTimeCnt1--;
  741.                                                                         if(ucSetTimeCnt1>23)
  742.                                                                         {
  743.                                                                                 ucSetTimeCnt1=0;
  744.                                                                         }

  745.                                                                         ucWd2Part1Update=1;  //更新显示                                               
  746.                                                                     break;
  747.         
  748.                                                         case 2: //分
  749.                                                                         ucSetTimeCnt2--;
  750.                                                                         if(ucSetTimeCnt2>59)
  751.                                                                         {
  752.                                                                                 ucSetTimeCnt2=0;
  753.                                                                         }
  754.                                                                         ucWd2Part2Update=1;  //更新显示                                                      
  755.                                                                         break;
  756.                                                         }
  757.                                 break;
  758.                                        
  759.                                 case 3:        switch(ucPart)
  760.                                                 {
  761.                                                         
  762.                                                         case 1:
  763.                                                                 ucSetTepCnt1--;

  764.                                                                 if(ucSetTepCnt1>125)
  765.                                                                 {
  766.                                                                         ucSetTepCnt1 = 0;
  767.                                                                 }
  768.                                                                 ucWd3Part1Update = 1;
  769.                                                                 break;
  770.                                                         
  771.                                                         }
  772.                                                 break;


  773.                       }
  774.         
  775.               ucVoiceLock=1;  //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
  776.               uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。
  777.               ucVoiceLock=0;  //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
  778.               ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  779.               break;
  780.                   
  781.                 case 3://短按设置按键
  782.                                 switch(ucWd)  //在不同的窗口下,设置不同的参数
  783.                                 {
  784.                                        
  785.                                         case 1:
  786.                                                 if(ucAlarmPrompt == 1)         //此时报警启动
  787.                                                         {
  788.                                                             ucAlarmPrompt = 0;          //报警关闭
  789.                                                         }

  790.                                                         if(ucPart>0) //在窗口2的时候,要第一次激活设置时间,必须是长按3秒才可以,这里短按激活不了第一次
  791.                                                         {
  792.                                                                 ucPart++;
  793.                                                                 if(ucPart>2)  //设置时间结束
  794.                                                                 {
  795.                                                                         ucPart=0;
  796.                                                                         /* 注释五:
  797.                                                                         * 每个月份的天数最大值是不一样的,在写入ds1302时钟芯片内部数据前,应该做一次调整。
  798.                                                                         * 有的月份最大28天,有的月份最大29天,有的月份最大30天,有的月份最大31天,
  799.                                                                         */                                                   
  800.                                                                         ucHourBCD=number_to_bcd(ucHour);  //原始数值转BCD
  801.                                                                         ucMinuteBCD=number_to_bcd(ucMinute);  //原始数值转BCD
  802.                                                                         ucSecondBCD=number_to_bcd(ucSecond);  //原始数值转BCD

  803.                                                                         Write1302 (WRITE_PROTECT,0X00);          //禁止写保护
  804.                                                                         Write1302 (WRITE_HOUR,ucHourBCD);        //小时修改
  805.                                                                         Write1302 (WRITE_MINUTE,ucMinuteBCD);    //分钟修改
  806.                                                                         Write1302 (WRITE_SECOND,ucSecondBCD);    //秒位修改
  807.                                                                         Write1302 (WRITE_PROTECT,0x80);          //允许写保护

  808.                                                                 }
  809.                                                                 ucWd1Update=1;  //窗口1更新显示
  810.                                                         }
  811.                                                 break;

  812.                                            case 2:
  813.                                                         if(ucPart>0)
  814.                                                         {
  815.                                                                 ucPart++;
  816.                                                                 if(ucPart>2)
  817.                                                                 {
  818.                                                                ucPart = 1;
  819.                                                                    ucWd=3; //切换到第三个窗口,设置预定时
  820.                                                                    ucWd3Update=1;  //窗口3更新显示
  821.                                                                 }
  822.                                                         }
  823.                                                         break;

  824.                                            case 3:
  825.                                                  if(ucPart>0)
  826.                                                          {
  827.                                                             ucPart++;
  828.                                                                 if(ucPart>1)
  829.                                                                 {
  830.                                                                     ucPart = 0;
  831.                                                                         ucWd = 4;  //切换到第四个窗口,
  832.                                                                         ucPart = 1;
  833.                                                                         ucDigTimeLock = 1;  //小数点不显示
  834.                                                                 }
  835.                                                          }
  836.                                                         break;

  837.                                            case 4:
  838.                                                  if(ucPart>0)
  839.                                                          {
  840.                                                             ucPart++;
  841.                                                                 if(ucPart>1)
  842.                                                                 {
  843.                                                                     ucPart = 0;
  844.                                                                         ucWd = 1;
  845.                                                                         ucWd1Update = 1;
  846.                                                                         ucDigTimeLock = 0;  //显示小数点
  847.                                                                         ucStartheat = 1;//启动加热
  848.                                                                 }
  849.                                                          }

  850.                                                         break;
  851.                                 }
  852.         
  853.               ucVoiceLock=1;  //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
  854.               uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。
  855.               ucVoiceLock=0;  //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
  856.               ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  857.               break;      
  858.                      
  859.                 case 4:
  860.                            if(ucBootScreen == 0)  //开机
  861.                            {
  862.                                         ucWd=1;
  863.                                         ucWd1Update=1;  //窗口1更新显示
  864.                                         ucDigTimeLock = 0; //显示小数点
  865.                                         ucBootScreen = 1; //开关标志位置1,为关机做准备
  866.                            }
  867. //                                 if(ucBootScreen == 1)//关机
  868. //                           {
  869. //                                        ucWd=6;
  870. //                                        ucBootScreen = 0; //开关标志位清零,为开机做准备
  871. //                                        ucStartheat = 0; //停止加热
  872. //                                        ucSetTimeCnt1 = 12; //复位默认设的小时
  873. //                                    ucSetTimeCnt2 = 30; //复位默认设的分钟
  874. //                    ucSetTepCnt1 = 50; //复位默认温度值
  875. //                                        ucPart = 0;         //设置清零
  876. //                           }
  877.               ucVoiceLock=1;  //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
  878.               uiVoiceCnt=const_voice_long; //按键声音触发,滴一声就停。
  879.               ucVoiceLock=0;  //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
  880.               ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  881.                 break;

  882.                  case 5:
  883.                            if(ucBootScreen == 1)//关机
  884.                            {
  885.                                         ucWd=6;
  886.                                         ucBootScreen = 0; //开关标志位清零,为开机做准备
  887.                                         ucStartheat = 0; //停止加热
  888.                                         ucSetTimeCnt1 = 12; //复位默认设的小时
  889.                                     ucSetTimeCnt2 = 30; //复位默认设的分钟
  890.                     ucSetTepCnt1 = 50; //复位默认温度值
  891.                                         ucPart = 0;         //设置清零
  892.                            }
  893.               ucVoiceLock=1;  //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
  894.               uiVoiceCnt=const_voice_long; //按键声音触发,滴一声就停。
  895.               ucVoiceLock=0;  //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
  896.               ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  897.                 break;

  898.                 case 17://长按3秒设置按键
  899.                         switch(ucWd)  //在不同的窗口下,设置不同的参数
  900.                         {
  901.                                 case 1:
  902.                                                 if(ucPart==0) //处于非设置时间的状态下,要第一次激活设置时间,必须是长按3秒才可以
  903.                                                 {
  904.                                                                 ucWd=2;
  905.                                                                 ucPart=1;  //进入到设置日期的状态下
  906.                                                                 ucWd2Update=1;  //窗口1更新显示
  907.                                                 }
  908.                                                 break;
  909. //                                case 4:
  910. //                                       if(ucPart == 0)
  911. //                                           {
  912. //                                                      ucWd=2;
  913. //                                                   ucPart=1;  //进入到设置时间的状态下
  914. //                                                   ucWd2Update=1;  //窗口2更新显示
  915. //                                           }
  916. //                                        break;
  917.                         }
  918.         
  919.               ucVoiceLock=1;  //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
  920.               uiVoiceCnt=const_voice_long; //按键声音触发,滴一声就停。
  921.               ucVoiceLock=0;  //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
  922.               ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  923.               break;  
  924.                   
  925.                  case 18:
  926.                        switch(ucWd)
  927.                            {
  928.                               case 0:break;
  929.                                   case 2:
  930.                                          ucPart = 0;
  931.                                             if(ucPart == 0&& ucStartheat == 0)          //处于非设置的情况下,长按设置系统时间
  932.                                                 {
  933.                                                     ucWd = 1;
  934.                                                         ucPart = 1;
  935.                                                         ucWd1Update = 1;
  936.                                                 }
  937.                                                 else if(ucPart == 0&&ucStartheat == 1)
  938.                                                 {
  939.                                                             //处于非设置的情况下,久长按退出定时恒温热水
  940.                                                     ucWd = 1;
  941. //                                                        ucPart = 1;
  942.                                                         ucWd1Update = 1;

  943.                                                         ucStartheat = 0; //停止加热
  944.                                                         ucSetTimeCnt1 = 12; //复位默认设的小时
  945.                                                     ucSetTimeCnt2 = 30; //复位默认设的分钟
  946.                             ucSetTepCnt1 = 50; //复位默认温度值
  947.                                                         ucDigTimeLock = 0; //显示小数点
  948.                                                 }
  949.                                   break;

  950.                            }

  951.                   ucVoiceLock=1;  //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
  952.               uiVoiceCnt=const_voice_long; //按键声音触发,滴一声就停。
  953.               ucVoiceLock=0;  //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
  954.               ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  955.       
  956.                  break;  
  957.         }         

  958. }

  959. /********************************************************************************************
  960. 函数名称:DS1302采样程序
  961. 功    能:读取DS1302的数据
  962. 返 回 值:无
  963. 时    间:2014-11-11        
  964. 备    注:系统不用时时刻刻采集ds1302的内部数据,每隔一段时间更新采集一次就可以了。
  965.           这个间隔时间应该小于或者等于1秒钟的时间,否则在数码管上看不到每秒钟的时间变化。
  966. **************************************************************************************************/
  967. void ds1302_sampling(void) //ds1302采样程序,内部每秒钟采集更新一次
  968. {
  969.    if(ucPart==0)  //当系统不是处于设置日期和时间的情况下
  970.    {
  971.       ++uiSampingCnt;  //累计主循环次数的时间

  972.       if(uiSampingCnt>const_ds1302_sampling_time)  //每隔一段时间就更新采集一次Ds1302数据
  973.       {
  974.                         uiSampingCnt=0;
  975.                         ucHourBCD=Read1302(READ_HOUR); //读取时
  976.                         ucMinuteBCD=Read1302(READ_MINUTE); //读取分

  977.                         ucHour=bcd_to_number(ucHourBCD);  //BCD转原始数值
  978.                         ucMinute=bcd_to_number(ucMinuteBCD);  //BCD转原始数值
  979.                         ucWd1Update=1; //窗口1更新显示时间
  980.       }
  981.   }
  982. }


  983. /********************************************************************************************
  984. 函数名称:修改DS1302时间的驱动程序
  985. 功    能:读取DS1302的数据
  986. 返 回 值:无
  987. 时    间:2014-11-11        
  988. 备    注:此处写的是BCD码
  989. **************************************************************************************************/
  990. void Write1302 ( unsigned char addr, unsigned char dat )
  991. {
  992.      
  993.          unsigned char i,temp;//单片机驱动DS1302属于SPI通讯方式,根据我的经验,不用关闭中断
  994.      DS1302_CE_dr=0;      //CE引脚为低,数据传送中止
  995.      delay_short(1);           
  996.      SCLK_dr=0;           //清零时钟总线
  997.      delay_short(1);
  998.      DS1302_CE_dr = 1;    //CE引脚为高,逻辑控制有效
  999.      delay_short(1);
  1000.      for ( i=0; i<8; i++ )//循环8次移位
  1001.      {
  1002.         DIO_dr_sr = 0;
  1003.         temp = addr;
  1004.         if(temp&0x01)
  1005.         {
  1006.             DIO_dr_sr =1;
  1007.         }
  1008.         else
  1009.         {
  1010.             DIO_dr_sr =0;
  1011.         }
  1012.         delay_short(1);
  1013.         addr >>= 1;                                           //右移一位
  1014.         SCLK_dr = 1;
  1015.         delay_short(1);
  1016.         SCLK_dr = 0;
  1017.         delay_short(1);
  1018.      }
  1019.      //发送数据

  1020.      for ( i=0; i<8; i++ )                                    //循环8次移位
  1021.      {
  1022.         DIO_dr_sr = 0;
  1023.         temp = dat;
  1024.         if(temp&0x01)
  1025.         {
  1026.             DIO_dr_sr =1;
  1027.         }
  1028.         else
  1029.         {
  1030.            DIO_dr_sr =0;
  1031.         }
  1032.         delay_short(1);
  1033.         dat >>= 1;                                             //右移一位
  1034.         SCLK_dr = 1;
  1035.         delay_short(1);
  1036.         SCLK_dr = 0;
  1037.         delay_short(1);
  1038.      }
  1039.      DS1302_CE_dr = 0;
  1040.      delay_short(1);
  1041. }         


  1042. /********************************************************************************************
  1043. 函数名称:读取DS1302时间的驱动程序
  1044. 功    能:读取DS1302的数据
  1045. 返 回 值:无
  1046. 时    间:2014-11-11        
  1047. 备    注:此处读的是BCD码
  1048. **************************************************************************************************/
  1049. unsigned char Read1302 ( unsigned char addr )
  1050. {
  1051.     unsigned char i,temp,dat1;
  1052.     DS1302_CE_dr=0;      //单片机驱动DS1302属于SPI通讯方式,根据我的经验,不用关闭中断
  1053.     delay_short(1);
  1054.     SCLK_dr=0;
  1055.     delay_short(1);
  1056.     DS1302_CE_dr = 1;
  1057.     delay_short(1);
  1058.     for ( i=0; i<8; i++ )                                      //循环8次移位
  1059.     {
  1060.        DIO_dr_sr = 0;
  1061.        temp = addr;
  1062.        if(temp&0x01)
  1063.        {
  1064.           DIO_dr_sr =1;
  1065.        }
  1066.        else
  1067.        {
  1068.           DIO_dr_sr =0;
  1069.        }
  1070.        delay_short(1);
  1071.        addr >>= 1;                                             //右移一位
  1072.        SCLK_dr = 1;
  1073.        delay_short(1);
  1074.        SCLK_dr = 0;
  1075.        delay_short(1);
  1076.     }

  1077. /********************************************************************************************
  1078. 注    释:51单片机IO口的特点,在读取数据之前必须先输出高电平,
  1079.           如果是PIC,AVR等单片机,这里应该把IO方向寄存器设置为输入
  1080. 时    间:2014-11-11        
  1081. **************************************************************************************************/
  1082.    DIO_dr_sr =1;   //51单片机IO口的特点,在读取数据之前必须先输出高电平,
  1083.    temp=0;

  1084.    for ( i=0; i<8; i++ )
  1085.    {
  1086.       temp>>=1;
  1087.       if(DIO_dr_sr==1)
  1088.       {
  1089.          temp=temp+0x80;
  1090.       }

  1091.       DIO_dr_sr =1;  //51单片机IO口的特点,在读取数据之前必须先输出高电平
  1092.       delay_short(1);
  1093.       SCLK_dr = 1;
  1094.       delay_short(1);
  1095.       SCLK_dr = 0;
  1096.       delay_short(1);
  1097.     }

  1098.     DS1302_CE_dr=0;
  1099.     delay_short(1);
  1100.     dat1=temp;
  1101.     return (dat1);
  1102. }

  1103. /********************************************************************************************
  1104. 函数名称:BCD转原始数值程序
  1105. 功    能:
  1106. 返 回 值:无
  1107. 时    间:2014-11-11        
  1108. 备    注:
  1109. **************************************************************************************************/
  1110. unsigned char bcd_to_number(unsigned char ucBcdTemp)  //BCD转原始数值
  1111. {
  1112.    unsigned char ucNumberResult=0;
  1113.    unsigned char ucBcdTemp10;
  1114.    unsigned char ucBcdTemp1;

  1115.    ucBcdTemp10=ucBcdTemp;
  1116.    ucBcdTemp10=ucBcdTemp10>>4;
  1117.    ucBcdTemp1=ucBcdTemp;
  1118.    ucBcdTemp1=ucBcdTemp1&0x0f;
  1119.    ucNumberResult=ucBcdTemp10*10+ucBcdTemp1;
  1120.    return ucNumberResult;
  1121. }


  1122. /********************************************************************************************
  1123. 函数名称:原始数值转换成BCD码
  1124. 功    能:
  1125. 返 回 值:无
  1126. 时    间:2014-11-11        
  1127. 备    注:
  1128. **************************************************************************************************/
  1129. unsigned char number_to_bcd(unsigned char ucNumberTemp) //原始数值转BCD
  1130. {
  1131.    unsigned char ucBcdResult=0;
  1132.    unsigned char ucNumberTemp10;
  1133.    unsigned char ucNumberTemp1;

  1134.    ucNumberTemp10=ucNumberTemp;
  1135.    ucNumberTemp10=ucNumberTemp10/10;
  1136.    ucNumberTemp10=ucNumberTemp10<<4;
  1137.    ucNumberTemp10=ucNumberTemp10&0xf0;
  1138.    ucNumberTemp1=ucNumberTemp;
  1139.    ucNumberTemp1=ucNumberTemp1%10;
  1140.    ucBcdResult=ucNumberTemp10|ucNumberTemp1;
  1141.    return ucBcdResult;
  1142. }

  1143. /********************************************************************************************
  1144. 函数名称:DS1302备用电池电量用完报警程序
  1145. 功    能:DS1302备用电池电量用完后,蜂鸣器在0.5S发也鸣叫
  1146. 返 回 值:无
  1147. 时    间:2014-11-11        
  1148. 备    注:
  1149. **************************************************************************************************/
  1150. void ds1302_alarm_service(void) //ds1302出错报警
  1151. {
  1152.     if(ucDs1302Error==1)  //备用电池的电量用完了报警提示         
  1153.     {
  1154.            if(uiDs1302Cnt>const_ds1302_0_5s)  //大概0.5秒钟蜂鸣器响一次
  1155.            {
  1156.                                 ucDs1302Lock=1;  //原子锁加锁
  1157.                                 uiDs1302Cnt=0; //计时器清零
  1158.                                 uiVoiceCnt=const_voice_short; //蜂鸣器声音触发,滴一声就停。
  1159.                                 ucDs1302Lock=0;  //原子锁解锁
  1160.            }
  1161.    }
  1162. }

  1163. /********************************************************************************************
  1164. 函数名称:热水完毕报警程序
  1165. 功    能:热水完毕后,发出报警声
  1166. 返 回 值:无
  1167. 时    间:2014-11-14        
  1168. 备    注:
  1169. **************************************************************************************************/
  1170. void ucAlarmPrompt_service()
  1171. {
  1172.     static        unsigned int uiAlarmPromptCnt;        //报警延时计数器
  1173.         static  unsigned char ucNumberCnt;                //报警次数计数器
  1174.         static  unsigned int const_time_2s = 400; //报警的时间间隔
  1175.         static  unsigned int const_voice_AlarmPrompt = 200;

  1176.    if(ucAlarmPrompt == 1)                                        //报警标志位置位后报警
  1177.    {
  1178.        uiAlarmPromptCnt++;                                        //报警延时计数器自加1

  1179.        if(uiAlarmPromptCnt>const_time_2s)        //2S发出报警声音
  1180.            {
  1181.                       uiAlarmPromptCnt = 0;                        //报警延时计数器清零
  1182.                    uiVoiceCnt=const_voice_AlarmPrompt;                //
  1183.                    ucNumberCnt++;                                        //报警次数计数器加1
  1184.                   
  1185.                    if(ucNumberCnt == 5)                        //报警次数为10次
  1186.                    {
  1187.                               ucNumberCnt = 0;                                //报警次数计数器清零
  1188.                            ucAlarmPrompt = 0;                        //关闭报警
  1189.                    }
  1190.            }
  1191.    }
  1192. }

  1193. /********************************************************************************************
  1194. 函数名称:数码管显示驱动程序
  1195. 功    能:显示对应的时间
  1196. 返 回 值:无
  1197. 时    间:2014-11-11        
  1198. 备    注:
  1199. **************************************************************************************************/
  1200. void display()
  1201. {
  1202.         switch(ucDigStep)          //步骤变量
  1203.         {
  1204.            case 1:
  1205.                  P0 = array[ucDigShow1];                  //第一位数码管显示的内容
  1206.                          dig1_dr = 0;
  1207.                          delay(10);
  1208.                          dig1_dr = 1;
  1209.                          ucDigStep = 2;
  1210.            break;

  1211.            case 2:
  1212.                             P0 = array[ucDigShow2];                  //第二位数码管显示的内容
  1213.                          dig2_dr = 0;
  1214.                          delay(10);
  1215.                          dig2_dr = 1;
  1216.                          ucDigStep = 3;
  1217.            break;

  1218.            case 3:
  1219.                             P0 = array[ucDigShow3];                  //第三位数码管显示的内容
  1220.                          dig3_dr = 0;
  1221.                          delay(10);
  1222.                          dig3_dr = 1;
  1223.                          ucDigStep = 4;
  1224.            break;

  1225.            case 4:
  1226.                             P0 = array[ucDigShow4];                  //第四位数码管显示的内容
  1227.                          dig4_dr = 0;
  1228.                          delay(10);
  1229.                          dig4_dr = 1;
  1230.                          ucDigStep =1;
  1231.            break;
  1232.         }         
  1233. }


  1234. /********************************************************************************************
  1235. 函数名称:热水时间和温度数据对比
  1236. 功    能:将设定的时间于当前的时间作对比,数据正确执行。
  1237. 返 回 值:无
  1238. 时    间:2014-11-11        
  1239. 备    注:
  1240. **************************************************************************************************/
  1241. void TimeData_contrast()
  1242. {
  1243.         static unsigned char preser_heat = 0;        //保温标志位
  1244.         static unsigned char  ucCheakFault = 0;                //故障检查标志位
  1245.         static unsigned char ucTimeEqual = 0;       //设定时间相等的标志位
  1246.         static unsigned char ucTimeAfter  = 0;      //两分钟前的时间
  1247.         static unsigned char ucTepAfter  = 0;      //两分钟前的时间

  1248.         if(ucStartheat == 1&&ucPart == 0)   //开始预设加热标志
  1249.         {
  1250.                 if((ucHour == ucSetTimeCnt1) && (ucMinute == ucSetTimeCnt2)&&ucTimeEqual == 0)  //设定的时间相等
  1251.             {
  1252. //                        ucStartheat = 1;//启动加热标志位
  1253.                         ucWd = 4;                  //更新到窗口4,显示温度
  1254.                         ucWd4Update = 1;
  1255.                         ucDigTimeLock = 1;  //小数点不显示

  1256.                         relay_dr = 1;        //继电器输出高(吸合)
  1257.                         ucCheakFault = 1;//故障检查
  1258.                         ucTimeEqual = 1;//时间对比完成
  1259.                         ucTimeAfter         = 0;//先对变量清零
  1260.                         ucTepAfter         = 0;//先对变量清零
  1261.                         ucTimeAfter = ucMinute;
  1262.                         ucTepAfter = ucAD_value_Tem;
  1263. //                        ucAlarmPrompt = 1;  //故障报警
  1264.                 }

  1265.                 if(ucCheakFault == 1&&(ucTimeAfter+3) == ucMinute)
  1266.                 {
  1267.                         if(ucAD_value_Tem>=(ucTepAfter+2))
  1268.                         {
  1269.                            ucCheakFault = 0;   //故障检测清零,只做一次检测
  1270.                            ucTimeEqual = 0;//时间对比完成标志清零,为下一次做准备

  1271.                         }
  1272.                         else
  1273.                         {
  1274.                                 relay_dr = 0;        //继电器输出(断开)

  1275.                                 ucWd = 5;                  //更新到窗口5,显示错误代码E001
  1276.                                 ucWd5Update = 1;

  1277.                                 ucTemp1 = 12; //E
  1278.                                 ucTemp2 = 0;  //0
  1279.                                 ucTemp3 = 0;  //0
  1280.                                 ucTemp4 = 1;  //1

  1281.                                 ucDigTimeLock = 1;  //小数点不显示
  1282.                                 ucAlarmPrompt = 1;  //故障报警
  1283.                                 ucCheakFault = 0;   //故障检测清零,只做一次检测
  1284.                                 ucStartheat = 0;  //检测到有故障,停止加热
  1285.                         }
  1286.                         
  1287.                 }

  1288.                 if(ucAD_value_Tem>=ucSetTepCnt1)        //设定到加热温度相等         
  1289.             {
  1290.                         ucStartheat = 0;//停止预设加热标志
  1291.                         relay_dr = 0;        //继电器输出(断开)

  1292. //                        ucCheakFault = 0;//故障检查标志清零,为下一次做准备

  1293.                         ucAlarmPrompt = 1; //报警标志位置1,启动报警
  1294.                         preser_heat = 1;   //执行保温标志位,开始进行保温

  1295.                         ucWd = 1;                //切换到窗口1显示时间
  1296.                         ucWd1Update = 1;//更新窗口1
  1297.                         ucDigTimeLock = 0; //显示小数点
  1298.                 }

  1299.         }
  1300.         
  1301.         if(preser_heat == 1)        //保温程序,开始执行
  1302.         {
  1303.                 if((ucSetTepCnt1-5) >= ucAD_value_Tem)
  1304.                 {
  1305.                            relay_dr = 1;        //继电器输出

  1306.                         ucWd = 4;                //切换到窗口4显示时间
  1307.                         ucWd4Update = 1;//更新窗口4
  1308.                         ucDigTimeLock = 1; //不显示小数点

  1309.                 }

  1310.                 if((ucSetTepCnt1+5) <= ucAD_value_Tem)
  1311.                 {
  1312.                         relay_dr = 0;        //继电器输出

  1313.                         ucWd = 1;                //切换到窗口1显示时间
  1314.                         ucWd1Update = 1;//更新窗口1
  1315.                         ucDigTimeLock = 0; //显示小数点

  1316.                 }
  1317.         }
  1318. }


  1319. /********************************************************************************************
  1320. 函数名称:ADC采样程序
  1321. 功    能:读取ADC0832转换后的数据
  1322. 返 回 值:
  1323. 时    间:2014-11-24        
  1324. 备    注:
  1325. **************************************************************************************************/
  1326. void ADC_sampling_service()
  1327. {
  1328.         static unsigned char i = 0;  //读取数据8位的次数变量
  1329.         static unsigned char ucADC;  //AD值
  1330.         static unsigned char ucCheckADC; //校验的AD值
  1331.         static unsigned int ucTemp;   //参与换算的中间变量
  1332.         static unsigned int uiTempFilterV=0; //参与换算的中间变量
  1333. //    static unsigned long ulBackupFilterV=255;  //备份最新采样数据的中间变量
  1334. //        static unsigned int  uiTimpFilterTep = 0;
  1335.         static unsigned char wendu;
  1336.         static unsigned int Adresult;
  1337.     static unsigned char ucSamplingCnt=0; //统计采样的次数  本程序采样8次后求平均值

  1338.         adc0832_CS_dr = 0;        //使能端置低

  1339.         adc0832_DI_sr_dr = 1;  //起始位
  1340.         adc0832_CLK_dr = 0;           //输出低电平
  1341.         delay_short(1);                   //小延时
  1342.         adc0832_CLK_dr = 1;           //输出高电平

  1343.         adc0832_DI_sr_dr = 1;  //选择通道,输出数据1
  1344.         adc0832_CLK_dr = 0;
  1345.         adc0832_CLK_dr = 1;

  1346.         adc0832_DI_sr_dr = 0;  //选择通道。输出数据0
  1347.         adc0832_CLK_dr = 0;
  1348.         adc0832_CLK_dr = 1;

  1349.     adc0832_DI_sr_dr = 1;  //拉高数据线
  1350.         delay_short(2);                   //延时

  1351.         adc0832_CLK_dr = 1;           //一个下降延
  1352.         adc0832_CLK_dr = 0;
  1353.         delay_short(1);

  1354.         for(i = 0;i<8;i++)                //读取8位
  1355.         {
  1356.             ucADC <<= 1;
  1357.             adc0832_CLK_dr = 1;
  1358.             adc0832_CLK_dr = 0;

  1359.                 if(adc0832_DI_sr_dr == 1)
  1360.                 {
  1361.                    ucADC  |= 0x01;
  1362.                 }

  1363.         }

  1364.         for(i=0;i<8;i++)                //读取校验位
  1365.         {
  1366.            ucCheckADC >>= 1;

  1367.            if(adc0832_DI_sr_dr == 1)
  1368.            {
  1369.                ucCheckADC |= 0x80;
  1370.            }
  1371.            adc0832_CLK_dr = 1;
  1372.            adc0832_CLK_dr = 0;

  1373.         }
  1374.         
  1375.         adc0832_CS_dr = 1;                //拉高使能端

  1376.         if(ucADC == ucCheckADC)        //校验两个读取的数据是否一致
  1377.         {
  1378.         ucTemp=ucADC; //把char类型数据赋值给long类型数据,参与乘除法运算的数据,为了避免运算结果溢出,我都用long类型


  1379.                 uiTempFilterV=uiTempFilterV+ucTemp;  //累加8次后求平均值
  1380.                 ucSamplingCnt++;  //统计已经采样累计的次数

  1381.                 if(ucSamplingCnt>=8)
  1382.                 {

  1383. /* 注释二:
  1384. * 求平均值滤波法,为了得到的数据更加圆滑,去除小毛刺。
  1385. * 向右边移动3位相当于除以8。
  1386. */

  1387. //                     uiTempFilterV=uiTempFilterV>>3; //求平均值滤波法


  1388.                                     Adresult=(255000/uiTempFilterV)-100;//求得当前温度对应的阻值,十欧为单位,此公式的演变请看上述详细说明

  1389. //                                     if(ulBackupFilterV>=20)  //最近备份的上一次数据大于等于0.02V的情况下
  1390. //                    {
  1391. //                                                if(Adresult<(ulBackupFilterV-5)||Adresult>(ulBackupFilterV+5)) //在正负0.020V偏差范围外,更新
  1392. //                                                {
  1393. //                                                        ulBackupFilterV=Adresult;  //备份最新采样的数据,方便下一次对比判断
  1394. //                                                        uiTimpFilterTep=Adresult; //得到经过滤波处理的实时电压值
  1395. ////                                                        ucWd4Part1Update=1; //局部更新显示经过滤波处理的电压
  1396. //                                                }
  1397. //                    }
  1398. //                    else   //最近备份的上一次数据小于0.02V的情况下
  1399. //                    {
  1400. //                                                if(uiTempFilterV>(ulBackupFilterV+2))  //在正0.020V偏差范围外,更新
  1401. //                                                {
  1402. //                                                        ulBackupFilterV=Adresult;  //备份最新采样的数据,方便下一次对比判断
  1403. //                                                        uiTimpFilterTep=Adresult; //得到经过滤波处理的实时电压值
  1404. ////                                                        ucWd4Part1Update=1; //局部更新显示经过滤波处理的电压
  1405. //                                                }
  1406. //                  
  1407. //                    }

  1408.                                          wendu = 0;//清零

  1409.                                          while(1)
  1410.                                          {
  1411.                                              if(Adresult>=wendu_tab[wendu])
  1412.                                                  {
  1413.                                                         break;
  1414.                                                  }

  1415.                                                  wendu++;

  1416.                                                  if(wendu>=105)
  1417.                                                  {
  1418.                                                      wendu = 105;
  1419.                                                          break;
  1420.                                                  }
  1421.                                                 
  1422.                                          }

  1423.                                         ucAD_value_Tem = wendu;

  1424.                     ucSamplingCnt=0;  //清零,为下一轮采样滤波作准备。
  1425.                     uiTempFilterV=0;
  1426.                 }
  1427.         
  1428.         }
  1429.         else
  1430.         {
  1431.             ucADC = 0;                        //两次读取的数据不一致,就把数据清零
  1432.                 ucAD_value_Tem = wendu;

  1433.         }
  1434.     ucWd4Update = 1;//更新窗口4

  1435. }


  1436. /********************************************************************************************
  1437. 函数名称:定时器中断程序
  1438. 功    能:
  1439. 返 回 值:无
  1440. 时    间:2014-11-11        
  1441. 备    注:
  1442. **************************************************************************************************/
  1443. void T0_time() interrupt 1
  1444. {

  1445.    TF0=0;  //清除中断标志
  1446.    TR0=0; //关中断
  1447.    display();                 //数码管显示放在中断里
  1448.    key_scan();                 //按键扫描放在中断里
  1449. /********************************************************************************************
  1450. 功    能:按键去抖动延时计数器在外部可以关闭,不开启计时功能
  1451. 时    间:2014-11-11        
  1452. **************************************************************************************************/
  1453.    if(ucKeyStartFlag1==1)           //启动计数器
  1454.    {
  1455.        if(uiKeyTimeCnt1<0xffff)//防止计数器超出范围
  1456.            {
  1457.                uiKeyTimeCnt1++;           //按键去抖动延时计数器自加1
  1458.            }   
  1459.    }

  1460. /********************************************************************************************
  1461. 功    能:按键去抖动延时计数器在外部可以关闭,不开启计时功能
  1462. 时    间:2014-11-11        
  1463. **************************************************************************************************/
  1464.    if(ucKeyStartFlag2==1)          //启动计数器
  1465.    {
  1466.        if(uiKeyTimeCnt2<0xffff)        //防止计数器超出范围
  1467.            {
  1468.                uiKeyTimeCnt2++;           //按键去抖动延时计数器自加1
  1469.            }
  1470.    }

  1471. /********************************************************************************************
  1472. 功    能:按键去抖动延时计数器在外部可以关闭,不开启计时功能
  1473. 时    间:2014-11-11        
  1474. **************************************************************************************************/
  1475.    if(ucKeyStartFlag3==1)          //启动计数器
  1476.    {
  1477.        if(uiKeyTimeCnt3<0xffff)        //防止计数器超出范围
  1478.            {
  1479.                uiKeyTimeCnt3++;           //按键去抖动延时计数器自加1
  1480.            }
  1481.    }

  1482. /********************************************************************************************
  1483. 功    能:按键去抖动延时计数器在外部可以关闭,不开启计时功能
  1484. 时    间:2014-11-11        
  1485. **************************************************************************************************/
  1486.    if(ucKeyStartFlag4==1)          //启动计数器
  1487.    {
  1488.        if(uiKeyTimeCnt3<0xffff)        //防止计数器超出范围
  1489.            {
  1490.                uiKeyTimeCnt4++;           //按键去抖动延时计数器自加1
  1491.            }
  1492.    }

  1493. /********************************************************************************************
  1494. 功    能:间歇性蜂鸣器报警计数器在外部可以关闭,不开启计时功能
  1495. 时    间:2014-11-11        
  1496. **************************************************************************************************/
  1497.     if(ucDs1302Error>0) //EEPROM出错
  1498.         {
  1499.                 if(ucDs1302Lock==0)//原子锁判断
  1500.                 {
  1501.                         uiDs1302Cnt++;  //间歇性蜂鸣器报警的计时器
  1502.                 }
  1503.         }

  1504. /********************************************************************************************
  1505. 功    能:蜂鸣器驱动放在中断里面
  1506. 时    间:2014-11-11        
  1507. **************************************************************************************************/
  1508.    if(uiVoiceCnt!=0)   //蜂鸣器
  1509.    {
  1510.        uiVoiceCnt--;  //每次进入定时中断都自减1,直到等于零为止。才停止鸣叫
  1511.            beep_dr = 0;          //蜂鸣器是PNP三极管控制,低电平就开始鸣叫
  1512.    }
  1513.    else
  1514.    {
  1515.        beep_dr = 1;   //蜂鸣器是PNP三极管控制,高电平就停止鸣叫。
  1516.    }


  1517.         TH0=0xf8;   //重装初始值(65535-2000)=63535=0xf82f
  1518.         TL0=0x2f;
  1519.         EA = 1;
  1520.         ET0 = 1;
  1521.         TR0=1;  //开中断
  1522. }


  1523. /********************************************************************************************
  1524. 函数名称:定时器初始化程序
  1525. 功    能:
  1526. 返 回 值:无
  1527. 时    间:2014-11-11        
  1528. 备    注:
  1529. **************************************************************************************************/
  1530. void T0_init()
  1531. {
  1532.    TH0=0xf8;   //重装初始值(65535-2000)=63535=0xf82f
  1533.    TL0=0x2f;
  1534.    EA = 1;
  1535.    ET0 = 1;
  1536.    TR0=1;  //开中断

  1537.    /* 注释七:
  1538.         * 检查ds1302芯片的备用电池电量是否用完了。
  1539.         * 在上电的时候,在一个特定的地址里把数据读出来,如果发现不等于0x5a,
  1540.         * 则是因为备用电池电量用完了,导致保存在ds1302内部RAM数据区的数据被更改,
  1541.         * 与此同时,应该重新写入一次0x5a,为下一次通电判断做准备
  1542.         */
  1543.         ucCheckDs1302=Read1302(READ_CHECK); //判断ds1302内部的数据是否被更改
  1544.         if(ucCheckDs1302!=0x5a)  
  1545.         {
  1546.                 Write1302 (WRITE_PROTECT,0X00);          //禁止写保护
  1547.                 Write1302 (WRITE_CHECK,0x5a);            //重新写入标志数据,方便下一次更换新电池后的判断
  1548.                 Write1302 (WRITE_PROTECT,0x80);          //允许写保护
  1549.                 ucDs1302Error = 1;                                //1表示报警启动
  1550.                 ucWd = 5;                  //更新到窗口5,显示错误代码E001
  1551.                 ucWd5Update = 1;
  1552.                
  1553.                 ucTemp1 = 12; //E
  1554.                 ucTemp2 = 0;  //0
  1555.                 ucTemp3 = 0;  //0
  1556.                 ucTemp4 = 2;  //1
  1557.                
  1558.                 ucDigTimeLock = 1;  //小数点不显示

  1559.         }
  1560. }


  1561. /********************************************************************************************
  1562. 函数名称:初始化单片机内部和外部IO口
  1563. 功    能:
  1564. 返 回 值:无
  1565. 时    间:2014-11-11        
  1566. 备    注:
  1567. **************************************************************************************************/
  1568. void initial_myself(void)  //第一区 初始化单片机
  1569. {
  1570.         beep_dr=1; //用PNP三极管控制蜂鸣器,输出高电平时不叫。
  1571.         relay_dr = 0;
  1572.         dig1_dr = 1;
  1573.         dig2_dr = 1;
  1574.         dig3_dr = 1;
  1575.         dig4_dr = 1;
  1576.         delay_long(30);
  1577. }


  1578. /********************************************************************************************
  1579. 函数名称:延时程序
  1580. 功    能:
  1581. 返 回 值:无
  1582. 时    间:2014-11-11        
  1583. 备    注:
  1584. **************************************************************************************************/
  1585. void delay(unsigned int delay_ms)                  //延时函数
  1586. {
  1587.     unsigned int i,j;

  1588.         for(i = delay_ms;i>0;i--)
  1589.            for(j = 10;j>0;j--);
  1590. }

  1591. /********************************************************************************************
  1592. 函数名称:延时程序
  1593. 功    能:
  1594. 返 回 值:无
  1595. 时    间:2014-11-11        
  1596. 备    注:
  1597. **************************************************************************************************/
  1598. void delay_short(unsigned int uiDelayShort)
  1599. {
  1600.    unsigned int i;  

  1601.    for(i=0;i<uiDelayShort;i++)
  1602.    {
  1603.       ;   //一个分号相当于执行一条空语句
  1604.    }
  1605. }

  1606. /********************************************************************************************
  1607. 函数名称: 延时程序
  1608. 功    能:
  1609. 返 回 值:无
  1610. 时    间:2014-11-11        
  1611. 备    注:
  1612. **************************************************************************************************/
  1613. void delay_long(unsigned int uiDelayLong)
  1614. {
  1615.    unsigned int i;
  1616.    unsigned int j;

  1617.    for(i=uiDelayLong;i>0;i--)
  1618.       for(j=50;j>0;j--);  //内嵌循环的空指令数量
  1619. }
复制代码



由于水平能力有限,纰漏之处,还望各位读者指出。。。。。。。
















IMG_20141202_151857.jpg (1.66 MB, 下载次数: 329)

IMG_20141202_151857.jpg

IMG_20141202_151918.jpg (1.5 MB, 下载次数: 331)

IMG_20141202_151918.jpg

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:1 发表于 2014-12-3 15:20 | 只看该作者
下面是楼主的程序:
  1. /********************************************************************************************
  2. 名    称:智能热水器控制系统
  3. 功    能:
  4.           1、数码管显示当前北京时间。可对时间进行修改。
  5.                   2、设定时间,到达设定的时间开始加热。
  6.                   3、设定温度,到达设定的温度值,停止加热。
  7.                   4、加热完毕后,蜂鸣器报警提示,温度控制在设定温度+-5度变化。
  8.                   5、DS1302备用电池电量用完时,蜂鸣器报警。并在数码管上显示E002代码
  9.                   6、发热体好坏判别,如果坏了,蜂鸣器报警,并在数码管上显示E001代码。
  10.                   7、没有水的情况下,不加热,并且蜂鸣器发出报警。

  11. 作    者:肖亚平
  12. 创建时间:2014年11月11日
  13. 修改时间:
  14. 备    注:
  15. **************************************************************************************************/
  16. #include<reg52.h>                                //头文件

  17. #define const_dpy_time_half  200  //数码管闪烁时间的半值
  18. #define const_dpy_time_all   400  //数码管闪烁时间的全值 一定要比const_dpy_time_half 大
  19. #define const_voice_short  40   //蜂鸣器短叫的持续时间
  20. #define const_voice_long  120 //蜂鸣器长鸣叫的时间
  21. #define const_DigTime_level 240        //小数点计时上限值
  22. #define const_KeyTime_level 30 //按键去抖动延时的时间
  23. #define const_key_time_short3  30    //短按的按键去抖动延时的时间
  24. #define const_key_time_long3   1024     //长按的按键去抖动延时的时间
  25. #define const_time_0_25s  111   //0.25秒钟的时间需要的定时中断次数
  26. #define const_time_1s     444   //1秒钟的时间需要的定时中断次数
  27. #define const_ds1302_0_5s  200   //大概0.5秒的时间
  28. #define const_ds1302_sampling_time    300   //累计主循环次数的时间,每次刷新采样时钟芯片的时间

  29. #define WRITE_SECOND    0x80    //DS1302内部的相关地址
  30. #define WRITE_MINUTE    0x82
  31. #define WRITE_HOUR      0x84
  32. #define WRITE_DATE      0x86
  33. #define WRITE_MONTH     0x88
  34. #define WRITE_YEAR      0x8C
  35. #define WRITE_CHECK     0xC2  //用来检查芯片的备用电池是否用完了的地址
  36. #define READ_CHECK      0xC3  //用来检查芯片的备用电池是否用完了的地址
  37. #define READ_SECOND     0x81
  38. #define READ_MINUTE     0x83
  39. #define READ_HOUR       0x85
  40. #define READ_DATE       0x87
  41. #define READ_MONTH      0x89
  42. #define READ_YEAR       0x8D
  43. #define WRITE_PROTECT   0x8E

  44. #define WRITE_SET_HOUR     0xC4  //用来检查芯片的备用电池是否用完了的地址
  45. #define READ_SET_HOUR      0xC5  //用来检查芯片的备用电池是否用完了的地址

  46. #define WRITE_SET_MINUTE     0xC6  //用来检查芯片的备用电池是否用完了的地址
  47. #define READ_SET_MINUTE      0xC7  //用来检查芯片的备用电池是否用完了的地址

  48. sbit SCLK_dr      =P1^0;  
  49. sbit DIO_dr_sr    =P1^1;  
  50. sbit DS1302_CE_dr =P1^2;  

  51. sbit dig1_dr =  P2^0;                        //第一位数码管位选输出
  52. sbit dig2_dr =  P2^1;                        //第二位数码管位选输出
  53. sbit dig3_dr =  P2^2;                        //第三位数码管位选输出
  54. sbit dig4_dr =  P2^3;                        //第四位数码管位选输出
  55. sbit digital_dp_dr = P2^4;                //小数点输出

  56. sbit beep_dr = P2^5;           //蜂鸣器输出
  57. sbit Key_sr1 = P3^7;                        //确认/选择键
  58. sbit Key_sr2 = P3^6;                           //上选择键        Down
  59. sbit Key_sr3 = P3^5;                        //下选择键        UP
  60. sbit relay_dr = P1^5;                        //继电器输出
  61. sbit Key_sr4 = P1^3;                        //开机按键

  62. sbit adc0832_CS_dr = P1^4;                        //adc0832的使能端口
  63. sbit adc0832_DI_sr_dr = P1^6;                        //adc0832的数据端口
  64. sbit adc0832_CLK_dr = P1^7;                //adc0832的时钟端口

  65. unsigned char ucShortTouchFlag3 = 0; //短按的自锁标志、
  66. unsigned char ucShortTouchFlag4 = 0; //短按的自锁标志

  67. unsigned char ucDigStep = 1;        //步骤变量          
  68. unsigned int uiDigTimeCnt = 0;        //小数点延时计数器
  69. unsigned char ucDigTimeLock = 0;//原子锁
  70. unsigned int uiVoiceCnt        = 0;         //蜂鸣器计数器

  71. unsigned int uiDigTemp1 = 0;        //第一位数码管显示内容
  72. unsigned int uiDigTemp2 = 0;        //第二位数码管显示内容
  73. unsigned int uiDigTemp3 = 0;        //第三位数码管显示内容
  74. unsigned int uiDigTemp4 = 0;        //第四位数码管显示内容

  75. unsigned int uiDigTemp = 0;     //计数的变量

  76. unsigned int uiKeyTimeCnt1 = 0;  //按键去抖动延时计数器
  77. unsigned char ucKeyLock1 = 0;         //按键触发后自锁的变量标志
  78. unsigned char ucKeySec = 0;                         //被触发的按键编号

  79. unsigned int uiKeyTimeCnt2 = 0;  //按键去抖动延时计数器
  80. unsigned char ucKeyLock2 = 0;         //按键触发后自锁的变量标志

  81. unsigned int uiKeyTimeCnt3 = 0;  //按键去抖动延时计数器
  82. unsigned char ucKeyLock3 = 0;         //按键触发后自锁的变量标志

  83. unsigned int uiKeyTimeCnt4 = 0;  //按键去抖动延时计数器
  84. unsigned char ucKeyLock4 = 0;         //按键触发后自锁的变量标志

  85. unsigned char ucKeyStartFlag1=0; //启动定时中断计数的开关
  86. unsigned char ucKeyStartFlag2=0; //启动定时中断计数的开关
  87. unsigned char ucKeyStartFlag3=0; //启动定时中断计数的开关
  88. unsigned char ucKeyStartFlag4=0; //启动定时中断计数的开关

  89. unsigned int uiKeyCtntyCnt1 = 0; //连续触发延时计数器累加
  90. unsigned int uiKeyCtntyCnt2 = 0;
  91. /*****************************************************************************************/

  92. unsigned char  ucVoiceLock=0;  //蜂鸣器鸣叫的原子锁

  93. unsigned char ucDigShowTemp=0; //临时中间变量
  94. unsigned char ucWd=6;  //本程序的核心变量,窗口显示变量。类似于一级菜单的变量。代表显示不同的窗口。
  95. unsigned char ucPart=0;//本程序的核心变量,局部显示变量。类似于二级菜单的变量。代表显示不同的局部。
  96. unsigned char ucWd1Update=0; //窗口1更新显示标志
  97. unsigned char ucWd2Update=1; //窗口2更新显示标志
  98. unsigned char ucWd3Update=1; //窗口3更新显示标志
  99. unsigned char ucWd4Update=1; //窗口4更新显示标志
  100. unsigned char ucWd5Update=1; //窗口5更新显示标志

  101. unsigned char ucWd1Part1Update=0;  //在窗口1中,局部1的更新显示标志
  102. unsigned char ucWd1Part2Update=0; //在窗口1中,局部2的更新显示标志

  103. unsigned char ucWd2Part1Update=0;  //在窗口2中,局部1的更新显示标志
  104. unsigned char ucWd2Part2Update=0; //在窗口2中,局部2的更新显示标志

  105. unsigned char ucWd3Part1Update=0; //在窗口3中,局部1的更新显示标志
  106. unsigned char ucWd3Part2Update=0; //在窗口3中,局部2的更新显示标志

  107. unsigned char ucWd4Part1Update = 0;        //在窗口4中,局部1的更新显示标志
  108. unsigned char ucWd4Part2Update = 0;        //在窗口4中,局部2的更新显示标志

  109. unsigned char ucWd5Part1Update = 0;        //在窗口5中,局部1的更新显示标志


  110. unsigned char ucDelayTimerLock=0; //原子锁

  111. //unsigned int  uiDelayTimer=0;
  112. unsigned char ucCheckDs1302=0;  //检查Ds1302芯片是否正常
  113. unsigned char ucDs1302Error=0; //Ds1302芯片的备用电池是否用完了的报警标志
  114. unsigned char ucDs1302Lock=0;//原子锁
  115. unsigned int  uiDs1302Cnt=0; //间歇性蜂鸣器报警的计时器
  116. unsigned char ucDpyTimeLock=0; //原子锁
  117. unsigned int  uiDpyTimeCnt=0;  //数码管的闪烁计时器,放在定时中断里不断累加
  118. unsigned char ucAutoDisplayDateLock1 = 0;  //原子锁
  119. unsigned char ucAutoDisplayDateLock2 = 0;  //原子锁

  120. unsigned char  ucHour=0;  
  121. unsigned char  ucMinute=0;  
  122. unsigned char  ucSecond=0;  

  123. unsigned char  ucHourBCD=0;  
  124. unsigned char  ucMinuteBCD=0;  
  125. unsigned char  ucSecondBCD=0;  

  126. unsigned char ucSetTimedataCnt1;
  127. unsigned char ucSetTimedataCnt2;
  128. unsigned char ucSetTimeCnt1BCD;
  129. unsigned char ucSetTimeCnt2BCD;

  130. unsigned char ucTemp1=0;  //中间过渡变量
  131. unsigned char ucTemp2=0;  //中间过渡变量
  132. unsigned char ucTemp3=0;  //中间过渡变量
  133. unsigned char ucTemp4=0;  //中间过渡变量

  134. unsigned char ucSetTimeCnt1 = 12; //设定时间变量
  135. unsigned char ucSetTimeCnt2 = 30;

  136. unsigned char ucSetTepCnt1 = 50;         //设置温度计数器

  137. unsigned char ucDigShow4;  //第4位数码管要显示的内容
  138. unsigned char ucDigShow3;  //第3位数码管要显示的内容
  139. unsigned char ucDigShow2;  //第2位数码管要显示的内容
  140. unsigned char ucDigShow1;  //第1位数码管要显示的内容

  141. unsigned int uiSampingCnt=0;   //采集Ds1302的计时器,每秒钟更新采集一次
  142. unsigned char ucStartheat = 0;  //启动加热标志位
  143. unsigned char ucAlarmPrompt = 0;//加热完毕报警提示标志位

  144. unsigned char ucAD_value_Tem = 0;//AD转换过后的温度数据
  145. unsigned char ucADC_value = 0;//AD数据
  146. unsigned char ucADC_sampling_number = 1; //开启ADC采样的标志位
  147. unsigned char ucADC_samplingCnt = 0;         //ADC采样次数变量
  148. unsigned char KeyChangeTimeFlag;
  149. unsigned char ucBootScreen = 0;  //开机标志位

  150. /************************************************************************************************/

  151. void ds1302_alarm_service(void); //ds1302出错报警
  152. void ds1302_sampling(void); //ds1302采样程序,内部每秒钟采集更新一次
  153. void Write1302 ( unsigned char addr, unsigned char dat );//修改时间的驱动
  154. void display_service(void); //显示的窗口菜单服务程序

  155. void delay_short(unsigned int uiDelayShort);
  156. void delay_long(unsigned int uiDelayLong);

  157. unsigned char Read1302 ( unsigned char addr );//读取时间的驱动
  158. unsigned char bcd_to_number(unsigned char ucBcdTemp);  //BCD转原始数值
  159. unsigned char number_to_bcd(unsigned char ucNumberTemp); //原始数值转BCD

  160. void initial_myself(void);  //第一区 初始化单片机
  161. void delay(unsigned int delay_ms);
  162. void display();
  163. void T0_time();
  164. void key_scan();
  165. void key_service();
  166. void T0_init();
  167. void TimeData_contrast();
  168. void ucAlarmPrompt_service();
  169. void ADC_sampling_service();
  170.                                                   
  171. unsigned char array[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xc6,0x86,
  172.                        0xc6,0xf6,0xf6,0xf0};

  173. const unsigned int code wendu_tab[106]=
  174. {
  175.    3274,3111,2957,2812,2674,2545,2422,2306,2196,2092, //0~9
  176.    1993,1900,1811,1728,1648,1573,1501,1433,1369,1308, //10~19
  177.    1250,1194,1142,1092,1045,1000,957,916,877,840,          //20~29
  178.    805,771,739,709,679,652,625,600,576,553,                          //30~39
  179.    531,510,490,471,453,435,418,402,387,372,                          //40~49
  180.    358,345,332,320,308,297,286,276,266,256,                          //50~59
  181.    247,238,230,222,214,207,199,193,186,180,                          //60~69
  182.    174,168,162,157,152,147,142,137,133,128,                          //70~79
  183.    124,120,116,113,109,106,102,99,96,93,                          //80~89
  184.    90,88,85,82,80,78,75,73,71,69,                                          //90~99
  185.    67,65,63,61,59,58                                                                  //100~105
  186. };

  187. /********************************************************************************************
  188. 函数名称:主程序
  189. 功    能:程序执行的入口
  190. 返 回 值:无
  191. 时    间:2014-11-11       
  192. 备    注:
  193. **************************************************************************************************/
  194. void main()
  195. {
  196.     T0_init();
  197.         initial_myself();
  198.         while(1)
  199.         {

  200.                  ds1302_alarm_service(); //ds1302出错报警
  201.                  ucAlarmPrompt_service();
  202.                  display_service(); //显示的窗口菜单服务程序
  203.                  ds1302_sampling(); //ds1302采样程序,内部每秒钟采集更新一次
  204.                  key_service();                         //按键服务函数放在主程序里
  205.                  TimeData_contrast();

  206.                 if(ucADC_sampling_number == 1)
  207.                 {
  208.                         ucADC_samplingCnt++;

  209.                         if(ucADC_samplingCnt==10)
  210.                         {
  211.                             ucADC_sampling_number = 0;
  212.                                 ucADC_samplingCnt = 0;
  213.                                 ADC_sampling_service();
  214.                             ucADC_sampling_number = 1;
  215.                         }
  216.                 }

  217.                  if(ucDigTimeLock == 0 && ucPart == 0)          //开始计数器标志
  218.                  {
  219.                     uiDigTimeCnt++;                  //计数器开始计数
  220.                  }
  221.                  else
  222.                  {
  223.                     digital_dp_dr = 1;  //关闭小数点显示
  224.                  }
  225.                  
  226.                  if(uiDigTimeCnt >= const_DigTime_level)  //计数时间到
  227.                  {
  228.                          ucDigTimeLock = 1;                                          //计数器标志位置1
  229.                          uiDigTimeCnt = 0;                                          //计数器清零
  230.                          digital_dp_dr = ~digital_dp_dr;          //小数点输出
  231.                          ucDigTimeLock = 0;                                          //计数器标志位清零,开始计数。
  232.                  }
  233.                  
  234. /********************************************************************************************
  235. 功    能:数码管闪烁计数器在外部可以关闭,不开启计时功能
  236. 时    间:2014-11-11       
  237. **************************************************************************************************/
  238.     if(ucDpyTimeLock==0) //原子锁判断
  239.         {
  240.                 uiDpyTimeCnt++;  //数码管的闪烁计时器
  241.         }


  242.         }  
  243. }         


  244. /********************************************************************************************
  245. 函数名称:按键扫描
  246. 功    能:
  247.          1、按下Key_sr1,加1,如果安下一直不松,就连续加。
  248.                  2、按下Key_sr2,加减1,如果安下一直不松,就连续减。
  249.                  3、按下Key_sr3,单击单步触发,和长按触发
  250. 返 回 值:无
  251. 时    间:2014-11-11       
  252. 备    注:按键运用了,单击,长按,连续触发的方法。
  253. **************************************************************************************************/
  254. void key_scan()
  255. {
  256.         static unsigned char KeyChangeTimeFlag3;

  257.         if(Key_sr1 == 1)                 //1号键
  258.         {
  259.            ucKeyStartFlag1 = 0;         //启动定时中断计数的开关清零
  260.            uiKeyTimeCnt1 = 0;         //按键去抖动延时计数器清零
  261.            ucKeyLock1 = 0;                  //按键触发后自锁的变量标志清零
  262.           
  263.         }
  264.         else if(ucKeyLock1 == 0)
  265.         {
  266.               ucKeyStartFlag1 = 1;                //开启计数器开关,开始计数

  267.                 if(uiKeyTimeCnt1>=const_KeyTime_level)
  268.                 {
  269.                     ucKeyStartFlag1 = 0;        //开启计数器关闭,停止计数
  270.                         ucKeyLock1 = 1;                        //自锁按键置位,避免一直触发
  271.                         uiKeyTimeCnt1 = 0;           //按键去抖动延时计数器清零
  272.                         ucKeySec = 1;                   //触发1号键
  273.                 }
  274.         }

  275.         else if(uiKeyTimeCnt1<const_time_1s)
  276.         {
  277.                  uiKeyTimeCnt1++;
  278.         }
  279.         else
  280.         {
  281.                  uiKeyCtntyCnt1++; //连续触发延时计数器累加

  282.                 if(uiKeyCtntyCnt1>const_time_0_25s)
  283.                 {
  284.                         uiKeyCtntyCnt1 = 0;
  285.                         ucKeySec = 1;                   //触发1号键
  286.                 }
  287.         }


  288.         if(Key_sr2 == 1)                 //2号键
  289.         {
  290.            ucKeyStartFlag2 = 0;         //启动定时中断计数的开关清零
  291.            uiKeyTimeCnt2 = 0;         //按键去抖动延时计数器清零
  292.            ucKeyLock2 = 0;                  //按键触发后自锁的变量标志清零
  293.         }
  294.         else if(ucKeyLock2 == 0)
  295.         {
  296.               ucKeyStartFlag2 = 1;                //开启计数器开关,开始计数

  297.                 if(uiKeyTimeCnt2>=const_KeyTime_level)
  298.                 {
  299.                     ucKeyStartFlag2 = 0;        //开启计数器关闭,停止计数
  300.                         ucKeyLock2 = 1;                        //自锁按键置位,避免一直触发
  301.                         uiKeyTimeCnt2 = 0;           //按键去抖动延时计数器清零
  302.                         ucKeySec = 2;                   //触发2号键
  303.                 }
  304.         }
  305.         else if(uiKeyTimeCnt2<const_time_1s)
  306.         {
  307.                  uiKeyTimeCnt2++;
  308.         }
  309.         else
  310.         {
  311.                  uiKeyCtntyCnt2++; //连续触发延时计数器累加

  312.                 if(uiKeyCtntyCnt2>const_time_0_25s)
  313.                 {
  314.                         uiKeyCtntyCnt2 = 0;
  315.                         ucKeySec = 2;                   //触发1号键
  316.                 }
  317.         }
  318.             
  319.         if(Key_sr3 == 1)                 //3,4号键
  320.         {
  321.            ucKeyStartFlag3 = 0;         //启动定时中断计数的开关清零
  322.            uiKeyTimeCnt3 = 0;         //按键去抖动延时计数器清零
  323.            ucKeyLock3 = 0;                  //按键触发后自锁的变量标志清零
  324.            ucShortTouchFlag3 = 0; //短按的自锁标志清零
  325.             KeyChangeTimeFlag3 = 0;
  326.         }
  327.         else if(ucKeyLock3 == 0)
  328.         {
  329.               ucKeyStartFlag3 = 1;                //开启计数器开关,开始计数

  330.                 if(ucShortTouchFlag3 == 0)
  331.                 {
  332.                         if(uiKeyTimeCnt3>=const_key_time_short3)  //短按中间间隔的时间
  333.                         {
  334.                             ucShortTouchFlag3 = 1;
  335.                                 ucKeySec = 3;                   //触发3号键
  336.                         }
  337.                 }

  338.                 if(uiKeyTimeCnt3>=const_key_time_long3&&KeyChangeTimeFlag3 == 0)
  339.                 {
  340.             KeyChangeTimeFlag3 = 1;
  341.                         ucKeySec = 17;                   //触发17号键
  342.                 }
  343.             if(uiKeyTimeCnt3>=const_key_time_long3+const_key_time_long3)
  344.                 {
  345.                     ucKeyStartFlag3 = 0;        //开启计数器关闭,停止计数
  346.                         ucKeyLock3 = 1;                        //自锁按键置位,避免一直触发
  347.                         uiKeyTimeCnt3 = 0;           //按键去抖动延时计数器清零
  348.                         ucKeySec = 18;                   //触发17号键
  349.                 }

  350.         }

  351.         if(Key_sr4 == 1)                 //1号键
  352.         {
  353.            ucKeyStartFlag4 = 0;         //启动定时中断计数的开关清零
  354.            uiKeyTimeCnt4 = 0;         //按键去抖动延时计数器清零
  355.            ucKeyLock4 = 0;                  //按键触发后自锁的变量标志清零
  356.            ucShortTouchFlag4 = 0; ///短按的自锁标志清零
  357.           
  358.         }
  359.         else if(ucKeyLock4 == 0)
  360.         {
  361.               ucKeyStartFlag4 = 1;                //开启计数器开关,开始计数

  362.                 if(ucShortTouchFlag4 == 0)
  363.                 {         
  364.                         if(uiKeyTimeCnt4>=const_KeyTime_level)
  365.                         {
  366.                                 ucShortTouchFlag4 = 1;
  367.                                 ucKeySec = 4;                   //触发4号键
  368.                         }

  369.                
  370.                 }

  371.            if(uiKeyTimeCnt4>=const_key_time_long3)
  372.            {
  373.                         ucKeyStartFlag4 = 0;        //开启计数器关闭,停止计数
  374.                         ucKeyLock4 = 1;                        //自锁按键置位,避免一直触发
  375.                         uiKeyTimeCnt4 = 0;           //按键去抖动延时计数器清零
  376.                         ucKeySec = 5;                   //触发5号键

  377.            }
  378.         }
  379. }

  380. /********************************************************************************************
  381. 函数名称:显示的窗口菜单服务程序
  382. 功    能:更新显示内容
  383. 返 回 值:无
  384. 时    间:2014-11-11       
  385. 备    注:
  386. **************************************************************************************************/

  387. void display_service(void) //显示的窗口菜单服务程序
  388. {
  389.    switch(ucWd)  //本程序的核心变量,窗口显示变量。类似于一级菜单的变量。代表显示不同的窗口。
  390.    {
  391.            case 1:   //显示时间窗口的数据  数据格式 SS FF MM 时 分 秒
  392.                 if(ucWd1Update==1)  //窗口1要全部更新显示
  393.                 {
  394.                                 ucWd1Update=0;  //及时清零标志,避免一直进来扫描
  395.                                 ucWd1Part1Update=1;  //局部时更新显示
  396.                                 ucWd1Part2Update=1;  //局部分更新显示
  397.                 }
  398.        
  399.                         if(ucWd1Part1Update==1)//局部时更新显示
  400.                         {
  401.                                 ucWd1Part1Update=0;
  402.                                 ucTemp1=ucHour/10;  //时
  403.                                 ucTemp2=ucHour%10;
  404.                                 ucDigShow1=ucTemp1; //数码管显示实际内容
  405.                                 ucDigShow2=ucTemp2;
  406.                         }
  407.        
  408.                         if(ucWd1Part2Update==1)//局部分更新显示
  409.                         {
  410.                                 ucWd1Part2Update=0;
  411.                                 ucTemp3=ucMinute/10;  //分
  412.                                 ucTemp4=ucMinute%10;
  413.                                 ucDigShow3=ucTemp3; //数码管显示实际内容
  414.                                 ucDigShow4=ucTemp4;
  415.                         }
  416.        
  417.              //数码管闪烁
  418.                 switch(ucPart)  //相当于二级菜单,根据局部变量的值,使对应的参数产生闪烁的动态效果。
  419.                         {
  420.                             case 0:  //都不闪烁
  421.                                  break;
  422.                             case 1:  //时参数闪烁
  423.                                  if(uiDpyTimeCnt==const_dpy_time_half)
  424.                                  {
  425.                                        ucDigShow1=ucTemp1; //数码管显示实际内容
  426.                                        ucDigShow2=ucTemp2;
  427.                                   }
  428.                                  else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
  429.                                  {
  430.                                                 ucDpyTimeLock=1; //原子锁加锁
  431.                                                 uiDpyTimeCnt=0;   //及时把闪烁记时器清零
  432.                                                 ucDpyTimeLock=0;  //原子锁解锁
  433.                                                 ucDigShow1=10;   //数码管显示空,什么都不显示
  434.                                                 ucDigShow2=10;
  435.                                  }
  436.                                  break;
  437.                        
  438.                             case 2:   //分参数闪烁
  439.                                  if(uiDpyTimeCnt==const_dpy_time_half)
  440.                                  {
  441.                                                 ucDigShow1=ucTemp1; //数码管显示实际内容,显示前两位,
  442.                                     ucDigShow2=ucTemp2;         //目的是上面闪烁后,数码管显示内容会清零

  443.                                                 ucDigShow3=ucTemp3; //数码管显示实际内容
  444.                                                 ucDigShow4=ucTemp4;
  445.                                  }
  446.                                  else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
  447.                                  {
  448.                                                 ucDpyTimeLock=1; //原子锁加锁
  449.                                                 uiDpyTimeCnt=0;   //及时把闪烁记时器清零
  450.                                                 ucDpyTimeLock=0;  //原子锁解锁
  451.                                                 ucDigShow3=10;   //数码管显示空,什么都不显示
  452.                                                 ucDigShow4=10;

  453.                                  }
  454.                                 break;
  455.                         }
  456.             break;

  457.                 case 2:
  458.                     if(ucWd2Update==1)  //窗口1要全部更新显示
  459.                 {
  460.                                 ucWd2Update=0;  //及时清零标志,避免一直进来扫描
  461.                                 ucWd2Part1Update=1;  //局部时更新显示
  462.                                 ucWd2Part2Update=1;  //局部分更新显示
  463.                 }

  464.                         if(ucWd2Part1Update == 1)
  465.                         {
  466.                                    ucWd2Part1Update = 0;
  467.                                 ucTemp1=ucSetTimeCnt1/10;  //时
  468.                                 ucTemp2=ucSetTimeCnt1%10;
  469.                                 ucDigShow1=ucTemp1; //数码管显示实际内容
  470.                                 ucDigShow2=ucTemp2;
  471.                         }

  472.                         if(ucWd2Part2Update == 1)
  473.                         {
  474.                                    ucWd2Part2Update = 0;
  475.                                 ucTemp3=ucSetTimeCnt2/10;  //时
  476.                                 ucTemp4=ucSetTimeCnt2%10;
  477.                                 ucDigShow3=ucTemp3; //数码管显示实际内容
  478.                                 ucDigShow4=ucTemp4;
  479.                         }

  480.                     switch(ucPart)  //相当于二级菜单,根据局部变量的值,使对应的参数产生闪烁的动态效果。
  481.                         {
  482.                             case 0:  //都不闪烁
  483.                                  break;
  484.                             case 1:  //时参数闪烁
  485.                                  if(uiDpyTimeCnt==const_dpy_time_half)
  486.                                  {
  487.                                        ucDigShow1=ucTemp1; //数码管显示实际内容
  488.                                        ucDigShow2=ucTemp2;
  489.                                   }
  490.                                  else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
  491.                                  {
  492.                                                 ucDpyTimeLock=1; //原子锁加锁
  493.                                                 uiDpyTimeCnt=0;   //及时把闪烁记时器清零
  494.                                                 ucDpyTimeLock=0;  //原子锁解锁
  495.                                                 ucDigShow1=10;   //数码管显示空,什么都不显示
  496.                                                 ucDigShow2=10;
  497.                                  }
  498.                                  break;
  499.                        
  500.                             case 2:   //分参数闪烁
  501.                                  if(uiDpyTimeCnt==const_dpy_time_half)
  502.                                  {
  503.                                                 ucDigShow1=ucTemp1; //数码管显示实际内容,这里是为了显示前两位
  504.                                     ucDigShow2=ucTemp2;         //目的是上面闪烁后,数码管显示内容会清零

  505.                                                 ucDigShow3=ucTemp3; //数码管显示实际内容
  506.                                                 ucDigShow4=ucTemp4;
  507.                                  }
  508.                                  else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
  509.                                  {
  510.                                                 ucDpyTimeLock=1; //原子锁加锁
  511.                                                 uiDpyTimeCnt=0;   //及时把闪烁记时器清零
  512.                                                 ucDpyTimeLock=0;  //原子锁解锁
  513.                                                 ucDigShow3=10;   //数码管显示空,什么都不显示
  514.                                                 ucDigShow4=10;

  515.                                  }
  516.                                 break;
  517.                         }
  518.             break;

  519.                  case 3:
  520.                        if(ucWd3Update==1)  //窗口3要全部更新显示
  521.                    {
  522.                                    ucWd3Update=0;  //及时清零标志,避免一直进来扫描
  523.                                    ucWd3Part1Update=1;  //局部时更新显示
  524.                                    ucWd3Part2Update=1;  //局部分更新显示
  525.                    }  
  526.                           
  527.                            if(ucWd3Part1Update == 1)
  528.                            {
  529.                                       ucWd3Part1Update = 0;

  530.                                    if(ucSetTepCnt1>=100)
  531.                                    {
  532.                                               ucTemp1 = ucSetTepCnt1/100;
  533.                                        ucTemp2 = ucSetTepCnt1/10%10;
  534.                                            ucTemp3 = ucSetTepCnt1%10;
  535.                                    }
  536.                                    else
  537.                                    {
  538.                                               ucTemp1 = ucSetTepCnt1/10;
  539.                                        ucTemp2 = ucSetTepCnt1%10;
  540.                                            ucTemp3 = 10;
  541.                                    }

  542.                                    ucDigShow1=ucTemp1; //数码管显示实际内容
  543.                                    ucDigShow2=ucTemp2; //数码管显示实际内容
  544.                                    ucDigShow3=ucTemp3; //数码管显示实际内容
  545.                            }

  546.                            if(ucWd3Part2Update == 1)
  547.                            {
  548.                                        ucWd3Part2Update = 0;       
  549.                                         ucDigShow4 = 11;
  550.                            }

  551.                            switch(ucPart)
  552.                            {
  553.                                 case 0:  break;
  554.                                 case 1:
  555.                                          if(uiDpyTimeCnt==const_dpy_time_half)
  556.                                          {
  557.                                                         ucDigShow1=ucTemp1; //数码管显示实际内容
  558.                                                         ucDigShow2=ucTemp2;
  559.                                          }
  560.                                          else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
  561.                                          {
  562.                                                         ucDpyTimeLock=1; //原子锁加锁
  563.                                                         uiDpyTimeCnt=0;   //及时把闪烁记时器清零
  564.                                                         ucDpyTimeLock=0;  //原子锁解锁
  565.                                                         ucDigShow1=10;   //数码管显示空,什么都不显示
  566.                                                         ucDigShow2=10;
  567.        
  568.                                          }
  569.                                                  break;

  570.                            }
  571.                            break;

  572.                 case 4:       
  573.                        if(ucWd4Update==1)  //窗口4要全部更新显示
  574.                    {
  575.                                    ucWd4Update=0;  //及时清零标志,避免一直进来扫描
  576.                                    ucWd4Part1Update=1;  //局部时更新显示
  577.                                    ucWd4Part2Update=1;  //局部分更新显示
  578.                    }  
  579.                           
  580.                            if(ucWd4Part1Update == 1)
  581.                            {
  582.                                       ucWd4Part1Update = 0;

  583.                                    if(ucAD_value_Tem>=100)
  584.                                    {
  585.                                               ucTemp1 = ucAD_value_Tem/100;
  586.                                        ucTemp2 = ucAD_value_Tem/10%10;
  587.                                            ucTemp3 = ucAD_value_Tem%10;
  588.                                    }
  589.                                    else
  590.                                    {
  591.                                               ucTemp1 = ucAD_value_Tem/10;
  592.                                        ucTemp2 = ucAD_value_Tem%10;
  593.                                            ucTemp3 = 10;
  594.                                    }

  595.                                    ucDigShow1=ucTemp1; //数码管显示实际内容
  596.                                    ucDigShow2=ucTemp2; //数码管显示实际内容
  597.                                    ucDigShow3=ucTemp3; //数码管显示实际内容
  598.                            }

  599.                            if(ucWd4Part2Update == 1)
  600.                            {
  601.                                        ucWd4Part2Update = 0;       
  602.                                         ucDigShow4 = 11;
  603.                            }
  604.                 break;

  605.                 case 5:if(ucWd5Update==1)  //窗口5要全部更新显示
  606.                    {
  607.                                    ucWd5Update=0;  //及时清零标志,避免一直进来扫描
  608.                                    ucWd5Part1Update=1;  //局部时更新显示
  609.                    }  
  610.                           
  611.                            if(ucWd5Part1Update == 1)
  612.                            {
  613. //                                      ucWd5Part1Update = 0;
  614.                   
  615.                                    ucDigShow1=ucTemp1; //数码管显示实际内容
  616.                                    ucDigShow2=ucTemp2; //数码管显示实际内容
  617.                                    ucDigShow3=ucTemp3; //数码管显示实际内容
  618.                                    ucDigShow4=ucTemp4; //数码管显示实际内容

  619.                            }
  620.                            break;

  621.                  case 6:ucDigTimeLock = 1; //不显示小数点
  622.                                 ucDigShow1=13; //数码管显示实际内容
  623.                                 ucDigShow2=14; //数码管显示实际内容
  624.                                 ucDigShow3=15; //数码管显示实际内容
  625.                                 ucDigShow4=16; //数码管显示实际内容

  626.                  break;
  627.       }
  628. }


  629. /********************************************************************************************
  630. 函数名称:按键服务程序
  631. 功    能:按键处理的事务
  632. 返 回 值:无
  633. 时    间:2014-11-11       
  634. 备    注:
  635. **************************************************************************************************/
  636. void key_service(void) //按键服务的应用程序
  637. {
  638.         switch(ucKeySec) //按键服务状态切换
  639.         {
  640.                 case 1:// 加按键  
  641.                                 switch(ucWd)  //在不同的窗口下,设置不同的参数
  642.                                 {
  643.                                
  644.                                 case 1:switch(ucPart) //在不同的局部变量下,相当于二级菜单
  645.                                                 {
  646.                                                         case 1:  //时
  647.                                                                         ucHour++;
  648.                        
  649.                                                                         if(ucHour>23)
  650.                                                                         {
  651.                                                                                 ucHour=23;
  652.                                                                         }
  653.                                                                         ucWd1Part1Update=1;  //更新显示                                               
  654.                                                                         break;
  655.        
  656.                                                         case 2: //分
  657.                                                                         ucMinute++;
  658.                                                                         if(ucMinute>59)
  659.                                                                         {
  660.                                                                                 ucMinute=59;
  661.                                                                         }
  662.                                                                         ucWd1Part2Update=1;  //更新显示                                                      
  663.                                                                         break;
  664.                                                 }
  665.                                         break;

  666.                                  case 2:
  667.                                         switch(ucPart)
  668.                                                 {
  669.                                                         case 1:
  670.                                                               ucSetTimeCnt1++;
  671.                                                                   if(ucSetTimeCnt1>23)
  672.                                                                   {
  673.                                                                      ucSetTimeCnt1 = 23;
  674.                                                                   }

  675.                                                                   ucWd2Part1Update=1;  //更新显示
  676.                                                                  break;

  677.                                                         case 2:
  678.                                                                    ucSetTimeCnt2++;
  679.                                                                   if(ucSetTimeCnt2>59)
  680.                                                                   {
  681.                                                                      ucSetTimeCnt2 = 59;
  682.                                                                   }
  683.                                                                   ucWd2Part2Update=1;  //更新显示
  684.                                                               break;
  685.                                                 }
  686.                                  break;

  687.                                  case 3:
  688.                                        switch(ucPart)
  689.                                            {
  690.                                              
  691.                                                    case 1:
  692.                                                          ucSetTepCnt1++;
  693.                                                                  if(ucSetTepCnt1>125)
  694.                                                                  {
  695.                                                                      ucSetTepCnt1 = 125;
  696.                                                                  }
  697.                                                                  ucWd3Part1Update = 1;
  698.                                                    break;
  699.                                                   
  700.                                            }
  701.                                  break;

  702.                                 }
  703.        
  704.               ucVoiceLock=1;  //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
  705.               uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。
  706.               ucVoiceLock=0;  //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
  707.               ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  708.               break;   
  709.        
  710.        
  711.                 case 2:// 减按键  
  712.                       switch(ucWd)  //在不同的窗口下,设置不同的参数
  713.                       {
  714.                                       case 1:
  715.                                 switch(ucPart) //在不同的局部变量下,相当于二级菜单
  716.                                                 {
  717.                                                         case 1:  //时
  718.                                                                         ucHour--;
  719.                                                                         if(ucHour>23)
  720.                                                                         {
  721.                                                                                 ucHour=0;
  722.                                                                         }
  723.                                                                         ucWd1Part1Update=1;  //更新显示                                               
  724.                                                                 break;
  725.        
  726.                                                         case 2: //分
  727.                                                                         ucMinute--;
  728.                                                                         if(ucMinute>59)
  729.                                                                         {
  730.                                                                                 ucMinute=0;
  731.                                                                         }
  732.                                                                         ucWd1Part2Update=1;  //更新显示                                                      
  733.                                                                         break;
  734.                                                         }
  735.                                 break;
  736.                                    case 2:
  737.                                 switch(ucPart) //在不同的局部变量下,相当于二级菜单
  738.                                                 {
  739.                                                         case 1:  //时
  740.                                                                         ucSetTimeCnt1--;
  741.                                                                         if(ucSetTimeCnt1>23)
  742.                                                                         {
  743.                                                                                 ucSetTimeCnt1=0;
  744.                                                                         }

  745.                                                                         ucWd2Part1Update=1;  //更新显示                                               
  746.                                                                     break;
  747.        
  748.                                                         case 2: //分
  749.                                                                         ucSetTimeCnt2--;
  750.                                                                         if(ucSetTimeCnt2>59)
  751.                                                                         {
  752.                                                                                 ucSetTimeCnt2=0;
  753.                                                                         }
  754.                                                                         ucWd2Part2Update=1;  //更新显示                                                      
  755.                                                                         break;
  756.                                                         }
  757.                                 break;
  758.                                        
  759.                                 case 3:        switch(ucPart)
  760.                                                 {
  761.                                                        
  762.                                                         case 1:
  763.                                                                 ucSetTepCnt1--;

  764.                                                                 if(ucSetTepCnt1>125)
  765.                                                                 {
  766.                                                                         ucSetTepCnt1 = 0;
  767.                                                                 }
  768.                                                                 ucWd3Part1Update = 1;
  769.                                                                 break;
  770.                                                        
  771.                                                         }
  772.                                                 break;


  773.                       }
  774.        
  775.               ucVoiceLock=1;  //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
  776.               uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。
  777.               ucVoiceLock=0;  //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
  778.               ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  779.               break;
  780.                   
  781.                 case 3://短按设置按键
  782.                                 switch(ucWd)  //在不同的窗口下,设置不同的参数
  783.                                 {
  784.                                        
  785.                                         case 1:
  786.                                                 if(ucAlarmPrompt == 1)         //此时报警启动
  787.                                                         {
  788.                                                             ucAlarmPrompt = 0;          //报警关闭
  789.                                                         }

  790.                                                         if(ucPart>0) //在窗口2的时候,要第一次激活设置时间,必须是长按3秒才可以,这里短按激活不了第一次
  791.                                                         {
  792.                                                                 ucPart++;
  793.                                                                 if(ucPart>2)  //设置时间结束
  794.                                                                 {
  795.                                                                         ucPart=0;
  796.                                                                         /* 注释五:
  797.                                                                         * 每个月份的天数最大值是不一样的,在写入ds1302时钟芯片内部数据前,应该做一次调整。
  798.                                                                         * 有的月份最大28天,有的月份最大29天,有的月份最大30天,有的月份最大31天,
  799.                                                                         */                                                   
  800.                                                                         ucHourBCD=number_to_bcd(ucHour);  //原始数值转BCD
  801.                                                                         ucMinuteBCD=number_to_bcd(ucMinute);  //原始数值转BCD
  802.                                                                         ucSecondBCD=number_to_bcd(ucSecond);  //原始数值转BCD

  803.                                                                         Write1302 (WRITE_PROTECT,0X00);          //禁止写保护
  804.                                                                         Write1302 (WRITE_HOUR,ucHourBCD);        //小时修改
  805.                                                                         Write1302 (WRITE_MINUTE,ucMinuteBCD);    //分钟修改
  806.                                                                         Write1302 (WRITE_SECOND,ucSecondBCD);    //秒位修改
  807.                                                                         Write1302 (WRITE_PROTECT,0x80);          //允许写保护

  808.                                                                 }
  809.                                                                 ucWd1Update=1;  //窗口1更新显示
  810.                                                         }
  811.                                                 break;

  812.                                            case 2:
  813.                                                         if(ucPart>0)
  814.                                                         {
  815.                                                                 ucPart++;
  816.                                                                 if(ucPart>2)
  817.                                                                 {
  818.                                                                ucPart = 1;
  819.                                                                    ucWd=3; //切换到第三个窗口,设置预定时
  820.                                                                    ucWd3Update=1;  //窗口3更新显示
  821.                                                                 }
  822.                                                         }
  823.                                                         break;

  824.                                            case 3:
  825.                                                  if(ucPart>0)
  826.                                                          {
  827.                                                             ucPart++;
  828.                                                                 if(ucPart>1)
  829.                                                                 {
  830.                                                                     ucPart = 0;
  831.                                                                         ucWd = 4;  //切换到第四个窗口,
  832.                                                                         ucPart = 1;
  833.                                                                         ucDigTimeLock = 1;  //小数点不显示
  834.                                                                 }
  835.                                                          }
  836.                                                         break;

  837.                                            case 4:
  838.                                                  if(ucPart>0)
  839.                                                          {
  840.                                                             ucPart++;
  841.                                                                 if(ucPart>1)
  842.                                                                 {
  843.                                                                     ucPart = 0;
  844.                                                                         ucWd = 1;
  845.                                                                         ucWd1Update = 1;
  846.                                                                         ucDigTimeLock = 0;  //显示小数点
  847.                                                                         ucStartheat = 1;//启动加热
  848.                                                                 }
  849.                                                          }

  850.                                                         break;
  851.                                 }
  852.        
  853.               ucVoiceLock=1;  //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
  854.               uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。
  855.               ucVoiceLock=0;  //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
  856.               ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  857.               break;      
  858.                      
  859.                 case 4:
  860.                            if(ucBootScreen == 0)  //开机
  861.                            {
  862.                                         ucWd=1;
  863.                                         ucWd1Update=1;  //窗口1更新显示
  864.                                         ucDigTimeLock = 0; //显示小数点
  865.                                         ucBootScreen = 1; //开关标志位置1,为关机做准备
  866.                            }
  867. //                                 if(ucBootScreen == 1)//关机
  868. //                           {
  869. //                                        ucWd=6;
  870. //                                        ucBootScreen = 0; //开关标志位清零,为开机做准备
  871. //                                        ucStartheat = 0; //停止加热
  872. //                                        ucSetTimeCnt1 = 12; //复位默认设的小时
  873. //                                    ucSetTimeCnt2 = 30; //复位默认设的分钟
  874. //                    ucSetTepCnt1 = 50; //复位默认温度值
  875. //                                        ucPart = 0;         //设置清零
  876. //                           }
  877.               ucVoiceLock=1;  //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
  878.               uiVoiceCnt=const_voice_long; //按键声音触发,滴一声就停。
  879.               ucVoiceLock=0;  //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
  880.               ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  881.                 break;

  882.                 case 5:
  883.                            if(ucBootScreen == 1)//关机
  884.                            {
  885.                                         ucWd=6;
  886.                                         ucBootScreen = 0; //开关标志位清零,为开机做准备
  887.                                         ucStartheat = 0; //停止加热
  888.                                         ucSetTimeCnt1 = 12; //复位默认设的小时
  889.                                     ucSetTimeCnt2 = 30; //复位默认设的分钟
  890.                     ucSetTepCnt1 = 50; //复位默认温度值
  891.                                         ucPart = 0;         //设置清零
  892.                            }
  893.               ucVoiceLock=1;  //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
  894.               uiVoiceCnt=const_voice_long; //按键声音触发,滴一声就停。
  895.               ucVoiceLock=0;  //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
  896.               ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  897.                 break;

  898.                 case 17://长按3秒设置按键
  899.                         switch(ucWd)  //在不同的窗口下,设置不同的参数
  900.                         {
  901.                                 case 1:
  902.                                                 if(ucPart==0) //处于非设置时间的状态下,要第一次激活设置时间,必须是长按3秒才可以
  903.                                                 {
  904.                                                                 ucWd=2;
  905.                                                                 ucPart=1;  //进入到设置日期的状态下
  906.                                                                 ucWd2Update=1;  //窗口1更新显示
  907.                                                 }
  908.                                                 break;
  909. //                                case 4:
  910. //                                       if(ucPart == 0)
  911. //                                           {
  912. //                                                      ucWd=2;
  913. //                                                   ucPart=1;  //进入到设置时间的状态下
  914. //                                                   ucWd2Update=1;  //窗口2更新显示
  915. //                                           }
  916. //                                        break;
  917.                         }
  918.        
  919.               ucVoiceLock=1;  //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
  920.               uiVoiceCnt=const_voice_long; //按键声音触发,滴一声就停。
  921.               ucVoiceLock=0;  //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
  922.               ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  923.               break;  
  924.                   
  925.                  case 18:
  926.                        switch(ucWd)
  927.                            {
  928.                               case 0:break;
  929.                                   case 2:
  930.                                          ucPart = 0;
  931.                                             if(ucPart == 0&& ucStartheat == 0)          //处于非设置的情况下,长按设置系统时间
  932.                                                 {
  933.                                                     ucWd = 1;
  934.                                                         ucPart = 1;
  935.                                                         ucWd1Update = 1;
  936.                                                 }
  937.                                                 else if(ucPart == 0&&ucStartheat == 1)
  938.                                                 {
  939.                                                             //处于非设置的情况下,久长按退出定时恒温热水
  940.                                                     ucWd = 1;
  941. //                                                        ucPart = 1;
  942.                                                         ucWd1Update = 1;

  943.                                                         ucStartheat = 0; //停止加热
  944.                                                         ucSetTimeCnt1 = 12; //复位默认设的小时
  945.                                                     ucSetTimeCnt2 = 30; //复位默认设的分钟
  946.                             ucSetTepCnt1 = 50; //复位默认温度值
  947.                                                         ucDigTimeLock = 0; //显示小数点
  948.                                                 }
  949.                                   break;

  950.                            }

  951.                   ucVoiceLock=1;  //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
  952.               uiVoiceCnt=const_voice_long; //按键声音触发,滴一声就停。
  953.               ucVoiceLock=0;  //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
  954.               ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发
  955.       
  956.                  break;  
  957.         }         

  958. }

  959. /********************************************************************************************
  960. 函数名称:DS1302采样程序
  961. 功    能:读取DS1302的数据
  962. 返 回 值:无
  963. 时    间:2014-11-11       
  964. 备    注:系统不用时时刻刻采集ds1302的内部数据,每隔一段时间更新采集一次就可以了。
  965.           这个间隔时间应该小于或者等于1秒钟的时间,否则在数码管上看不到每秒钟的时间变化。
  966. **************************************************************************************************/
  967. void ds1302_sampling(void) //ds1302采样程序,内部每秒钟采集更新一次
  968. {
  969.    if(ucPart==0)  //当系统不是处于设置日期和时间的情况下
  970.    {
  971.       ++uiSampingCnt;  //累计主循环次数的时间

  972.       if(uiSampingCnt>const_ds1302_sampling_time)  //每隔一段时间就更新采集一次Ds1302数据
  973.       {
  974.                         uiSampingCnt=0;
  975.                         ucHourBCD=Read1302(READ_HOUR); //读取时
  976.                         ucMinuteBCD=Read1302(READ_MINUTE); //读取分

  977.                         ucHour=bcd_to_number(ucHourBCD);  //BCD转原始数值
  978.                         ucMinute=bcd_to_number(ucMinuteBCD);  //BCD转原始数值
  979.                         ucWd1Update=1; //窗口1更新显示时间
  980.       }
  981.   }
  982. }


  983. /********************************************************************************************
  984. 函数名称:修改DS1302时间的驱动程序
  985. 功    能:读取DS1302的数据
  986. 返 回 值:无
  987. 时    间:2014-11-11       
  988. 备    注:此处写的是BCD码
  989. **************************************************************************************************/
  990. void Write1302 ( unsigned char addr, unsigned char dat )
  991. {
  992.      
  993.          unsigned char i,temp;//单片机驱动DS1302属于SPI通讯方式,根据我的经验,不用关闭中断
  994.      DS1302_CE_dr=0;      //CE引脚为低,数据传送中止
  995.      delay_short(1);           
  996.      SCLK_dr=0;           //清零时钟总线
  997.      delay_short(1);
  998.      DS1302_CE_dr = 1;    //CE引脚为高,逻辑控制有效
  999.      delay_short(1);
  1000.      for ( i=0; i<8; i++ )//循环8次移位
  1001.      {
  1002.         DIO_dr_sr = 0;
  1003.         temp = addr;
  1004.         if(temp&0x01)
  1005.         {
  1006.             DIO_dr_sr =1;
  1007.         }
  1008.         else
  1009.         {
  1010.             DIO_dr_sr =0;
  1011.         }
  1012.         delay_short(1);
  1013.         addr >>= 1;                                           //右移一位
  1014.         SCLK_dr = 1;
  1015.         delay_short(1);
  1016.         SCLK_dr = 0;
  1017.         delay_short(1);
  1018.      }
  1019.      //发送数据

  1020.      for ( i=0; i<8; i++ )                                    //循环8次移位
  1021.      {
  1022.         DIO_dr_sr = 0;
  1023.         temp = dat;
  1024.         if(temp&0x01)
  1025.         {
  1026.             DIO_dr_sr =1;
  1027.         }
  1028.         else
  1029.         {
  1030.            DIO_dr_sr =0;
  1031.         }
  1032.         delay_short(1);
  1033.         dat >>= 1;                                             //右移一位
  1034.         SCLK_dr = 1;
  1035.         delay_short(1);
  1036.         SCLK_dr = 0;
  1037.         delay_short(1);
  1038.      }
  1039.      DS1302_CE_dr = 0;
  1040.      delay_short(1);
  1041. }         


  1042. /********************************************************************************************
  1043. 函数名称:读取DS1302时间的驱动程序
  1044. 功    能:读取DS1302的数据
  1045. 返 回 值:无
  1046. 时    间:2014-11-11       
  1047. 备    注:此处读的是BCD码
  1048. **************************************************************************************************/
  1049. unsigned char Read1302 ( unsigned char addr )
  1050. {
  1051.     unsigned char i,temp,dat1;
  1052.     DS1302_CE_dr=0;      //单片机驱动DS1302属于SPI通讯方式,根据我的经验,不用关闭中断
  1053.     delay_short(1);
  1054.     SCLK_dr=0;
  1055.     delay_short(1);
  1056.     DS1302_CE_dr = 1;
  1057.     delay_short(1);
  1058.     for ( i=0; i<8; i++ )                                      //循环8次移位
  1059.     {
  1060.        DIO_dr_sr = 0;
  1061.        temp = addr;
  1062.        if(temp&0x01)
  1063.        {
  1064.           DIO_dr_sr =1;
  1065.        }
  1066.        else
  1067.        {
  1068.           DIO_dr_sr =0;
  1069.        }
  1070.        delay_short(1);
  1071.        addr >>= 1;                                             //右移一位
  1072.        SCLK_dr = 1;
  1073.        delay_short(1);
  1074.        SCLK_dr = 0;
  1075.        delay_short(1);
  1076.     }

  1077. /********************************************************************************************
  1078. 注    释:51单片机IO口的特点,在读取数据之前必须先输出高电平,
  1079.           如果是PIC,AVR等单片机,这里应该把IO方向寄存器设置为输入
  1080. 时    间:2014-11-11       
  1081. **************************************************************************************************/
  1082.    DIO_dr_sr =1;   //51单片机IO口的特点,在读取数据之前必须先输出高电平,
  1083.    temp=0;

  1084.    for ( i=0; i<8; i++ )
  1085.    {
  1086.       temp>>=1;
  1087.       if(DIO_dr_sr==1)
  1088.       {
  1089.          temp=temp+0x80;
  1090.       }

  1091.       DIO_dr_sr =1;  //51单片机IO口的特点,在读取数据之前必须先输出高电平
  1092.       delay_short(1);
  1093.       SCLK_dr = 1;
  1094.       delay_short(1);
  1095.       SCLK_dr = 0;
  1096.       delay_short(1);
  1097.     }

  1098.     DS1302_CE_dr=0;
  1099.     delay_short(1);
  1100.     dat1=temp;
  1101.     return (dat1);
  1102. }

  1103. /********************************************************************************************
  1104. 函数名称:BCD转原始数值程序
  1105. 功    能:
  1106. 返 回 值:无
  1107. 时    间:2014-11-11       
  1108. 备    注:
  1109. **************************************************************************************************/
  1110. unsigned char bcd_to_number(unsigned char ucBcdTemp)  //BCD转原始数值
  1111. {
  1112.    unsigned char ucNumberResult=0;
  1113.    unsigned char ucBcdTemp10;
  1114.    unsigned char ucBcdTemp1;

  1115.    ucBcdTemp10=ucBcdTemp;
  1116.    ucBcdTemp10=ucBcdTemp10>>4;
  1117.    ucBcdTemp1=ucBcdTemp;
  1118.    ucBcdTemp1=ucBcdTemp1&0x0f;
  1119.    ucNumberResult=ucBcdTemp10*10+ucBcdTemp1;
  1120.    return ucNumberResult;
  1121. }


  1122. /********************************************************************************************
  1123. 函数名称:原始数值转换成BCD码
  1124. 功    能:
  1125. 返 回 值:无
  1126. 时    间:2014-11-11       
  1127. 备    注:
  1128. **************************************************************************************************/
  1129. unsigned char number_to_bcd(unsigned char ucNumberTemp) //原始数值转BCD
  1130. {
  1131.    unsigned char ucBcdResult=0;
  1132.    unsigned char ucNumberTemp10;
  1133.    unsigned char ucNumberTemp1;

  1134.    ucNumberTemp10=ucNumberTemp;
  1135.    ucNumberTemp10=ucNumberTemp10/10;
  1136.    ucNumberTemp10=ucNumberTemp10<<4;
  1137.    ucNumberTemp10=ucNumberTemp10&0xf0;
  1138.    ucNumberTemp1=ucNumberTemp;
  1139.    ucNumberTemp1=ucNumberTemp1%10;
  1140.    ucBcdResult=ucNumberTemp10|ucNumberTemp1;
  1141.    return ucBcdResult;
  1142. }

  1143. /********************************************************************************************
  1144. 函数名称:DS1302备用电池电量用完报警程序
  1145. 功    能:DS1302备用电池电量用完后,蜂鸣器在0.5S发也鸣叫
  1146. 返 回 值:无
  1147. 时    间:2014-11-11       
  1148. 备    注:
  1149. **************************************************************************************************/
  1150. void ds1302_alarm_service(void) //ds1302出错报警
  1151. {
  1152.     if(ucDs1302Error==1)  //备用电池的电量用完了报警提示         
  1153.     {
  1154.            if(uiDs1302Cnt>const_ds1302_0_5s)  //大概0.5秒钟蜂鸣器响一次
  1155.            {
  1156.                                 ucDs1302Lock=1;  //原子锁加锁
  1157.                                 uiDs1302Cnt=0; //计时器清零
  1158.                                 uiVoiceCnt=const_voice_short; //蜂鸣器声音触发,滴一声就停。
  1159.                                 ucDs1302Lock=0;  //原子锁解锁
  1160.            }
  1161.    }
  1162. }

  1163. /********************************************************************************************
  1164. 函数名称:热水完毕报警程序
  1165. 功    能:热水完毕后,发出报警声
  1166. 返 回 值:无
  1167. 时    间:2014-11-14       
  1168. 备    注:
  1169. **************************************************************************************************/
  1170. void ucAlarmPrompt_service()
  1171. {
  1172.     static        unsigned int uiAlarmPromptCnt;        //报警延时计数器
  1173.         static  unsigned char ucNumberCnt;                //报警次数计数器
  1174.         static  unsigned int const_time_2s = 400; //报警的时间间隔
  1175.         static  unsigned int const_voice_AlarmPrompt = 200;

  1176.    if(ucAlarmPrompt == 1)                                        //报警标志位置位后报警
  1177.    {
  1178.        uiAlarmPromptCnt++;                                        //报警延时计数器自加1

  1179.        if(uiAlarmPromptCnt>const_time_2s)        //2S发出报警声音
  1180.            {
  1181.                       uiAlarmPromptCnt = 0;                        //报警延时计数器清零
  1182.                    uiVoiceCnt=const_voice_AlarmPrompt;                //
  1183.                    ucNumberCnt++;                                        //报警次数计数器加1
  1184.                   
  1185.                    if(ucNumberCnt == 5)                        //报警次数为10次
  1186.                    {
  1187.                               ucNumberCnt = 0;                                //报警次数计数器清零
  1188.                            ucAlarmPrompt = 0;                        //关闭报警
  1189.                    }
  1190.            }
  1191.    }
  1192. }

  1193. /********************************************************************************************
  1194. 函数名称:数码管显示驱动程序
  1195. 功    能:显示对应的时间
  1196. 返 回 值:无
  1197. 时    间:2014-11-11       
  1198. 备    注:
  1199. **************************************************************************************************/
  1200. void display()
  1201. {
  1202.         switch(ucDigStep)          //步骤变量
  1203.         {
  1204.            case 1:
  1205.                  P0 = array[ucDigShow1];                  //第一位数码管显示的内容
  1206.                          dig1_dr = 0;
  1207.                          delay(10);
  1208.                          dig1_dr = 1;
  1209.                          ucDigStep = 2;
  1210.            break;

  1211.            case 2:
  1212.                             P0 = array[ucDigShow2];                  //第二位数码管显示的内容
  1213.                          dig2_dr = 0;
  1214.                          delay(10);
  1215.                          dig2_dr = 1;
  1216.                          ucDigStep = 3;
  1217.            break;

  1218.            case 3:
  1219.                             P0 = array[ucDigShow3];                  //第三位数码管显示的内容
  1220.                          dig3_dr = 0;
  1221.                          delay(10);
  1222.                          dig3_dr = 1;
  1223.                          ucDigStep = 4;
  1224.            break;

  1225.            case 4:
  1226.                             P0 = array[ucDigShow4];                  //第四位数码管显示的内容
  1227.                          dig4_dr = 0;
  1228.                          delay(10);
  1229.                          dig4_dr = 1;
  1230.                          ucDigStep =1;
  1231.            break;
  1232.         }         
  1233. }


  1234. /********************************************************************************************
  1235. 函数名称:热水时间和温度数据对比
  1236. 功    能:将设定的时间于当前的时间作对比,数据正确执行。
  1237. 返 回 值:无
  1238. 时    间:2014-11-11       
  1239. 备    注:
  1240. **************************************************************************************************/
  1241. void TimeData_contrast()
  1242. {
  1243.         static unsigned char preser_heat = 0;        //保温标志位
  1244.         static unsigned char  ucCheakFault = 0;                //故障检查标志位
  1245.         static unsigned char ucTimeEqual = 0;       //设定时间相等的标志位
  1246.         static unsigned char ucTimeAfter  = 0;      //两分钟前的时间
  1247.         static unsigned char ucTepAfter  = 0;      //两分钟前的时间

  1248.         if(ucStartheat == 1&&ucPart == 0)   //开始预设加热标志
  1249.         {
  1250.                 if((ucHour == ucSetTimeCnt1) && (ucMinute == ucSetTimeCnt2)&&ucTimeEqual == 0)  //设定的时间相等
  1251.             {
  1252. //                        ucStartheat = 1;//启动加热标志位
  1253.                         ucWd = 4;                  //更新到窗口4,显示温度
  1254.                         ucWd4Update = 1;
  1255.                         ucDigTimeLock = 1;  //小数点不显示

  1256.                         relay_dr = 1;        //继电器输出高(吸合)
  1257.                         ucCheakFault = 1;//故障检查
  1258.                         ucTimeEqual = 1;//时间对比完成
  1259.                         ucTimeAfter         = 0;//先对变量清零
  1260.                         ucTepAfter         = 0;//先对变量清零
  1261.                         ucTimeAfter = ucMinute;
  1262.                         ucTepAfter = ucAD_value_Tem;
  1263. //                        ucAlarmPrompt = 1;  //故障报警
  1264.                 }

  1265.                 if(ucCheakFault == 1&&(ucTimeAfter+3) == ucMinute)
  1266.                 {
  1267.                         if(ucAD_value_Tem>=(ucTepAfter+2))
  1268.                         {
  1269.                            ucCheakFault = 0;   //故障检测清零,只做一次检测
  1270.                            ucTimeEqual = 0;//时间对比完成标志清零,为下一次做准备

  1271.                         }
  1272.                         else
  1273.                         {
  1274.                                 relay_dr = 0;        //继电器输出(断开)

  1275.                                 ucWd = 5;                  //更新到窗口5,显示错误代码E001
  1276.                                 ucWd5Update = 1;

  1277.                                 ucTemp1 = 12; //E
  1278.                                 ucTemp2 = 0;  //0
  1279.                                 ucTemp3 = 0;  //0
  1280.                                 ucTemp4 = 1;  //1

  1281.                                 ucDigTimeLock = 1;  //小数点不显示
  1282.                                 ucAlarmPrompt = 1;  //故障报警
  1283.                                 ucCheakFault = 0;   //故障检测清零,只做一次检测
  1284.                                 ucStartheat = 0;  //检测到有故障,停止加热
  1285.                         }
  1286.                        
  1287.                 }

  1288.                 if(ucAD_value_Tem>=ucSetTepCnt1)        //设定到加热温度相等         
  1289.             {
  1290.                         ucStartheat = 0;//停止预设加热标志
  1291.                         relay_dr = 0;        //继电器输出(断开)

  1292. //                        ucCheakFault = 0;//故障检查标志清零,为下一次做准备

  1293.                         ucAlarmPrompt = 1; //报警标志位置1,启动报警
  1294.                         preser_heat = 1;   //执行保温标志位,开始进行保温

  1295.                         ucWd = 1;                //切换到窗口1显示时间
  1296.                         ucWd1Update = 1;//更新窗口1
  1297.                         ucDigTimeLock = 0; //显示小数点
  1298.                 }

  1299.         }
  1300.        
  1301.         if(preser_heat == 1)        //保温程序,开始执行
  1302.         {
  1303.                 if((ucSetTepCnt1-5) >= ucAD_value_Tem)
  1304.                 {
  1305.                            relay_dr = 1;        //继电器输出

  1306.                         ucWd = 4;                //切换到窗口4显示时间
  1307.                         ucWd4Update = 1;//更新窗口4
  1308.                         ucDigTimeLock = 1; //不显示小数点

  1309.                 }

  1310.                 if((ucSetTepCnt1+5) <= ucAD_value_Tem)
  1311.                 {
  1312.                         relay_dr = 0;        //继电器输出

  1313.                         ucWd = 1;                //切换到窗口1显示时间
  1314.                         ucWd1Update = 1;//更新窗口1
  1315.                         ucDigTimeLock = 0; //显示小数点

  1316.                 }
  1317.         }
  1318. }


  1319. /********************************************************************************************
  1320. 函数名称:ADC采样程序
  1321. 功    能:读取ADC0832转换后的数据
  1322. 返 回 值:
  1323. 时    间:2014-11-24       
  1324. 备    注:
  1325. **************************************************************************************************/
  1326. void ADC_sampling_service()
  1327. {
  1328.         static unsigned char i = 0;  //读取数据8位的次数变量
  1329.         static unsigned char ucADC;  //AD值
  1330.         static unsigned char ucCheckADC; //校验的AD值
  1331.         static unsigned int ucTemp;   //参与换算的中间变量
  1332.         static unsigned int uiTempFilterV=0; //参与换算的中间变量
  1333. //    static unsigned long ulBackupFilterV=255;  //备份最新采样数据的中间变量
  1334. //        static unsigned int  uiTimpFilterTep = 0;
  1335.         static unsigned char wendu;
  1336.         static unsigned int Adresult;
  1337.     static unsigned char ucSamplingCnt=0; //统计采样的次数  本程序采样8次后求平均值

  1338.         adc0832_CS_dr = 0;        //使能端置低

  1339.         adc0832_DI_sr_dr = 1;  //起始位
  1340.         adc0832_CLK_dr = 0;           //输出低电平
  1341.         delay_short(1);                   //小延时
  1342.         adc0832_CLK_dr = 1;           //输出高电平

  1343.         adc0832_DI_sr_dr = 1;  //选择通道,输出数据1
  1344.         adc0832_CLK_dr = 0;
  1345.         adc0832_CLK_dr = 1;

  1346.         adc0832_DI_sr_dr = 0;  //选择通道。输出数据0
  1347.         adc0832_CLK_dr = 0;
  1348.         adc0832_CLK_dr = 1;

  1349.     adc0832_DI_sr_dr = 1;  //拉高数据线
  1350.         delay_short(2);                   //延时

  1351.         adc0832_CLK_dr = 1;           //一个下降延
  1352.         adc0832_CLK_dr = 0;
  1353.         delay_short(1);

  1354.         for(i = 0;i<8;i++)                //读取8位
  1355.         {
  1356.             ucADC <<= 1;
  1357.             adc0832_CLK_dr = 1;
  1358.             adc0832_CLK_dr = 0;

  1359.                 if(adc0832_DI_sr_dr == 1)
  1360.                 {
  1361.                    ucADC  |= 0x01;
  1362.                 }

  1363.         }

  1364.         for(i=0;i<8;i++)                //读取校验位
  1365.         {
  1366.            ucCheckADC >>= 1;

  1367.            if(adc0832_DI_sr_dr == 1)
  1368.            {
  1369.                ucCheckADC |= 0x80;
  1370.            }
  1371.            adc0832_CLK_dr = 1;
  1372.            adc0832_CLK_dr = 0;

  1373.         }
  1374.        
  1375.         adc0832_CS_dr = 1;                //拉高使能端

  1376.         if(ucADC == ucCheckADC)        //校验两个读取的数据是否一致
  1377.         {
  1378.         ucTemp=ucADC; //把char类型数据赋值给long类型数据,参与乘除法运算的数据,为了避免运算结果溢出,我都用long类型


  1379.                 uiTempFilterV=uiTempFilterV+ucTemp;  //累加8次后求平均值
  1380.                 ucSamplingCnt++;  //统计已经采样累计的次数

  1381.                 if(ucSamplingCnt>=8)
  1382.                 {

  1383. /* 注释二:
  1384. * 求平均值滤波法,为了得到的数据更加圆滑,去除小毛刺。
  1385. * 向右边移动3位相当于除以8。
  1386. */

  1387. //                     uiTempFilterV=uiTempFilterV>>3; //求平均值滤波法


  1388.                                     Adresult=(255000/uiTempFilterV)-100;//求得当前温度对应的阻值,十欧为单位,此公式的演变请看上述详细说明

  1389. //                                     if(ulBackupFilterV>=20)  //最近备份的上一次数据大于等于0.02V的情况下
  1390. //                    {
  1391. //                                                if(Adresult<(ulBackupFilterV-5)||Adresult>(ulBackupFilterV+5)) //在正负0.020V偏差范围外,更新
  1392. //                                                {
  1393. //                                                        ulBackupFilterV=Adresult;  //备份最新采样的数据,方便下一次对比判断
  1394. //                                                        uiTimpFilterTep=Adresult; //得到经过滤波处理的实时电压值
  1395. ////                                                        ucWd4Part1Update=1; //局部更新显示经过滤波处理的电压
  1396. //                                                }
  1397. //                    }
  1398. //                    else   //最近备份的上一次数据小于0.02V的情况下
  1399. //                    {
  1400. //                                                if(uiTempFilterV>(ulBackupFilterV+2))  //在正0.020V偏差范围外,更新
  1401. //                                                {
  1402. //                                                        ulBackupFilterV=Adresult;  //备份最新采样的数据,方便下一次对比判断
  1403. //                                                        uiTimpFilterTep=Adresult; //得到经过滤波处理的实时电压值
  1404. ////                                                        ucWd4Part1Update=1; //局部更新显示经过滤波处理的电压
  1405. //                                                }
  1406. //                  
  1407. //                    }

  1408.                                          wendu = 0;//清零

  1409.                                          while(1)
  1410.                                          {
  1411.                                              if(Adresult>=wendu_tab[wendu])
  1412.                                                  {
  1413.                                                         break;
  1414.                                                  }

  1415.                                                  wendu++;

  1416.                                                  if(wendu>=105)
  1417.                                                  {
  1418.                                                      wendu = 105;
  1419.                                                          break;
  1420.                                                  }
  1421.                                                  
  1422.                                          }

  1423.                                         ucAD_value_Tem = wendu;

  1424.                     ucSamplingCnt=0;  //清零,为下一轮采样滤波作准备。
  1425.                     uiTempFilterV=0;
  1426.                 }
  1427.         
  1428.         }
  1429.         else
  1430.         {
  1431.             ucADC = 0;                        //两次读取的数据不一致,就把数据清零
  1432.                 ucAD_value_Tem = wendu;

  1433.         }
  1434.     ucWd4Update = 1;//更新窗口4

  1435. }


  1436. /********************************************************************************************
  1437. 函数名称:定时器中断程序
  1438. 功    能:
  1439. 返 回 值:无
  1440. 时    间:2014-11-11       
  1441. 备    注:
  1442. **************************************************************************************************/
  1443. void T0_time() interrupt 1
  1444. {

  1445.    TF0=0;  //清除中断标志
  1446.    TR0=0; //关中断
  1447.    display();                 //数码管显示放在中断里
  1448.    key_scan();                 //按键扫描放在中断里
  1449. /********************************************************************************************
  1450. 功    能:按键去抖动延时计数器在外部可以关闭,不开启计时功能
  1451. 时    间:2014-11-11       
  1452. **************************************************************************************************/
  1453.    if(ucKeyStartFlag1==1)           //启动计数器
  1454.    {
  1455.        if(uiKeyTimeCnt1<0xffff)//防止计数器超出范围
  1456.            {
  1457.                uiKeyTimeCnt1++;           //按键去抖动延时计数器自加1
  1458.            }   
  1459.    }

  1460. /********************************************************************************************
  1461. 功    能:按键去抖动延时计数器在外部可以关闭,不开启计时功能
  1462. 时    间:2014-11-11       
  1463. **************************************************************************************************/
  1464.    if(ucKeyStartFlag2==1)          //启动计数器
  1465.    {
  1466.        if(uiKeyTimeCnt2<0xffff)        //防止计数器超出范围
  1467.            {
  1468.                uiKeyTimeCnt2++;           //按键去抖动延时计数器自加1
  1469.            }
  1470.    }

  1471. /********************************************************************************************
  1472. 功    能:按键去抖动延时计数器在外部可以关闭,不开启计时功能
  1473. 时    间:2014-11-11       
  1474. **************************************************************************************************/
  1475.    if(ucKeyStartFlag3==1)          //启动计数器
  1476.    {
  1477.        if(uiKeyTimeCnt3<0xffff)        //防止计数器超出范围
  1478.            {
  1479.                uiKeyTimeCnt3++;           //按键去抖动延时计数器自加1
  1480.            }
  1481.    }

  1482. /********************************************************************************************
  1483. 功    能:按键去抖动延时计数器在外部可以关闭,不开启计时功能
  1484. 时    间:2014-11-11       
  1485. **************************************************************************************************/
  1486.    if(ucKeyStartFlag4==1)          //启动计数器
  1487.    {
  1488.        if(uiKeyTimeCnt3<0xffff)        //防止计数器超出范围
  1489.            {
  1490.                uiKeyTimeCnt4++;           //按键去抖动延时计数器自加1
  1491.            }
  1492.    }

  1493. /********************************************************************************************
  1494. 功    能:间歇性蜂鸣器报警计数器在外部可以关闭,不开启计时功能
  1495. 时    间:2014-11-11       
  1496. **************************************************************************************************/
  1497.     if(ucDs1302Error>0) //EEPROM出错
  1498.         {
  1499.                 if(ucDs1302Lock==0)//原子锁判断
  1500.                 {
  1501.                         uiDs1302Cnt++;  //间歇性蜂鸣器报警的计时器
  1502.                 }
  1503.         }

  1504. /********************************************************************************************
  1505. 功    能:蜂鸣器驱动放在中断里面
  1506. 时    间:2014-11-11       
  1507. **************************************************************************************************/
  1508.    if(uiVoiceCnt!=0)   //蜂鸣器
  1509.    {
  1510.        uiVoiceCnt--;  //每次进入定时中断都自减1,直到等于零为止。才停止鸣叫
  1511.            beep_dr = 0;          //蜂鸣器是PNP三极管控制,低电平就开始鸣叫
  1512.    }
  1513.    else
  1514.    {
  1515.        beep_dr = 1;   //蜂鸣器是PNP三极管控制,高电平就停止鸣叫。
  1516.    }


  1517.         TH0=0xf8;   //重装初始值(65535-2000)=63535=0xf82f
  1518.         TL0=0x2f;
  1519.         EA = 1;
  1520.         ET0 = 1;
  1521.         TR0=1;  //开中断
  1522. }


  1523. /********************************************************************************************
  1524. 函数名称:定时器初始化程序
  1525. 功    能:
  1526. 返 回 值:无
  1527. 时    间:2014-11-11       
  1528. 备    注:
  1529. **************************************************************************************************/
  1530. void T0_init()
  1531. {
  1532.    TH0=0xf8;   //重装初始值(65535-2000)=63535=0xf82f
  1533.    TL0=0x2f;
  1534.    EA = 1;
  1535.    ET0 = 1;
  1536.    TR0=1;  //开中断

  1537.    /* 注释七:
  1538.         * 检查ds1302芯片的备用电池电量是否用完了。
  1539.         * 在上电的时候,在一个特定的地址里把数据读出来,如果发现不等于0x5a,
  1540.         * 则是因为备用电池电量用完了,导致保存在ds1302内部RAM数据区的数据被更改,
  1541.         * 与此同时,应该重新写入一次0x5a,为下一次通电判断做准备
  1542.         */
  1543.         ucCheckDs1302=Read1302(READ_CHECK); //判断ds1302内部的数据是否被更改
  1544.         if(ucCheckDs1302!=0x5a)  
  1545.         {
  1546.                 Write1302 (WRITE_PROTECT,0X00);          //禁止写保护
  1547.                 Write1302 (WRITE_CHECK,0x5a);            //重新写入标志数据,方便下一次更换新电池后的判断
  1548.                 Write1302 (WRITE_PROTECT,0x80);          //允许写保护
  1549.                 ucDs1302Error = 1;                                //1表示报警启动
  1550.                 ucWd = 5;                  //更新到窗口5,显示错误代码E001
  1551.                 ucWd5Update = 1;
  1552.                
  1553.                 ucTemp1 = 12; //E
  1554.                 ucTemp2 = 0;  //0
  1555.                 ucTemp3 = 0;  //0
  1556.                 ucTemp4 = 2;  //1
  1557.                
  1558.                 ucDigTimeLock = 1;  //小数点不显示

  1559.         }
  1560. }


  1561. /********************************************************************************************
  1562. 函数名称:初始化单片机内部和外部IO口
  1563. 功    能:
  1564. 返 回 值:无
  1565. 时    间:2014-11-11       
  1566. 备    注:
  1567. **************************************************************************************************/
  1568. void initial_myself(void)  //第一区 初始化单片机
  1569. {
  1570.         beep_dr=1; //用PNP三极管控制蜂鸣器,输出高电平时不叫。
  1571.         relay_dr = 0;
  1572.         dig1_dr = 1;
  1573.         dig2_dr = 1;
  1574.         dig3_dr = 1;
  1575.         dig4_dr = 1;
  1576.         delay_long(30);
  1577. }


  1578. /********************************************************************************************
  1579. 函数名称:延时程序
  1580. 功    能:
  1581. 返 回 值:无
  1582. 时    间:2014-11-11       
  1583. 备    注:
  1584. **************************************************************************************************/
  1585. void delay(unsigned int delay_ms)                  //延时函数
  1586. {
  1587.     unsigned int i,j;

  1588.         for(i = delay_ms;i>0;i--)
  1589.            for(j = 10;j>0;j--);
  1590. }

  1591. /********************************************************************************************
  1592. 函数名称:延时程序
  1593. 功    能:
  1594. 返 回 值:无
  1595. 时    间:2014-11-11       
  1596. 备    注:
  1597. **************************************************************************************************/
  1598. void delay_short(unsigned int uiDelayShort)
  1599. {
  1600.    unsigned int i;  

  1601.    for(i=0;i<uiDelayShort;i++)
  1602.    {
  1603.       ;   //一个分号相当于执行一条空语句
  1604.    }
  1605. }

  1606. /********************************************************************************************
  1607. 函数名称: 延时程序
  1608. 功    能:
  1609. 返 回 值:无
  1610. 时    间:2014-11-11       
  1611. 备    注:
  1612. **************************************************************************************************/
  1613. void delay_long(unsigned int uiDelayLong)
  1614. {
  1615.    unsigned int i;
  1616.    unsigned int j;

  1617.    for(i=uiDelayLong;i>0;i--)
  1618.       for(j=50;j>0;j--);  //内嵌循环的空指令数量
  1619. }
复制代码

评分

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

查看全部评分

回复

使用道具 举报

板凳
ID:26188 发表于 2014-12-9 22:09 | 只看该作者
这个东西很实用 ,,楼主的diy能力太强了 不过继电器容易坏 特别是在潮湿的环境里面 建议改成可控硅的 ,成本也基本上差不多
回复

使用道具 举报

地板
ID:69862 发表于 2014-12-10 09:15 | 只看该作者
hujia 发表于 2014-12-9 22:09
这个东西很实用 ,,楼主的diy能力太强了 不过继电器容易坏 特别是在潮湿的环境里面 建议改成可控硅的 ,成 ...

相与学习,感谢您的宝贵意见,我也考虑过用可控硅,但是控制电路相对于继电器来说要复杂一些。我的继电器采用的12V 40A应该问题不大。
回复

使用道具 举报

5#
ID:70104 发表于 2014-12-19 22:00 | 只看该作者
不错啦,值得收藏
回复

使用道具 举报

6#
ID:70104 发表于 2014-12-19 22:01 | 只看该作者
谢谢你了
回复

使用道具 举报

7#
ID:69862 发表于 2014-12-20 11:00 | 只看该作者
pps111 发表于 2014-12-19 22:00
不错啦,值得收藏

回复

使用道具 举报

8#
ID:69862 发表于 2014-12-20 11:00 | 只看该作者

不客气
回复

使用道具 举报

9#
ID:72565 发表于 2015-1-21 01:31 | 只看该作者
51Hei(51黑)论坛有你更精彩
回复

使用道具 举报

10#
ID:72947 发表于 2015-1-31 18:49 来自手机 | 只看该作者
谢谢啦,值得收藏!!!
回复

使用道具 举报

11#
ID:55202 发表于 2015-1-31 20:02 | 只看该作者
楼主 好强大
回复

使用道具 举报

12#
ID:7992 发表于 2015-2-16 20:39 | 只看该作者
学习一下,非常不错。谢谢楼主分享
回复

使用道具 举报

13#
ID:73870 发表于 2015-2-25 17:23 | 只看该作者
楼主太厉害了
回复

使用道具 举报

14#
ID:73870 发表于 2015-2-25 17:26 | 只看该作者
真是高手
回复

使用道具 举报

15#
ID:73870 发表于 2015-2-25 17:27 | 只看该作者
好强大
回复

使用道具 举报

16#
ID:73870 发表于 2015-2-25 17:27 | 只看该作者
功能强大
回复

使用道具 举报

17#
ID:73870 发表于 2015-2-25 18:49 | 只看该作者
有没有
回复

使用道具 举报

18#
ID:73870 发表于 2015-2-25 18:49 | 只看该作者
电路图
回复

使用道具 举报

19#
ID:63484 发表于 2015-2-26 22:41 | 只看该作者
功能很齐全,设计想到的很细,比较全面
回复

使用道具 举报

20#
ID:77907 发表于 2015-4-24 15:25 | 只看该作者
厉害!!
回复

使用道具 举报

21#
ID:72050 发表于 2015-4-26 13:47 | 只看该作者
这是个好的东西,
回复

使用道具 举报

22#
ID:72050 发表于 2015-4-26 13:47 | 只看该作者
谢谢楼主共享
回复

使用道具 举报

23#
ID:72050 发表于 2015-4-26 13:50 | 只看该作者
谢谢楼主
回复

使用道具 举报

24#
ID:72050 发表于 2015-4-26 13:50 | 只看该作者
电路板搞得漂亮
回复

使用道具 举报

25#
ID:78515 发表于 2015-5-3 10:49 | 只看该作者
做工精细,好好学习学习,多谢楼主分享
回复

使用道具 举报

26#
ID:54731 发表于 2015-5-3 18:09 | 只看该作者
楼主:你太强大了,必须顶你。资料不错,如果有电路图更好。
回复

使用道具 举报

27#
ID:78005 发表于 2015-5-6 15:14 | 只看该作者
没黑币了
回复

使用道具 举报

28#
ID:78005 发表于 2015-5-6 15:14 | 只看该作者
再鼎一下
回复

使用道具 举报

29#
ID:77586 发表于 2015-5-6 15:51 | 只看该作者
膜拜啊
回复

使用道具 举报

30#
ID:48994 发表于 2015-5-8 13:03 | 只看该作者

好好学习学习,多谢楼主分享
回复

使用道具 举报

31#
ID:78702 发表于 2015-5-14 14:37 | 只看该作者
好好学习
回复

使用道具 举报

32#
ID:78702 发表于 2015-5-14 14:37 | 只看该作者
学习一下,非常不错。谢谢楼主分享
回复

使用道具 举报

33#
ID:78702 发表于 2015-5-14 15:21 | 只看该作者
楼主强大,
回复

使用道具 举报

34#
ID:84574 发表于 2015-7-2 15:14 | 只看该作者
很有用的。
回复

使用道具 举报

35#
ID:90949 发表于 2015-9-24 11:26 | 只看该作者
膜拜,学习学习
回复

使用道具 举报

36#
ID:44267 发表于 2015-9-27 19:52 | 只看该作者
不说什么,就是顶
回复

使用道具 举报

37#
ID:91613 发表于 2015-10-5 08:54 | 只看该作者
高手中的高手啊,看的我好崇拜
回复

使用道具 举报

38#
ID:12312 发表于 2015-11-9 16:39 | 只看该作者
高手中的高手啊,看的我好崇拜
回复

使用道具 举报

39#
ID:52139 发表于 2015-12-11 01:33 | 只看该作者
做工精细,好好学习学习,多谢楼主分享
回复

使用道具 举报

40#
ID:70330 发表于 2015-12-12 12:48 | 只看该作者
请问楼主,xps文件打不开,怎么办?谢谢!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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