【蓝桥杯】CT107D单片机之DS18B20

1、DS18B20的基本概述

工作电压:3.0V~5.5V。
测量范围:-55摄氏度~+125摄氏度。
通信方式:单总线,数据线接上拉电阻,使总线空闲时处于高电平。
转换精度:9~12位分辨率可调,默认为12位,即分辨率是0.0625。
转换时间:典型值200ms。

2、DS18B20内部结构

  主要由4部分组成:64 位ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。ROM中的64位序列号是出厂前被光刻好的,它可以看作是该DS18B20的地址序列码,每个DS18B20的64位序列号均不相同。64位ROM的排的循环冗余校验码(CRC=X8+X5+X^4+1)。 ROM的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20的目的。

在这里插入图片描述

3、DS18B20的内部存储结构

DS18B20的内部有64位的ROM单元和9字节的高速暂存器。64位ROM单元包含了DS18B20唯一的序列号。

在这里插入图片描述

第0字节:温度数据的低8位。
第1字节:温度数据的高8位。
第3字节:TH用户字节,设置报警温度最高值。
第4字节:TL用户字节,设置报警温度最低值。
第5字节:配置寄存器,设置转换精度,默认12位。
第6字节和第7字节:保留,不用管。
第8字节:CRC码。
注:上电后,第2字节、第3字节和第4字节的状态值为EEPROM中的数据。

4、DS18B20的数据处理

  DS18B20以16位带符号位扩展的二进制补码形式读出。低4位为小数部分,中间7位为整数部分,高5位为符号位。
在这里插入图片描述

  DS18B20的分辨率为0.0625。读出数据为正温度时,将LSB和MSB整合成的16位整数,直接乘以0.0625即可。读出数据为负温度时,则需要将LSB和MSB整合成的16位整数,取反加1后,再乘以0.0625。
  例如:
  读出结果为00A2H,温度值 = 162×0.0625 = 10.125 摄氏度。
  读出结果为FF5EH,取反加1就是00A2H,温度值则为 -10.125 摄氏度。

  注意:在上电复位的时候,温度寄存器中的值为0x0550,即+85摄氏度。

5、DS18B20的复位时序

在这里插入图片描述
【1】微处理器首先将总线拉低480us以上,然后释放总线。
【2】总线释放后,上拉电阻会将其拉至高电平。
【3】DS18B20发现总线有上升沿,等待15~60us后,拉低总线,表示应答。
【4】微处理器在DS18B20应答期间,读取总线上的电平,如果是低电平则表示复位成功。
【5】DS18B20在产生60~240us的应答信号后,会释放总线。

bit Init_DS18B20(void)
{
	bit initflag = 0;
	DQ = 0;
	Delay_OneWire(50);   //拉低总线480us以上 		
	DQ = 1;		         //释放总线							
	Delay_OneWire(5); 	 //等待15~60us		
	initflag = DQ;       //读取18B20的复位应答信号		
	Delay_OneWire(10);	 //等待60~240us		
  	return initflag;	 //应答信号为低电平,表示复位成功			
}

6、DS18B20的写时序(低位先发)

在这里插入图片描述
【1】微处理器将总线拉低10~15us。
【2】在接下来的15~45us直接,根据逻辑1或逻辑0,控制总线的高低电平。
【3】释放总线。

void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)             
	{
		DQ = 0;		         //先拉低总线电平10~15us						
		DQ = dat&0x01;	     //向总线写入一个位数据			
		Delay_OneWire(5);    //维持状态20~45us
		DQ = 1;	             //释放总线			
		dat >>= 1;           //准备发送下一个数据位			
	}
}

7、DS18B20的读时序(低位先读)

在这里插入图片描述
【1】微处理器先将总线拉低1us,然后释放总线。
【2】微处理器读取总线上的电平。
【3】微处理器读取电平后,延时约45us。

unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
	for(i=0;i<8;i++)
	{
		DQ = 0;              //先将总线电平拉低10~15us
		dat >>= 1;	     					
		DQ = 1;		     	 //然后释放总线						
		if(DQ)		     	 //读取总线上的电平状态						
		{
		    dat |= 0x80;
		}	    
		Delay_OneWire(5);    //延时45us左右,再度下一个数据位		
	}
	return dat;
}

8、DS18B20的温度转换与读取流程

[1] DS18B20复位。
[2]写入字节0xCC,跳过ROM指令。
[3]写入字节0x44,开始温度转换。
[4]延时700~900ms。
[5] DS18B20复位。
[6]写入字节0xCC,跳过ROM指令。
[7]写入字节0xBE,读取高速暂存器。
[8]读取暂存器的第0字节,即温度数据的LSB.
[9]读取暂存器的第1字节,即温度数据的MSB.
[10] DS18B20复位。 表示读取数据结束。
[11]将LSB和MSB整合成为一个16位数据。
[12]判断读取结果的符号,进行正负温度的数据处理。

9、DS18B20温度采集完整代码

硬件说明: IAP15F2K61S2
在这里插入图片描述

程序代码:

1、main.c

#include "reg52.h"  //定义51单片机特殊功能寄存器
#include "temp.h"  
#include "absacc.h"

sfr AUXR = 0x8E; 

unsigned char dspbuf[8] = {10,10,10,10,10,10,10,10};//显示缓冲区
unsigned char dspcom = 0;
unsigned char intr;
bit temper_flag = 0;//温度读取标志
code unsigned char tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
                            0xff};

void display(void);

void cls_buzz()
{
	P2 = ((P2&0x1f)|0xA0); 
	P0 = 0x00;
	P2 &= 0x1f;
}
void cls_led()
{
	P2 = ((P2&0x1f)|0x80); 
	P0 = 0xFF;
	P2 &= 0x1f;
}

//主函数
void main(void)
{ 
    unsigned char temperature;
	
	cls_buzz();cls_led();
    
	AUXR |= 0x80;
	TMOD &= 0xF0;
	TL0 = 0xCD;	
	TH0 = 0xD4;	
	TF0 = 0;	
	TR0 = 1;
	ET0 = 1;
	EA = 1;
	
    while(1)
    {
        if(temper_flag)
		{
			temper_flag = 0;
			temperature = rd_temperature();  //读温度         
        }
		
		//显示数据更新    
		(temperature>=10)?(dspbuf[6] = temperature/10):(dspbuf[6]=10);       
		dspbuf[7] = temperature%10; 
    }
}

//定时器中断服务函数
void isr_timer_0(void)  interrupt 1  //默认中断优先级 1
{
    display();
	if(++intr == 100)  //1ms执行一次
	{
        intr = 0;
		temper_flag = 1;  //100ms温度读取标志位置1
    }
}

//显示函数
void display(void)
{   
	P2 = ((P2&0x1f)|0xE0); 
	P0 = 0xff;
	P2 &= 0x1f;

	P0 = 1<<dspcom;	
	P2 = ((P2&0x1f)|0xC0); 
	P2 &= 0x1f;
	
	P0 = tab[dspbuf[dspcom]];	
    P2 = ((P2&0x1f)|0xE0); 
	P2 &= 0x1f;
	
    if(++dspcom == 8){
        dspcom = 0;
    }    
}

2、temp.c

#include "reg52.h"

sbit DQ = P1^4;

//单总线延时函数
#ifndef STC12  
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	while(t--);
}
#else
void Delay_OneWire(unsigned int t)  //STC12C5260S2
{
	unsigned char i;
	while(t--){
		for(i=0;i<12;i++);
	}
}
#endif

//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);
}

//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}

//DS18B20初始化
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(12);
  	DQ = 0;
  	Delay_OneWire(80); // 延时大于480us
  	DQ = 1;
  	Delay_OneWire(10);  // 14
  	initflag = DQ;     // initflag等于1初始化失败
  	Delay_OneWire(5);
  
  	return initflag;
}

//DS18B20温度采集程序:整数
unsigned char rd_temperature(void)
{
    unsigned char low,high;
  	char temp;
  
  	init_ds18b20();
  	Write_DS18B20(0xCC);
  	Write_DS18B20(0x44); //启动温度转换
  	Delay_OneWire(200);

  	init_ds18b20();
  	Write_DS18B20(0xCC);
  	Write_DS18B20(0xBE); //读取寄存器

  	low = Read_DS18B20(); //低字节
  	high = Read_DS18B20(); //高字节
  
  	temp = high<<4;
  	temp |= (low>>4);
  
  	return temp;
}

3、temp.h

#ifndef _TEMP_H
#define _TEMP_H

#define OW_SKIP_ROM 0xcc
#define DS18B20_CONVERT 0x44
#define DS18B20_READ 0xbe

//函数声明
unsigned char rd_temperature(void);

#endif
  • 3
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值