#include "reg52.h"
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit ds=P2^1; //sbit ds=P3^2;//DS18B20
sbit duan=P2^6;
sbit wei=P2^7;
uchar i;
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x00,0x40}; //0x00是用在显示函数中0x40显示“-”(负号)
//****************************************************************
void delay(uchar i)
{
uint j;
while(i--)
{
for(j = 0; j < 125; j++);
}
}
//****************************************************************
//延时函数, 对于11.0592MHz时钟, 例i=10,则大概延时10ms.
void dsInit()
{
//对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于8us
unsigned int i;
ds = 0;
i = 100; //拉低约800us, 符合协议要求的480us以上
while(i>0) i--;
ds = 1; //产生一个上升沿, 进入等待应答状态
i = 4;
while(i>0) i--;
}
void dsWait()
{
unsigned int i;
while(ds); //等待应答信号
while(~ds); //检测到应答脉冲
i = 4;
while(i > 0) i--;
}
//向DS18B20读取一位数据
//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,
//之后DS18B20则会输出持续一段时间的一位数据
bit readBit()
{
unsigned int i;
bit b;
ds = 0;
i++; //延时约8us, 符合协议要求至少保持1us
ds = 1;
i++;
i++; //延时约16us, 符合协议要求的至少延时15us以上
b = ds;
i = 8;
while(i>0) i--; //延时约64us, 符合读时隙不低于60us要求
return b;
}
//读取一字节数据, 通过调用readBit()来实现
unsigned char readByte()
{
unsigned int i;
unsigned char j, dat;
dat = 0;
for(i=0; i<8; i++)
{
j = readBit();
//最先读出的是最低位数据
dat = (j << 7) | (dat >> 1);
}
return dat;
}
//向DS18B20写入一字节数据
void writeByte(unsigned char dat)
{
unsigned int i;
unsigned char j;
bit b;
for(j = 0; j < 8; j++)
{
b = dat & 0x01;
dat >>= 1;
//写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1
if(b)
{
ds = 0;
i++;
i++; //拉低约16us, 符号要求15~60us内
ds = 1;
i = 8; while(i>0) i--; //延时约64us, 符合写时隙不低于60us要求
}
else //写"0", 将DQ拉低60us~120us
{
ds = 0;
i = 8; while(i>0) i--; //拉低约64us, 符号要求
ds = 1;
i++;
i++; //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us了
}
}
}
//向DS18B20发送温度转换命令
void sendChangeCmd()
{
dsInit(); //初始化DS18B20, 无论什么命令, 首先都要发起初始化
dsWait(); //等待DS18B20应答
delay(1); //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号
writeByte(0xcc); //写入跳过序列号命令字 Skip Rom
writeByte(0x44); //写入温度转换命令字 Convert T
}
//向DS18B20发送读取数据命令
void sendReadCmd()
{
// EA=0;//关闭中断是因为进入显示中断会影响到DS18B20的读写时序
dsInit();
dsWait();
delay(1);
writeByte(0xcc); //写入跳过序列号命令字 Skip Rom
writeByte(0xbe); //写入读取数据令字 Read Scratchpad
// EA=1;
}
//获取当前温度值
int getTmpValue()
{
unsigned int tmpvalue;
int value; //存放温度数值
float t;
unsigned char low, high;
// EA=0;
sendReadCmd();
//连续读取两个字节数据
low = readByte();
high = readByte();
//将高低两个字节合成一个整形变量
//计算机中对于负数是利用补码来表示的
//若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的value
tmpvalue = high;
tmpvalue <<= 8;
tmpvalue |= low;
value = tmpvalue;
//使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度
t = value * 0.0625;
//将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入
//如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度
//如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度
value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5
return value;
// EA=1;
}
/*
void Init_timer0()
{
TMOD=0x01;
TH0=th0;
TL0=tl0;
EA=1;
ET0=1;
TR0=1;
} */
void display(int dd)
{
uchar SH,SZ,SL,GH,GL,i,temp;
uchar dis[8]={10,10,10,10,10,10,10,10}; //从【5-8】的数字为10,相应的段码是0x00,即不显示
uint dda;
dda=abs(dd);
SH = dda/ 10000;
SZ = dda % 10000 / 1000;
SL = dda % 1000 / 100;
GH = dda % 100 / 10;
GL = dda % 10;
dis[0]=GL;
dis[1]=GH;
dis[2]=SL;
if((SZ==0)&&(SH==0))
dis[3]=10;
else
dis[3]=SZ;
if (dd<0)
dis[4]=11; //是负温度,显示“-”
else
{
if(SH==0)
dis[4]=10; //温度高位是0,不显示
else
dis[4]=SH;
}
temp=0xbf;
for(i=0;i<8;i++)
{
P0=0xff;
wei=1;
temp=_cror_(temp,1);
P0=temp;
wei=0;
P0=0;
duan=1;
if(i==2)
{
P0=0x80|table[dis[2]];
}
else
P0=table[dis[i]];
duan=0;
delay(1);
}
/*
P0=0xff;
wei=1;
P0=0xdf;
wei=0;
P0=0;
duan=1;
P0=table[GL];
delay(1);
duan=0;
P0=0xff;
wei=1;
P0=0xef;
wei=0;
P0=0;
duan=1;
P0=table[GH];
delay(1);
duan=0;
P0=0xff;
wei=1;
P0=0xf7;
wei=0;
P0=0;
duan=1;
P0=table[SL]|0x80;
delay(1);
duan=0;
P0=0xff;
wei=1;
P0=0xfb;
wei=0;
P0=0;
duan=1;
P0=table[SZ];
delay(1);
duan=0;
P0=0xff;
wei=1;
P0=0xfd;
wei=0;
P0=0;
duan=1;
P0=table[SH];
delay(1);
duan=0;
P0=0xff;
wei=1;
P0=0xff;
wei=0; */
}
void main()
{
int tempValue1;
// init();
// Init_timer0();
while(1)
{
//启动温度转换
sendChangeCmd();
tempValue1 = getTmpValue();
display(tempValue1);
}
}
//根据自己的硬件改改端口,我已经成功了
呀 C我看不懂,我只会点汇编,如果你的温度显示是8.5.9显然是你程序错了,两个小数点,如果程序调试没问题的话,大概有两种情况,一是你的DS18B20接反了,二是坏了,你用万用表检查一下,坏了就换一个
应该是时序不对,18B20对时序要求很严格