找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于51单片机的温度控制系统

[复制链接]
跳转到指定楼层
楼主
本温度控制系统共有四个模块,分别是单片机控制系统,矩阵键盘电路,温度检测电路,液晶显示电路,其中以单片机控制系统为控制核心,首先由温度检测电路对环境进行温度采集,本系统中检测电路中用的温度传感器是DS18B20,将所在环境温度检测出来,单片机读取温度数据,接着进行液晶显示。矩阵键盘输入设定的数据,然后与实际温度比较,决定加热还是降温,并在液晶显示屏上显示相应的状态。
仿真图:

程序:#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define ActualTemp_worth 9
#define TempSet_worth 9
#define row_worth 16
void dentify_key(uchar key);
void get_temp(void);
uchar keyscan();
void solid_data(void);
uchar sk,temp2;//sk表示有键按下标志,temp2用来临时存储扫描值
uchar code table[]="RealTemp:";
uchar code table1[]="TempRset:";
uchar code table2[]={0xdf,'C'};
uchar code table3[]="ADD";
uchar code table4[]="SUB";
uchar a,a_low,b,t,t1,temp1,key,c;//t表示温度整数部分,t1表示温度小数部分,temp1为中间变量(P3)
float t2,f_temp;
uint temp;
uchar sg=0,made_temp=0,made_temp1=0;
sbit lcden=P1^7;       //*******************LCD1602的使能端
sbit lcdrs=P1^6;       //*******************LCD1602的数据命令端
sbit DQ=P1^1;         //*******************DS18B20的DS端
sbit SIG=P1^5;         //******************按键输入信号
sbit ADD=P1^2;
sbit SUB=P1^3;
sbit ex0_enter=P3^2;
uchar code tablenum[]={0xc0,0xf9,0xa4,0xb0,0x99,        //0~9
                       0x92,0x82,0xf8,0x80,0x90};

uchar code tablenum2[]={0x30,0x31,0x32,0x33,0x34,       //0~9的ASIIC值
                        0x35,0x36,0x37,0x38,0x39};

/*****************************************************************
                    LCD1602液晶显示
*****************************************************************/
uchar num=0;
void delay(int z)//延迟函数delay
{
    uint x,y;
    for(x=z;x>0;x--)
        for(y=110;y>0;y--);
}
void delay1(uint i)//延迟函数delay1
{
    while(i>0) i--;
}
void write_com(uchar com)
{
    lcdrs=0;
    P0=com;
    delay(1);
    lcden=1;
    delay(1);
    lcden=0;
}
void write_data(uchar date)
{
    lcdrs=1;
    P0=date;
    delay(1);
    lcden=1;
    delay(1);
    lcden=0;
}
void init_lcd()//LCD1602初始化函数
{
    lcden=0;
    write_com(0x38);
    write_com(0x0c);
    write_com(0x06);
    write_com(0x01);
}
bit int_DS18B20(void)//DS18B20初始化函数
{
    unsigned char x=0;
    uint i;
    DQ=0;
    i=103;
    while(i>0)i--;
    DQ=1;
    i=4;
    while(i>0)i--;
    x=DQ;           //延时片刻后,若x=0,则初始化成功;若x=1,则初始化失败
    delay(20);
    return x;
}
//*************DS18B20读取一位数据函数
bit tempreadbit(void)
{
    uint i;
    bit dat;
    DQ=0;i++;
    DQ=1;i++;i++;
    dat=DQ;
    i=8;while(i>0)i--;
    return (dat);
}

//*************DS18B20读取一个字节函数
uchar Read(void)//DS18B20读取一个字节
{
unsigned char i=0;
unsigned char j=0;
unsigned char dat=0;
for(i=8;i>0;i--)
    {
        j=tempreadbit();
        dat=(j<<7)|(dat>>1);
   
    }   
        return(dat);
}
//*************DS18B20写一个字节函数
Write(unsigned char dat)
{
    uint i;
    uchar j;
    bit testb;
    for(j=1;j<=8;j++)
    {
        testb=dat&0x01;
        dat=dat>>1;
        if(testb)
        {
            DQ=0;
            i++;i++;
            DQ=1;
            i=8;while(i>0)i--;
        }
        else
        {
            DQ=0;
            i=8;while(i>0)i--;
            DQ=1;
            i++;i++;
        }
    }
}
//****************启动转换函数
void int_(void)
{
while(int_DS18B20());//若为1,重新初始化
delay(1);
Write(0xcc);
Write(0x44);
}

//main()主函数
void main()
{
    init_lcd();//液晶初始化
    int_();   //启动温度转换
    sk=0;
    c=0;
    EA=1;   //开总中断
    EX0=1;  //打开外部中断0中断
    solid_data();//打印固定数据
    while(1)
    {
        int_();
        
        delay1(1700);//等待温度传感器转换温度
        
        get_temp();
        keyscan(); //此次扫描主要是用来检测设置按键是否被按下

        if((sk!=0)&&(c==1))//表明所要设置的温度已经给定
        {
            if((t+1)>made_temp)
            {
                ADD=1;
                SUB=0;
                write_com(0x80+0x4c);
                for(num=0;num<3;num++)
                    write_data(table4[num]);
            }
            else
            {
                SUB=1;
                ADD=0;
                write_com(0x80+0x4c);
                for(num=0;num<3;num++)
                    write_data(table3[num]);            
            }   
        }
    }
}//main函数

//***********************温度读取函数
void get_temp(void)
{
    while(int_DS18B20());
   
    Write(0xcc);
    Write(0xBE);//读取温度寄存器指令
    a=Read();
    b=Read();
    temp=b;
    temp<<=8;
    temp=temp|a;
    f_temp=temp*0.0625;
    t=(uchar)(f_temp);
    t2=f_temp-t;
    t1=(uchar)(t2*10);
/*      if(b>127)
    {
        sg=1;
        temp=~temp;
        temp=temp+1;
        if(a==0x00)
            b=b+1;
        a_low=a&0x0f;
        t2=a_low*5/80;
        t1=(uchar)(t2*10);
        a=a>>4;
        b=b<<4;
        b=b&0x70;//把b中的最高位符号位置0
        t=b|a;
        t=t*5/80;
    }
    else
    {
        sg=0;
        a_low=a&0x0f;
        t2=a_low*5/80;
        t1=(uchar)(t2*10);
        a=a>>4;
        b=b<<4;
        b=b&0x70;
        t=b|a;
        t=t*5/80;
    }
*/  

//*************************输入温度小数部分
    write_com(0x80+0x0d);
    write_data(0x30+t1);
//*************************输入温度整数部分
    write_com(0x80+0x0a);
    write_data(0x30+t/10);
   
    write_com(0x80+0x0b);
    write_data(0x30+t%10);

//  int_();
}
//显示数据函数
void dentify_key(uchar key)
{
        
        if(key>=0&&key<=9)
        {
            write_data(tablenum2[key]);
        }
}
//*************************显示固定数据
void solid_data(void)
{
//*************************写第一行显示数据
    write_com(0x80);
    for(num=0;num<ActualTemp_worth;num++)
    {
        write_data(table[num]);
        delay(1);
    }

//*************************打印温度小数点以及摄氏度" °"
    write_com(0x80+0x0c);
    write_data(0x2e);//打印小数点,'0x2e'为小数点的ASCII码
    write_com(0x80+0x0e);
    for(num=0;num<2;num++)
    {
        write_data(table2[num]);
        delay(1);
    }

//*************************写第二行显示数据
    write_com(0x80+0x40);
    for(num=0;num<TempSet_worth;num++)
    {
        write_data(table1[num]);
        delay(1);
    }
}

//*************************矩阵键盘扫描函数
uchar keyscan()
{
//*************************矩阵键盘第一列扫描
    P2=0xfe;
    temp1=P2;
    temp1=temp1&0xf0;
    if(temp1!=0xf0)
    {
        delay(10);//延时消斗
        temp1=P2;
        temp1=temp1&0xf0;
        while(temp1!=0xf0)
        {
            sk=sk+1;//有按键按下标志
            temp1=P2;
            switch(temp1)
            {
                case 0xee:key=0;break;
                case 0xde:key=4;break;
                case 0xbe:key=8;break;
            }
            while(temp1!=0xf0)
            {
                temp1=P2;
                temp1=temp1&0xf0;
            }      
        }
    }
//*************************矩阵键盘第二列扫描
    P2=0xfd;
    temp1=P2;
    temp1=temp1&0xf0;
    if(temp1!=0xf0)
    {
        delay(10);
        temp1=P2;
        temp1=temp1&0xf0;
        while(temp1!=0xf0)  
        {   
            sk=sk+1;//有按键按下标志
            temp1=P2;
            switch(temp1)
            {
                case 0xed:key=1;break;
                case 0xdd:key=5;break;
                case 0xbd:key=9;break;
            }
            while(temp1!=0xf0)
            {
                temp1=P2;
                temp1=temp1&0xf0;
            }           
        }
    }
//*************************矩阵键盘第三列扫描
    P2=0xfb;
    temp1=P2;
    temp1=temp1&0xf0;
    if(temp1!=0xf0)
    {
        delay(10);
        temp1=P2;
        temp1=temp1&0xf0;
        while(temp1!=0xf0)  
        {
            temp1=P2;
            sk=sk+1;//有按键按下标志
            switch(temp1)
            {
                case 0xeb:key=2;break;
                case 0xdb:key=6;break;
                case 0xbb:key=10;break;
            }
            while(temp1!=0xf0)
            {
                temp1=P2;
                temp1=temp1&0xf0;
            }           
        }
    }
//*************************矩阵键盘第四列扫描
    P2=0xf7;
    temp1=P2;
    temp1=temp1&0xf0;
    if(temp1!=0xf0)
    {
        delay(10);
        temp1=P2;
        temp1=temp1&0xf0;
        while(temp1!=0xf0)
        {
            temp1=P2;
            sk=sk+1;//有按键按下标志
            switch(temp1)
            {
                case 0xe7:key=3;break;
                case 0xd7:key=7;break;
                case 0xb7:key=11;break;
            }
            while(temp1!=0xf0)
            {
                temp1=P2;
                temp1=temp1&0xf0;
            }
            
        }
    }
   
    return (key);   
}

//*************************中断函数
void ex_enter() interrupt 0
{
    c=1;//表明已进入中断
    delay(100);
    write_com(0x80+0x4c);
    for(num=0;num<4;num++)//在按下设置后清屏设置部分的数据
    {
        write_data(0x20);
    }
    ADD=1;
    SUB=1;
    write_com(0x80+0x49);
    write_com(0x0f);//开光标并闪烁
   
    sk=0;
    ex0_enter=1;//外部中断0中断复位
    SIG=0;
    write_com(0x80+0x49);
    delay(100);//******************可能是因为刚刚按设置键的时候,由于单片机速度过快,进入中断后还没
               //******************释放按键,导致进入do...while语句,使得sk值迅速变为1;
               //******************因此在此加一延时,可以防止这种情况发生。                             
    do
    {
        sk=0;
        made_temp=temp2=keyscan();          //sk自加已在keyscan函数中实现
    }while((sk!=1)||(temp2==10||temp2==11));//检测按键是否是设置键,如是设置键,继续扫描
    if(sk!=0)//打印数据
    {
        for(num=0;num<sk;num++)
        dentify_key(temp2);
    }
    made_temp=made_temp*10;

    sk=0;
    delay(100);//******************作用于上面相同
    do
    {
        sk=0;
        made_temp1=temp2=keyscan();//sk自加已在keyscan函数中实现
    }while((sk!=1)||(temp2==10||temp2==11));

    if(sk!=0)
    {
        for(num=0;num<sk;num++)
        dentify_key(temp2);
    }
   
    made_temp=made_temp+made_temp1;
    write_com(0x0c);
    sk=0;
    delay(100);
    do                  //***************检测确定按键
    {
        sk=0;
        temp2=keyscan();//sk自加已在keyscan函数中实现
    }while((sk!=1)||(temp2!=11));
    delay(50);
    SIG=1;
   
        if(sk!=0)
        {
            if((t+1)>made_temp)
            {
                ADD=1;
                SUB=0;
                write_com(0x80+0x4c);
                for(num=0;num<3;num++)
                    write_data(table4[num]);
            }
            else
            {   
                SUB=1;
                ADD=0;
                write_com(0x80+0x4c);
                for(num=0;num<3;num++)
                    write_data(table3[num]);            
            }
        }
   
}

温度控制系统 包含 C语言程序 protues仿真图.zip

208.33 KB, 下载次数: 79, 下载积分: 黑币 -5

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

使用道具 举报

沙发
ID:1018243 发表于 2022-4-13 23:55 来自手机 | 只看该作者
有没有他的电路图,或者程序的详细解说
回复

使用道具 举报

板凳
ID:1022036 发表于 2022-4-27 10:07 | 只看该作者
可以来个上下限报警
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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