【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;		
}		
相关推荐
Tomhex2 小时前
C语言内存安全防护指南
c语言
230万光年的思念4 小时前
zerotier连不上的问题
c语言
LNN20225 小时前
STM32H7 + 迪文屏 DGUS 开发实战:从零构建工业级时间设置界面
stm32·单片机·嵌入式硬件
Fanfanaas7 小时前
Linux 基础开发工具(二)
linux·运维·服务器·c语言
leaves falling8 小时前
C/C++ const:修饰变量和指针的区别(和引用底层关系)
c语言·开发语言·c++
网域小星球8 小时前
C 语言从 0 入门(十二)|指针与数组:数组名本质、指针遍历数组
c语言·算法·指针·数组·指针遍历数组
Tairitsu_H8 小时前
C语言:排序(一)
c语言·数据结构·排序
Z文的博客8 小时前
嵌入式MCU与迪文屏通信:DMA+环形FIFO+变长队列+状态机完整手册
stm32·单片机·串口·dma·中断·串口dma·嵌入式单片机
12.=0.9 小时前
【stm32_5】Systick嘀嗒定时器、解析时钟源、分析时钟树、应用Systick设计延时
c语言·stm32·单片机·嵌入式硬件
达不溜的日记9 小时前
CAN总线网络传输层CanTp详解
网络·stm32·嵌入式硬件·网络协议·网络安全·信息与通信·信号处理