视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
DS18B20+LCD1602+AT24C02智能温度控制系统
2025-10-03 15:09:22 责编:小OO
文档


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

                          智能温控器

问题描述:当温控开关打开时,若测得环境温度大于设定温度,则继电器吸合

          ,启动压缩机工作;若测得环境温度小于设定温度,则继电器释放,

          压缩机停止工作。

          该实验可以应用于对温度控制精度要求不是很高的场合,例如,粮仓,

          电冰箱,空调,电饭锅等。如果配以通讯接口,可以做成多点温度检

          测监控系统。具有极强的扩展性。

注意: 此文档为仿真程序,若要在试验板上验证,需要须改一下函数

        

void lcd_wait(void)

{

    DATAPORT=0xff;         

    LCM_EN=1;

    LCM_RS=0;               

    LCM_RW=1;               

    _nop_();

    while(DATAPORT&BUSY);

       LCM_EN=0;

    

}

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

#include

#include

#include

#define uchar unsigned char

#define uint   unsigned int

#define BUSY  0x80                               //lcd忙检测标志

#define DATAPORT P0                              //定义P0口为LCD通讯端口

#define PLAYE_ADDR XBYTE[0XBFFF]                 //语音报警地址

sbit RED_ALARM=P1^0;                                //红色指示灯

sbit WRITE_ALARM=P1^1;                          //白色指示灯

sbit GREEN_ALARM=P1^2;                          //绿色指示灯

sbit BLUE_ALARM=P1^3;

sbit P1_4=P1^4;                                    //时钟调整

sbit P1_5=P1^5;                                 //时钟加

sbit P1_6=P1^6;                                 //时钟减

sbit DQ = P1^7;                                 //定义ds18b20通信端口 

sbit LCM_RS=P2^0;                                //数据/命令端

sbit LCM_RW=P2^1;                                //读/写选择端

sbit LCM_EN=P2^2;

sbit sda=P2^3;                          //IO口定义

sbit scl=P2^4;                              //LCD使能信号

sbit ad_busy=P3^2;                              //adc中断方式接口

sbit RECLED_EOC=P3^5;                           //ISD1420放音结束查询标志

sbit OUT=P3^7;

uchar ad_data;                                  //ad采样值存储                        

uchar seconde;                                //定义并初始化时钟变量

uchar minite;

uchar hour;

uchar mstcnt=0;

uchar temp1,temp2,temp;                         //温度显示变量

uchar t,set;

uchar K;

bit ON_OFF=0;

bit outflag;

bit write=0;

uchar code str0[]={"---  :  :  ---  "};

uchar code str1[]={"SET:  C SA:  . C"};

void delay_LCM(uint);                                                         //LCD延时子程序

void initLCM( void);                                                           //LCD初始化子程序

void lcd_wait(void);                                                          //LCD检测忙子程序

void WriteCommandLCM(uchar WCLCM,uchar BusyC);                              //写指令到ICM子函数

void WriteDataLCM(uchar WDLCM);                                             //写数据到LCM子函数

void DisplayOneChar(uchar X,uchar Y,uchar DData);                           //显示指定坐标的一个字符子函数

void DisplayListChar(uchar X,uchar Y,uchar code *DData);                    //显示指定坐标的一串字符子函数

void init_timer0(void);                                                       //定时器初始化

void displayfun1(void);

void displayfun2(void);

void displayfun3(void);

void displayfun4(void);

void keyscan(void );                                                        //键盘扫描子程序

void set_adj(void);

void inc_key(void);

void dec_key(void);

void delay_18B20(unsigned int i);

void Init_DS18B20(void) ;

uchar ReadOneChar(void);

void WriteOneChar(unsigned char dat);

void ReadTemperature(void);

void ad0809(void);

void playalarm(void); 

/*********延时K*1ms,12.000mhz**********/

void delay_LCM(uint k)

{

    uint i,j;

for(i=0;i    {

for(j=0;j<60;j++)

            {;}

    }

}   

/**********写指令到LCM子函数************/

void WriteCommandLCM(uchar WCLCM,uchar BusyC)

{

    if(BusyC)lcd_wait();

    DATAPORT=WCLCM;

    LCM_RS=0;                   // 选中指令寄存器

    LCM_RW=0;                   // 写模式    

    LCM_EN=1;    

    _nop_();   

    _nop_();

    _nop_(); 

    LCM_EN=0;  

}

/**********写数据到LCM子函数************/

void WriteDataLCM(uchar WDLCM)

    lcd_wait( );            //检测忙信号    

    DATAPORT=WDLCM;

    LCM_RS=1;               // 选中数据寄存器

    LCM_RW=0;               // 写模式

    LCM_EN=1;

    _nop_();

    _nop_();

    _nop_();

    LCM_EN=0;

}

/***********lcm内部等待函数*************/

void lcd_wait(void)

{

    DATAPORT=0xff;         

    LCM_EN=1;

    LCM_RS=0;               

    LCM_RW=1;               

    _nop_();

    while(DATAPORT&BUSY)

    {  LCM_EN=0;

       _nop_();

       _nop_();

       LCM_EN=1;

       _nop_();

       _nop_();

       }

       LCM_EN=0;

    

}

/**********LCM初始化子函数***********/

void initLCM( )

{   

    DATAPORT=0;    

    delay_LCM(15);

    WriteCommandLCM(0x38,0);    //三次显示模式设置,不检测忙信号

    delay_LCM(5); 

    WriteCommandLCM(0x38,0);

    delay_LCM(5); 

    WriteCommandLCM(0x38,0);

    delay_LCM(5); 

    WriteCommandLCM(0x38,1);    //8bit数据传送,2行显示,5*7字型,检测忙信号

    WriteCommandLCM(0x08,1);    //关闭显示,检测忙信号

    WriteCommandLCM(0x01,1);    //清屏,检测忙信号

    WriteCommandLCM(0x06,1);    //显示光标右移设置,检测忙信号

    WriteCommandLCM(0x0c,1);    //显示屏打开,光标不显示,不闪烁,检测忙信号

}

/****************显示指定坐标的一个字符子函数*************/

void DisplayOneChar(uchar X,uchar Y,uchar DData)

{

    Y&=1;

    X&=15;

    if(Y)X|=0x40;               //若y为1(显示第二行),地址码+0X40

    X|=0x80;                    //指令码为地址码+0X80

    WriteCommandLCM(X,0);

    WriteDataLCM(DData);

}

/***********显示指定坐标的一串字符子函数***********/

void DisplayListChar(uchar X,uchar Y,uchar code *DData)

{

    uchar ListLength=0;

    Y&=0x01;

    X&=0x0f;

while(X<16)

    {

        DisplayOneChar(X,Y,DData[ListLength]);

        ListLength++;

        X++;

    }

}

/***********ds18b20延迟子函数(晶振12MHz )*******/ 

void delay_18B20(unsigned int i)

{

    while(i--);

}

/**********ds18b20初始化函数**********************/

void Init_DS18B20(void) 

{

     unsigned char x=0;

     DQ = 1;          //DQ复位

     delay_18B20(8);  //稍做延时

     DQ = 0;          //单片机将DQ拉低

     delay_18B20(80); //精确延时 大于 480us

     DQ = 1;          //拉高总线

     delay_18B20(14);

     x=DQ;            //稍做延时后 如果x=0则初始化成功 x=1则初始化失败

     delay_18B20(20);

}

/***********ds18b20读一个字节**************/  

unsigned char ReadOneChar(void)

{

    uchar i=0;

    uchar dat = 0;

for (i=8;i>0;i--)

     {

          DQ = 0; // 给脉冲信号

     dat>>=1;

          DQ = 1; // 给脉冲信号

          if(DQ)

          dat|=0x80;

          delay_18B20(4);

     }

     return(dat);

}

/*************ds18b20写一个字节****************/  

void WriteOneChar(uchar dat)

{

     unsigned char i=0;

  for (i=8; i>0; i--)

     {

          DQ = 0;

         DQ = dat&0x01;

        delay_18B20(5);

         DQ = 1;

     dat>>=1;

 }

}

/**************读取ds18b20当前温度************/

void ReadTemperature(void)

{

    unsigned char a=0;

    unsigned char b=0;

    unsigned char t=0;

    Init_DS18B20();

    WriteOneChar(0xCC);        // 跳过读序号列号的操作

    WriteOneChar(0x44);     // 启动温度转换

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

    Init_DS18B20();

    WriteOneChar(0xCC);     //跳过读序号列号的操作

    WriteOneChar(0xBE);     //读取温度寄存器等(共可读9个寄存器) 前两个就是温度

    delay_18B20(100);

    a=ReadOneChar();        //读取温度值低位

    b=ReadOneChar();           //读取温度值高位

temp1=b<<4;

temp1+=(a&0xf0)>>4;

    temp2=a&0x0f;

temp=((b*256+a)>>4); //当前采集温度值除16得实际温度值

}

/***************液晶显示子函数1正常显示*****************/

void displayfun1(void)

{    

    WriteCommandLCM(0x0c,1);                        //显示屏打开,光标不显示,不闪烁,检测忙信号    

    DisplayListChar(0,0,str0);    

    DisplayListChar(0,1,str1);    

                                                      

    DisplayOneChar(3,0,hour/10+0x30);            //液晶上显示小时

    DisplayOneChar(4,0,hour%10+0x30);

    DisplayOneChar(6,0,minite/10+0x30);            //液晶上显示分

    DisplayOneChar(7,0,minite%10+0x30);

    

    DisplayOneChar(9,0,seconde/10+0x30);        //液晶上显示秒

    DisplayOneChar(10,0,seconde%10+0x30);

    DisplayOneChar(4,1,K/10+0x30);                //液晶上显示设定的温度

    DisplayOneChar(5,1,K%10+0x30);

 

       DisplayOneChar(11,1,temp1/10+0x30);         //液晶上显示测得的温度  

    DisplayOneChar(12,1,temp1%10+0x30);

    DisplayOneChar(14,1,temp2/10+0x30);

    if(ON_OFF==0)                              //若温控标志为0

    {

        DisplayOneChar(14,0,0x4f);               // 液晶上显示不控温的标志

        DisplayOneChar(15,0,0x46);

    }

    else

    {

        DisplayOneChar(14,0,0x4f);               // 液晶上显示控温的标志

        DisplayOneChar(15,0,0x4e);

        if(outflag==1)

            DisplayOneChar(0,0,0x7c);               

        else

            DisplayOneChar(0,0,0xef);

    }

    

}

/************液晶显示子函数2***************/

void displayfun2(void)

{

    WriteCommandLCM(0x0c,1);                     //显示屏打开,光标不显示,不闪烁,检测忙信号    

    DisplayListChar(0,0,str0);    

    DisplayListChar(0,1,str1);    

        

    DisplayOneChar(6,0,minite/10+0x30);

    DisplayOneChar(7,0,minite%10+0x30);

    

    DisplayOneChar(9,0,seconde/10+0x30);

    DisplayOneChar(10,0,seconde%10+0x30);

    DisplayOneChar(4,1,K/10+0x30);               

    DisplayOneChar(5,1,K%10+0x30);

 

       DisplayOneChar(11,1,temp1/10+0x30);         

    DisplayOneChar(12,1,temp1%10+0x30);

    DisplayOneChar(14,1,temp2/10+0x30);

       WriteCommandLCM(0x0f,1);                        //显示屏打开,光标显示,闪烁,检测忙信号    

    DisplayOneChar(3,0,hour/10+0x30);

    DisplayOneChar(4,0,hour%10+0x30);

}

/**************液晶显示子函数3*****************/

void displayfun3(void)

{

    WriteCommandLCM(0x0c,1);                    //显示屏打开,光标不显示,不闪烁,检测忙信号    

    DisplayListChar(0,0,str0);    

    DisplayListChar(0,1,str1);    

    

    DisplayOneChar(3,0,hour/10+0x30);

    DisplayOneChar(4,0,hour%10+0x30); 

    DisplayOneChar(9,0,seconde/10+0x30);

    DisplayOneChar(10,0,seconde%10+0x30);

    DisplayOneChar(4,1,K/10+0x30);               

    DisplayOneChar(5,1,K%10+0x30);

       DisplayOneChar(11,1,temp1/10+0x30);         

    DisplayOneChar(12,1,temp1%10+0x30);

    DisplayOneChar(14,1,temp2/10+0x30);

   

    WriteCommandLCM(0x0f,1);                        //显示屏打开,光标显示,闪烁,检测忙信号

    DisplayOneChar(6,0,minite/10+0x30);

    DisplayOneChar(7,0,minite%10+0x30);

}

/**************液晶显示子函数4 *****************/

void displayfun4(void)

{

    WriteCommandLCM(0x0c,1);                    //显示屏打开,光标不显示,不闪烁,检测忙信号    

    DisplayListChar(0,0,str0);    

    DisplayListChar(0,1,str1);    

    

    DisplayOneChar(3,0,hour/10+0x30);

    DisplayOneChar(4,0,hour%10+0x30); 

    DisplayOneChar(6,0,minite/10+0x30);

    DisplayOneChar(7,0,minite%10+0x30);

    DisplayOneChar(9,0,seconde/10+0x30);

    DisplayOneChar(10,0,seconde%10+0x30);

    

       DisplayOneChar(11,1,temp1/10+0x30);         

    DisplayOneChar(12,1,temp1%10+0x30);

    DisplayOneChar(14,1,temp2/10+0x30);

   

    WriteCommandLCM(0x0f,1);                        //显示屏打开,光标显示,闪烁,检测忙信号

    DisplayOneChar(4,1,K/10+0x30);               

    DisplayOneChar(5,1,K%10+0x30);

}

/**************键盘扫描子函数******************/

void keyscan(void)

{

    uchar xx;                                           //局部变量

    P1=0xff;

    if(P1!=0xff)

      {

        delay_LCM(50);

        if(P1!=0xff)

          {    

            xx=P1;

            switch(xx)                                   // 根据按键状态,调用不同的子函数

            {

                case 0xfe:set_adj();       break;               

                case 0xfd:inc_key();       break;               

                case 0xfb:dec_key();       break;               

                case 0xf7:{delay_LCM(150);ON_OFF=!ON_OFF;while(!BLUE_ALARM);}  break;

                default:break;

            }

        

          }

        

      }

  

}

/**************设定工作模式子函数****************/

void set_adj(void)

{

    delay_LCM(100);

    set++;

if(set>=4)set=0;

    while(!RED_ALARM);        

}

/****************按键加法子函数******************/

void inc_key(void)

{

    delay_LCM(150);

        

    switch(set)

    {

        case 0:if(P1==0xf7){delay_LCM(150);ON_OFF=!ON_OFF;}       break;

     case 1:hour++; if(hour>=23)hour=23; break;

     case 2:minite++; if(minite>=59)minite=59;break;

     case 3:K++;if(K>=99)K=99;                 break; 

        default:break;

    }

    while(!WRITE_ALARM);

}

/****************按键减法子函数*****************/

void dec_key(void)

{

    delay_LCM(150);

    

    switch(set)

    {

           case 0:if(P1==0xf7){delay_LCM(150);ON_OFF=!ON_OFF;}    break;

     case 1:hour--; if(hour<=0)hour=0; break;

     case 2:minite--;if(minite<=0)minite=0;break;

     case 3:K--;if(K<=1)K=1;                  break; 

        default:break;

    }

    while(!GREEN_ALARM);    

}

/////////24C02读写驱动程序////////////////////

void delay1(uchar x)

{  

    uint i;

for(i=0;i}

void flash()

{  ;  ; }

void x24c02_init()  //24c02初始化子程序

{

    scl=1; 

    flash(); 

    sda=1; 

    flash();

}

void start()        //启动I2C总线

{

    sda=1; 

    flash(); 

    scl=1; 

    flash(); 

    sda=0; 

    flash(); 

    scl=0; 

    flash();

}

void stop()         //停止I2C总线

{

    sda=0; 

    flash(); 

    scl=1; 

    flash(); 

    sda=1; 

    flash();

}

void writex(uchar j)  //写一个字节

{  

    uchar i,temp;

    temp=j;

for (i=0;i<8;i++)

        {

         temp=temp<<1;

            scl=0; 

            flash(); 

            sda=CY; 

            flash(); 

            scl=1; 

            flash();

        }

    scl=0; 

    flash(); 

    sda=1; 

    flash();

}

uchar readx()   //读一个字节

{

    uchar i,j,k=0;

    scl=0; 

    flash(); 

    sda=1;

for (i=0;i<8;i++)

        {  

            flash(); 

            scl=1; 

            flash();

            if (sda==1) j=1;

            else j=0;

         k=(k<<1)|j;

            scl=0;

        }

    flash(); 

    return(k);

}

void clock()         //I2C总线时钟

{

    uchar i=0;

    scl=1; 

    flash();

while ((sda==1)&&(i<255))i++;

    scl=0; 

    flash();

}

////////从24c02的地址address中读取一个字节数据/////

uchar x24c02_read(uchar address)

{

    uchar i;

    start(); 

    writex(0xa0);

    clock(); 

    writex(address);

    clock(); 

    start();

    writex(0xa1); 

    clock();

    i=readx(); 

    stop();

    delay1(10);

    return(i);

}

//////向24c02的address地址中写入一字节数据info/////

void x24c02_write(uchar address,uchar info)

{

    EA=0;

    start(); 

    writex(0xa0);

    clock(); 

    writex(address);

    clock(); 

    writex(info);

    clock(); 

    stop(); 

    EA=1;

    delay1(50);

}

/***************定时器t0初始化*******************/

void init_timer0(void)

{

     TMOD=0x01;                                  //time0为定时器,方式1

     TH0=0x3c;                                   //预置计数初值

     TL0=0xb0;

     EA=1;                                   

     ET0=1;                                                      

     TR0=1;                  

}

/***********定时器t0中断子函数**************/

void timer0(void) interrupt 1 using 0          //定时器0方式1,50ms中断一次

{

     TH0=0x3c;

     TL0=0xb0;

     mstcnt++;

if(mstcnt>=20 ) {seconde++; write=1; mstcnt=0; }

if(seconde>=60) {minite++; seconde=0;}

if(minite>=60 ) {hour++; minite=0; }

if(hour>=24 ) {hour=0;}

     keyscan( );                               //按键扫描

}

/***********the main funtion*************/

    

void main(void)

    P1=0xff;                                                   //初始化p1口,全设为1 

    x24c02_init();                                          //初始化24C08

    K=x24c02_read(2);                                       //读出保存的数据赋于K

    seconde=x24c02_read(4);

    minite=x24c02_read(6);

    hour=x24c02_read(8);       

    delay_LCM(500);                                            //延时500ms启动

    initLCM( );                                               //LCD初始化

    init_timer0( );                                               //时钟定时器0初始化    

    Init_DS18B20( ) ;                                          //DS18B20初始化

    DisplayListChar(0,0,str0);    

    DisplayListChar(0,1,str1);  

                         

    while (1)

    {   

           keyscan();                                            //按键扫描        

        ReadTemperature();                                    //温度采集

        switch(set)                                           //LCD根据工作模式显示

        {

            case 0:displayfun1();delay_LCM(1000);break;       //正常工作显示

            case 1:displayfun2();delay_LCM(1000);break;       //调整时显示

            case 2:displayfun3();delay_LCM(1000);break;       //调整分显示

            case 3:displayfun4();delay_LCM(1000);break;       //温度设定

            default:break;

        }     

        keyscan( );                                           //相当于延时

        if(ON_OFF==1)                                           //若温控标志位1, 控制LAMP动作

        {

         if(temp1>=K+1){outflag=1;OUT=0;}

         if(temp1            { 

                delay_LCM(1000);

             if(temp1            }

        }

        else{outflag=0;OUT=1;}

        if(write==1)                                      //判断计时器是否计时一秒

       {

          write=0;                                        //清零

          x24c02_write(8,hour);                           //在24c08的地址2中写入数据hour

          delay_LCM(11);

          x24c02_write(6,minite);

          delay_LCM(11);

          x24c02_write(4,seconde);

          delay_LCM(11);

          x24c02_write(2,K);

              

       }    

    }

    

}下载本文

显示全文
专题