调了好久,总是显示30多度,可是现在室温只有20多度啊,而且有时还跳到60多。时序也用示波器查了很久,实在是没招了,还望有大侠能给出出主意。
#include<reg51.h>
#include<intrins.h>
#include<math.h>
#include<stdio.h>
#include<string.h>
typedef unsigned char uchar;
typedef unsigned int uint;
bit Measure_temp_flag;
bit Display_flag;
bit flag;
sbit LE=P2^4;//573锁存端
sbit DQ=P3^7;//DS18B20的数据通信线
int tpl_test,tph_test;//温度值的低位和高位字节
int temp_Dis[]={0,0,0,0,0};//测试温度的十进制数值
int temp_Set_Dis[]={0,0,0,0};//设置温度的十进制数值
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79}; //共阴字符表,不显示小数点(0~9,P,I,d,F,灭)
unsigned char code table_p[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //共阴字符表,显示小数点(0~9)
unsigned char code table_Wei[6]= {0x02,0x01,0x00,0x05,0x04,0x03};//位选,对应U3低位中位高位,u5低位中位高位
uint TIM0;//定时器0发生定时的次数
uint TIM1;//定时器1发生定时的次数
uint INTO_TIME;//外中断0发生次数
void display(int Dis[], uint U_D)
{
int i=0,j=0;
if(U_D==0)//U3数码管显示测试的温度
{
for(i=0;i<3;i++)//选择某一位数码管
{
P2&=0xf0;
P2|=table_Wei[i];
LE=1;
if(i==1)
{
P0=table_p[Dis[i]];//中间位显示带小数点的
}
else
{
P0=table[Dis[i]];//送要显示的数
}
LE=0;
for(j=0;j<=1000;j++);//延时
// delay(2);
// P0=0x00;
}
}
if(U_D==1)//U5数码管显示设置的温度
{
for(i=0;i<3;i++)//选择某一位数码管
{
P2&=0xf0;
P2=P2|table_Wei[i+3];
LE=1;
if(i==1)//if((i==1)&&(INTO_TIME==1))
{
P0=table_p[Dis[i]];//中间位显示带小数点的
}
else P0=table[Dis[i]];//送要显示的数
LE=0;
for(j=0;j<=1000;j++);//延时
}
}
}
void BtoD(int value_h,int value_l)
{
uint j=0;
uint tempD;
int tzheng,txiao,a,b;
float k;
a=(value_l&0xf0)>>4;b=value_h;
tzheng=a|b;//取整
txiao=value_l&0x0f; //取小数
if(value_h&0x80)//说明是负数
{
tzheng=~tzheng;
txiao=(txiao^0x0f)+0x01;
k=((float)(tzheng|0x80)+(float)txiao*0.0625);
}
else//说明是正数
{
k=(float)(b*16+a)+(float)(txiao*0.0625);
}
k=k*10;//只取前三位
tempD=(uint)k;
while(tempD!=0)//分离用于显示,temp_Dis[0]最低位,其次为temp_Dis[1],temp_Dis[2],其中temp_Dis[1]要求显示小数点
{
temp_Dis[j]=tempD%10;
tempD/=10;
j++;
}
}
void delay2us(uchar t)//延时2us,误差最大5us
{
while(--t);
}
void delay(unsigned int t)//延时函数,实测延时1.52ms
{
unsigned int i;
while(t--)
{
for(i=0;i<125;i++)//延时1ms
{}
}
}
bit TxReset(void)
{
DQ=1;//DQ复位;
delay2us(4);//稍做延迟,实测拉低14us
DQ=0;
delay2us(240);//拉低至少480us,本操作实测拉低490us
delay2us(80);//实测拉低170us;
DQ=1;
delay2us(25);//实测拉高56us
flag=DQ;
delay2us(100);
DQ=1;
return (flag);
}
void WrByte(uchar dat)//写时序
{
uint i;
bit btmp;
for(i=0;i<8;i++)
{
btmp=dat&0x01;
dat>>=1;
if(btmp)//写1
{
DQ=1;
_nop_();
DQ=0;
_nop_();
DQ=1;
delay2us(30);//写1至少释放60us,实测
}
else//写0
{
DQ=1;
_nop_();
DQ=0;
delay2us(30);//写0拉低至少60us
DQ=1;
_nop_();
_nop_();
}
delay2us(5);
}
}
uchar RdByte(void)
{
uchar i,dat;
dat=0;
for(i=0;i<8;i++)
{
DQ=1;
_nop_();
DQ=0;
_nop_();
DQ=1;
delay2us(1);//实测
if(DQ)
{dat|=0x80;}
dat>>=1;
delay2us(20);
}
return (dat);
}
void t_test(void)
{
TxReset();//产生复位脉冲,初始化DS18B20
if(flag==0)
{
WrByte(0xcc);//0xcc表示DS18B20的skip rom命令
WrByte(0x44);//DS18B20温度转换命令
delay(200);//实测延时304ms
delay(200);
TxReset();
WrByte(0xcc);
WrByte(0xbe);//DS18B20的Read Scratchpad 命令,用于读取暂存器内容
tpl_test=RdByte();//温度值的低位字节
tph_test=RdByte();//温度值的高位字节
}
}
void timer0(void) interrupt 1 using 1//定时器0
{
TIM0++;
P2_6=0;
if(TIM0==500)//1000ms
{
Measure_temp_flag=1;
TIM0=0;
P2_6=!P2_6;
}
TH0=-(10000/256);// 重新装载T0定时器
TL0=-(10000%256);
}
void main(void)
{
P2_6=1;P2_7=1;//初始灭灯
Measure_temp_flag=0;
TIM0=0;TIM1=0;
INTO_TIME=0;
IE=0x8B;//打开ET1,ET0,EX0
IP=0x01;//INTO优先级最高
TMOD=0x11;//T1T0同为定时器,方式1
TR0=1;//定时器0启动
TH0=-(10000/256);//
TL0=-(10000%256);
do
{
do
{
BtoD(tph_test,tpl_test);
//调用显示温度子程序
display(temp_Dis,0);//数码管U3显示
}while(!Measure_temp_flag);
Measure_temp_flag=0;
t_test(); //调用测温函数
}while(1);
}
|