【DAY29】DS18B20 传感器特性、时序协议及 51 单片机驱动开发

ds18b20: 半双工、异步、串行

1.分辨率

概念:传感器对温度变化的敏感程度(实际温度 = 传感器检测到的温度 * 分辨率)

|----|--------|
| 分辨率(位可调) ||
| 9 | 0.5 |
| 10 | 0.25 |
| 11 | 0.125 |
| 12 | 0.0625 |

2.DS18B20相关参数

|------|-------------|--------------------------------------|--------|-------|
| 功能 | 量程(摄氏度) | 精度(摄氏度) | 分辨率 | 工作电压 |
| 温度采集 | -55 ~ +125 | 0.5 | 0.0625 | 3V-5V |

3.建立ROM操作协议命令

  1. 读ROM (0x33)
  2. 搜索ROM (0xF0)
  3. 匹配ROM (0x55)
  4. 跳过ROM (0xCC)
  5. 报警搜索 (0xEC)

4.特性

  • 单线通信 "线与特性"
  • 0功耗等待

5.接上拉电阻的目的

EG:在HC6800-MS原理图中,我们外接ds18b20传感器后DQ引脚与P37连通,接10K的上拉电阻

目的

  • ds18b20的数据线是开漏输出(Open-Drain Output)结构。这种设计使得数据线在未被主动驱动时处于高阻态,既不输出高电平也不输出低电平。若直接连接到主控设备,可能会导致信号无法正确传输,特别是在没有外部电路的情况下,数据线可能无法维持稳定的逻辑状态。因此,为了确保在没有主动驱动时数据线保持高电平,必须外接一个上拉电阻。

  • 提高信号的抗干扰能力

6.采集温度流程

  1. 复位
  2. 跳过ROM(0xCC)
  3. 开启温度转换 (0x44)
  4. 延时1s
  5. 复位
  6. 0xCC
  7. 读取温度 (0xBE)
  8. 读取两个字节温度

7.DS18B20时序

1.复位时序

  • 主机将总线拉低至少480us,再释放总线(拉高电平),代表主机发送复位脉冲
  • 主机在60-240us检测总线出现低电平,代表DS18B20回复存在脉冲,传感器能正常工作
  • DS18B20释放,总线为高电平
cpp 复制代码
#include <reg51.h>
#include <intrins.h>
#include "uart.h"

#define DQ_P_H		(P3 |= (1 << 7))
#define DQ_P_L		(P3 &= ~(1 << 7))
#define DQ_P_CH		((P3 & (1 << 7)) != 0) //是否为高电平

void Delay10us(unsigned int n)	//@12.000MHz
{
	unsigned char data i;
	
	_nop_();
	_nop_();
	_nop_();
	i = 2 * n;
	while (--i)
	{			
		_nop_();		
	}
}

void Delay1ms(unsigned int n)
{
	while(n--)
	{
		Delay10us(100);		
	}
}
 
int rest(void)
{
    int time = 0;
    
    DQ_P_L;
    Delay10us(7);
    DQ_P_H;
    Delay10us(5);

    while(DQ_P_CH && time < 30)
    {
        Delay10us(1);
        time++;
    }

    if(time >= 30)
    {
        uart_sendstr("wait P_low \r\n");
        return -1;
    }

    time = 0;
    while(!DQ_P_CH && time < 30)
    {
        Delay10us(1);
        time++;
    }

    if(time >= 30)
    {
        uart_sendstr("wait P_high \r\n");
        return -2;
    }
    return 1;
}

2.写时序

写0时序:

主机将总线拉低大于60us

ds18b20在60us内进行采样,如果采到低电平,代表主机发送了一个0

主机释放总线,将引脚拉高

写1时序:

主机将总线拉低大于1us

主机释放总线,将引脚拉高

ds18b20在45us内进行采样,如果采到高电平,代表主机发送了一个1

cpp 复制代码
void write_ds18b20(unsigned char dat)
{
	int i = 0;

	for(i = 0; i < 8; i++)
	{
		if(dat & 1)
		{	
			DQ_P_L;
			_nop_();
			_nop_();
			DQ_P_H;
			Delay10us(5);	
		}
		else
		{
			DQ_P_L;
			Delay10us(6);
			DQ_P_H;
		}
		dat >>= 1;
	}
}

3.读时序

主机将总线拉低大于1us,释放总线,引脚变为高电平

主机再15us内进行采样

若采到一个高电平,代表读到1,若采到低电平,代表读到0

最终ds18b20释放总线

cpp 复制代码
unsigned char read_ds18b20(void)
{
	unsigned char dat = 0;
	int i = 0;

	for(i = 0; i < 8; i++)
	{
		DQ_P_L;
		_nop_();
		_nop_();
		DQ_P_H;
		_nop_();
		_nop_();
		_nop_();

		//读到1
		if(DQ_P_CH)
		{
			dat |= (1 << i);
		}
		Delay10us(6);
	}

	return dat;
}

4.采集

cpp 复制代码
float get_temp(void)
{
	unsigned char temp_low = 0;
	unsigned char temp_high = 0;
	short temp = 0;

	ds18b20_rest();
	write_ds18b20(0xCC);
	write_ds18b20(0x44);
	Delay1ms(1000);
	ds18b20_rest();
	write_ds18b20(0xCC);
	write_ds18b20(0xBE);

	temp_low = read_ds18b20();
	temp_high = read_ds18b20();

	temp = temp_high << 8;
	temp |= temp_low;
	
	return temp * 0.0625;		
}		
相关推荐
无敌昊哥战神2 小时前
LeetCode 112. 路径总和 - 避坑指南与多语言全解法(C/C++/Python)
c语言·c++·leetcode
计算机安禾2 小时前
【数据结构与算法】第2篇:C语言核心机制回顾(一):指针、数组与结构体
c语言·开发语言·数据结构·c++·算法·链表·visual studio
-Try hard-2 小时前
单片机 | 温度传感器(DS18B20)
单片机·嵌入式硬件
天天爱吃肉82182 小时前
【电机双闭环控制问答:PI 输出为何不同?测功机台架选型有多关键】
功能测试·嵌入式硬件·信息可视化·汽车
sonnet-10292 小时前
拓扑排序的实现
java·c语言·开发语言·笔记·算法
学嵌入式的小杨同学2 小时前
STM32 进阶封神之路(二十四):低功耗实战全攻略 —— 电池供电传感器节点(RTC 唤醒 + DHT11 采集 + 功耗优化)
c++·stm32·单片机·嵌入式硬件·mcu·架构·硬件架构
C++ 老炮儿的技术栈2 小时前
Qt 开发机器人客户端程序
c语言·开发语言·c++·windows·qt·机器人
电子工程师成长日记-C512 小时前
51单片机热敏电阻测温
单片机·嵌入式硬件·51单片机
Hello World . .2 小时前
51单片机——UART 串口通信
网络·嵌入式硬件·51单片机