DS18B20设计1个温度监测系统
项目要求
采集环境温度(0~99.9℃)显示在前3位数码管上。
原理图
代码编写
#include <reg52.h>
#include <intrins.h> //包含函数库,用于调用_nop_()函数
#define uchar unsigned char
#define uint unsigned int
bit flag; //定义标志位,返回值作为是否存在的标志
sbit ds=P2^2;
sbit dula=P2^6;
sbit wela=P2^7;
uint temp; //16位变量
uchar code table_du[]=
{
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
void delayus(uint t) //us级延时函数
{
while(t--);
}
void delay_ms(uchar z) //ms级延时
{
uchar i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
void ds_reset() //复位初始化程序
{
ds=1; //先将数据线置高电平1
delayus(5); //如果11.0592M,大约为66us
ds=0; //数据线拉低到低电平0
delayus(80); //延时约700us
ds=1; //数据线拉到高电平1
delayus(14); //延时约154us
if(ds==0)
flag=1; //标志位,表示18B20存在
else
flag=0;
delayus(20); //约200us
}
bit ds_read_bit() //读取1位时序,用于下面读字节
{
bit dat; //定义一个位变量,作为返回值
ds=0; //拉低总线到0
_nop_(); //一个机器周期,大约1us
_nop_(); //延时约1us,加上上面的总计约2us
ds=1; //主机采样
_nop_(); //延时用于稳定数据
dat=ds; //ds的电平的高低即为数据
delayus(10); //约100us
return dat; //这里之所以有返回值是因为单片机从DS18B20读出数据时,DS18B20要返回数据给到单片机。
} //写操作里是因为单片机直接写数据到DS18B20,不需要DS18B20返回值。
uchar ds_read_byte() //读1个字节,即单片机从DS18B20读数据,需要DS18B20返回数据
{
uchar i,j,k;
for(i=0;i<8;i++) //1个字节由8位组成,将读的位数据一位一位的移入,
{ //移入8位就组成1字节
j=ds_read_bit(); //例如:j=1010 0101
k=(j<<7)|(k>>1); //Ex: j=1010 0101|k=0000 0000=1010 0101
}
return k; //循环8次返回的值为j=1010 0101
}
void ds_write_byte(uchar dat) //写1个字节,dat即为单片机向DS18B20中写的数据
{
uchar i;
for(i=0;i<8;i++)
{
ds=0; //数据线先置低电平
_nop_(); //约1us
_nop_();
ds=dat&0x01; //每次只能写1位,即dat的最低位,数据读写均按照从低位到高位
delayus(6); //延时约70us
ds=1; //将数据线拉到高电平1,准备下次的写入
dat=dat>>1; //右移1位
}
delayus(6); //约70us
}
uint read_temperature() //单片机读取DS18B20温度值
{
uchar a,b;
ds_reset(); //初始化
ds_write_byte(0xcc); //ROM操作指令,跳过ROM
ds_write_byte(0xbe); //存储器操作指令,读取温度指令
a=ds_read_byte(); //执行/数据,低8位,a为8位变量。例a=0101 1010
b=ds_read_byte(); //高8位, b为8位变量。例b=1010 0101
temp=b; //16位变量存放温度值(高8位+低8位)将b的值赋给temp。由于temp为16位变量,所以高位补0。temp=0000 0000 1010 0101
temp=temp<<8; //temp<<8为1010 0101 0000 0000
temp=temp|a; //temp|a为1010 0101 0101 1010
temp=temp*0.0625*10+0.5;//按照固定公式进行转换运算,加0.5是用于四舍五入
return temp; //返回温度值
}
void display(uint temp) //数码管显示程序
{ //将温度值得每位分开进行单独显示
P0=table_du[temp/100]; //显示十位
dula=1;
dula=0;
P0=0xfe; //点亮第一个数码管
wela=1;
wela=0;
delay_ms(10);
P0=table_du[temp%100/10]|0x80;//添加小数点,使dp=1.即dp g f e d c b a =1000 0000
dula=1;
dula=0;
P0=0xfd;
wela=1;
wela=0;
delay_ms(10);
P0=table_du[temp%100%10];
dula=1;
dula=0;
P0=0xfb;
wela=1;
wela=0;
delay_ms(10);
}
void main()
{
while(1)
{
ds_reset(); //初始化
ds_write_byte(0xcc); //跳过ROM
ds_write_byte(0x44); //启动温度转换
display(read_temperature());
}
}