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操作协议命令
- 读ROM (0x33)
- 搜索ROM (0xF0)
- 匹配ROM (0x55)
- 跳过ROM (0xCC)
- 报警搜索 (0xEC)
4.特性
- 单线通信 "线与特性"
- 0功耗等待
5.接上拉电阻的目的
EG:在HC6800-MS原理图中,我们外接ds18b20传感器后DQ引脚与P37连通,接10K的上拉电阻
目的
ds18b20的数据线是开漏输出(Open-Drain Output)结构。这种设计使得数据线在未被主动驱动时处于高阻态,既不输出高电平也不输出低电平。若直接连接到主控设备,可能会导致信号无法正确传输,特别是在没有外部电路的情况下,数据线可能无法维持稳定的逻辑状态。因此,为了确保在没有主动驱动时数据线保持高电平,必须外接一个上拉电阻。
提高信号的抗干扰能力
6.采集温度流程
- 复位
- 跳过ROM(0xCC)
- 开启温度转换 (0x44)
- 延时1s
- 复位
- 0xCC
- 读取温度 (0xBE)
- 读取两个字节温度
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;
}





