51 温度传感器 DS18B20程序代码

我们先来看一下 DS18B20 的硬件原理图:
51 温度传感器 DS18B20程序代码_第1张图片
DS18B20 通过编程,可以实现最高 12 位的温度存储值,在寄存器中,以补码的格式存储,如图所示。

51 温度传感器 DS18B20程序代码_第2张图片
下面我们就写一个程序,将读到的温度值显示在 1602 液晶上,并且保留一位小数位。

/**
1、温度从哪里来–》DS18B20传感器,
2、怎么去获取温度,配置好了,何时去取出温度?,需要过多久你才去拿一次温度的值
时间操作 -》 定时器操作 —> 中断 + 标志位
3、取出温度后,要进行怎样的处理? 数据类型的一个转换处理, 整型 -》 字符串型
4、温度的值有可能是负数,也有可能是正数, -》》 做一个判断

5、相关显示操作

**/

/ds18b20.h文件程序源代*/

#ifndef _DS18B20_H_
#define _DS18B20_H_

#include 
#include 
#define uchar unsigned char
#define uint unsigned int


//实现位绑定操作
sbit DS18B20_IO = P3^2;

/**初始化DS18B20**/
bit InitDS18B20ACK();

/**us延时函数**/
void delay_10us(uchar count);

/**向DS18B20写入一个字节的数据**/
void writeToDs18b20(uchar dat); 

/**向DS18B20读取一个字节的数据**/
uchar readeToDs18b20(); 

/**启动DS18B20进行温度的采集以及转换,并返回读取成功与否**/
bit startDs18b20();

/**读取DS18B20中的温度转换,并返回读取成功与否,而已还需要吧温度回去**/
bit getTempForDs18b20(int *temp);

#endif


/ds18b20.c文件程序源代*/

#include "ds18b20.h"

//DS18B20_IO = 0;

/**初始化DS18B20**/
bit InitDS18B20ACK(){
	bit ACK;//用来判断DS18B20是否初始化成功
	EA = 0;
	DS18B20_IO = 0;
	delay_10us(60);
	DS18B20_IO = 1;
	delay_10us(5);
	ACK = DS18B20_IO;
	while(!DS18B20_IO);//等待脉冲结束
	EA = 1;
	return ACK;
}

/**向DS18B20写入一个字节的数据**/
void writeToDs18b20(uchar dat){
		uchar mask;
		EA = 0;//关闭总中断开关
		for(mask = 0x01; mask != 0; mask <<= 1){
				DS18B20_IO = 0;
			_nop_();
			_nop_();
			if((mask & dat) == 0){
					DS18B20_IO = 0;
			}else{
				DS18B20_IO = 1;	////
			}
			delay_10us(6);
			DS18B20_IO = 1;
		}
		EA = 1;//开启中断
}

/**向DS18B20读取一个字节的数据**/
uchar readeToDs18B20(){
		uchar readData;
		uchar mask;
		EA = 0;
		for(mask = 0x01; mask !=0; mask <<= 1){
				DS18B20_IO = 0;
				_nop_();
				_nop_();
				DS18B20_IO = 1;
				_nop_();
				_nop_();
				if(!DS18B20_IO){
						readData &= ~mask;//读取0
				}else{
						readData |= mask;//读取1
				}
				delay_10us(6);
		}
			EA = 1;
			return readData;
}

/**启动DS18B20进行温度的采集以及转换,并返回读取成功与否**/
bit startDs18b20(){	
	bit ACK;
	ACK = InitDS18B20ACK();//总线初始化是否完成
	if(ACK == 0){
		writeToDs18b20(0xcc);//跳过ROM的验证操作
		writeToDs18b20(0x44);//启动温度的转换
	}
	return ACK;//ACK == 0 启动成功,1就不成功
}

/**读取DS18B20中的温度转换,并返回读取成功与否,而已还需要吧温度回去**/
bit getTempForDs18b20(int *temp){
	bit ACK;
	uchar MSB,LSB;
	ACK = InitDS18B20ACK();
	if(ACK == 0){
		writeToDs18b20(0xcc);//跳过ROM的验证操作
		writeToDs18b20(0xbe);//发送一个读取的命令
		LSB = readeToDs18b20();
		MSB = readeToDs18b20();
		*temp = ((int)MSB << 8) + LSB;
	}
	return ACK;
}

/**us延时函数**/
void delay_10us(uchar count){
	do{
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
	}while(count--);
}

/lcd1602.h文件程序源代*/
/lcd1602.c文件程序源代*/
(此处省略,可参考之前博客的代码)

/main.c文件程序源代*/

#include "ds18b20.h"
#include "lcd1602.h"

#define  ulong unsigned long
ulong time_count = 0;//记录定时器溢出次数
bit readTemFlags = 0;//读取温度标志位
int temperature = 0;//温度值
bit ACK;
int temp = 0;
int i;

/**配置定时器0**/
void cofigTimerZero(){
	TMOD &= 0xf0;//定时器寄存器低四位清零
	TMOD |=0x01;//配置工作模式
	TH0 = 0xb8;
	TL0 = 0x00;//定时20ms
	EA = 1; //总中断开关
	ET0 = 1; //定时器0开关
	TR0 = 1;//定时器运行
}

/**定时器0的中断服务函数**/
void timer_zeroInterrupt() interrupt 1{
	TH0 = 0xb8;
	TL0 = 0x00;//定时20ms
	time_count++;
	if(time_count%20 == 0){
		readTemFlags = 1;
	}
}

/**整形转换成字符类型,参数:传入你要转换的数据,返回字符串的长度**/
uchar IntToString(uchar *str,int changeDat){
	uchar len_str = 0,i = 0;//记录字符串的长度
	uchar temp_buf[6]; 
	if(changeDat < 0){
			changeDat = -changeDat;//赋值为负数
			*str++ = '-';
			len_str++;
	}
	do{
		temp_buf[i++] = changeDat % 10;
		changeDat /= 10;
	}while(changeDat > 0);
		len_str = len_str + i;//得到最新的长度
		while(i--){
			*str++ = temp_buf[i] + '0';//对于转换成字符串
		}
		*str = '\0';//字符串接收标志位的添加
		return len_str;
}

/* 串口配置函数,baud-通信波特率 */
void ConfigUART(unsigned int baud)
{
 SCON = 0x50; //配置串口为模式 1
 TMOD &= 0x0F; //清零 T1 的控制位
 TMOD |= 0x20; //配置 T1 为模式 2
 TH1 = 256 - (11059200/12/32)/baud; //计算 T1 重载值
 TL1 = TH1; //初值等于重载值
 ET1 = 0; //禁止 T1 中断
 ES = 1; //使能串口中断
 TR1 = 1; //启动 T1
	
}

/**串口数据提交**/
void TXD_Dat(uchar dat){
	SBUF = dat;
	while(!TI);
	TI = 0;
}
/* UART 中断服务函数 */
void InterruptUART() interrupt 4
{
	if(RI){
		temp = SBUF;
		RI = 0;
	}
}

/**主函数**/
void main(){
	
	int temp_int,temp_dec;//温度的整数和小数
	uchar len;//长度
	uchar str[8];
	cofigTimerZero();
	inItLcd1602();
	startDs18b20();
	
	EA = 1; //使能总中断
  ConfigUART(9600); //配置波特率为 9600
	
	while(1){
		if(readTemFlags == 1){
			readTemFlags = 0;//清零
			ACK = getTempForDs18b20(&temperature);
			
			if(~ACK){
				temp_int = temperature >> 4;//取整数部分
				temp_dec = temperature & 0xf;//取小数部分
				len = IntToString(str,temp_int);
				str[len++] = '.';//添加一个小数点
				
				//处理小数部分
				temp_dec = (temp_dec * 10)/16;//二进制小数部分转换为十六进制
				str[len++] = temp_dec + '0';
				while(len < 6){
					str[len++] = ' ';
				}
					for(i = 0;i < sizeof(str);i++){
						TXD_Dat(str[i]);
					}
					str[len] = '\0';
					Lcd1602Display(0,2,str);
			}else{
					Lcd1602Display(0,0,"error!!");//错误信息
			}
		}
		startDs18b20();
	}
}


	

效果图:

51 温度传感器 DS18B20程序代码_第3张图片

你可能感兴趣的:(51 温度传感器 DS18B20程序代码)