注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

耳朵的博客

做自己想做的人

 
 
 

日志

 
 

温控系统设计  

2009-05-13 12:04:58|  分类: 单片机 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

       

 

摘要: 使用STC89C51单片机做CPU处理器处理控制;DS18B20做为温度采集设备;3位数码管显示温度;按键切换及设定目标温度,上下限温度;继电器控制加热电阻,温度低于目标温度时自动加热;蜂鸣器作为当前温度超出温度范围时的警报;

关键词:单片机,DS18B20,可调温度控制,温度显示

功能:

?      温度实时显示

?      目标温度设定

?      温度上下限设定

?      超出温度范围报警

?      (自动加热)

原理:

?      温度采集->DS18B20

DS18B20数字温度传感器为单总线器件,具有线路简单,体积小的特点。

在程序中设定温度读取间隔时间,利用定时器中断,定时读取

?      显示->数码管

采用动态扫描3位数码管,可显示0.01-999的实型数据

?      温度设定->按键

用三个按键分别为切换键,上调键,下调键。

切换键用于切换数码管显示的温度(当前温度,目标温度,上限温度,下限温度)

上调键,下调键用于调整当前显示内容的温度,在显示当前温度时无效.

?      报警->蜂鸣器

当采集到的温度超过上限温度或低于下限温度时,蜂鸣器报警,温度恢复正常或重新设定上下限温度报警自动解除.

 

?      加热->继电器控制加热电阻

利用继电器控制加热电阻,即可使用5V电源,也可使用外部较高电压,使加热速度更快

 

程序实现基本思路:

数码管显示和按键扫描都需要较高的频率

温度采集根据实际情况需要大概每秒读取1-2次

 

数码管动态显示及键盘扫描在不同时间片宏观上同时进行,温度间隔一段时间读取一次

 

  

温度切换及温度设置算法描述

定义temperature[4]

temperature[0]=read_ds18b20_ temperature()

temperature[1]=上限温度

temperature[2]=下限温度

temperature[3]=目标温度

 

定义显示状态mode

当前显示temperature[mode]

切换键设置mode值0-3

“+”,“-”键改变temperature[mode]值

测试指标:

?      温度实时显示

?      目标温度设定

?      温度上下限设定

?      超出温度范围报警

?      自动加热

功能全部实现.

存在缺陷:温度采集时数码管闪烁

原因分析:读取温度时,单片机没有扫描数码管

解决方案:

1.将读取温度时延时部分用于扫描数码管 ?

  2.RTOS ?

 

 

源程序:

/***********************************\

*       DS18B20温度读取函数      *

*            晶振12M              *

*   返回double,精确到小数点后4位     *

*  只需调用read_temperature函数即可 *

\***********************************/

sbit DQ =P2^0; //定义连接DS18B20的数据口

//延时函数

void delay(unsigned int i)

{

     while(i--);   

}

//初始化函数

void init_DS18B20(void)

{

    bit flag=1;

    while(flag==1)

    {

        DQ = 1;    //DQ复位

        DQ = 0;    //DQ拉低

        delay(100); //延时约500us

        DQ = 1;    //释放DQ

        delay(10); //DS18B20收到下拉信号后延时

        flag=DQ;   //读取DQ值(为0表示DS18B20复位成功)

        delay(20);

    }

}

//串行读取一个字节

unsigned char read_DS18B20(void)

{

    unsigned char i = 0, dat = 0;

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

    {

        DQ = 0;

        dat>>=1;

        DQ = 1;

        if(DQ)

            dat|=0x80;

        delay(4);

    }

    return dat;

}

//串行写入一个字节

void write_DS18B20(unsigned char dat)

{

    unsigned char i=0;

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

    {

        DQ = 0;

        DQ = dat&0x01;

        delay(3);

        DQ = 1;

        dat>>=1;

    }

    delay(5);

}

//读取温度

double read_temperature(void)       //返回double

{

    unsigned int temp=0;

    double d;

    init_DS18B20();

    write_DS18B20(0xCC); //忽略读序列号

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

    init_DS18B20();

    write_DS18B20(0xCC); //忽略读序列号

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

    temp=read_DS18B20();   //读取温度值低位

    temp=temp+read_DS18B20()*0x100;   //读取温度值高位

    if(temp<0xf000)    

    {

        d=temp*0.0625;

    }

    else    //零下

    {

        temp=~temp+1;        

        d=-(temp*0.0625);

    }

    return  d;

}

#include<reg51.h>

#include<DS18B20.h>

#define duan P0

sbit wei_1=P3^5;

sbit wei_2=P3^6;

sbit wei_3=P3^7;

sbit heat=P2^7;

sbit been=P2^5;

long timer=0;

double now_display,temperature[4]={ 0,   10,  40,  35};

//temperature[4]存储数据温度值意义:当前,下限,上限,目的

bit key_flag=0;

//共阴段码

unsigned char code w[]={

    //0-F无小数点

    0x3f,0x06,0x5b,0x4f,

    0x66,0x6d,0x7d,0x07,

    0x7f,0x6f,0x77,0x7c,

    0x39,0x5e,0x79,0x71,

    //0-F带小数点

    0xbf,0x86,0xdb,0xcf, 

    0xe6,0xed,0xfd,0x87,

    0xff,0xef,0xf7,0xfc,

    0xb9,0xde,0xf9,0xf1,

    //小数点  负号

    0x80,     0x40};

//数码管显示函数

void display(double n)

{

    unsigned long temp,t=400; //设置t值可以改变亮度及扫描频率

    temp=n*1000.0;

    while(temp>=1000)

        temp/=10;

    duan=0x00;

    wei_1=0;

    duan=w[temp/100+16*(char)(n<10)]; //最高位数码管显示

    delay(t);

    wei_1=1;

    duan=0x00;

    wei_2=0;

    duan=w[temp/10%10+16*(char)(n>=10&&n<100)];//中间位数码管显示

    delay(t);

    wei_2=1;

    duan=0x00;

    wei_3=0;

    duan=w[temp%10+16*(char)(n>=100&&n<1000)];//最低位数码管显示

    delay(t);  

    wei_3=1;   

}

//键盘扫描函数

unsigned char keyboard_scan()

{

    int i=50;

    P1=0xfe;

    if(P1!=0xfe)

    {

        while(i--);

        return 0xff-P1;

    }

    return 0;

}

//主函数

void main(void)

{

    unsigned char mode=0,key;

    TMOD=0x01;

    EA=1;

    ET0=1;

    TH0=0x00;

    TL0=0x00;      

    TR0=1;

    while(1)

    {

        now_display=temperature[mode];//设置当前显示内容

        display(now_display);//显示温度

        P1=0xfe;       //用于检测是否有键按下

        if(P1==0xfe)   //没键按下

            key_flag=0;   //键标志置0

        if(key_flag==0)

        {

            key=keyboard_scan(); //扫描一次键盘,并返回键值

            if(key!=0)  //有键按下

            {

                been=1;   //用于按键声音

                been=0;   //用于按键声音

                key_flag=1; //键标志置1

                switch (key)

                {

                    case 3: //按下设置键

                        mode++;

                        if(mode>3)

                            mode=0;

                        break;

                    case 5: //按下"+"

                        if(mode!=0)

                            temperature[mode]++;

                        break;

                    case 9: //按下"-"

                        if(mode!=0)

                            temperature[mode]--; 

                        break;

                    default : break;

                }

            }

        }

    }

}

void timer_1() interrupt 1

{

    TH0=0x00;

    TL0=0x00;

    timer++;

    if(timer>20)//改变此值改变温度采集频率

    {

        temperature[0]=read_temperature();//读取一次温度

        if(temperature[0]<temperature[3]) //读取的温度低于目标温度

            heat=1; //加热

        else

            heat=0;

        if(temperature[0]>temperature[2]||temperature[0]<temperature[1]) //读取的温度超出温度范围

            been=0; //报警

        else

            been=1; //取消报警

        timer=0;

    }

}

  评论这张
 
阅读(809)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018