基于51单片机ds1302时钟、ds18b20的恒温器

 

                                                                  基于51单片机ds1302时钟、ds18b20的恒温器

​                                                                                  广西河池学院                                            

                                                                       广西高校重点实验室培训基地                                                   

                                                                     系统控制与信息处理重点实验室                                     

                                                         本篇博客来自河池学院:OpenWRT无线路由组                                        

                                                                  写作时间:2020年8月12日22:00:00
 

 

首先要感谢学长学姐们在制作项目的时间里指导,期间遇到许多的问题,有的得到了解决,有的实在解决不了的只能另选方法,在问题中发现、学习和吸取教训才重要:

       第一:做一个工程项目前,一定要设计和规划好项目,要明确达到什么功能,有目标的去做。

       第二:一定要建好单独项目文件,不要混在一起,工程名尽量使用英文命名,中文命名有几率会使工程无法使用或出现故障。

       第三:在使用多个模块时,要注意各个模块使用的引脚是否重复,例如:LED灯、蜂鸣器同时无法与12864液晶显示屏使用,可能是由于LED灯所使用的P2端口与12864的使能信号端、读/写选择端、数据/命令选择端冲突。

       第四:使用模块时,要仔细辨认器件是否插入正确,若插反器件极易发烫、烧坏,损坏元器件。

       第五:使用函数封装,程序简洁明了,使用简便。

 

项目:基于51单片机ds1302时钟、ds18b20的恒温器

 

所需模块:51单片机,STC15F2K60S2,DS1302时钟芯片,DS18B20温度传感器,LCD12864,矩阵按键,独立按键,蜂鸣器,LED

如图:

基于51单片机ds1302时钟、ds18b20的恒温器

 

功能说明:

  1. 采用STC15F2K60S2芯片、DS1302时钟芯片、DS18B20温度传感器,LCD12864、独立按键,矩阵键盘。
  2. 开机进入第一界面,显示时间,作者。
  3. 第二界面显示实时温度,上下限,以及温度显示是否正常提示。
  4. 按下第三个独立按键则进入第三界面,显示时间,时间不会因为切换界面而从新开始,并可以后台提供温度报警。

 

运行流程:

 

①开机问候,时间显示在12864上,温度在上下限范围时仅亮三个led灯作为待机指示,当温度超出设定范围时则led全亮,蜂鸣器也开始响,开始声光报警。

②第一界面显示时间,可通过矩阵键盘调节年、月、日、时、分。(秒不必要调)按下第一个独立按键就跳到第二界面,采用DS18B20+12864显示温度和上下限值 。按下第三个独立按键跳回第一界面继续走时,即在第非时间显示界面时,时间在后台正常走。温度达到限值则触发流水灯闪亮与蜂鸣器鸣叫,同时在界面底部显示“温度超出范围”,温度在范围内则显示“温度稳定”。

从新切回到时间界面时,温度仍然实时监测,只是在最后一行显示“温度超出范围”或“温度稳定”。

④时间,温度报警可以同时起作用。

 

效果展示:

(拍照太快,时间还没有显示)

基于51单片机ds1302时钟、ds18b20的恒温器

(温度正常时)

基于51单片机ds1302时钟、ds18b20的恒温器

(温度报警时)

基于51单片机ds1302时钟、ds18b20的恒温器

(时间持续走)

基于51单片机ds1302时钟、ds18b20的恒温器

 

供电方式:

USB直连或外接电池组。

 

用途:

家居日常

 

提高:

完成上述功能后,可以添加其他模块,如温湿度传感器,红外接收修改报警范围,以扩展恒温器用途与便捷性。

 

附:

 

/**************LCD12864上显示时钟、实时温度、报警温度上下限*************************
原创于河池学院OpenWRT无线路由组:小蔡
显示屏第一页为时钟,可用矩阵按键来控制年月日时分秒的值。
独立按键可以实现翻页功能,当由时钟页面跳到报警器页面时,时钟的值依旧跳动
第二页为温度报警器,可用独立按键调节温度上限,矩阵按键调节温度下限,
当温度高于上限值或者低于下限值时,显示屏出现“温度超出范围”,并拉响蜂鸣,LED灯闪烁以达到报警效果。
若温度正常,显示屏将显示“温度稳定”;
*********************************************************************************/

#include "DS18B20.H"
#include "LCD12864.H"
#include "DS1302.h"
#include <stdio.h>


uchar table1[]="当前温度        ";
uchar table2[]="上限值        度";
uchar table3[]="下限值        度";
uchar table4[]="  温度超出范围  ";
uchar table5[]="    温度稳定    ";


unsigned char Time_buf[8]={0x20,0x00,0x00,0x00,0x15,0x08,0x03,0x20};//年,秒,分,时,日,月,星期,年


sbit BUZZ = P1^1;     //定义蜂鸣器引脚

sbit key1 = P3^2;     //独立按键右一切换到温度显示界面
sbit key2 = P3^3;      //上限加一
sbit key3 = P3^4;   //左一切换到时间界面
sbit key4 = P3^5;        //上限减一

/*================================================================================
                                按键调节时间
=================================================================================*/
void SetTime(void)
{
    
                    uint i;
                    switch(array())                                //矩阵按键扫描
                    {
                        
                        case 0:    Time_buf[7] = Time_buf[7] + 0x01;break;            //年+
                        case 1: Time_buf[5] = Time_buf[5] + 0x01;break;     //月+
                        case 2: Time_buf[4] = Time_buf[4] + 0x01;break;     //日+
                        case 8:    Time_buf[3] = Time_buf[3] + 0x01;break;     //时+
                        case 9: Time_buf[2] = Time_buf[2] + 0x01;break;     //分+
                                
                        case 4:    Time_buf[7] = Time_buf[7] - 0x01;break;            //年-
                        case 5: Time_buf[5] = Time_buf[5] - 0x01;break;     //月-
                        case 6: Time_buf[4] = Time_buf[4] - 0x01;break;     //日-
                        case 12:Time_buf[3] = Time_buf[3] - 0x01;break;     //时-
                        case 13:Time_buf[2] = Time_buf[2] - 0x01;break;     //分-

                        default:;
                }
        
                    for( i = 0; i < 8;i++)
            {
                        if( (Time_buf[i] & 0x0F) > 9)
                    {
                        Time_buf[i] = ((Time_buf[i]+0x10)&0xF0);
                    }
            }
        
                DS1302_Data_Input(DS1302_CONTROL_ADD,0x00);                //关闭写保护

                DS1302_Data_Input(DS1302_MIN_ADD,Time_buf[2]);        //分
                DS1302_Data_Input(DS1302_HR_ADD,Time_buf[3]);            //时
                DS1302_Data_Input(DS1302_DAY_ADD,Time_buf[4]);        //日
                DS1302_Data_Input(DS1302_MONTH_ADD,Time_buf[5]);    //月
                DS1302_Data_Input(DS1302_YEAR_ADD,Time_buf[7]);        //年

                DS1302_Data_Input(DS1302_CONTROL_ADD,0x80);                //打开写保护
        
}
    
/*================================================================================
                               主函数
=================================================================================*/
void main()
{
                unsigned char sec_buf = 0x00;    //用来保存上一次的秒数
                uint i,z;
                int hight=27,low=25;  //定义上限为27度,下限为20度。
                uchar L, H;
                init_12864();                   //12864初始化
            
                DS1302_Init();                    //DS1302初始化
                DS1302_Write_Time();            //初始化数据
    

        
                print(4,0,"  祝你生活愉快  ");
    get:    print(1,0,"    年  月  日");
                print(2,0,"    时  分  秒");
                print(3,0,"华人牌温度报警器");
    
    
/*----------------------------------------------------------------------------------    
                                 时间显示
----------------------------------------------------------------------------------*/
            while(1)
        {
                    DS1302_Read_Time();

            
                    SetTime(); //设定时间
            
             if(Time_buf[1] != sec_buf)                    //当前时间与原来时间不同
                {    
                      sec_buf = Time_buf[1];                        //把当前的秒数赋值给临时变量
            display_int(1,0,ChangeTime(Time_buf[0]));
            display_int(1,1,ChangeTime(Time_buf[7]));        //年
            display_int(1,3,ChangeTime(Time_buf[5]));   //月
                  display_int(1,5,ChangeTime(Time_buf[4]));   //日
            display_int(2,1,ChangeTime(Time_buf[3]));   //时
            display_int(2,3,ChangeTime(Time_buf[2]));   //分
                  display_int(2,5,ChangeTime(Time_buf[1]));        //秒
                    
                }
                
                if(key1 == 0)
                {
                        init_12864();
                        break;//按下切换到温度显示界面
                }
        }

//-----------------------------------------------------------
//-----------------------------------------------------------
                    //作用:    将三行汉子固定显示,不刷新
                    display(1,0,&table1);  //在第1行显示
                    display(2,0,&table2);
                    display(3,0,&table3);
        
        
        
        
/*----------------------------------------------------------------------------------
                                  温度显示
----------------------------------------------------------------------------------*/
            while(1)
        {

                            Init_DS18B20();              //初始化DS18B20
                            Write_Byte(0xcc);          //发送跳跃ROM指令
                            Write_Byte(0x44);          //发送温度转换指令
                            Init_DS18B20();              //初始化DS18B20
                            Write_Byte(0xcc);          //发送跳跃ROM指令
                            Write_Byte(0xbe);         //读取DS18B20暂存器值
                            L = Read_Byte();          //读高速暂存器的byte0(低字节,二进制数)
                            H = Read_Byte();     //读高速暂存器的byte1(高字节,二进制数)
                            i = H;                      //低8位赋值给i
                            i <<= 8;                    // 低8位的数据整体左移8位
                            i |= L;                      // 高8位的数据填充低8位移走的空位,组成16位的二进制赋值给i
                            i = i * 0.0625 * 10 + 0.5;  //读到的二进制数据转换温度的算法
            
                            LcdDisplay(i); //温度显示函数
                            LcdDisplay_hight(hight);
                            LcdDisplay_low(low);
            
                if((i>=hight*10)|(i<=low*10)) //温度高于上限就报警
                    {

                                display(4,0,&table4);
                                for(z = 0;z<5;z++)
                                {                                            
                                            BUZZ = 0;    //拉低蜂鸣器响
                                        //    P2=1;//会出错,啥原因暂不晓得....
                                            Delay50ms();
                                            BUZZ =~BUZZ;
                                        //    P2=~P2;//会出错,啥原因暂不晓得....
                                            Delay50ms();
                           }
                                     
                                P2=1;
                                Delay50ms();
                                P2=~P2;
                            Delay50ms();
        }
                    
            else
                    {
                                
                                display(4,0,&table5);
                    }
                                        
//---------------------------------------------------------------------
//按键调上限
                                
                    
                    if(key2==0)    //当key2按下一次时,上限温度加一,一直按一直加
                                    {
                                        hight++;
                                        }
                    if(key4==0)   //当key4按下一次时,上限温度减一,一直按一直减
                                    {
                                            hight--;
                                    }
//-----------------------------------------------------------------------
//调下限
                                        
                    if(array()==11)    //当key11按下一次时,下限温度加一,一直按一直加
                                        {
                                                low++;
                                        }
                    if(array()==15)   //当key15按下一次时,下限温度减一,一直按一直减
                                        {
                                                low--;
                                        }
//--------------------------------------------------------------------
//跳回时间
                                        
            if(key3 == 0)//按下切换到时间显示界面,但不初始化时间,接着开机时计算(后台走时)
                {
                        init_12864 ();
                        goto get;
                    //    break;
                }
            }
        }

.........................

        文章限制,需要请复制至网盘下载完整代码。