操作DS18B20的顺序:
初始化 -> 发送跳过读序列号命令(0xcc) -> 发送命令让DS18B20启动温度转换(0x44) **->**延时1ms以让其完成温度转换 -> 初始化 -> 发送跳过读序列号命令(0xcc) -> 发送读暂存存储器命令(0xbe) -> 先读取低8位TL -> 在读取高8位 -> 数据处理获得真实温度值(具体处理过程如下)。
数据处理过程:
- temp = TL | (TH << 8);获得温度值对应的16位字节
说明:16位字节的高5位为符号位,如果温度temp>0,那么高5位为00000;如果温度temp<0,那么高5位为11111。
- 如果温度temp>0,实际温度为temp = temp*0.0625
- 如果温度temp<0,应先将11位数据取反以后 再+1,最后乘以0.0625
.Attention 1:如果要控制温度显示的精度,那么最后的之不仅要乘以0.0625,还要乘以10^n(n为显示数字小数点后的位数),这事只要控制好小数点的谓之就可以了。 . Attention 2:最后的结果应该加上0.5,以达到四舍五入的效果
DS12B20.c
#include "DS18B20.h"
void delay1ms(void) //误差 0us
{
unsigned char a,b,c;
for(c=1;c>0;c--)
for(b=142;b>0;b--)
for(a=2;a>0;a--);
}
void delay500us(void) //误差 0us
{
unsigned char a,b;
for(b=71;b>0;b--)
for(a=2;a>0;a--);
}
void delay20us(void) //误差 0us
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=7;a>0;a--);
}
void delay70us(void) //误差 0us
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=32;a>0;a--);
}
unsigned char DS18B20_Init()//初始化
{
unsigned char j = 0;
DSPORT = 0;
delay500us();
DSPORT = 1;
_nop_();
while(DSPORT)//初始化完成DSPORT会变成1,等待15~60us
{
delay500us();
++j;
if(j>3){
return 0;//初始化失败
}
}
return 1;//初始化完成
}
unsigned char DS18B20_ReadByte()
{
unsigned char i,byte,dat;
for(i=8;i>0;i--)
{
DSPORT = 0;
_nop_();
DSPORT = 1; //2个读周期之间至少1us的恢复时间
delay20us();
byte = DSPORT;
delay70us();
dat = (dat>>1) | (byte<<7);
}
return dat;
}
void DS18B20_WriteByte(unsigned char cmd)
{
unsigned char i;
for(i = 0;i<8;++i)
{
DSPORT = 0;
delay20us();
DSPORT = cmd &0x01; //然后写入一个数据,从最低位开始
delay70us();
DSPORT = 1;
_nop_();//1us的恢复时间
cmd=cmd>>1;
}
}
int DS18B20_GetTemp()
{
int temp;
unsigned char TH,TL;
//温度转换
DS18B20_Init();
delay1ms();
DS18B20_WriteByte(0xcc);
DS18B20_WriteByte(0x44);
delay1ms();
//发出读取温度的命令
DS18B20_Init();
delay1ms();
DS18B20_WriteByte(0xcc);
DS18B20_WriteByte(0xbe);
//获得温度
TL = DS18B20_ReadByte();
TH = DS18B20_ReadByte();
temp = TL | (TH<<8);
return temp;
}