资源链接:加我QQ:1271370903
一、摘要
随着微机测量和控制技术的迅速发展与广泛应用,以单片机为核心的温度采集系统与控制系统的研发与应用在很大程度上提高了生产生活中对温度的控制水平。本设计论述了一种以STC89C52单片机为主控制单元,以DS18B20为温度传感器的温度控制系统。该控制系统可以实时存储相关的温度数据并记录当前的时间。系统设计了相关的硬件电路和相关应用程序。硬件电路主要包括STC89C52单片机最小系统,18B20测温电路,温度显示电路,报警电路等。系统程序主要包括主程序,读温度子程序,计算温度子程序,按键处理子程序,LED显示子程序等。
关键字:AT89C51单片机;DS18B20;显示电路
二、设计
1.设计方案
考虑到用温度传感器,在单片机电路设计中,大多都是使用传感器,所以这是非常容易想到的,所以可以采用一只温度传感器DS18B20,此传感器,可以很容易直接读取被测温度值,进行转换,电路简单,精度高,软硬件都以实现,而且使用单片机的接口便于系统的再扩展,满足设计要求。
2.系统总体框图
3.系统的功能
温度测量功能:利用DS18B20数字温度传感器实现对温度进行准确的测量,使温度值显示到数码管上。
4.本系统优点
DS18B20与单片机之间一根导线进行数据传输,不需要对数据进行转换,接线
DS18B20的温度分辨率为0.0625,所以对温度值可以进行准确的温度转换。
三、Keil软件及C语言设计
作为本科期间学习的第一门编程语言,C语言是我们最熟悉的编程语言之一。当然,由于其功能强大,C语言是当前世界上使用最广泛、最受欢迎的编程语言。在单片机设计中,C语言已经逐步完全取代汇编语言,因为相比于汇编语言,C语言编译与运行、调试十分方便,且可移植性高,可读性好,便于烧录与写入硬件系统,因此C语言被广泛应用在单片机设计中。keil软件由于其兼容单片机的设计,能够实现快速调试,并生成烧录文件,被广泛应用于C语言的编写和单片机的设计。
1、proteus仿真设计软件
Protues也是在单片机仿真设计中常用的设计软件之一,通过设计出硬件电路图,及写入驱动程序,就能在不实现硬件的情况进行电路调试。另外,protues还能实现PCB的设计,在仿真中也可以与KEIL实现联调,便于程序的调试,且支持多种平台,使用简单便捷。
四、主要硬件模块介绍
1、STC单片机功能介绍
单片机是随着大规模集成电路的出现极其发展,将计算机的CPU,RAM,ROM,定时/计数器和多种I/O接口集成在一片芯片上,形成了芯片级的计算机,因此单片机早期的含义称为单片微型计算(single chipmicrocomputer).它拥有优异的性价比、集成度高、体积小、可靠性高、控制功能强、低电压、低功耗的显著优点.主要应用于智能仪器仪表、工业检测控制、机电一体化等方面。
2.系统模块
系统由单片机最小系统、显示电路、按键、18B20温度传感器、蜂鸣器报警电路组成。
主控制器:晶振电路采用12MHZ,复位电路采用上电加按钮复位
显示电路:显示电路采用4 位共阴极LED 数码管,P0 口由上拉电阻提高驱动能力,作为段码输出并作为数码管的驱动。P2 口的低四位作为数码管的位选端。采用动态扫描的方式显示。
报警温度调整按键电路:本系统设计三个按键,一个用于选择设定,另外两个分别用于设置报警温度的加和减。
3、DS18B20数字温度传感器介绍
• 独特的单线接口仅需一个端口引脚进行通讯
• 简单的多点分布应用
• 无需外部器件
• 可通过数据线供电
• 零待机功耗
• 测温范围-55℃+125℃,以0.5℃递增。华氏器件-67+2570F,以0.90F 递增
• 温度以9 或12位数字量读出
• 温度数字量转换时间200ms(典型值)
• 用户可定义的非易失性温度报警设置
• 报警搜索命令识别并标志超过程序限定温度(温度报警条件)的器件
• 应用包括温度控制、工业系统、消费品、温度计或任何热感测系统
说明:
DS1820 数字温度计以9 位或12位数字量的形式反映器件的温度值。
DS1820 通过一个单线接口发送或接收信息,因此在中央微处理器和DS1820 之间仅需一条连
接线(加上地线)。用于读写和温度转换的电源可以从数据线本身获得,无需外部电源。
因为每个 DS1820 都有一个独特的片序列号,所以多只DS1820 可以同时连在一根单线总线上,
这样就可以把温度传感器放在许多不同的地方。这一特性在HVAC 环境控制、探测建筑物、仪器或机器的温度以及过程监测和控制等方面非常有用。
五、仿真
1.仿真开始
高温是30,低温10
通过调整DS1820 数字温度计的上下键设置温度,低于10或高于30,蜂鸣器会发出报警
六、软件设计
1、复位时序
void ds_reset()
{
uint i;
ds=0; // 数据时钟线拉低
i=103; // 延时480us~960us
while(i>0)i--;
ds=1; // 拉高数据时钟线
i=4; // 延时15us~60us
while(i>0)i--;
while(ds); // 检测18b20的存在
while(~ds);
i=30;
while(i>0)i--;}
4.2 读/写时序
//功能:单片机向18b20写一个字节//
void ds_write_byte(uchar date)
{
uint i,j;
bit a;
for(j=8;j>0;j--)
{
a=date&0x01; // 先写低位
date=date>>1;
if(a) // 要写的位为1
{
ds=0; // 数据时钟线拉低
i++;i++; //延时15us之内
ds=1; //ds拉低15us之内必须把要写的数据1放到数据时钟线上
i=8; // 延时大于1us
while(i>0)i--;
}
else //写0
{
ds=0; //数据时钟线拉低
i=8;
while(i>0)i--;//延时大于15us,15us之后18b20对数据采集
ds=1; //数据时钟线拉高释放数据线
i++;i++; //延时
}
}
}
//功能:单片机读一位
//========================//
bit ds_read_bit()
{
uint i;
bit dat;
ds=0; //数据时钟线拉低
i++; //延时大于1us
ds=1; //释放数据线
i++; // 延时小于15us
dat=ds; //读数据
i=8; //延时
while(i>0)i--;
return dat;
}
//功能:单片机读一个字节数据
uchar ds_read_byte()
{
uchar i,j,date;
date=0;
for(i=8;i>0;i--)
{
j=ds_read_bit();
date=(j<<7)|(date>>1);//先读低位数据
}
return date;
}
六、程序设计
#include<reg52.h>
#include<intrins.h>
#include"18b20.h"
#define uint unsigned int
#define uchar unsigned char
uchar T_H=40,T_L=0;
uchar flag1,flag2,flag3;
uchar flag;
float tem; // 定义一个温度 变量存储温度
uchar code tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//不带小数点0~9编码
uchar code tab1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //带小数点的0~9编码
sbit wei1=P2^0; //数码管位选定义
sbit wei2=P2^1; // 数码管位选定义
sbit wei3=P2^2; // 数码管位选定义
sbit wei4=P2^3; //数码管位选定义
sbit key1=P2^4;
sbit key2=P2^5;
sbit key3=P2^6;
sbit beep=P1^0;
sbit ds=P2^7; //18b20数据时钟线
//=======================//
//功能:18b20复位函数
//=======================//
void ds_reset()
{
uint i;
ds=0; // 数据时钟线拉低
i=103; // 延时480us~960us
while(i>0)i--;
ds=1; // 拉高数据时钟线
i=4; // 延时15us~60us
while(i>0)i--;
while(ds); // 检测18b20的存在
while(~ds);
i=30;
while(i>0)i--;
}
//=========================//
//功能:单片机向18b20写一个字节
//========================//
void ds_write_byte(uchar date)
{
uint i,j;
bit a;
for(j=8;j>0;j--)
{
a=date&0x01; // 先写低位
date=date>>1;
if(a) // 要写的位为1
{
ds=0; // 数据时钟线拉低
i++;i++; //延时15us之内
ds=1; //ds拉低15us之内必须把要写的数据1放到数据时钟线上
i=8; // 延时大于1us
while(i>0)i--;
}
else //写0
{
ds=0; //数据时钟线拉低
i=8;
while(i>0)i--;//延时大于15us,15us之后18b20对数据采集
ds=1; //数据时钟线拉高释放数据线
i++;i++; //延时
}
}
}
//========================//
//功能:单片机读一位
//========================//
bit ds_read_bit()
{
uint i;
bit dat;
ds=0; //数据时钟线拉低
i++; //延时大于1us
ds=1; //释放数据线
i++; // 延时小于15us
dat=ds; //读数据
i=8; //延时
while(i>0)i--;
return dat;
}
//====================//
//功能:单片机读一个字节数据
//====================//
uchar ds_read_byte()
{
uchar i,j,date;
date=0;
for(i=8;i>0;i--)
{
j=ds_read_bit();
date=(j<<7)|(date>>1);//先读低位数据
}
return date;
}
//====================//
//功能:启动18b20转换
//=====================//
void init_18b20()
{
ds_reset(); //18b20复位
ds_write_byte(0xcc); //跳过读ROM
ds_write_byte(0x44); //启动温度转换
}
//=======================//
//功能:读温度
//=======================//
float get_temp()
{
uchar n,m,m1;
uint temp;
float T;
ds_reset(); //18b20复位
ds_write_byte(0xcc); //跳过ROM
ds_write_byte(0xbe); //读温度暂存器
m=ds_read_byte(); // 读低字节
n=ds_read_byte(); //读高字节
m1=n&0xf8; //判断温度的符号位
if(m1==0x00) // 温度为正
{
temp=(n*256+m);
T=temp*0.0625;
flag=1; // 温度为正的标志位
}
else //温度为负
{
temp=(n*256+m);
temp=~temp+1; //取补码
T=temp*0.0625;
flag=2; // 温度为负的标志位
}
return T;
}
/*=====================================
功能:延时函数,变量Z为多少就延时多少毫秒
例如Z=10,就是延时10MS
=======================================*/
void delay(uint z) // 延时函数
{
uint x,y;
for(y=110;y>0;y--)
for(x=z;x>0;x--);
}
/*==================================
功能:温度显示函数
显示采用的是动态扫描的方式
===================================*/
void display(uint dat) //温度显示函数
{
wei1=0; // 显示温度整数的百位
wei2=1;
wei3=1;
wei4=1;
P0=tab[dat/1000];
delay(2);
wei1=1; // 显示温度整数 的十位
wei2=0;
wei3=1;
wei4=1;
P0=tab[dat%1000/100];
delay(2);
wei1=1; // 显示温度整数 的个位
wei2=1;
wei3=0;
wei4=1;
P0=tab1[dat%1000%100/10];
delay(2);
wei1=1; // 显示温度的小数位
wei2=1;
wei3=1;
wei4=0;
P0=tab[dat%10];
delay(2);
}
/*===================================
功能:温度范围设定函数
====================================*/
void key()
{
if(key1==0) // 温度范围设定选择键,按第一次设定上限,按第二次设定下限
{
delay(10);// 延时消抖动
if(key1==0)
{
flag1++;
}
while(!key1); // 按键松手检测
delay(5);
while(!key1);
}
if(key2==0) // 温度加按键
{
delay(10);
if(key2==0)
{
flag2=1;
}
while(!key2);
delay(5);
while(!key2);
}
if(key3==0) // 温度减键
{
delay(10);
if(key3==0)
{
flag3=1;
}
while(!key3);
delay(5);
while(!key3);
}
if(flag1==1) // 按第一次设定 温度上限
{
if(flag2==1) // 温度上限加
{
flag2=0;
T_H++;
}
if(flag3==1) // 温度上限减
{
flag3=0;
T_H--;
}
display(10*T_H);
}
if(flag1==2) // 按第二次设定温度下限
{
if(flag2==1) // 温度下限加
{
flag2=0;
T_L++;
}
if(flag3==1) // 温度下限减
{
flag3=0;
T_L--;
}
display(10*T_L);
}
if(flag1==3) //退出温度设定显示
{
flag1=0;
}
}
/*===================================
主函数
====================================*/
void main()
{
while(1)
{
if(flag1==0)
{
init_18b20(); // 温度传感器初始化
tem=get_temp();// 温度测试
display(10*tem); //温度显示
}
key();
if(tem>T_H||tem<T_L)
beep=0;
else
beep=1;
}
}