|
本帖最后由 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, 下载次数: 382)
-------->源程序
智能热水器.zip
(120.23 KB, 下载次数: 402)
主要器件说明:
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, 下载次数: 136)
5、继电器
由于是热水器,发热体的功率比较大,所以就选用:12V、40A
注:原理图和中的继电器驱动用的是低电平,程序中用的是高电平。
6、数码管
共阳极数码管,PNP三极管做驱动。中间两点是时间的秒,要单独用一个I/O控制。
为什么要单独用一个I/O口控制?
因为:中间两点闪亮一下就是1S,不可以放在P0数据端口,这样数码管要500MS才扫描一次,数码管会闪烁,所以要单独用一个I/O来控制。
程序如下:- /********************************************************************************************
- 名 称:智能热水器控制系统
- 功 能:
- 1、数码管显示当前北京时间。可对时间进行修改。
- 2、设定时间,到达设定的时间开始加热。
- 3、设定温度,到达设定的温度值,停止加热。
- 4、加热完毕后,蜂鸣器报警提示,温度控制在设定温度+-5度变化。
- 5、DS1302备用电池电量用完时,蜂鸣器报警。并在数码管上显示E002代码
- 6、发热体好坏判别,如果坏了,蜂鸣器报警,并在数码管上显示E001代码。
- 7、没有水的情况下,不加热,并且蜂鸣器发出报警。
- 作 者:肖亚平
- 创建时间:2014年11月11日
- 修改时间:
- 备 注:
- **************************************************************************************************/
- #include<reg52.h> //头文件
- #define const_dpy_time_half 200 //数码管闪烁时间的半值
- #define const_dpy_time_all 400 //数码管闪烁时间的全值 一定要比const_dpy_time_half 大
- #define const_voice_short 40 //蜂鸣器短叫的持续时间
- #define const_voice_long 120 //蜂鸣器长鸣叫的时间
- #define const_DigTime_level 240 //小数点计时上限值
- #define const_KeyTime_level 30 //按键去抖动延时的时间
- #define const_key_time_short3 30 //短按的按键去抖动延时的时间
- #define const_key_time_long3 1024 //长按的按键去抖动延时的时间
- #define const_time_0_25s 111 //0.25秒钟的时间需要的定时中断次数
- #define const_time_1s 444 //1秒钟的时间需要的定时中断次数
- #define const_ds1302_0_5s 200 //大概0.5秒的时间
- #define const_ds1302_sampling_time 300 //累计主循环次数的时间,每次刷新采样时钟芯片的时间
- #define WRITE_SECOND 0x80 //DS1302内部的相关地址
- #define WRITE_MINUTE 0x82
- #define WRITE_HOUR 0x84
- #define WRITE_DATE 0x86
- #define WRITE_MONTH 0x88
- #define WRITE_YEAR 0x8C
- #define WRITE_CHECK 0xC2 //用来检查芯片的备用电池是否用完了的地址
- #define READ_CHECK 0xC3 //用来检查芯片的备用电池是否用完了的地址
- #define READ_SECOND 0x81
- #define READ_MINUTE 0x83
- #define READ_HOUR 0x85
- #define READ_DATE 0x87
- #define READ_MONTH 0x89
- #define READ_YEAR 0x8D
- #define WRITE_PROTECT 0x8E
- #define WRITE_SET_HOUR 0xC4 //用来检查芯片的备用电池是否用完了的地址
- #define READ_SET_HOUR 0xC5 //用来检查芯片的备用电池是否用完了的地址
- #define WRITE_SET_MINUTE 0xC6 //用来检查芯片的备用电池是否用完了的地址
- #define READ_SET_MINUTE 0xC7 //用来检查芯片的备用电池是否用完了的地址
- sbit SCLK_dr =P1^0;
- sbit DIO_dr_sr =P1^1;
- sbit DS1302_CE_dr =P1^2;
- sbit dig1_dr = P2^0; //第一位数码管位选输出
- sbit dig2_dr = P2^1; //第二位数码管位选输出
- sbit dig3_dr = P2^2; //第三位数码管位选输出
- sbit dig4_dr = P2^3; //第四位数码管位选输出
- sbit digital_dp_dr = P2^4; //小数点输出
- sbit beep_dr = P2^5; //蜂鸣器输出
- sbit Key_sr1 = P3^7; //确认/选择键
- sbit Key_sr2 = P3^6; //上选择键 Down
- sbit Key_sr3 = P3^5; //下选择键 UP
- sbit relay_dr = P1^5; //继电器输出
- sbit Key_sr4 = P1^3; //开机按键
- sbit adc0832_CS_dr = P1^4; //adc0832的使能端口
- sbit adc0832_DI_sr_dr = P1^6; //adc0832的数据端口
- sbit adc0832_CLK_dr = P1^7; //adc0832的时钟端口
- unsigned char ucShortTouchFlag3 = 0; //短按的自锁标志、
- unsigned char ucShortTouchFlag4 = 0; //短按的自锁标志
- unsigned char ucDigStep = 1; //步骤变量
- unsigned int uiDigTimeCnt = 0; //小数点延时计数器
- unsigned char ucDigTimeLock = 0;//原子锁
- unsigned int uiVoiceCnt = 0; //蜂鸣器计数器
- unsigned int uiDigTemp1 = 0; //第一位数码管显示内容
- unsigned int uiDigTemp2 = 0; //第二位数码管显示内容
- unsigned int uiDigTemp3 = 0; //第三位数码管显示内容
- unsigned int uiDigTemp4 = 0; //第四位数码管显示内容
- unsigned int uiDigTemp = 0; //计数的变量
- unsigned int uiKeyTimeCnt1 = 0; //按键去抖动延时计数器
- unsigned char ucKeyLock1 = 0; //按键触发后自锁的变量标志
- unsigned char ucKeySec = 0; //被触发的按键编号
- unsigned int uiKeyTimeCnt2 = 0; //按键去抖动延时计数器
- unsigned char ucKeyLock2 = 0; //按键触发后自锁的变量标志
- unsigned int uiKeyTimeCnt3 = 0; //按键去抖动延时计数器
- unsigned char ucKeyLock3 = 0; //按键触发后自锁的变量标志
- unsigned int uiKeyTimeCnt4 = 0; //按键去抖动延时计数器
- unsigned char ucKeyLock4 = 0; //按键触发后自锁的变量标志
- unsigned char ucKeyStartFlag1=0; //启动定时中断计数的开关
- unsigned char ucKeyStartFlag2=0; //启动定时中断计数的开关
- unsigned char ucKeyStartFlag3=0; //启动定时中断计数的开关
- unsigned char ucKeyStartFlag4=0; //启动定时中断计数的开关
- unsigned int uiKeyCtntyCnt1 = 0; //连续触发延时计数器累加
- unsigned int uiKeyCtntyCnt2 = 0;
- /*****************************************************************************************/
- unsigned char ucVoiceLock=0; //蜂鸣器鸣叫的原子锁
- unsigned char ucDigShowTemp=0; //临时中间变量
- unsigned char ucWd=6; //本程序的核心变量,窗口显示变量。类似于一级菜单的变量。代表显示不同的窗口。
- unsigned char ucPart=0;//本程序的核心变量,局部显示变量。类似于二级菜单的变量。代表显示不同的局部。
- unsigned char ucWd1Update=0; //窗口1更新显示标志
- unsigned char ucWd2Update=1; //窗口2更新显示标志
- unsigned char ucWd3Update=1; //窗口3更新显示标志
- unsigned char ucWd4Update=1; //窗口4更新显示标志
- unsigned char ucWd5Update=1; //窗口5更新显示标志
- unsigned char ucWd1Part1Update=0; //在窗口1中,局部1的更新显示标志
- unsigned char ucWd1Part2Update=0; //在窗口1中,局部2的更新显示标志
- unsigned char ucWd2Part1Update=0; //在窗口2中,局部1的更新显示标志
- unsigned char ucWd2Part2Update=0; //在窗口2中,局部2的更新显示标志
- unsigned char ucWd3Part1Update=0; //在窗口3中,局部1的更新显示标志
- unsigned char ucWd3Part2Update=0; //在窗口3中,局部2的更新显示标志
- unsigned char ucWd4Part1Update = 0; //在窗口4中,局部1的更新显示标志
- unsigned char ucWd4Part2Update = 0; //在窗口4中,局部2的更新显示标志
- unsigned char ucWd5Part1Update = 0; //在窗口5中,局部1的更新显示标志
- unsigned char ucDelayTimerLock=0; //原子锁
- //unsigned int uiDelayTimer=0;
- unsigned char ucCheckDs1302=0; //检查Ds1302芯片是否正常
- unsigned char ucDs1302Error=0; //Ds1302芯片的备用电池是否用完了的报警标志
- unsigned char ucDs1302Lock=0;//原子锁
- unsigned int uiDs1302Cnt=0; //间歇性蜂鸣器报警的计时器
- unsigned char ucDpyTimeLock=0; //原子锁
- unsigned int uiDpyTimeCnt=0; //数码管的闪烁计时器,放在定时中断里不断累加
- unsigned char ucAutoDisplayDateLock1 = 0; //原子锁
- unsigned char ucAutoDisplayDateLock2 = 0; //原子锁
- unsigned char ucHour=0;
- unsigned char ucMinute=0;
- unsigned char ucSecond=0;
- unsigned char ucHourBCD=0;
- unsigned char ucMinuteBCD=0;
- unsigned char ucSecondBCD=0;
- unsigned char ucSetTimedataCnt1;
- unsigned char ucSetTimedataCnt2;
- unsigned char ucSetTimeCnt1BCD;
- unsigned char ucSetTimeCnt2BCD;
- unsigned char ucTemp1=0; //中间过渡变量
- unsigned char ucTemp2=0; //中间过渡变量
- unsigned char ucTemp3=0; //中间过渡变量
- unsigned char ucTemp4=0; //中间过渡变量
- unsigned char ucSetTimeCnt1 = 12; //设定时间变量
- unsigned char ucSetTimeCnt2 = 30;
- unsigned char ucSetTepCnt1 = 50; //设置温度计数器
- unsigned char ucDigShow4; //第4位数码管要显示的内容
- unsigned char ucDigShow3; //第3位数码管要显示的内容
- unsigned char ucDigShow2; //第2位数码管要显示的内容
- unsigned char ucDigShow1; //第1位数码管要显示的内容
- unsigned int uiSampingCnt=0; //采集Ds1302的计时器,每秒钟更新采集一次
- unsigned char ucStartheat = 0; //启动加热标志位
- unsigned char ucAlarmPrompt = 0;//加热完毕报警提示标志位
- unsigned char ucAD_value_Tem = 0;//AD转换过后的温度数据
- unsigned char ucADC_value = 0;//AD数据
- unsigned char ucADC_sampling_number = 1; //开启ADC采样的标志位
- unsigned char ucADC_samplingCnt = 0; //ADC采样次数变量
- unsigned char KeyChangeTimeFlag;
- unsigned char ucBootScreen = 0; //开机标志位
- /************************************************************************************************/
- void ds1302_alarm_service(void); //ds1302出错报警
- void ds1302_sampling(void); //ds1302采样程序,内部每秒钟采集更新一次
- void Write1302 ( unsigned char addr, unsigned char dat );//修改时间的驱动
- void display_service(void); //显示的窗口菜单服务程序
- void delay_short(unsigned int uiDelayShort);
- void delay_long(unsigned int uiDelayLong);
- unsigned char Read1302 ( unsigned char addr );//读取时间的驱动
- unsigned char bcd_to_number(unsigned char ucBcdTemp); //BCD转原始数值
- unsigned char number_to_bcd(unsigned char ucNumberTemp); //原始数值转BCD
- void initial_myself(void); //第一区 初始化单片机
- void delay(unsigned int delay_ms);
- void display();
- void T0_time();
- void key_scan();
- void key_service();
- void T0_init();
- void TimeData_contrast();
- void ucAlarmPrompt_service();
- void ADC_sampling_service();
-
- unsigned char array[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xc6,0x86,
- 0xc6,0xf6,0xf6,0xf0};
- const unsigned int code wendu_tab[106]=
- {
- 3274,3111,2957,2812,2674,2545,2422,2306,2196,2092, //0~9
- 1993,1900,1811,1728,1648,1573,1501,1433,1369,1308, //10~19
- 1250,1194,1142,1092,1045,1000,957,916,877,840, //20~29
- 805,771,739,709,679,652,625,600,576,553, //30~39
- 531,510,490,471,453,435,418,402,387,372, //40~49
- 358,345,332,320,308,297,286,276,266,256, //50~59
- 247,238,230,222,214,207,199,193,186,180, //60~69
- 174,168,162,157,152,147,142,137,133,128, //70~79
- 124,120,116,113,109,106,102,99,96,93, //80~89
- 90,88,85,82,80,78,75,73,71,69, //90~99
- 67,65,63,61,59,58 //100~105
- };
- /********************************************************************************************
- 函数名称:主程序
- 功 能:程序执行的入口
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:
- **************************************************************************************************/
- void main()
- {
- T0_init();
- initial_myself();
- while(1)
- {
- ds1302_alarm_service(); //ds1302出错报警
- ucAlarmPrompt_service();
- display_service(); //显示的窗口菜单服务程序
- ds1302_sampling(); //ds1302采样程序,内部每秒钟采集更新一次
- key_service(); //按键服务函数放在主程序里
- TimeData_contrast();
- if(ucADC_sampling_number == 1)
- {
- ucADC_samplingCnt++;
- if(ucADC_samplingCnt==10)
- {
- ucADC_sampling_number = 0;
- ucADC_samplingCnt = 0;
- ADC_sampling_service();
- ucADC_sampling_number = 1;
- }
- }
- if(ucDigTimeLock == 0 && ucPart == 0) //开始计数器标志
- {
- uiDigTimeCnt++; //计数器开始计数
- }
- else
- {
- digital_dp_dr = 1; //关闭小数点显示
- }
-
- if(uiDigTimeCnt >= const_DigTime_level) //计数时间到
- {
- ucDigTimeLock = 1; //计数器标志位置1
- uiDigTimeCnt = 0; //计数器清零
- digital_dp_dr = ~digital_dp_dr; //小数点输出
- ucDigTimeLock = 0; //计数器标志位清零,开始计数。
- }
-
- /********************************************************************************************
- 功 能:数码管闪烁计数器在外部可以关闭,不开启计时功能
- 时 间:2014-11-11
- **************************************************************************************************/
- if(ucDpyTimeLock==0) //原子锁判断
- {
- uiDpyTimeCnt++; //数码管的闪烁计时器
- }
- }
- }
- /********************************************************************************************
- 函数名称:按键扫描
- 功 能:
- 1、按下Key_sr1,加1,如果安下一直不松,就连续加。
- 2、按下Key_sr2,加减1,如果安下一直不松,就连续减。
- 3、按下Key_sr3,单击单步触发,和长按触发
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:按键运用了,单击,长按,连续触发的方法。
- **************************************************************************************************/
- void key_scan()
- {
- static unsigned char KeyChangeTimeFlag3;
- if(Key_sr1 == 1) //1号键
- {
- ucKeyStartFlag1 = 0; //启动定时中断计数的开关清零
- uiKeyTimeCnt1 = 0; //按键去抖动延时计数器清零
- ucKeyLock1 = 0; //按键触发后自锁的变量标志清零
-
- }
- else if(ucKeyLock1 == 0)
- {
- ucKeyStartFlag1 = 1; //开启计数器开关,开始计数
- if(uiKeyTimeCnt1>=const_KeyTime_level)
- {
- ucKeyStartFlag1 = 0; //开启计数器关闭,停止计数
- ucKeyLock1 = 1; //自锁按键置位,避免一直触发
- uiKeyTimeCnt1 = 0; //按键去抖动延时计数器清零
- ucKeySec = 1; //触发1号键
- }
- }
- else if(uiKeyTimeCnt1<const_time_1s)
- {
- uiKeyTimeCnt1++;
- }
- else
- {
- uiKeyCtntyCnt1++; //连续触发延时计数器累加
- if(uiKeyCtntyCnt1>const_time_0_25s)
- {
- uiKeyCtntyCnt1 = 0;
- ucKeySec = 1; //触发1号键
- }
- }
- if(Key_sr2 == 1) //2号键
- {
- ucKeyStartFlag2 = 0; //启动定时中断计数的开关清零
- uiKeyTimeCnt2 = 0; //按键去抖动延时计数器清零
- ucKeyLock2 = 0; //按键触发后自锁的变量标志清零
- }
- else if(ucKeyLock2 == 0)
- {
- ucKeyStartFlag2 = 1; //开启计数器开关,开始计数
- if(uiKeyTimeCnt2>=const_KeyTime_level)
- {
- ucKeyStartFlag2 = 0; //开启计数器关闭,停止计数
- ucKeyLock2 = 1; //自锁按键置位,避免一直触发
- uiKeyTimeCnt2 = 0; //按键去抖动延时计数器清零
- ucKeySec = 2; //触发2号键
- }
- }
- else if(uiKeyTimeCnt2<const_time_1s)
- {
- uiKeyTimeCnt2++;
- }
- else
- {
- uiKeyCtntyCnt2++; //连续触发延时计数器累加
- if(uiKeyCtntyCnt2>const_time_0_25s)
- {
- uiKeyCtntyCnt2 = 0;
- ucKeySec = 2; //触发1号键
- }
- }
-
- if(Key_sr3 == 1) //3,4号键
- {
- ucKeyStartFlag3 = 0; //启动定时中断计数的开关清零
- uiKeyTimeCnt3 = 0; //按键去抖动延时计数器清零
- ucKeyLock3 = 0; //按键触发后自锁的变量标志清零
- ucShortTouchFlag3 = 0; //短按的自锁标志清零
- KeyChangeTimeFlag3 = 0;
- }
- else if(ucKeyLock3 == 0)
- {
- ucKeyStartFlag3 = 1; //开启计数器开关,开始计数
- if(ucShortTouchFlag3 == 0)
- {
- if(uiKeyTimeCnt3>=const_key_time_short3) //短按中间间隔的时间
- {
- ucShortTouchFlag3 = 1;
- ucKeySec = 3; //触发3号键
- }
- }
- if(uiKeyTimeCnt3>=const_key_time_long3&&KeyChangeTimeFlag3 == 0)
- {
- KeyChangeTimeFlag3 = 1;
- ucKeySec = 17; //触发17号键
- }
- if(uiKeyTimeCnt3>=const_key_time_long3+const_key_time_long3)
- {
- ucKeyStartFlag3 = 0; //开启计数器关闭,停止计数
- ucKeyLock3 = 1; //自锁按键置位,避免一直触发
- uiKeyTimeCnt3 = 0; //按键去抖动延时计数器清零
- ucKeySec = 18; //触发17号键
- }
- }
- if(Key_sr4 == 1) //1号键
- {
- ucKeyStartFlag4 = 0; //启动定时中断计数的开关清零
- uiKeyTimeCnt4 = 0; //按键去抖动延时计数器清零
- ucKeyLock4 = 0; //按键触发后自锁的变量标志清零
- ucShortTouchFlag4 = 0; ///短按的自锁标志清零
-
- }
- else if(ucKeyLock4 == 0)
- {
- ucKeyStartFlag4 = 1; //开启计数器开关,开始计数
- if(ucShortTouchFlag4 == 0)
- {
- if(uiKeyTimeCnt4>=const_KeyTime_level)
- {
- ucShortTouchFlag4 = 1;
- ucKeySec = 4; //触发4号键
- }
-
- }
- if(uiKeyTimeCnt4>=const_key_time_long3)
- {
- ucKeyStartFlag4 = 0; //开启计数器关闭,停止计数
- ucKeyLock4 = 1; //自锁按键置位,避免一直触发
- uiKeyTimeCnt4 = 0; //按键去抖动延时计数器清零
- ucKeySec = 5; //触发5号键
- }
- }
- }
- /********************************************************************************************
- 函数名称:显示的窗口菜单服务程序
- 功 能:更新显示内容
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:
- **************************************************************************************************/
- void display_service(void) //显示的窗口菜单服务程序
- {
- switch(ucWd) //本程序的核心变量,窗口显示变量。类似于一级菜单的变量。代表显示不同的窗口。
- {
- case 1: //显示时间窗口的数据 数据格式 SS FF MM 时 分 秒
- if(ucWd1Update==1) //窗口1要全部更新显示
- {
- ucWd1Update=0; //及时清零标志,避免一直进来扫描
- ucWd1Part1Update=1; //局部时更新显示
- ucWd1Part2Update=1; //局部分更新显示
- }
-
- if(ucWd1Part1Update==1)//局部时更新显示
- {
- ucWd1Part1Update=0;
- ucTemp1=ucHour/10; //时
- ucTemp2=ucHour%10;
- ucDigShow1=ucTemp1; //数码管显示实际内容
- ucDigShow2=ucTemp2;
- }
-
- if(ucWd1Part2Update==1)//局部分更新显示
- {
- ucWd1Part2Update=0;
- ucTemp3=ucMinute/10; //分
- ucTemp4=ucMinute%10;
- ucDigShow3=ucTemp3; //数码管显示实际内容
- ucDigShow4=ucTemp4;
- }
-
- //数码管闪烁
- switch(ucPart) //相当于二级菜单,根据局部变量的值,使对应的参数产生闪烁的动态效果。
- {
- case 0: //都不闪烁
- break;
- case 1: //时参数闪烁
- if(uiDpyTimeCnt==const_dpy_time_half)
- {
- ucDigShow1=ucTemp1; //数码管显示实际内容
- ucDigShow2=ucTemp2;
- }
- else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
- {
- ucDpyTimeLock=1; //原子锁加锁
- uiDpyTimeCnt=0; //及时把闪烁记时器清零
- ucDpyTimeLock=0; //原子锁解锁
- ucDigShow1=10; //数码管显示空,什么都不显示
- ucDigShow2=10;
- }
- break;
-
- case 2: //分参数闪烁
- if(uiDpyTimeCnt==const_dpy_time_half)
- {
- ucDigShow1=ucTemp1; //数码管显示实际内容,显示前两位,
- ucDigShow2=ucTemp2; //目的是上面闪烁后,数码管显示内容会清零
- ucDigShow3=ucTemp3; //数码管显示实际内容
- ucDigShow4=ucTemp4;
- }
- else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
- {
- ucDpyTimeLock=1; //原子锁加锁
- uiDpyTimeCnt=0; //及时把闪烁记时器清零
- ucDpyTimeLock=0; //原子锁解锁
- ucDigShow3=10; //数码管显示空,什么都不显示
- ucDigShow4=10;
- }
- break;
- }
- break;
- case 2:
- if(ucWd2Update==1) //窗口1要全部更新显示
- {
- ucWd2Update=0; //及时清零标志,避免一直进来扫描
- ucWd2Part1Update=1; //局部时更新显示
- ucWd2Part2Update=1; //局部分更新显示
- }
- if(ucWd2Part1Update == 1)
- {
- ucWd2Part1Update = 0;
- ucTemp1=ucSetTimeCnt1/10; //时
- ucTemp2=ucSetTimeCnt1%10;
- ucDigShow1=ucTemp1; //数码管显示实际内容
- ucDigShow2=ucTemp2;
- }
- if(ucWd2Part2Update == 1)
- {
- ucWd2Part2Update = 0;
- ucTemp3=ucSetTimeCnt2/10; //时
- ucTemp4=ucSetTimeCnt2%10;
- ucDigShow3=ucTemp3; //数码管显示实际内容
- ucDigShow4=ucTemp4;
- }
- switch(ucPart) //相当于二级菜单,根据局部变量的值,使对应的参数产生闪烁的动态效果。
- {
- case 0: //都不闪烁
- break;
- case 1: //时参数闪烁
- if(uiDpyTimeCnt==const_dpy_time_half)
- {
- ucDigShow1=ucTemp1; //数码管显示实际内容
- ucDigShow2=ucTemp2;
- }
- else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
- {
- ucDpyTimeLock=1; //原子锁加锁
- uiDpyTimeCnt=0; //及时把闪烁记时器清零
- ucDpyTimeLock=0; //原子锁解锁
- ucDigShow1=10; //数码管显示空,什么都不显示
- ucDigShow2=10;
- }
- break;
-
- case 2: //分参数闪烁
- if(uiDpyTimeCnt==const_dpy_time_half)
- {
- ucDigShow1=ucTemp1; //数码管显示实际内容,这里是为了显示前两位
- ucDigShow2=ucTemp2; //目的是上面闪烁后,数码管显示内容会清零
- ucDigShow3=ucTemp3; //数码管显示实际内容
- ucDigShow4=ucTemp4;
- }
- else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
- {
- ucDpyTimeLock=1; //原子锁加锁
- uiDpyTimeCnt=0; //及时把闪烁记时器清零
- ucDpyTimeLock=0; //原子锁解锁
- ucDigShow3=10; //数码管显示空,什么都不显示
- ucDigShow4=10;
- }
- break;
- }
- break;
- case 3:
- if(ucWd3Update==1) //窗口3要全部更新显示
- {
- ucWd3Update=0; //及时清零标志,避免一直进来扫描
- ucWd3Part1Update=1; //局部时更新显示
- ucWd3Part2Update=1; //局部分更新显示
- }
-
- if(ucWd3Part1Update == 1)
- {
- ucWd3Part1Update = 0;
- if(ucSetTepCnt1>=100)
- {
- ucTemp1 = ucSetTepCnt1/100;
- ucTemp2 = ucSetTepCnt1/10%10;
- ucTemp3 = ucSetTepCnt1%10;
- }
- else
- {
- ucTemp1 = ucSetTepCnt1/10;
- ucTemp2 = ucSetTepCnt1%10;
- ucTemp3 = 10;
- }
- ucDigShow1=ucTemp1; //数码管显示实际内容
- ucDigShow2=ucTemp2; //数码管显示实际内容
- ucDigShow3=ucTemp3; //数码管显示实际内容
- }
- if(ucWd3Part2Update == 1)
- {
- ucWd3Part2Update = 0;
- ucDigShow4 = 11;
- }
- switch(ucPart)
- {
- case 0: break;
- case 1:
- if(uiDpyTimeCnt==const_dpy_time_half)
- {
- ucDigShow1=ucTemp1; //数码管显示实际内容
- ucDigShow2=ucTemp2;
- }
- else if(uiDpyTimeCnt>const_dpy_time_all) //const_dpy_time_all一定要比const_dpy_time_half 大
- {
- ucDpyTimeLock=1; //原子锁加锁
- uiDpyTimeCnt=0; //及时把闪烁记时器清零
- ucDpyTimeLock=0; //原子锁解锁
- ucDigShow1=10; //数码管显示空,什么都不显示
- ucDigShow2=10;
-
- }
- break;
- }
- break;
- case 4:
- if(ucWd4Update==1) //窗口4要全部更新显示
- {
- ucWd4Update=0; //及时清零标志,避免一直进来扫描
- ucWd4Part1Update=1; //局部时更新显示
- ucWd4Part2Update=1; //局部分更新显示
- }
-
- if(ucWd4Part1Update == 1)
- {
- ucWd4Part1Update = 0;
- if(ucAD_value_Tem>=100)
- {
- ucTemp1 = ucAD_value_Tem/100;
- ucTemp2 = ucAD_value_Tem/10%10;
- ucTemp3 = ucAD_value_Tem%10;
- }
- else
- {
- ucTemp1 = ucAD_value_Tem/10;
- ucTemp2 = ucAD_value_Tem%10;
- ucTemp3 = 10;
- }
- ucDigShow1=ucTemp1; //数码管显示实际内容
- ucDigShow2=ucTemp2; //数码管显示实际内容
- ucDigShow3=ucTemp3; //数码管显示实际内容
- }
- if(ucWd4Part2Update == 1)
- {
- ucWd4Part2Update = 0;
- ucDigShow4 = 11;
- }
- break;
- case 5:if(ucWd5Update==1) //窗口5要全部更新显示
- {
- ucWd5Update=0; //及时清零标志,避免一直进来扫描
- ucWd5Part1Update=1; //局部时更新显示
- }
-
- if(ucWd5Part1Update == 1)
- {
- // ucWd5Part1Update = 0;
-
- ucDigShow1=ucTemp1; //数码管显示实际内容
- ucDigShow2=ucTemp2; //数码管显示实际内容
- ucDigShow3=ucTemp3; //数码管显示实际内容
- ucDigShow4=ucTemp4; //数码管显示实际内容
- }
- break;
- case 6:ucDigTimeLock = 1; //不显示小数点
- ucDigShow1=13; //数码管显示实际内容
- ucDigShow2=14; //数码管显示实际内容
- ucDigShow3=15; //数码管显示实际内容
- ucDigShow4=16; //数码管显示实际内容
- break;
- }
- }
- /********************************************************************************************
- 函数名称:按键服务程序
- 功 能:按键处理的事务
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:
- **************************************************************************************************/
- void key_service(void) //按键服务的应用程序
- {
- switch(ucKeySec) //按键服务状态切换
- {
- case 1:// 加按键
- switch(ucWd) //在不同的窗口下,设置不同的参数
- {
-
- case 1:switch(ucPart) //在不同的局部变量下,相当于二级菜单
- {
- case 1: //时
- ucHour++;
-
- if(ucHour>23)
- {
- ucHour=23;
- }
- ucWd1Part1Update=1; //更新显示
- break;
-
- case 2: //分
- ucMinute++;
- if(ucMinute>59)
- {
- ucMinute=59;
- }
- ucWd1Part2Update=1; //更新显示
- break;
- }
- break;
- case 2:
- switch(ucPart)
- {
- case 1:
- ucSetTimeCnt1++;
- if(ucSetTimeCnt1>23)
- {
- ucSetTimeCnt1 = 23;
- }
- ucWd2Part1Update=1; //更新显示
- break;
- case 2:
- ucSetTimeCnt2++;
- if(ucSetTimeCnt2>59)
- {
- ucSetTimeCnt2 = 59;
- }
- ucWd2Part2Update=1; //更新显示
- break;
- }
- break;
- case 3:
- switch(ucPart)
- {
-
- case 1:
- ucSetTepCnt1++;
- if(ucSetTepCnt1>125)
- {
- ucSetTepCnt1 = 125;
- }
- ucWd3Part1Update = 1;
- break;
-
- }
- break;
- }
-
- ucVoiceLock=1; //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
- uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。
- ucVoiceLock=0; //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
- ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一致触发
- break;
-
-
- case 2:// 减按键
- switch(ucWd) //在不同的窗口下,设置不同的参数
- {
- case 1:
- switch(ucPart) //在不同的局部变量下,相当于二级菜单
- {
- case 1: //时
- ucHour--;
- if(ucHour>23)
- {
- ucHour=0;
- }
- ucWd1Part1Update=1; //更新显示
- break;
-
- case 2: //分
- ucMinute--;
- if(ucMinute>59)
- {
- ucMinute=0;
- }
- ucWd1Part2Update=1; //更新显示
- break;
- }
- break;
- case 2:
- switch(ucPart) //在不同的局部变量下,相当于二级菜单
- {
- case 1: //时
- ucSetTimeCnt1--;
- if(ucSetTimeCnt1>23)
- {
- ucSetTimeCnt1=0;
- }
- ucWd2Part1Update=1; //更新显示
- break;
-
- case 2: //分
- ucSetTimeCnt2--;
- if(ucSetTimeCnt2>59)
- {
- ucSetTimeCnt2=0;
- }
- ucWd2Part2Update=1; //更新显示
- break;
- }
- break;
-
- case 3: switch(ucPart)
- {
-
- case 1:
- ucSetTepCnt1--;
- if(ucSetTepCnt1>125)
- {
- ucSetTepCnt1 = 0;
- }
- ucWd3Part1Update = 1;
- break;
-
- }
- break;
- }
-
- ucVoiceLock=1; //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
- uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。
- ucVoiceLock=0; //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
- ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一致触发
- break;
-
- case 3://短按设置按键
- switch(ucWd) //在不同的窗口下,设置不同的参数
- {
-
- case 1:
- if(ucAlarmPrompt == 1) //此时报警启动
- {
- ucAlarmPrompt = 0; //报警关闭
- }
- if(ucPart>0) //在窗口2的时候,要第一次激活设置时间,必须是长按3秒才可以,这里短按激活不了第一次
- {
- ucPart++;
- if(ucPart>2) //设置时间结束
- {
- ucPart=0;
- /* 注释五:
- * 每个月份的天数最大值是不一样的,在写入ds1302时钟芯片内部数据前,应该做一次调整。
- * 有的月份最大28天,有的月份最大29天,有的月份最大30天,有的月份最大31天,
- */
- ucHourBCD=number_to_bcd(ucHour); //原始数值转BCD
- ucMinuteBCD=number_to_bcd(ucMinute); //原始数值转BCD
- ucSecondBCD=number_to_bcd(ucSecond); //原始数值转BCD
- Write1302 (WRITE_PROTECT,0X00); //禁止写保护
- Write1302 (WRITE_HOUR,ucHourBCD); //小时修改
- Write1302 (WRITE_MINUTE,ucMinuteBCD); //分钟修改
- Write1302 (WRITE_SECOND,ucSecondBCD); //秒位修改
- Write1302 (WRITE_PROTECT,0x80); //允许写保护
- }
- ucWd1Update=1; //窗口1更新显示
- }
- break;
- case 2:
- if(ucPart>0)
- {
- ucPart++;
- if(ucPart>2)
- {
- ucPart = 1;
- ucWd=3; //切换到第三个窗口,设置预定时
- ucWd3Update=1; //窗口3更新显示
- }
- }
- break;
- case 3:
- if(ucPart>0)
- {
- ucPart++;
- if(ucPart>1)
- {
- ucPart = 0;
- ucWd = 4; //切换到第四个窗口,
- ucPart = 1;
- ucDigTimeLock = 1; //小数点不显示
- }
- }
- break;
- case 4:
- if(ucPart>0)
- {
- ucPart++;
- if(ucPart>1)
- {
- ucPart = 0;
- ucWd = 1;
- ucWd1Update = 1;
- ucDigTimeLock = 0; //显示小数点
- ucStartheat = 1;//启动加热
- }
- }
- break;
- }
-
- ucVoiceLock=1; //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
- uiVoiceCnt=const_voice_short; //按键声音触发,滴一声就停。
- ucVoiceLock=0; //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
- ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一致触发
- break;
-
- case 4:
- if(ucBootScreen == 0) //开机
- {
- ucWd=1;
- ucWd1Update=1; //窗口1更新显示
- ucDigTimeLock = 0; //显示小数点
- ucBootScreen = 1; //开关标志位置1,为关机做准备
- }
- // if(ucBootScreen == 1)//关机
- // {
- // ucWd=6;
- // ucBootScreen = 0; //开关标志位清零,为开机做准备
- // ucStartheat = 0; //停止加热
- // ucSetTimeCnt1 = 12; //复位默认设的小时
- // ucSetTimeCnt2 = 30; //复位默认设的分钟
- // ucSetTepCnt1 = 50; //复位默认温度值
- // ucPart = 0; //设置清零
- // }
- ucVoiceLock=1; //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
- uiVoiceCnt=const_voice_long; //按键声音触发,滴一声就停。
- ucVoiceLock=0; //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
- ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一致触发
- break;
- case 5:
- if(ucBootScreen == 1)//关机
- {
- ucWd=6;
- ucBootScreen = 0; //开关标志位清零,为开机做准备
- ucStartheat = 0; //停止加热
- ucSetTimeCnt1 = 12; //复位默认设的小时
- ucSetTimeCnt2 = 30; //复位默认设的分钟
- ucSetTepCnt1 = 50; //复位默认温度值
- ucPart = 0; //设置清零
- }
- ucVoiceLock=1; //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
- uiVoiceCnt=const_voice_long; //按键声音触发,滴一声就停。
- ucVoiceLock=0; //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
- ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一致触发
- break;
- case 17://长按3秒设置按键
- switch(ucWd) //在不同的窗口下,设置不同的参数
- {
- case 1:
- if(ucPart==0) //处于非设置时间的状态下,要第一次激活设置时间,必须是长按3秒才可以
- {
- ucWd=2;
- ucPart=1; //进入到设置日期的状态下
- ucWd2Update=1; //窗口1更新显示
- }
- break;
- // case 4:
- // if(ucPart == 0)
- // {
- // ucWd=2;
- // ucPart=1; //进入到设置时间的状态下
- // ucWd2Update=1; //窗口2更新显示
- // }
- // break;
- }
-
- ucVoiceLock=1; //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
- uiVoiceCnt=const_voice_long; //按键声音触发,滴一声就停。
- ucVoiceLock=0; //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
- ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一致触发
- break;
-
- case 18:
- switch(ucWd)
- {
- case 0:break;
- case 2:
- ucPart = 0;
- if(ucPart == 0&& ucStartheat == 0) //处于非设置的情况下,长按设置系统时间
- {
- ucWd = 1;
- ucPart = 1;
- ucWd1Update = 1;
- }
- else if(ucPart == 0&&ucStartheat == 1)
- {
- //处于非设置的情况下,久长按退出定时恒温热水
- ucWd = 1;
- // ucPart = 1;
- ucWd1Update = 1;
- ucStartheat = 0; //停止加热
- ucSetTimeCnt1 = 12; //复位默认设的小时
- ucSetTimeCnt2 = 30; //复位默认设的分钟
- ucSetTepCnt1 = 50; //复位默认温度值
- ucDigTimeLock = 0; //显示小数点
- }
- break;
- }
- ucVoiceLock=1; //原子锁加锁,保护主函数与中断函数的共享变量uiVoiceCnt
- uiVoiceCnt=const_voice_long; //按键声音触发,滴一声就停。
- ucVoiceLock=0; //原子锁解锁,保护主函数与中断函数的共享变量uiVoiceCnt
- ucKeySec=0; //响应按键服务处理程序后,按键编号清零,避免一致触发
-
- break;
- }
- }
- /********************************************************************************************
- 函数名称:DS1302采样程序
- 功 能:读取DS1302的数据
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:系统不用时时刻刻采集ds1302的内部数据,每隔一段时间更新采集一次就可以了。
- 这个间隔时间应该小于或者等于1秒钟的时间,否则在数码管上看不到每秒钟的时间变化。
- **************************************************************************************************/
- void ds1302_sampling(void) //ds1302采样程序,内部每秒钟采集更新一次
- {
- if(ucPart==0) //当系统不是处于设置日期和时间的情况下
- {
- ++uiSampingCnt; //累计主循环次数的时间
- if(uiSampingCnt>const_ds1302_sampling_time) //每隔一段时间就更新采集一次Ds1302数据
- {
- uiSampingCnt=0;
- ucHourBCD=Read1302(READ_HOUR); //读取时
- ucMinuteBCD=Read1302(READ_MINUTE); //读取分
- ucHour=bcd_to_number(ucHourBCD); //BCD转原始数值
- ucMinute=bcd_to_number(ucMinuteBCD); //BCD转原始数值
- ucWd1Update=1; //窗口1更新显示时间
- }
- }
- }
- /********************************************************************************************
- 函数名称:修改DS1302时间的驱动程序
- 功 能:读取DS1302的数据
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:此处写的是BCD码
- **************************************************************************************************/
- void Write1302 ( unsigned char addr, unsigned char dat )
- {
-
- unsigned char i,temp;//单片机驱动DS1302属于SPI通讯方式,根据我的经验,不用关闭中断
- DS1302_CE_dr=0; //CE引脚为低,数据传送中止
- delay_short(1);
- SCLK_dr=0; //清零时钟总线
- delay_short(1);
- DS1302_CE_dr = 1; //CE引脚为高,逻辑控制有效
- delay_short(1);
- for ( i=0; i<8; i++ )//循环8次移位
- {
- DIO_dr_sr = 0;
- temp = addr;
- if(temp&0x01)
- {
- DIO_dr_sr =1;
- }
- else
- {
- DIO_dr_sr =0;
- }
- delay_short(1);
- addr >>= 1; //右移一位
- SCLK_dr = 1;
- delay_short(1);
- SCLK_dr = 0;
- delay_short(1);
- }
- //发送数据
- for ( i=0; i<8; i++ ) //循环8次移位
- {
- DIO_dr_sr = 0;
- temp = dat;
- if(temp&0x01)
- {
- DIO_dr_sr =1;
- }
- else
- {
- DIO_dr_sr =0;
- }
- delay_short(1);
- dat >>= 1; //右移一位
- SCLK_dr = 1;
- delay_short(1);
- SCLK_dr = 0;
- delay_short(1);
- }
- DS1302_CE_dr = 0;
- delay_short(1);
- }
- /********************************************************************************************
- 函数名称:读取DS1302时间的驱动程序
- 功 能:读取DS1302的数据
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:此处读的是BCD码
- **************************************************************************************************/
- unsigned char Read1302 ( unsigned char addr )
- {
- unsigned char i,temp,dat1;
- DS1302_CE_dr=0; //单片机驱动DS1302属于SPI通讯方式,根据我的经验,不用关闭中断
- delay_short(1);
- SCLK_dr=0;
- delay_short(1);
- DS1302_CE_dr = 1;
- delay_short(1);
- for ( i=0; i<8; i++ ) //循环8次移位
- {
- DIO_dr_sr = 0;
- temp = addr;
- if(temp&0x01)
- {
- DIO_dr_sr =1;
- }
- else
- {
- DIO_dr_sr =0;
- }
- delay_short(1);
- addr >>= 1; //右移一位
- SCLK_dr = 1;
- delay_short(1);
- SCLK_dr = 0;
- delay_short(1);
- }
- /********************************************************************************************
- 注 释:51单片机IO口的特点,在读取数据之前必须先输出高电平,
- 如果是PIC,AVR等单片机,这里应该把IO方向寄存器设置为输入
- 时 间:2014-11-11
- **************************************************************************************************/
- DIO_dr_sr =1; //51单片机IO口的特点,在读取数据之前必须先输出高电平,
- temp=0;
- for ( i=0; i<8; i++ )
- {
- temp>>=1;
- if(DIO_dr_sr==1)
- {
- temp=temp+0x80;
- }
- DIO_dr_sr =1; //51单片机IO口的特点,在读取数据之前必须先输出高电平
- delay_short(1);
- SCLK_dr = 1;
- delay_short(1);
- SCLK_dr = 0;
- delay_short(1);
- }
- DS1302_CE_dr=0;
- delay_short(1);
- dat1=temp;
- return (dat1);
- }
- /********************************************************************************************
- 函数名称:BCD转原始数值程序
- 功 能:
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:
- **************************************************************************************************/
- unsigned char bcd_to_number(unsigned char ucBcdTemp) //BCD转原始数值
- {
- unsigned char ucNumberResult=0;
- unsigned char ucBcdTemp10;
- unsigned char ucBcdTemp1;
- ucBcdTemp10=ucBcdTemp;
- ucBcdTemp10=ucBcdTemp10>>4;
- ucBcdTemp1=ucBcdTemp;
- ucBcdTemp1=ucBcdTemp1&0x0f;
- ucNumberResult=ucBcdTemp10*10+ucBcdTemp1;
- return ucNumberResult;
- }
- /********************************************************************************************
- 函数名称:原始数值转换成BCD码
- 功 能:
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:
- **************************************************************************************************/
- unsigned char number_to_bcd(unsigned char ucNumberTemp) //原始数值转BCD
- {
- unsigned char ucBcdResult=0;
- unsigned char ucNumberTemp10;
- unsigned char ucNumberTemp1;
- ucNumberTemp10=ucNumberTemp;
- ucNumberTemp10=ucNumberTemp10/10;
- ucNumberTemp10=ucNumberTemp10<<4;
- ucNumberTemp10=ucNumberTemp10&0xf0;
- ucNumberTemp1=ucNumberTemp;
- ucNumberTemp1=ucNumberTemp1%10;
- ucBcdResult=ucNumberTemp10|ucNumberTemp1;
- return ucBcdResult;
- }
- /********************************************************************************************
- 函数名称:DS1302备用电池电量用完报警程序
- 功 能:DS1302备用电池电量用完后,蜂鸣器在0.5S发也鸣叫
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:
- **************************************************************************************************/
- void ds1302_alarm_service(void) //ds1302出错报警
- {
- if(ucDs1302Error==1) //备用电池的电量用完了报警提示
- {
- if(uiDs1302Cnt>const_ds1302_0_5s) //大概0.5秒钟蜂鸣器响一次
- {
- ucDs1302Lock=1; //原子锁加锁
- uiDs1302Cnt=0; //计时器清零
- uiVoiceCnt=const_voice_short; //蜂鸣器声音触发,滴一声就停。
- ucDs1302Lock=0; //原子锁解锁
- }
- }
- }
- /********************************************************************************************
- 函数名称:热水完毕报警程序
- 功 能:热水完毕后,发出报警声
- 返 回 值:无
- 时 间:2014-11-14
- 备 注:
- **************************************************************************************************/
- void ucAlarmPrompt_service()
- {
- static unsigned int uiAlarmPromptCnt; //报警延时计数器
- static unsigned char ucNumberCnt; //报警次数计数器
- static unsigned int const_time_2s = 400; //报警的时间间隔
- static unsigned int const_voice_AlarmPrompt = 200;
- if(ucAlarmPrompt == 1) //报警标志位置位后报警
- {
- uiAlarmPromptCnt++; //报警延时计数器自加1
- if(uiAlarmPromptCnt>const_time_2s) //2S发出报警声音
- {
- uiAlarmPromptCnt = 0; //报警延时计数器清零
- uiVoiceCnt=const_voice_AlarmPrompt; //
- ucNumberCnt++; //报警次数计数器加1
-
- if(ucNumberCnt == 5) //报警次数为10次
- {
- ucNumberCnt = 0; //报警次数计数器清零
- ucAlarmPrompt = 0; //关闭报警
- }
- }
- }
- }
- /********************************************************************************************
- 函数名称:数码管显示驱动程序
- 功 能:显示对应的时间
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:
- **************************************************************************************************/
- void display()
- {
- switch(ucDigStep) //步骤变量
- {
- case 1:
- P0 = array[ucDigShow1]; //第一位数码管显示的内容
- dig1_dr = 0;
- delay(10);
- dig1_dr = 1;
- ucDigStep = 2;
- break;
- case 2:
- P0 = array[ucDigShow2]; //第二位数码管显示的内容
- dig2_dr = 0;
- delay(10);
- dig2_dr = 1;
- ucDigStep = 3;
- break;
- case 3:
- P0 = array[ucDigShow3]; //第三位数码管显示的内容
- dig3_dr = 0;
- delay(10);
- dig3_dr = 1;
- ucDigStep = 4;
- break;
- case 4:
- P0 = array[ucDigShow4]; //第四位数码管显示的内容
- dig4_dr = 0;
- delay(10);
- dig4_dr = 1;
- ucDigStep =1;
- break;
- }
- }
- /********************************************************************************************
- 函数名称:热水时间和温度数据对比
- 功 能:将设定的时间于当前的时间作对比,数据正确执行。
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:
- **************************************************************************************************/
- void TimeData_contrast()
- {
- static unsigned char preser_heat = 0; //保温标志位
- static unsigned char ucCheakFault = 0; //故障检查标志位
- static unsigned char ucTimeEqual = 0; //设定时间相等的标志位
- static unsigned char ucTimeAfter = 0; //两分钟前的时间
- static unsigned char ucTepAfter = 0; //两分钟前的时间
- if(ucStartheat == 1&&ucPart == 0) //开始预设加热标志
- {
- if((ucHour == ucSetTimeCnt1) && (ucMinute == ucSetTimeCnt2)&&ucTimeEqual == 0) //设定的时间相等
- {
- // ucStartheat = 1;//启动加热标志位
- ucWd = 4; //更新到窗口4,显示温度
- ucWd4Update = 1;
- ucDigTimeLock = 1; //小数点不显示
- relay_dr = 1; //继电器输出高(吸合)
- ucCheakFault = 1;//故障检查
- ucTimeEqual = 1;//时间对比完成
- ucTimeAfter = 0;//先对变量清零
- ucTepAfter = 0;//先对变量清零
- ucTimeAfter = ucMinute;
- ucTepAfter = ucAD_value_Tem;
- // ucAlarmPrompt = 1; //故障报警
- }
- if(ucCheakFault == 1&&(ucTimeAfter+3) == ucMinute)
- {
- if(ucAD_value_Tem>=(ucTepAfter+2))
- {
- ucCheakFault = 0; //故障检测清零,只做一次检测
- ucTimeEqual = 0;//时间对比完成标志清零,为下一次做准备
- }
- else
- {
- relay_dr = 0; //继电器输出(断开)
- ucWd = 5; //更新到窗口5,显示错误代码E001
- ucWd5Update = 1;
- ucTemp1 = 12; //E
- ucTemp2 = 0; //0
- ucTemp3 = 0; //0
- ucTemp4 = 1; //1
- ucDigTimeLock = 1; //小数点不显示
- ucAlarmPrompt = 1; //故障报警
- ucCheakFault = 0; //故障检测清零,只做一次检测
- ucStartheat = 0; //检测到有故障,停止加热
- }
-
- }
- if(ucAD_value_Tem>=ucSetTepCnt1) //设定到加热温度相等
- {
- ucStartheat = 0;//停止预设加热标志
- relay_dr = 0; //继电器输出(断开)
- // ucCheakFault = 0;//故障检查标志清零,为下一次做准备
- ucAlarmPrompt = 1; //报警标志位置1,启动报警
- preser_heat = 1; //执行保温标志位,开始进行保温
- ucWd = 1; //切换到窗口1显示时间
- ucWd1Update = 1;//更新窗口1
- ucDigTimeLock = 0; //显示小数点
- }
- }
-
- if(preser_heat == 1) //保温程序,开始执行
- {
- if((ucSetTepCnt1-5) >= ucAD_value_Tem)
- {
- relay_dr = 1; //继电器输出
- ucWd = 4; //切换到窗口4显示时间
- ucWd4Update = 1;//更新窗口4
- ucDigTimeLock = 1; //不显示小数点
- }
- if((ucSetTepCnt1+5) <= ucAD_value_Tem)
- {
- relay_dr = 0; //继电器输出
- ucWd = 1; //切换到窗口1显示时间
- ucWd1Update = 1;//更新窗口1
- ucDigTimeLock = 0; //显示小数点
- }
- }
- }
- /********************************************************************************************
- 函数名称:ADC采样程序
- 功 能:读取ADC0832转换后的数据
- 返 回 值:
- 时 间:2014-11-24
- 备 注:
- **************************************************************************************************/
- void ADC_sampling_service()
- {
- static unsigned char i = 0; //读取数据8位的次数变量
- static unsigned char ucADC; //AD值
- static unsigned char ucCheckADC; //校验的AD值
- static unsigned int ucTemp; //参与换算的中间变量
- static unsigned int uiTempFilterV=0; //参与换算的中间变量
- // static unsigned long ulBackupFilterV=255; //备份最新采样数据的中间变量
- // static unsigned int uiTimpFilterTep = 0;
- static unsigned char wendu;
- static unsigned int Adresult;
- static unsigned char ucSamplingCnt=0; //统计采样的次数 本程序采样8次后求平均值
- adc0832_CS_dr = 0; //使能端置低
- adc0832_DI_sr_dr = 1; //起始位
- adc0832_CLK_dr = 0; //输出低电平
- delay_short(1); //小延时
- adc0832_CLK_dr = 1; //输出高电平
- adc0832_DI_sr_dr = 1; //选择通道,输出数据1
- adc0832_CLK_dr = 0;
- adc0832_CLK_dr = 1;
- adc0832_DI_sr_dr = 0; //选择通道。输出数据0
- adc0832_CLK_dr = 0;
- adc0832_CLK_dr = 1;
- adc0832_DI_sr_dr = 1; //拉高数据线
- delay_short(2); //延时
- adc0832_CLK_dr = 1; //一个下降延
- adc0832_CLK_dr = 0;
- delay_short(1);
- for(i = 0;i<8;i++) //读取8位
- {
- ucADC <<= 1;
- adc0832_CLK_dr = 1;
- adc0832_CLK_dr = 0;
- if(adc0832_DI_sr_dr == 1)
- {
- ucADC |= 0x01;
- }
- }
- for(i=0;i<8;i++) //读取校验位
- {
- ucCheckADC >>= 1;
- if(adc0832_DI_sr_dr == 1)
- {
- ucCheckADC |= 0x80;
- }
- adc0832_CLK_dr = 1;
- adc0832_CLK_dr = 0;
- }
-
- adc0832_CS_dr = 1; //拉高使能端
- if(ucADC == ucCheckADC) //校验两个读取的数据是否一致
- {
- ucTemp=ucADC; //把char类型数据赋值给long类型数据,参与乘除法运算的数据,为了避免运算结果溢出,我都用long类型
- uiTempFilterV=uiTempFilterV+ucTemp; //累加8次后求平均值
- ucSamplingCnt++; //统计已经采样累计的次数
- if(ucSamplingCnt>=8)
- {
- /* 注释二:
- * 求平均值滤波法,为了得到的数据更加圆滑,去除小毛刺。
- * 向右边移动3位相当于除以8。
- */
- // uiTempFilterV=uiTempFilterV>>3; //求平均值滤波法
- Adresult=(255000/uiTempFilterV)-100;//求得当前温度对应的阻值,十欧为单位,此公式的演变请看上述详细说明
- // if(ulBackupFilterV>=20) //最近备份的上一次数据大于等于0.02V的情况下
- // {
- // if(Adresult<(ulBackupFilterV-5)||Adresult>(ulBackupFilterV+5)) //在正负0.020V偏差范围外,更新
- // {
- // ulBackupFilterV=Adresult; //备份最新采样的数据,方便下一次对比判断
- // uiTimpFilterTep=Adresult; //得到经过滤波处理的实时电压值
- //// ucWd4Part1Update=1; //局部更新显示经过滤波处理的电压
- // }
- // }
- // else //最近备份的上一次数据小于0.02V的情况下
- // {
- // if(uiTempFilterV>(ulBackupFilterV+2)) //在正0.020V偏差范围外,更新
- // {
- // ulBackupFilterV=Adresult; //备份最新采样的数据,方便下一次对比判断
- // uiTimpFilterTep=Adresult; //得到经过滤波处理的实时电压值
- //// ucWd4Part1Update=1; //局部更新显示经过滤波处理的电压
- // }
- //
- // }
- wendu = 0;//清零
- while(1)
- {
- if(Adresult>=wendu_tab[wendu])
- {
- break;
- }
- wendu++;
- if(wendu>=105)
- {
- wendu = 105;
- break;
- }
-
- }
- ucAD_value_Tem = wendu;
- ucSamplingCnt=0; //清零,为下一轮采样滤波作准备。
- uiTempFilterV=0;
- }
-
- }
- else
- {
- ucADC = 0; //两次读取的数据不一致,就把数据清零
- ucAD_value_Tem = wendu;
- }
- ucWd4Update = 1;//更新窗口4
- }
- /********************************************************************************************
- 函数名称:定时器中断程序
- 功 能:
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:
- **************************************************************************************************/
- void T0_time() interrupt 1
- {
- TF0=0; //清除中断标志
- TR0=0; //关中断
- display(); //数码管显示放在中断里
- key_scan(); //按键扫描放在中断里
- /********************************************************************************************
- 功 能:按键去抖动延时计数器在外部可以关闭,不开启计时功能
- 时 间:2014-11-11
- **************************************************************************************************/
- if(ucKeyStartFlag1==1) //启动计数器
- {
- if(uiKeyTimeCnt1<0xffff)//防止计数器超出范围
- {
- uiKeyTimeCnt1++; //按键去抖动延时计数器自加1
- }
- }
- /********************************************************************************************
- 功 能:按键去抖动延时计数器在外部可以关闭,不开启计时功能
- 时 间:2014-11-11
- **************************************************************************************************/
- if(ucKeyStartFlag2==1) //启动计数器
- {
- if(uiKeyTimeCnt2<0xffff) //防止计数器超出范围
- {
- uiKeyTimeCnt2++; //按键去抖动延时计数器自加1
- }
- }
- /********************************************************************************************
- 功 能:按键去抖动延时计数器在外部可以关闭,不开启计时功能
- 时 间:2014-11-11
- **************************************************************************************************/
- if(ucKeyStartFlag3==1) //启动计数器
- {
- if(uiKeyTimeCnt3<0xffff) //防止计数器超出范围
- {
- uiKeyTimeCnt3++; //按键去抖动延时计数器自加1
- }
- }
- /********************************************************************************************
- 功 能:按键去抖动延时计数器在外部可以关闭,不开启计时功能
- 时 间:2014-11-11
- **************************************************************************************************/
- if(ucKeyStartFlag4==1) //启动计数器
- {
- if(uiKeyTimeCnt3<0xffff) //防止计数器超出范围
- {
- uiKeyTimeCnt4++; //按键去抖动延时计数器自加1
- }
- }
- /********************************************************************************************
- 功 能:间歇性蜂鸣器报警计数器在外部可以关闭,不开启计时功能
- 时 间:2014-11-11
- **************************************************************************************************/
- if(ucDs1302Error>0) //EEPROM出错
- {
- if(ucDs1302Lock==0)//原子锁判断
- {
- uiDs1302Cnt++; //间歇性蜂鸣器报警的计时器
- }
- }
- /********************************************************************************************
- 功 能:蜂鸣器驱动放在中断里面
- 时 间:2014-11-11
- **************************************************************************************************/
- if(uiVoiceCnt!=0) //蜂鸣器
- {
- uiVoiceCnt--; //每次进入定时中断都自减1,直到等于零为止。才停止鸣叫
- beep_dr = 0; //蜂鸣器是PNP三极管控制,低电平就开始鸣叫
- }
- else
- {
- beep_dr = 1; //蜂鸣器是PNP三极管控制,高电平就停止鸣叫。
- }
- TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f
- TL0=0x2f;
- EA = 1;
- ET0 = 1;
- TR0=1; //开中断
- }
- /********************************************************************************************
- 函数名称:定时器初始化程序
- 功 能:
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:
- **************************************************************************************************/
- void T0_init()
- {
- TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f
- TL0=0x2f;
- EA = 1;
- ET0 = 1;
- TR0=1; //开中断
- /* 注释七:
- * 检查ds1302芯片的备用电池电量是否用完了。
- * 在上电的时候,在一个特定的地址里把数据读出来,如果发现不等于0x5a,
- * 则是因为备用电池电量用完了,导致保存在ds1302内部RAM数据区的数据被更改,
- * 与此同时,应该重新写入一次0x5a,为下一次通电判断做准备
- */
- ucCheckDs1302=Read1302(READ_CHECK); //判断ds1302内部的数据是否被更改
- if(ucCheckDs1302!=0x5a)
- {
- Write1302 (WRITE_PROTECT,0X00); //禁止写保护
- Write1302 (WRITE_CHECK,0x5a); //重新写入标志数据,方便下一次更换新电池后的判断
- Write1302 (WRITE_PROTECT,0x80); //允许写保护
- ucDs1302Error = 1; //1表示报警启动
- ucWd = 5; //更新到窗口5,显示错误代码E001
- ucWd5Update = 1;
-
- ucTemp1 = 12; //E
- ucTemp2 = 0; //0
- ucTemp3 = 0; //0
- ucTemp4 = 2; //1
-
- ucDigTimeLock = 1; //小数点不显示
- }
- }
- /********************************************************************************************
- 函数名称:初始化单片机内部和外部IO口
- 功 能:
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:
- **************************************************************************************************/
- void initial_myself(void) //第一区 初始化单片机
- {
- beep_dr=1; //用PNP三极管控制蜂鸣器,输出高电平时不叫。
- relay_dr = 0;
- dig1_dr = 1;
- dig2_dr = 1;
- dig3_dr = 1;
- dig4_dr = 1;
- delay_long(30);
- }
- /********************************************************************************************
- 函数名称:延时程序
- 功 能:
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:
- **************************************************************************************************/
- void delay(unsigned int delay_ms) //延时函数
- {
- unsigned int i,j;
- for(i = delay_ms;i>0;i--)
- for(j = 10;j>0;j--);
- }
- /********************************************************************************************
- 函数名称:延时程序
- 功 能:
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:
- **************************************************************************************************/
- void delay_short(unsigned int uiDelayShort)
- {
- unsigned int i;
- for(i=0;i<uiDelayShort;i++)
- {
- ; //一个分号相当于执行一条空语句
- }
- }
- /********************************************************************************************
- 函数名称: 延时程序
- 功 能:
- 返 回 值:无
- 时 间:2014-11-11
- 备 注:
- **************************************************************************************************/
- void delay_long(unsigned int uiDelayLong)
- {
- unsigned int i;
- unsigned int j;
- for(i=uiDelayLong;i>0;i--)
- for(j=50;j>0;j--); //内嵌循环的空指令数量
- }
复制代码
由于水平能力有限,纰漏之处,还望各位读者指出。。。。。。。
|
评分
-
查看全部评分
|