关于DS18B20温度测量的小程序,求找错
初学单片机,仿照视频用郭天祥的TX-1C开发板写了个温度计的小程序,温度高于20度时还正常,但以低于20度就出错。用别人的程序试了一下板子,温度测量都正常,应该是代码问题,实在找不出错了,有木有高人能指点一下哈
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
/**************************************************
DS18B20相关数据定义
**************************************************/
sbit DQ=P2^2;//声明DS18B20
uchar th;//用于存储温度高字节
uchar tl;//用于存储温度低字节
short int temp;//用于存储转换完成以后的温度
float t;
/**************************************************
1602相关数据定义
**************************************************/
sbit lcden=P3^4;
sbit lcdrs=P3^5;
short int tem[5];
uint i;
uint j;
sbit dula=P2^6;
sbit wela=P2^7;
/**************************************************
公共数据定义
**************************************************/
uint time;
/**************************************************
公共函数
**************************************************/
//延时1微秒
void delay1ms()
{
unsigned char i,j;
for(i=0;i<4;i++)
for(j=0;j<33;j++);
}
//延时n微秒
void delaynms(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
delay1ms();
}
/**************************************************
DS18B20操作函数
**************************************************/
//初始化DS18B20
bit Init_DS18B20()
{
uint flag=1;
DQ=1;
for(time=2;time>0;time--);
DQ=0;
for(time=200;time>0;time--);
DQ=1;
for(time=10;time>0;time--);
flag=DQ;
for(time=200;time>0;time--);
return flag;
}
//从DS18B20读取一个字节
uchar ReadOneChar()
{
uint i;
uchar dat;
for(i=0;i<8;i++)
{
DQ=1;
_nop_();
DQ=0;
_nop_();
DQ=1;
for(time=0;time<2;time++);
dat>>=1;
if(DQ==1)
{
dat|=0x80;
}else
{
dat|=0x00;
}
for(time=0;time<8;time++);
}
return dat;
}
//向DS18B20写入一个字节
WriteOneChar(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DQ=1;
_nop_();
DQ=0;
_nop_();
DQ=dat&0x01;
for(time=0;time<15;time++);
DQ=1;
for(time=0;time<1;time++);
dat>>=1;
}
for(time=0;time<4;time++);
}
//温度换算
void TempByteToInt()
{
temp=th;
temp<<=8;
temp|=tl;
t=temp*0.0625;
temp=t*10+0.5;
}
//读取一次温度
void ReadOneTemp()
{
Init_DS18B20();
WriteOneChar(0xCC);
WriteOneChar(0x44);
delaynms(200);
Init_DS18B20();
WriteOneChar(0xCC);
WriteOneChar(0xBE);
tl=ReadOneChar();
th=ReadOneChar();
TempByteToInt();
}
/**************************************************
1602操作函数
**************************************************/
//向1602写指令
void write_com(uchar com)
{
lcdrs=0;
P0=com;
delaynms(5);
lcden=1;
delaynms(5);
lcden=0;
}
//向1602写数据
void write_data(uchar date)
{
lcdrs=1;
P0=date;
delaynms(5);
lcden=1;
delaynms(5);
lcden=0;
}
//初始化1602
void init_1260()
{
dula=0;
wela=0;
lcden=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
}
//显示温度
void writeTemp()
{
if(temp!=0){
if(temp>0)
{
write_data('+');
}
if(temp<0)
{
temp*=-1;
write_data('-');
}
i=0;
while(temp){
tem=temp%10;
temp/=10;
i++;
}
j=i;
for(;i>0;i--){
if(j==1){
write_data('0');
}
if(i==1){
write_data(0x2e);
}
write_data('0'+tem[i-1]);
}
}else
{
write_data('0');
write_data(0x2E);
write_data('0');
}
write_data(0x43);
write_data(0xDF);
}
void main()
{
while(1)
{
ReadOneTemp();
init_1260();
writeTemp();
for(time=0;time<20;time++)
{
delaynms(100);
}
}
}
20度以上正常
低于20度时
低于20度时
给你个参考
程序的一部分:
/********************DS18B20初始化操作***************************/
uchar init_DS18B20()
{
ucharstatus ;
DQ=1;
delay10us(); //延时10us
DQ=0;
delay614us();
DQ=1; //延时等待30us
delay10us();
delay10us();
delay10us();
status=DQ; //这个时间一定要长最少204us
delay102us();
delay102us();
delay102us();
delay102us();
DQ=1; //最后总线又拉高
returnstatus;
}
/**************************DS18B20读操作*****************************/
uchar DS18B20_readbyte()
{
uchari,dat=0;
DQ=1;
_nop_(); //稍微延时1us
for(i=0;i<8;i++)
{
DQ=0; //最少延时1us
_nop_();
_nop_();
_nop_();
dat>>=1;
DQ=1;
_nop_();
_nop_();
if(DQ)dat|=0x80;
else
dat=dat|0x00;
/****下面的延时时间一定要搞仔细了,时间太短会闪烁,估计是每两个读之间必须得隔离相当长的时间*****/
delay102us();
delay102us();
delay102us();
delay102us();
DQ=1; //数据线拉高
}
returndat;
}
/**************************************DS18B20写操作************************************/
void DS18B20_writebyte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DQ=0;
DQ=dat&0x01; //要延时确定时间15us
delay10us();
delay5us();
dat>>=1; //延时为45us ,同时需要注意写的时候是一位一位的写。
delay10us();
delay10us();
delay10us();
delay10us();
delay5us();
DQ=1;
}
DQ=1; //数据线最后又拉高
}
/************************************读取DS18B20当前温度值***********************************/
void read_temperature()
{
if(init_DS18B20()==0)
{
DS18B20_writebyte(0xcc); //跳过ROM
DS18B20_writebyte(0x44); //温度转换
}
if(init_DS18B20()==0) //注意啊,每一次读写操作都得先要将DS18B20初始化,而且还得确保初始化成功
{
DS18B20_writebyte(0xcc); //跳过ROM
DS18B20_writebyte(0xbe); //读取RAM中温度
temperature0=DS18B20_readbyte();
temperature1=DS18B20_readbyte();
}
}