51单片机学习笔记:DS18B20测温程序
扫描二维码
随时随地手机看文章
C代码
#include"my51.h"
#include"smg.h"
#include"ds18b20.h"
voidmain()//测试,6位数码管显示温度值
{
u8i=0;
u16temp=0;
while(1)
{
temp=ds18b20_readTemperaData();
for(i=0;i<100;i++)
{
displaySMG(ds18b20_processTempData(temp));
}
}
}
C代码
#ifndef_DS18B20_H
#define_DS18B20_H
#include"my51.h"
#include"smg.h"
externu8smgWela[7];//数码管位选数据
sbitDQ=P2^2;//总线定义
boolds18b20_init();//初始化函数
u8*ds18b20_processTempData(u16temp);//将temp数据处理成数码管可显示数据
u16ds18b20_readTemperaData();//读温度
u8ds18b20_readByte();//读一个字节
voidds18b20_writeByte(u8dat);//mcu向18b20写一个字节
#endif
C代码
#include"ds18b20.h"
/******************************************************************
当主机总线t0时刻从高拉至低电平时就产生写时间隙
从to时刻开始的1us之后,15us之前将所需写的位送到总线上
DSl820在t0后的15-60us对总线采样若低电平写入的位是0,若高电平写入的位是1
连续写2个位之间的间隙应大于1us
写1,总时间大于60us,在t0开始延时1us就可以写1,15us之后ic来采样,采样时间最大45us
写0,总时间是60~120us,15~60us是ic在采样,120以外就没必要了,mcu总得释放总线吧
不管写1还是写0,大于60us的话,ic肯定已经采样完成了,那mcu就可以释放了
*******************************************************************/
voidds18b20_writeByte(u8dat)//mcu向ic写一个字节
{
u8i;
u8tmep=dat;
for(i=0;i<8;i++)
{
DQ=0;//产生读写时序的起始信号
_nop_();//要求至少1us的延时
DQ=dat&0x01;//对总线赋值,从最低位开始写起
delayXus(10);//延时74us,写0在60~120us之间释放,写1的话大于60us均可释放
DQ=1;//释放总线,为下一次mcu送数据做准备,
dat>>=1;//有效数据移动到最低位,2次写数据间隙至少需1us
}
}
/**************************************************************************
下降沿产生读时序
整个读时序必须至少有60us的持续时间,相邻两个读时序必须要有至少1us的恢复时间
DS18B20在读时序产生1us后输出数据到总线上,也有可能需要2~3个微秒,但不会更多
而要求主机释放总线和采样总线等动作要在15μs内完成,那么让mcu采样的最佳时机
是读时序产生后的5~13us之间,在15~60us这段时间是18b20的私有时间,它会在这段
时间内的任意时刻释放总线,是不稳定期,我们不要让mcu在这段时间里对总线操作
*******************************************************/
u8ds18b20_readByte()//mcu读一个字节
{
u8i,value=0;
for(i=0;i<8;i++)
{
DQ=0;//起始信号
value>>=1;//顺便延时3~4个机器周期
DQ=1;//mcu释放总线
_nop_();_nop_();_nop_();//再延时3.3us
if(DQ)
{
value|=0x80;//保存高电平数据,低电平的话不用保存,移位后默认是0
}
delayXus(8);//延时60.76us
}
returnvalue;
}
u16ds18b20_readTemperaData()//读取温度值
{
u16temp=0;
if(ds18b20_init())
{
ds18b20_writeByte(0xcc);//写指令:跳过rom检测
ds18b20_writeByte(0x44);//写指令:温度转换
//delayms(750);//转换延时需要750ms以上,我们不等它
//首次转换未完成时,得到的初始化数据是85度,处理一下就可以了
//温度转换电路是硬件独立的,不会阻塞初始化功能
if(ds18b20_init())
{
ds18b20_writeByte(0xcc);//写指令:跳过检测rom
ds18b20_writeByte(0xbe);//写指令:读取温度值
temp=ds18b20_readByte();//先读低8位数据
temp|=(u16)ds18b20_readByte()<<8;//再读高8位数据,然后合并
temp&=0x0FFF;//高4位数据反正没用上,我们用来存放错误码
}
else
{
led5=0;//调试代码
temp=0x2000;//错误码,初始化失败
}
}
else
{
led6=0;//调试代码
temp=0x1000;//错误码,初始化失败,可能器件损坏
}
returntemp;
}
boolds18b20_init()//初始化
{
u8checkState=0;
DQ=1;//总线初始状态