代码由网上原有代码修改而来,主要是增加了传输和状态判断,在总线故障时返回0,正常返回1。
移植需要自己修改成实际的IO口,并且根据不同单片机,还需要修改ds18b20_bus.c中的延时函数。
ds18b20.c
#include "ds18b20.h"
#include "ds18b20_bus.h"
// 读取浮点类型的温度值
// 返回: 0-读取失败, 1-读取成功
unsigned char DS18B20_GetTemperature(float *temperatureBuf)
{
unsigned char TL, TH;
int temp;
unsigned char ret;
DS18B20_Reset(); //总线复位
ret = DS18B20_CheckOnline(); //等待DS应答
if(!ret)
{
return 0;
}
DS18B20_WriteByte(0xcc); //发命令
DS18B20_WriteByte(0x44); //发转换命令
DS18B20_Reset(); //复位
ret = DS18B20_CheckOnline(); //等待DS应答
if(!ret)
{
return 0;
}
DS18B20_WriteByte(0xcc); //发命令
DS18B20_WriteByte(0xbe); //发送读温度命令
TL = DS18B20_ReadByte(); //读温度值的低字节
TH = DS18B20_ReadByte(); //读温度值的高字节
temp = TH<<8 | TL; // 将高低字节合成温度值
if(TH > 0x07) // 如果温度数值是负的
{
*temperatureBuf = (temp + 1) / 16.0; //0.0625为12位温度采集的分辨率,乘0.0625等于除以16
}
else // 如果温度数值是正的
{
*temperatureBuf = temp / 16.0;
}
return 1;
}
//初始化DS18B20 同时检测DS的存在
//返回0: 不存在
//返回1: 存在
unsigned char DS18B20_Init(void)
{
DS18B20_Reset(); //复位总线
return DS18B20_CheckOnline();
}
ds18b20.h
#ifndef DS18B20_H
#define DS18B20_H
unsigned char DS18B20_Init(void);
unsigned char DS18B20_GetTemperature(float *temperatureBuf);
#endif
ds18b20_bus.c
#include "ds18b20_bus.h"
#include "debug.h"
// 这里延时需要修改成自己的
static void DS18B20_Delayus(unsigned char us) //@24.000MHz
{
unsigned int i;
i = 8 * us;
while (--i);
}
//DS18B20复位函数
void DS18B20_Reset(void)
{
DS18B20_DQ = 1;
DS18B20_DQ = 0;
// >480 us 低电平复位信号
DS18B20_Delayus(500);
DS18B20_DQ = 1;
// >15us 的上升沿 15-60us高电平后 是60-240us 的应答信号
DS18B20_Delayus(16);
}
unsigned char DS18B20_CheckOnline(void)
{
unsigned char retry = 0;
while ( DS18B20_DQ && (retry<50) )
{
retry++;
//大概4us
DS18B20_Delayus(4);
}
if(retry >= 50)
{
Debug_UartSendStr("DS18B20: Check online fail!\r\n");
return 0;
}
retry = 0;
// 保持240us的延时 完成整个的复位过程
while ( (!DS18B20_DQ) && (retry<60) )
{
retry++;
//大概4us
DS18B20_Delayus(4);
}
if(retry >= 60)
{
Debug_UartSendStr("DS18B20: Check online fail!\r\n");
return 0;
}
return 1;
}
// DS18B20写命令函数
// 向1-WIRE 总线上写1个字节
// u8 val 要写入字节
// DS18B20手册最下面有时序图
void DS18B20_WriteByte(unsigned char val)
{
unsigned char i;
for(i=0; i < 8; i++)
{
if(val&0x01) //写1
{
DS18B20_DQ = 0;
DS18B20_Delayus(4); //4us
DS18B20_DQ = 1;
DS18B20_Delayus(60); //60us
}
else //写0
{
DS18B20_DQ = 0;
DS18B20_Delayus(60); //60us
DS18B20_DQ = 1;
DS18B20_Delayus(4); //4us
}
val >>= 1;
}
}
// DS18B20读1字节函数
// 从总线上取1个字节
// 返回值为读取字节值
// 说明 一次1bit的读取最少需要60us 两次读取之间需要至少1us的恢复时间
// 单次读取1bit 总线拉低不能超过15us 然后马上拉高
unsigned char DS18B20_ReadByte(void)
{
unsigned char i;
unsigned char value = 0;
for(i=8; i>0; i--)
{
DS18B20_DQ = 1;
value >>= 1;
DS18B20_DQ = 0;
DS18B20_Delayus(8); //拉低4us
DS18B20_DQ = 1; //拉高
DS18B20_Delayus(12); //拉高10us 准备接收总线当前数据
if(DS18B20_DQ)
{
value |= 0x80; //将当前数据值存入临时变量
}
DS18B20_Delayus(55); //50 us延时 完成一次读取的延时(一次读取最少60us)跳过1us的恢复时间
}
DS18B20_DQ = 1;
return value;
}
ds18b20_bus.h
#ifndef __DS18B20_BUS_H_
#define __DS18B20_BUS_H_
#include <STC8.H>
#define DS18B20_DQ P53 //DS18B20 端口
void DS18B20_Reset(void);
unsigned char DS18B20_CheckOnline(void);
void DS18B20_WriteByte(unsigned char val);
unsigned char DS18B20_ReadByte(void);
#endif