单片机常用芯片系列(二)——DS18B20详解

温度范围:-55℃到125℃
默认12位精度,0.0625℃一格

因为网上很多ds18b20的中文资料,我只说一下最不容易理解的几个点。代码再最后

单总线通信。数据什么的都在一根线上传输。
读写时序为什么一样?因为在读写之前要先发命令。比如先发一个0x44,就是启动温度转换,然后发送0xbe,再读数据。温度转换后温度数据被放在ram中的第1.2字节,掉电丢失,芯片复位不丢失。所以执行一次温度转换,可以读好几次。不过记住,每次发送命令之前都要执行复位函数,再发命令。温度的2字节和配置可以放入eeprom中,不过目前没啥用。
出场默认精度12位,11位数据1位符号。剩下4位随着符号位变化。

在执行完ROM操作命令后,我们需要进行的就是RAM操作命令,我们先来认识一下高速暂存RAM。暂存器由9个字节组成。

第1第2两个字节包含测得温度信息,温度传感器(温度灵敏元件)测得的温度值被存储到高速暂存器的这两个字节(温度寄存器)。
以12位精度存储温度,最高位为符号位,负温度S=1,正温度S=0。将存储器中的二进制数求补再转换成十进制数乘以精度(0.5、0.25、0.0625)就得到被测温度值。如0550H为+85℃,0191H为
+25.0625℃,FC90H为-55℃,上电初始为+85℃。第3和第4个字节是 TH 和 TL 的易失性拷贝(从EEPROM拷贝到高速暂存器这两个字节),在每一次上电复位时被刷新;

第5个字节是配置寄存器,如图,用户可按照“温度计精确度配置”表,来修改R1R2的值,来设定DS18B20的精度,上电默认设置R1R0=11(12位精度),配置寄存器的其他为均保留,禁止写入;
第6、7、8字节被保留,禁止写入;
第9个字节是只读的,包含以上八个字节的CRC码;

再看一下RAM操作指令(功能指令)
在发送ROM操作指令后,下一步需要进行RAM操作指令。这些指令允许总线控制器读写DS18B20的暂存器,发起温度转换和识别电源模式。DS18B20的功能指令详见下文。
CONVERTT [44h] (温度转换指令)
这条命令用以启动一次温度转换。温度转换指令被执行,产生的温度转换结果数据以2个字节的形式被存储在高速暂存器中,而后DS18B20保持等待状态。如果寄生电源模式下发出该命令后,在温度转换期间(tconv),必须在10us(最多)内给单总线一个强上拉。如果DS18B20以外部电源供电,总线控制器在发出该命令后跟着发出读时序,DS18B20如处于转换中,将在总线上返回 0,若温度转换完成,则返回 1。寄生电源模式下,总线被强上拉拉高前这样的通讯技术不会被使用。
WRITESCRATCHPAD [4Eh] (写暂存器指令)
这条命令向 DS18B20 的暂存器写入数据,开始位置在 TH 寄存器(暂存器的第 2个字节),接下来写入 TL 寄存器(暂存器的第 3 个字节),最后写入配置寄存器(暂存器的第 4 个字节)。数据以最低有效位开始传送。上述三个字节的写入必须发生在总线控制器发出复位命令前,否则会中止写入。
在这里插入图片描述写是往2.3.4个字节里依次写数据。

在这里插入图片描述这个配置寄存器里只有两个能改动,R1R0;

在这里插入图片描述

在这里插入图片描述所以这样写就行,先把前两个给他添上,再接着写命令就可以写到配置寄存器里

			DS18B20Write(0x4e);			//写暂存器指令4E
			DS18B20Write(0x4b);			//写高速缓存器TH高温限值75度
			DS18B20Write(0x00);			//写高速缓存器TL低温限值0度
			DS18B20Write(0x1f);	
						//0x1f : 0.5000°C  转换时间93.75ms
						//0x3f : 0.2000°C  转换时间187.5ms
						//0x5f : 0.1250°C  转换时间375ms
						//0x7f : 0.0625°C  转换时间750ms

接下来是一些命令,有的前面带0是打错了,不用看第一个0

扫描二维码关注公众号,回复: 9124075 查看本文章

在这里插入图片描述每一次读写之前都要对 DS18B20 进行复位,复位成功后发送一条 ROM 指令,最后发送 RAM 指令,这样才能对 DS18B20 进行预定的操作。

温度报警虽然用不上,但是还是写一下,因为我们一般再外部控制,判断温度是否超标

在这里插入图片描述在这里插入图片描述
下面是一些详细的,有了解可以不看

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述推挽电路和漏极开路的帖子:
https://www.zhihu.com/question/28512432
https://blog.csdn.net/u012604283/article/details/84647237

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

代码开始

ds18b20.c

#include "ds18b20.h"
#include "public.h"


uchar ds18b20Init(void)
{
	uchar i=0;
	DATA=0;
	delay700us();
	DATA=1;
	delay100us();
	while(DATA)
	{
		if(i>=5)
		{
			return 0;
		}
		i++;
	}
	return 1;
}

void writeByte(uchar dat)
{
	uchar i;
	DATA=0;
	delay4us();
	for(i=0;i<8;i++)
	{
		DATA=0;
		delay4us();
		DATA=dat&0x01;
		delay60us();
		DATA=1;
		dat>>=1;
	}
}

uchar readByte()
{
	uchar i,dat=0;
	uchar da=0;
	
	for(i=0;i<8;i++)
	{
		DATA=0;
		_nop_();
		DATA=1;
		delay4us();
		da=DATA;
		da<<=7;
		dat=(dat>>1)|da;
		delay60us();
	}
	return dat;
}

void changeTemp()
{
	ds18b20Init();
	delay700us();
	writeByte(0xcc);
	writeByte(0x44);
	delay1s();
}

void readTempCommand()
{
	ds18b20Init();
	delay700us();
	writeByte(0xcc);
	writeByte(0xbe);
}


int readTemp()
{
	int dat=0;
	uchar tmh, tml;
	changeTemp();
	readTempCommand();
	tml = readByte();		//读取温度值共16位,先读低字节
	tmh = readByte();
	dat=tmh;
	dat<<=8;
	dat|=tml;
	return dat;
}


ds18b20.h

#ifndef __DS18B20_H_
#define __DS18B20_H_

#include "public.h"
sbit DATA=P3^7;

uchar ds18b20Init(void);
void writeByte(uchar dat);
uchar readByte();
void changeTemp();
void readTempCommand();
int readTemp();


#endif

main.c

#include "uart.h"
#include "public.h"
#include "ds18b20.h"


void main()
{
	int dat;
	int	DAT;
	uchar ge,shi,bai,qian;
	uart_init();
	while(1)
	{
	dat=readTemp();
	if(dat>0)
	{
		DAT=dat*6.25+0.5;
		qian=(uchar)(DAT/1000);
		bai=(uchar)(DAT/100%10);
		shi=(uchar)(DAT/10%10);
		ge=(uchar)(DAT%10);
		uart_send_sentence("now, the temperature is :");
		uart_send_byte('0'+qian);
		uart_send_byte('0'+bai);
		uart_send_byte('.');
		uart_send_byte('0'+shi);
		uart_send_byte('0'+ge);
		uart_send_byte('\r');
		uart_send_byte('\n');
	}
	else
	{
		dat=dat-1;
		dat=~dat;
		DAT=dat*0.0625*100+0.5;	
		qian=(uchar)(DAT/1000);
		bai=(uchar)(DAT/100%10);
		shi=(uchar)(DAT/10%10);
		ge=(uchar)(DAT%10);
		uart_send_byte('-');
		uart_send_byte('0'+qian);
		uart_send_byte('0'+bai);
		uart_send_byte('0'+shi);
		uart_send_byte('0'+ge);
	}
	 delay1s() ;  //误差 0us
	}
}
	
	

	
	
	
	
	
	
	
	
	/*	
	uchar i;
	i=ds18b20Init();
	while(1)
	{
		if(i==1)
			uart_send_byte('y');
		else
			uart_send_byte('n');
		delay();
	}
*/

uart.c

#include "uart.h"
#include "public.h"


// 串口设置为: 波特率9600、数据位8、停止位1、奇偶校验无
// 使用的晶振是11.0592MHz的,注意12MHz和24MHz的不行
void uart_init(void)
{
	// 波特率9600
	SCON=0X50;			//设置为工作方式1
	TMOD=0X20;			//设置计数器工作方式2
	PCON=0X80;			//波特率加倍
	TH1=0XF3;				//计数器初始值设置,注意波特率是4800的
	TL1=0XF3;
	//ES=1;						//打开接收中断
	//EA=1;						//打开总中断
	TR1=1;
}

// 通过串口发送1个字节出去
void uart_send_byte(unsigned char c)
{
   // 第1步,发送一个字节
   SBUF = c;

   // 第2步,先确认串口发送部分没有在忙
   while (!TI);

   // 第3步,软件复位TI标志位
   TI = 0;
}

void uart_send_sentence(unsigned char *sen)
{
	while(*sen!='\0')
	{
		uart_send_byte(*sen);
		sen++;
	}
}

uart.h

#ifndef __UART_H__
#define __UART_H__






void uart_init(void);
void uart_send_byte(unsigned char c);
void uart_send_sentence(unsigned char *sen);





#endif



public.c

#ifndef __PUBLIC_H__
#define __PUBLIC_H__

#include <reg51.h>
#include <intrins.h>

#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint 
#define uint unsigned int
#endif

void delay700us(void) ;  //误差 0us
void delay100us(void) ;  //误差 0us
void delay4us(void);   //误差 0us
void delay60us(void) ;  //误差 0us
void delay1s(void) ;  //误差 0us


#endif

public.h

#include "public.h"

void delay700us(void)   //误差 0us
{
    unsigned char a,b;
    for(b=41;b>0;b--)
        for(a=7;a>0;a--);
}


void delay100us(void)   //误差 0us
{
    unsigned char a,b;
    for(b=1;b>0;b--)
        for(a=47;a>0;a--);
}


void delay4us(void)   //误差 0us
{
    _nop_();  //if Keil,require use intrins.h
    _nop_();  //if Keil,require use intrins.h
}
void delay60us(void)   //误差 0us
{
    unsigned char a,b;
    for(b=3;b>0;b--)
        for(a=8;a>0;a--);
}
void delay1s(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=167;c>0;c--)
        for(b=171;b>0;b--)
            for(a=16;a>0;a--);
    _nop_();  //if Keil,require use intrins.h
}

发布了20 篇原创文章 · 获赞 4 · 访问量 2453

猜你喜欢

转载自blog.csdn.net/qq_41909909/article/details/104240153
今日推荐