当前位置:   article > 正文

普中51单片机:DS18B20温度传感器操作指南(十三)

普中51单片机:DS18B20温度传感器操作指南(十三)

在这里插入图片描述

引言

DS18B20是一款单总线接口的数字温度传感器,仅需一个IO口即可实现数据通信。这里只对如何简单操作开发板的DS1802进行讲解,关于DS18B20温度传感器的详细操作原理,可参考此博客:DS18B20数字温度传感器操作解析

电路图

下图显示了DS18B20的电路连接。数据总线通过J14排针引出,并连接到所选的IO口。数据总线上需要一个上拉电阻以确保稳定的通信。
在这里插入图片描述

引脚讲解

DS18B20传感器通常采用TO-92封装或PDIP封装,具有以下三个主要引脚:

  • VDD - 电源正极,为传感器提供工作电压。
  • GND - 电源负极,接地。
  • DQ - 数据引脚,用于与微控制器或计算机进行数据通信。

引脚详解

  1. VDD: 连接到传感器的工作电压,通常为3.3V或5V。确保不要超过传感器的最大工作电压,以避免损坏。
  2. GND: 连接到电路的地线,确保传感器的稳定工作。
  3. DQ: 是一个开漏输出引脚,需要通过上拉电阻连接到VDD。这个引脚负责与主控制器进行通信,支持1-Wire通信协议。

初始化时序

初始化过程从主机发送复位脉冲开始。主机将总线拉低至少480微秒(us),通常是500us,以确保所有从设备都能检测到复位信号。复位脉冲后,总线需保持高电平15-60微秒,等待从设备响应。

从设备通过发送存在脉冲来响应,表示它们已经检测到复位信号,并将总线拉低60-240微秒。表明它已检测到复位信号。之后将电平拉高。
在这里插入图片描述

sbit DS18B20_DQ = P3^7;

unsigned char DS18B20_Init()
{
	
	unsigned char i;
	unsigned char ackBit;

	DS18B20_DQ = 1;
	DS18B20_DQ = 0;
	i = 247;
	while (--i);	 //延时500us
	DS18B20_DQ = 1;
	i = 32;
	while (--i);
	ackBit = DS18B20_DQ;
	i = 247;
	while (--i);	 //延时500us
	return ackBit;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

写时序

写时序包括主机发送数据位“0”或“1”到从设备。每个位的写入时序稍有不同。每次写入一个数据位都需要初始化一个写周期。主机将总线拉低至少1微秒(通常是1-15微秒),然后释放总线,这是初始化写周期。

写0时序:

  • 主机将总线拉低至少60微秒(通常是60-120微秒),然后释放总线。

写1时序:

  • 主机将总线拉低至少1微秒(通常是1-15微秒),然后在剩余时间内保持高电平(释放总线)。

写入一个字节(8位)需要重复上述写0和写1时序八次。写入顺序为低位在前(LSB first)。

  1. 开始写入字节:初始化第一个写周期。
  2. 写入每个位:根据数据位的值,执行写0或写1时序。
  3. 结束写入字节:完成8个位的写入后,字节写入结束。

假设我们要写入字节0x5A(01011010)。

  • 写入0位:主机将总线拉低至少60微秒,释放总线。
  • 写入1位:主机将总线拉低至少1微秒,释放总线。
  • 写入0位:重复写0时序。
  • 写入1位:重复写1时序。
  • 写入1位:重复写1时序。
  • 写入0位:重复写0时序。
  • 写入1位:重复写1时序。
  • 写入0位:重复写0时序。

在这里插入图片描述

//发送一位
void ds18b20_write_bit(unsigned char bits)
{ 
	unsigned char i;
	DS18B20_DQ = 0;
	i = 4;
	while (--i); //延时10us
	DS18B20_DQ = bits;
	i = 24;
	while (--i); //延时50us
	DS18B20_DQ = 1;
}

//发送字节
void ds18b20_write_byte(unsigned char byte)
{
	unsigned char i;
	for(i = 0;i<8;i++)
	{
		ds18b20_write_bit(byte & 0x01<<i);//先发送低位
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

读时序

每次读取一个数据位都需要初始化一个读周期。初始化读周期期间需要主机将总线拉低至少1微秒(通常是1-15微秒),然后释放总线。之后读取数据位,主机在读周期内读取从设备发送的数据位。需要主机将总线拉低至少1微秒(通常是1-15微秒)。然后释放总线,主机释放总线,并在15微秒内读取总线状态。读取数据位期间如果总线保持低电平,读取到的数据位为0;如果总线拉高,读取到的数据位为1。要读取一个字节(8位),需要重复上述读取数据位的过程八次,按低位在前(LSB first)的顺序读取。

假设我们要读取一个字节的数据,具体步骤如下:

  1. 初始化读周期:主机将总线拉低至少1微秒,然后释放总线。
  2. 读取每个位:在读周期内,主机读取从设备发送的每个位数据。
  3. 完成字节读取:重复上述步骤八次,读取一个完整的字节。

在这里插入图片描述

//接收一位
unsigned char ds18b20_read_bit()
{ 
	unsigned char i;
	unsigned char bits;
	DS18B20_DQ = 0;
	i = 2;
	while (--i); //延时5us
	DS18B20_DQ = 1;
	i = 2;
	while (--i); //延时5us
	bits = DS18B20_DQ;
	i = 24;
	while (--i); //延时50us
	return bits;
}

unsigned char ds18b20_read_byte()
{
	unsigned char i;
	unsigned char byte = 0x00;
	for(i = 0;i<8;i++)
	{
		if(ds18b20_read_bit())
		{
			byte |= 0x01<<i;	
		}
	}
	return byte;	
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

温度变换

DS18B20温度传感器的温度转换功能允许用户读取精确的温度数据。为了实现温度转换,必须遵循特定的时序和命令流程。

温度转换流程包括以下几个主要步骤:

  1. 发送初始化命令:主机需要发送初始化命令来复位总线并检测从设备的存在。
  2. 跳过ROM命令:向总线上的所有设备广播命令。所有设备都会响应接下来的命令。
  3. 发送启动温度转换命令:0x44用于启动温度转换(Convert T)

在这里插入图片描述

//转换温度
void ds18b20_ConvertT()
{
	DS18B20_Init();
	ds18b20_write_byte(0xCC);
	ds18b20_write_byte(0x44);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

温度读取

读取DS18B20温度传感器的数据是一个包括命令发送和数据处理的过程。

温度读取过程包括以下几个主要步骤:

  1. 发送初始化命令:主机需要发送初始化命令来复位总线并检测从设备的存在。
  2. 跳过ROM命令:向总线上的所有设备广播命令。所有设备都会响应接下来的命令。
  3. 发送读暂存器命令:用于从DS18B20传感器的暂存器中读取温度数据、报警阈值和配置寄存器信息。

在这里插入图片描述
先读取低位,后读取高位,温度数据是16位带符号的二进制数,最低位代表 2 − 4 2^{-4} 24摄氏度(即0.0625摄氏度)

//读取温度
float ds18b20_ReadT()
{
	unsigned char byteL;
	unsigned char byteH;
	int temp;
	float T;
	DS18B20_Init();
	ds18b20_write_byte(0xCC);
	ds18b20_write_byte(0xBE);
	byteL = ds18b20_read_byte();//低字节
	byteH = ds18b20_read_byte();//高字节
	temp = (byteH << 8) | byteL;
	T = temp / 16.0;
	return T;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

完整代码

LCD1602液晶显示屏实时获取温度变化

#include <REGX52.H>
#include <LCD1602.H>
#include "stdio.h"
sbit DS18B20_DQ = P3^7;

unsigned char DS18B20_Init()
{
	unsigned char i;
	unsigned char ackBit;

	DS18B20_DQ = 1;
	DS18B20_DQ = 0;
	i = 247;
	while (--i);	 //延时500us
	DS18B20_DQ = 1;
	i = 32;
	while (--i);
	ackBit = DS18B20_DQ;
	i = 247;
	while (--i);	 //延时500us
	return ackBit;
}

//发送一位
void ds18b20_write_bit(unsigned char bits)
{ 
	unsigned char i;
	DS18B20_DQ = 0;
	i = 4;
	while (--i); //延时10us
	DS18B20_DQ = bits;
	i = 24;
	while (--i); //延时50us
	DS18B20_DQ = 1;
}

//接收一位
unsigned char ds18b20_read_bit()
{ 
	unsigned char i;
	unsigned char bits;
	DS18B20_DQ = 0;
	i = 2;
	while (--i); //延时5us
	DS18B20_DQ = 1;
	i = 2;
	while (--i); //延时5us
	bits = DS18B20_DQ;
	i = 24;
	while (--i); //延时50us
	return bits;
}

//发送字节
void ds18b20_write_byte(unsigned char byte)
{
	unsigned char i;
	for(i = 0;i<8;i++)
	{
		ds18b20_write_bit(byte & 0x01<<i);//先发送低位
	}
}

unsigned char ds18b20_read_byte()
{
	unsigned char i;
	unsigned char byte = 0x00;
	for(i = 0;i<8;i++)
	{
		if(ds18b20_read_bit())
		{
			byte |= 0x01<<i;	
		}
	}
	return byte;	
}

//转换温度
void ds18b20_ConvertT()
{
	DS18B20_Init();
	ds18b20_write_byte(0xCC);
	ds18b20_write_byte(0x44);
}

//读取温度
float ds18b20_ReadT()
{
	unsigned char byteL;
	unsigned char byteH;
	int temp;
	float T;
	DS18B20_Init();
	ds18b20_write_byte(0xCC);
	ds18b20_write_byte(0xBE);
	byteL = ds18b20_read_byte();//低字节
	byteH = ds18b20_read_byte();//高字节
	temp = (byteH << 8) | byteL;
	T = temp / 16.0;
	return T;
}

unsigned char ack = 1;

float g_T;

void main()
{
	char temp_buff[50];
	LCD_Init();
	LCD_ShowString(1,1,"helloworld");
	ack = DS18B20_Init();
	LCD_ShowNum(2,1,ack,3);
	while(1)
	{
		ds18b20_ConvertT();
		g_T = ds18b20_ReadT();
		if(g_T<0)
		{
			//负数
			LCD_ShowChar(2,1,'-');
			g_T = -g_T;
		}
		else
		{
			LCD_ShowChar(2,1,'+');
		}
	    // 使用 sprintf 将浮点数转换为字符串
	    sprintf(temp_buff, "%.3f", g_T);
		LCD_ShowString(2,2,temp_buff);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/948316
推荐阅读
相关标签
  

闽ICP备14008679号