基于STC15单片机及DS18B20的测温实操
对于DS18B20,之前在AT89C51上有一次调试经历,后面没再接触过了。这次由于实际需要,又用到了DS18B20。当把旧程序移过去之后,傻眼了,不成功!于是开始了漫长的调试过程!之前有一篇文章也分享过DS18B20的驱动程序了,关于DS18B20的时,大家可以自己查阅手册,只需要记住,这个片子,对时序要求还是高的。这是旨在分享自己真实可用的程序,对于时序部分的控制,为便于大家移植,已经做成固定函数,到时大家把对应的函数改一下就行了。
电路图

2.驱动程序--以个人经验,初始化程序很重要

#include <intrins.h>
#include "STC15F2K60S2.H"
#include "DS18B20.H"
#include "max7219.h"
#include "mainapp.h"
void Delay5us() //@22.1184MHz
{
unsigned char i;
_nop_();
i = 24;
while (--i);
}
void Delay5us_xn(int x)
{
while(x--)
{
Delay5us();
}
}
/**************复位***********************/
unsigned char DS1B20Init(void)
{
unsigned char i;
DQ=1;
_nop_();
DQ=0;
Delay5us_xn(96); //延时480us
DQ=1;
Delay5us_xn(12); //延时60us
i=0;
while(DQ) //在480us内检测DQ是否变为低,如果为低则复位成功,否则复位不成功
{
Delay5us();
i++;
if(i>96)
{
i=255;
break;
}
}
if(i==255)
return 0; //初始化失败
while(!DQ); //等待DS18B20释放总线
return 1; //初始化成功
}
/**********写一个字节数据到DS18B20***********/
void WriteDat(unsigned char dat)
{
unsigned char i;
for (i=8; i>0; i--) //
{
DQ=1;
_nop_();_nop_();
DQ=0;
Delay5us();
DQ=dat&0x01; //最低位移出
Delay5us_xn(13);
dat=dat/2; //右移一位
}
DQ=1;
Delay5us_xn(2);
}
/**********读一个字节数据从DS18B20***********/
unsigned char ReadDat(void)
{
unsigned char dat,i;
for (i=8;i>0;i--)
{
DQ=1;_nop_();_nop_();
dat>>=1;
DQ=0; //
Delay5us_xn(1);
DQ=1;
Delay5us_xn(1);
if(DQ)
dat|=0x80;
Delay5us_xn(13);
}
DQ=1;
return(dat);
}
void GetTep(unsigned char *TempDat)
{
unsigned char TPH=0;
unsigned char TPL=0;
EA = 0;
if(DS1B20Init())
{
WriteDat(0xCC); //跳过器件匹配
WriteDat(0x44); //发出温度转换命令
if(DS1B20Init())
{
WriteDat(0xCC); //跳过器件匹配
WriteDat(0xBE); //发出读数据命
TPL=ReadDat(); //低八位
TPH=ReadDat(); //高八位
if(TPH>0xf8) //负温度(TPH高五位是1)求补码
{
TPH=(256-TPH);
TPL=(256-TPL);
TempDat[2]=1; //表示0度以下
}
TempDat[1]=(TPL&0x0f)*0.625;
if(TempDat[1]>9)
TempDat[1]=9;
TempDat[0]=((TPL&0xf0)>>4)|((TPH&0x0f)<<4);//
Dot[0]=0;
Dot[1]=0;
Dot[2]=1;
Dot[3]=0;
}
else
{
DisDat[0]=7;
DisDat[1]=7;
DisDat[2]=7;
DisDat[3]=7;
Dot[0]=1;
Dot[1]=1;
Dot[2]=1;
Dot[3]=1;
}
}
else
{
DisDat[0]=8;
DisDat[1]=8;
DisDat[2]=8;
DisDat[3]=8;
Dot[0]=1;
Dot[1]=1;
Dot[2]=1;
Dot[3]=1;
}
EA = 1;
}3.演示程序
#include <intrins.h>
#include "STC15F2K60S2.H"
#include "DS18B20.H"
#include "max7219.h"
#include "mainapp.h"
/********************************************************
系统初始化程序,用于配置硬件和变量初始化设置
*********************************************************/
void SysInsatll(void)
{
AUXR &= 0x7F; //定时器时钟12T模式//50毫秒@12.000MHz
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0xB0; //设置定时初值
TH0 = 0x3C; //设置定时初值
TF0 = 0; //清除TF0标志
ET0 = 1; //允许定时器中断0
TR0 = 1; //定时器0开始计时
EA=1; //开总中断
}
unsigned int uiTestNum = 1000;
unsigned char tc=0; //读温度值的时间间隔控制【tc*50ms】
unsigned char tck=0; //前10次读出的数据不要,当tck的值为255时温度值才是有效值
unsigned char tepd[3]={0};
void main(void)
{
DisDat[0]=1;DisDat[1]=2;DisDat[2]=3;DisDat[3]=4;
Dot[0]=0;Dot[1]=0;Dot[2]=1;Dot[3]=0;
InitialMax7219(); //MAX7219初始化
P1=0xff;
DisPlay(); //显示子程序
SysInsatll(); //系统(中断及IO口)初始化
DelayNx10ms(1); //等待主机启动
//DisDat[0]=0;DisDat[1]=0;DisDat[2]=0;DisDat[3]=0;
while(1)
{
DisPlay(); //显示子程序
}
}
/**********************定时中断0服务子程序[用于显示控制及10ms计时]*******************************/
//1.可以通过设置Time门限控制LED数码管闪烁位的频率;
void DisPlayTimeInt0(void) interrupt 1 using 2//计时,精确到10ms
{
//float temp;
TR0 = 0;
TF0 = 0;
tc++;
if(tc==10)
{
//tepd=GetTep(); //读温度值
GetTep(tepd);
tc=0;
tck++;
if(tck>10)
{
tck=255; //前10次读出的数据不要,当tck的值为255时温度值才是有效值
}
}
/*
if(tepd[2]) //温度是0度下则当0度
{
tepd[0]=0;
tepd[1]=0;
}
*/
if(tck==255)
{
DisDat[0]=(tepd[0]/100);
DisDat[1]=((tepd[0]%100)/10);
DisDat[2]=((tepd[0]%100)%10);
DisDat[3]=(tepd[1]);
}
TL0 = 0xB0; //设置定时初值
TH0 = 0x3C; //设置定时初值
TR0 = 1;
}以上为主要部分和程序,需要完整工程代码,请到这里下载:http://pan.baidu.com/s/1pJqwLsR

凯特网版权声明:以上内容允许转载,但请注明出处,谢谢!
