1、怎么读

由于与DS1302相关的子函数都已经在"onewire.c"中给出,因此我们直接调用即可。从DS18B20中得到的数据是16位的,有时我们读取的温度只需要整数部分即可,而有些时候则需要读出小数点后的一位至两位,那么如何实现呢?
若读取到的16位温度数据temp16(16代表该数据为int型),若精确到整数部分,则将temp0.0625;若精确到小数点后一位,则将temp0.625若;精确到小数点后两位,则将temp*6.25 ,例如此时温度为24.56摄氏度(LSB为低八位 MSB为高八位)
(1)只读取整数部分,注意此时的temp8为char类型,此时temp8 = 24;

	temp16 = (MSB<<8) | LSB;
	temp8 = temp * 0.0625;

(2)读取小数点后一位,此时的temp16为int类型,此时temp16 = 245;

	temp16 = (MSB<<8) | LSB;
	temp16 = temp16 * 0.625;

(3)读取小数点后两位,此时的temp16为int类型,此时temp16 = 2456;

	temp16 = (MSB<<8) | LSB;
	temp8 = temp16 * 6.25;

2、数码管显示温度:

注意:由于15的速度比51快12倍,所以在驱动程序里面的延时函数Delay_OneWire应该扩大12倍,以确保时序。

比赛中给出的延时函数驱动代码:

void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	while(t--);
}

更改之后:

void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	t=t*12;
	while(t--);
}

(1)只显示整数部分

在onewire.c文件中写DS18B20读温度函数

unsigned char rd_temperature(void)
{
	unsigned char LSB,MSB,temp8;
	unsigned int temp16;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	init_ds18b20();	
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	LSB = Read_DS18B20();
	MSB = Read_DS18B20();	
	temp16 = (MSB<<8) | LSB;
	temp8 = temp16 * 0.0625;
	return temp8;
}

main.c函数如下:

#include "STC15F2K60S2.h"
#include "intrins.h"
#include "onewire.h"
#define uchar unsigned char
#define uint unsigned int
	
uchar segCode[25]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,       //0~9的段码(不带小数点)
								 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff}; //0.~9.的段码(带小数点) 以及0xff全灭
uchar segVal[]={20,20,20,20,20,20,20,20};  //数码管初始化显示1 2 3 4 1. 2. 3. 4.

void SelectHC573(uchar val) 
{
	switch(val)
	{
		case 4 : P2 = (P2 & 0x1f) | 0x80; break;
		case 5 : P2 = (P2 & 0x1f) | 0xa0; break;
		case 6 : P2 = (P2 & 0x1f) | 0xc0; break;
		case 7 : P2 = (P2 & 0x1f) | 0xe0; break;
		default: P2 = (P2 & 0x1f); break;		
	}
}
void InitSystem()//系统初始化关闭蜂鸣器、继电器、LED
{
	SelectHC573(5);
	P0 = 0xbf;      //由于不同板子的引脚接法不同,此时的初始值也不同
	SelectHC573(4);	
	P0 = 0xff;     //LED全灭
}
void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
	EA = 1;
}
uchar segFlag = 0;//数码管显示位标志位
uint count1s = 0;//1s定时标志位
bit tempFlag = 1;//DS18B20读温度的标志位,为1时读温度,为0时不读
void ServiceTimer0() interrupt 1
{
	uchar pushp0,pushp2;
	pushp0 = P0;
	pushp2 = P2;//入栈
//数码管
	SelectHC573(6);
	P0 = (0x01<<segFlag);
	SelectHC573(7);	
	P0 = segCode[segVal[segFlag]];
	segFlag++;
	if(segFlag == 8) segFlag = 0;
//1s定时,DS18B20读温度
		count1s++;
		if(count1s>=1000)//定时1s
		{
			count1s = 0;
			tempFlag =1;//将读温度的标志位置1
		}
	P2 = pushp2;//出栈
	P0 = pushp0;
}
uchar tem;
void main()
{
	InitSystem();
	Timer0Init();
	tem = rd_temperature();//将DS1302第一次读取的温度丢弃
	while(1)
	{		
		if(tempFlag==1)//当读温度的标志位为1时,读一次温度
		{
			segVal[6] =  rd_temperature()/10;
			segVal[7] =  rd_temperature()%10;		
			tempFlag=0;//读完一次温度后,将读温度的标志位置0,实现1s读一次温度
		}
	}
}

显示结果如下:

(2)显示小数点部分

onewire.c文件:

unsigned int rd_temperature(void)
{
	unsigned char LSB,MSB;
	unsigned int temp16;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	init_ds18b20();	
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	LSB = Read_DS18B20();
	MSB = Read_DS18B20();	
	temp16 = (MSB<<8) | LSB;
	temp16 = temp16 * 0.625;
	return temp16;
}

main.c函数(其余地方不用修改):

	segVal[5] =  rd_temperature() / 100;
	segVal[6] =  rd_temperature() % 100 / 10 + 10;//+10是因为数码管段码中将含小数点的段码放到了9以后的数组中
	segVal[7] =  rd_temperature() % 10;		

显示结果如下: