温度传感器设计
总体设计框图
本方案设计的系统由单片机系统、数字温度传感器、数码管显示模块组成,其总体架构如下图。 单片机系统
本设计采用STC89C52单片机作为控制器,完成所有功能的控制,包括:
● DS18B20数字温度传感器的初始化和读取温度值
● LED数码管显示驱动与控制
数字温度传感器模块
DS18B20性能
● 测温范围-55~+125℃,以0.5℃递增
● 可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃ ● 温度数字量转换时间200ms,12位分辨率时最多在750ms内把温度转换为数字
DS18B20外形及引脚说明
DS18B20外形及引脚
● GND:地
● DQ:单线运用的数据输入/输出引脚
● VD:可选的电源引脚
软件设计
主程序模块
主程序需要调用1个子程序为:
● 实时温度显示子程序:驱动数码管把实时温度值送出在LED数码管显示
读温度值模块
读温度值模块需要调用4个子程序,分别为:
● DS18B20初始化子程序:让单片机知道DS18B20在总线上且已准备好操作
● DS18B20写字节子程序:对DS18B20发出命令
● DS18B20读字节子程序:读取DS18B20存储器的数据
● 延时子程序:对DS18B20操作时的时序控制
DS18B20测温流程
按照此步骤,程序设计时首先就要执行初始程序化程序 INI10
,其次将要跳过ROM匹配命令(代码CCH)写入到DS18B20
中,此时需根据数字温度传感器写时序编写对DS18B20一个写入字节程序
WRITE,将跳过ROM匹配命令写入
DS18B20。为了完成温度启动转换,需要将启动转换命令写入
DS18B20中。
用延时750ms
等待转换完成。随后再按照初始化时序执行初始化程序INI10
,用写入一个字节程序将匹配
ROM命令(代码为
55h)写入到DS18B20中。为了完成读便笺式存储器操作,需要先结合数字温度传感器写时序将读便笺式存储器命令(代码为BEH)写入到DS18B20中,再用温度传感器读时序编写的每一个字节程序READ,连续读取DS18B20便笺式存储器中9个字节的内容。由此可见。结合上述所介绍的初始化时序,温度传感器写时序和温度传感器读时序,才可以将所需的命令写入与读出,完成温度的正确读取。
软件程序
数码管显示温度程序:
//头文件:
#include "reg51.h"
#include "ds18b20.h"
//变量定义:
unsigned char ly_dis[4];//定义显示缓冲区
code unsigned char table[]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //表:共阳数码管 0-9 //引入DS18B20头文件
unsigned char l_posit=0; //显示位置
//引脚定义:
sbitSMG_q = P1^0; //定义数码管阳级控制脚(千位)
sbitSMG_b = P1^1; //定义数码管阳级控制脚(百位)
sbit SMG_s = P1^2; //定义数码管阳级控制脚(十位)
sbitSMG_g = P1^3; //定义数码管阳级控制脚(个位)
//函数声明:
void display(void);//显示函数,显示缓冲区内容
void delay(void);
//主函数,C语言的入口函数:
void main()
{
unsignedinti=0;
floattt; intltemp; while(1){ if(i==0) tmpchange(); //温度转换 if(i==100){ tt=tmp()*0.0625; //得到真实十进制温度值,因为DS18B20 //可以精确到0.0625度,所以读回数据的最低位代表的是0.0625度。
ltemp=tt*10+0.5; //放大十倍,这样做的目的将小数点后第一位也转换为可显示数字,同时进行一个四舍五入操作。
if(ltemp
} } i++; if(i==3000) i=0; //调用显示 } else ly_dis[0]=ltemp/1000;//显示百位值 //判断第一位显示整数还是负号 ly_dis[0]=0xbf; ltemp=0-ltemp; ltemp=ltemp%1000; ly_dis[1]=ltemp/100; //显示温度十位值 ltemp=ltemp%100; ly_dis[2]=ltemp/10; ly_dis[3]=ltemp%10; //显示温度个位值 //显示小数点后一位 display(); delay();
}//显示函数,参数为显示内容
void display()
{
P0=0XFF; // switch(l_posit){ case 0: //选择千位数码管,关闭其它位 SMG_q=0; SMG_b=1; SMG_s=1; SMG_g=1; P0=table[ly_dis[0]]; //输出显示内容 break; //选择百位数码管,关闭其它位 case 1:
}
SMG_q=1; SMG_b=0; SMG_s=1; SMG_g=1; P0=table[ly_dis[1]]; break; //选择十位数码管,关闭其它位 case 2: SMG_q=1; SMG_b=1; SMG_s=0; SMG_g=1; P0=table[ly_dis[2]]&0x7f; break; //选择个位数码管,关闭其它位 case 3: } l_posit++; if(l_posit>3) SMG_q=1; SMG_b=1; SMG_s=1; SMG_g=0; P0=table[ly_dis[3]]; break; //每调用一次将轮流显示一位 l_posit=0;
//延时子函数,短暂延时
void delay(void){
} unsigned char i=10; while(i--);
读温度值模块程序:
/****DS18B20.H****/
/********宏定义******************************************************/ #define uchar unsigned char
#define uint unsigned int
/********IO引脚定义***********************************************/ sbit DS=P3^2; //定义DS18B20接口
/*************延时子函数 *****************************************/ voiddelayb(uint count)
{
uinti;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}/*************DS18B20初始化************************************/ voiddsreset(void)
{
uinti;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
}/*************读一位*******************************************/ bittmpreadbit(void)
{
bitdat;
DS=0;
i++; //小延时一下
DS=1;
i++;i++;
dat=DS;
i=8;
while(i>0)i--;
return (dat);
}/*************读一个字节*****************************************/ uchartmpread(void)
{
uchari,j,dat;
dat=0;
for(i=1;i
{
j=tmpreadbit();
dat=(j>1); //读出的数据最低位在最前面,这样刚好//一个字节在DAT里
}
return(dat); //将一个字节数据返回
}/*************写一个字节*********************************************/ voidtmpwritebyte(uchardat)
{
uinti;
uchar j;
bittestb;
for(j=1;j
{
testb=dat&0x01;
dat=dat>>1;
if(testb) // 写1部分
DS=0;
i++;i++;
DS=1;
i=8;
while(i>0)i--;
}
else
{
DS=0; //写0部分
i=8;
while(i>0)i--;
DS=1;
i++;i++;
}
}
}
/***********发送温度转换命令********************************************/ voidtmpchange(void)
{
dsreset(); //初始化DS18B20
delayb(1); //延时
tmpwritebyte(0xcc); // 跳过序列号命令
tmpwritebyte(0x44); //发送温度转换命令
}/***********获得温度******************************************/ inttmp()
{
int temp;
uchara,b;
dsreset();
delayb(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe); //发送读取数据命令
a=tmpread(); //连续读两个字节数据
b=tmpread();
temp=b;
temp
temp=temp|a; //两字节合成一个整型变量。
return temp; //返回温度值
}/*******读取温度传感器的序列号***************************** void readrom()
{uchar sn1,sn2;
dsreset();
delayb(1);
tmpwritebyte(0x33);
sn1=tmpread();
sn2=tmpread();
}
//本程序中没有用到此函数
温度传感器设计
总体设计框图
本方案设计的系统由单片机系统、数字温度传感器、数码管显示模块组成,其总体架构如下图。 单片机系统
本设计采用STC89C52单片机作为控制器,完成所有功能的控制,包括:
● DS18B20数字温度传感器的初始化和读取温度值
● LED数码管显示驱动与控制
数字温度传感器模块
DS18B20性能
● 测温范围-55~+125℃,以0.5℃递增
● 可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃ ● 温度数字量转换时间200ms,12位分辨率时最多在750ms内把温度转换为数字
DS18B20外形及引脚说明
DS18B20外形及引脚
● GND:地
● DQ:单线运用的数据输入/输出引脚
● VD:可选的电源引脚
软件设计
主程序模块
主程序需要调用1个子程序为:
● 实时温度显示子程序:驱动数码管把实时温度值送出在LED数码管显示
读温度值模块
读温度值模块需要调用4个子程序,分别为:
● DS18B20初始化子程序:让单片机知道DS18B20在总线上且已准备好操作
● DS18B20写字节子程序:对DS18B20发出命令
● DS18B20读字节子程序:读取DS18B20存储器的数据
● 延时子程序:对DS18B20操作时的时序控制
DS18B20测温流程
按照此步骤,程序设计时首先就要执行初始程序化程序 INI10
,其次将要跳过ROM匹配命令(代码CCH)写入到DS18B20
中,此时需根据数字温度传感器写时序编写对DS18B20一个写入字节程序
WRITE,将跳过ROM匹配命令写入
DS18B20。为了完成温度启动转换,需要将启动转换命令写入
DS18B20中。
用延时750ms
等待转换完成。随后再按照初始化时序执行初始化程序INI10
,用写入一个字节程序将匹配
ROM命令(代码为
55h)写入到DS18B20中。为了完成读便笺式存储器操作,需要先结合数字温度传感器写时序将读便笺式存储器命令(代码为BEH)写入到DS18B20中,再用温度传感器读时序编写的每一个字节程序READ,连续读取DS18B20便笺式存储器中9个字节的内容。由此可见。结合上述所介绍的初始化时序,温度传感器写时序和温度传感器读时序,才可以将所需的命令写入与读出,完成温度的正确读取。
软件程序
数码管显示温度程序:
//头文件:
#include "reg51.h"
#include "ds18b20.h"
//变量定义:
unsigned char ly_dis[4];//定义显示缓冲区
code unsigned char table[]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //表:共阳数码管 0-9 //引入DS18B20头文件
unsigned char l_posit=0; //显示位置
//引脚定义:
sbitSMG_q = P1^0; //定义数码管阳级控制脚(千位)
sbitSMG_b = P1^1; //定义数码管阳级控制脚(百位)
sbit SMG_s = P1^2; //定义数码管阳级控制脚(十位)
sbitSMG_g = P1^3; //定义数码管阳级控制脚(个位)
//函数声明:
void display(void);//显示函数,显示缓冲区内容
void delay(void);
//主函数,C语言的入口函数:
void main()
{
unsignedinti=0;
floattt; intltemp; while(1){ if(i==0) tmpchange(); //温度转换 if(i==100){ tt=tmp()*0.0625; //得到真实十进制温度值,因为DS18B20 //可以精确到0.0625度,所以读回数据的最低位代表的是0.0625度。
ltemp=tt*10+0.5; //放大十倍,这样做的目的将小数点后第一位也转换为可显示数字,同时进行一个四舍五入操作。
if(ltemp
} } i++; if(i==3000) i=0; //调用显示 } else ly_dis[0]=ltemp/1000;//显示百位值 //判断第一位显示整数还是负号 ly_dis[0]=0xbf; ltemp=0-ltemp; ltemp=ltemp%1000; ly_dis[1]=ltemp/100; //显示温度十位值 ltemp=ltemp%100; ly_dis[2]=ltemp/10; ly_dis[3]=ltemp%10; //显示温度个位值 //显示小数点后一位 display(); delay();
}//显示函数,参数为显示内容
void display()
{
P0=0XFF; // switch(l_posit){ case 0: //选择千位数码管,关闭其它位 SMG_q=0; SMG_b=1; SMG_s=1; SMG_g=1; P0=table[ly_dis[0]]; //输出显示内容 break; //选择百位数码管,关闭其它位 case 1:
}
SMG_q=1; SMG_b=0; SMG_s=1; SMG_g=1; P0=table[ly_dis[1]]; break; //选择十位数码管,关闭其它位 case 2: SMG_q=1; SMG_b=1; SMG_s=0; SMG_g=1; P0=table[ly_dis[2]]&0x7f; break; //选择个位数码管,关闭其它位 case 3: } l_posit++; if(l_posit>3) SMG_q=1; SMG_b=1; SMG_s=1; SMG_g=0; P0=table[ly_dis[3]]; break; //每调用一次将轮流显示一位 l_posit=0;
//延时子函数,短暂延时
void delay(void){
} unsigned char i=10; while(i--);
读温度值模块程序:
/****DS18B20.H****/
/********宏定义******************************************************/ #define uchar unsigned char
#define uint unsigned int
/********IO引脚定义***********************************************/ sbit DS=P3^2; //定义DS18B20接口
/*************延时子函数 *****************************************/ voiddelayb(uint count)
{
uinti;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}/*************DS18B20初始化************************************/ voiddsreset(void)
{
uinti;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
}/*************读一位*******************************************/ bittmpreadbit(void)
{
bitdat;
DS=0;
i++; //小延时一下
DS=1;
i++;i++;
dat=DS;
i=8;
while(i>0)i--;
return (dat);
}/*************读一个字节*****************************************/ uchartmpread(void)
{
uchari,j,dat;
dat=0;
for(i=1;i
{
j=tmpreadbit();
dat=(j>1); //读出的数据最低位在最前面,这样刚好//一个字节在DAT里
}
return(dat); //将一个字节数据返回
}/*************写一个字节*********************************************/ voidtmpwritebyte(uchardat)
{
uinti;
uchar j;
bittestb;
for(j=1;j
{
testb=dat&0x01;
dat=dat>>1;
if(testb) // 写1部分
DS=0;
i++;i++;
DS=1;
i=8;
while(i>0)i--;
}
else
{
DS=0; //写0部分
i=8;
while(i>0)i--;
DS=1;
i++;i++;
}
}
}
/***********发送温度转换命令********************************************/ voidtmpchange(void)
{
dsreset(); //初始化DS18B20
delayb(1); //延时
tmpwritebyte(0xcc); // 跳过序列号命令
tmpwritebyte(0x44); //发送温度转换命令
}/***********获得温度******************************************/ inttmp()
{
int temp;
uchara,b;
dsreset();
delayb(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe); //发送读取数据命令
a=tmpread(); //连续读两个字节数据
b=tmpread();
temp=b;
temp
temp=temp|a; //两字节合成一个整型变量。
return temp; //返回温度值
}/*******读取温度传感器的序列号***************************** void readrom()
{uchar sn1,sn2;
dsreset();
delayb(1);
tmpwritebyte(0x33);
sn1=tmpread();
sn2=tmpread();
}
//本程序中没有用到此函数