代码:
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
typedef unsigned int u16;
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;
sbit DS = P3^7;
char code smgduan[13]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x00,0x80,0x40}; //0~9数码
char display_T[8];
//毫秒延迟函数
void delayms(uint ms)
{
uchar i;
while(ms--)
for(i=0;i<123;i++);
}
//数码管显示函数
void Digdisplay()
{
char i;
for(i=0;i<8;i++)
{
switch(i)
{
case 0: LSC=1;LSB=1;LSA=1; break; //显示第1位数码管
case 1: LSC=1;LSB=1;LSA=0; break; //显示第2位数码管
case 2: LSC=1;LSB=0;LSA=1; break; //显示第3位数码管
case 3: LSC=1;LSB=0;LSA=0; break; //显示第4位数码管
case 4: LSC=0;LSB=1;LSA=1; break; //显示第5位数码管
case 5: LSC=0;LSB=1;LSA=0; break; //显示第6位数码管
case 6: LSC=0;LSB=0;LSA=1; break; //显示第7位数码管
case 7: LSC=0;LSB=0;LSA=0; break; //显示第8位数码管
}
P0=smgduan[display_T[i]]; //发送数据
delayms(1); //延时1ms,让数码管不断显示
P0=0x00; //数码管消遣
}
}
//DS18B20初始化函数
uchar Ds18b20_init()
{
unsigned char i;
DS = 0; //将总线拉低480US~960us
i = 70;
while(i--); //延时642us
DS = 1; //拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
i = 0;
while(DS) //等待DS18B20拉低总线
{
delayms(1);
i++;
if(i>5) //等待大于5MS,说明总线没有被拉低,初始化失败
{
return 0; //初始化失败
}
}
return 1; //若为低电平,直接跳过while循环初始化成功
}
//写时序函数
void Ds18b20WriteByte(uchar dat)
{
int i,j;
for(j=0;j<8;j++) //8位数据
{
DS = 0; //每写入一位数据之前先把总线拉低1us
i++;
DS = dat & 0x01; //然后写入一个数据,从最低位开始。位运算的与运算,只要数据中有0,则相与后为0,只有为1相与为1
i=6; //延时初值
while(i--); //延时68us,因为持续时间最少为60us
DS = 1; //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值
dat >>= 1; //移位,从低位向高位写入数据,所以,最低为写入后,向右移,原来的次低位代替原来的低位。
}
}
//读时序函数
uchar Ds18b20ReadByte()
{
uchar byte,bi;
uint i,j;
for(j=8;j>0;j--)
{
DS = 0; //先将总线拉低1us
i++;
DS = 1; //然后释放总线
i++;
i++; //延迟6us等待数据稳定
bi = DS; //读取数据,从最低位开始读取
/*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0 */
byte = (byte >> 1) | (bi << 7); //现将byte右移一位,然后bi左移七位,相或得到数据
i=4; //读取完之后等待48us再接着读取下一个数
while(i--);
}
return byte;
}
//转换温度启动指令
void Ds18b20ChangTemp()
{
Ds18b20_init(); //初始化
delayms(1);
Ds18b20WriteByte(0xcc); //写入跳过ROM操作命令(cc)
Ds18b20WriteByte(0x44); //温度转换命令(44)
}
//读取温度命令
void Ds18b20ReadTempCom()
{
Ds18b20_init();
delayms(1);
Ds18b20WriteByte(0xcc); //跳过ROM操作命令
Ds18b20WriteByte(0xbe); //发送读取温度命令
}
//读取温度
int Ds18b20ReadTemp()
{
int temp = 0;
uchar tmh,tm1;
Ds18b20ChangTemp(); //先写入转换命令
Ds18b20ReadTempCom(); //然后等待转换完后发送读取温度命令
tm1 = Ds18b20ReadByte(); //读取温度值共16位,先读低字节
tmh = Ds18b20ReadByte(); //再读高字节
temp = tmh;
temp <<= 8; //移位运算,高字节左移8位,变为16位
temp |= tm1; //位运算中的或运算,组合
return temp; //高8位和低8位的组合
}
//数码管显示温度
void ds20b18display(int temp)
{
float tp;
if(temp < 0)
{
display_T[0] = 12; //显示“-”
temp=temp-1; //因为读取的温度是实际温度的补码,所以减1,再取反求出原码
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5; //0.0625是精度
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算加上0.5,还是在小数点后面。
}
else
{
display_T[0] = 10; //无显示
tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
//如果温度是正的那么,那么正数的原码就是补码它本身
temp=tp*0.0625*100+0.5;
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算加上0.5,还是在小数点后面。
}
display_T[2] = temp/10000; //显示百位
display_T[3] = temp%10000/1000; //显示十位
display_T[4] = temp%1000/100; //显示个位
display_T[6] = temp%10/10; //显示小数点后一位
display_T[7] = temp%10; //显示小数点后两位
display_T[1] = 10; //无显示
display_T[5] = 11; //显示“.”
}
void main()
{
Ds18b20_init();
while(1)
{
ds20b18display(Ds18b20ReadTemp());
Digdisplay();
}
}
结果图: