1.DS18B20工作原理
DS18B20数字温度计提供九位温度度数,指示器件的温度。
(单片机上的接口) (DS18B20模块)
按照IO<--->DQ链接,即可实现单片机对其的控制。

1.1DS18B20命令集

1.2DS18B20操作流程

(1)复位
(2)51单片机发送0xCC,代表跳过ROM
(3)51单片机发送0x44,代表ds18b20开启温度转换
(4)延时等待(1s)
(5)复位
(6)51单片机发送0xCC,代表跳过ROM
(7)51单片机发送0xBE,代表读取ds18b20发送过来的温度值
(8)读取温度数据
每次和ds18b20通信前必须先复位!
1.2.1复位时序

最开始是高电平,主机将其由高电平拉低为低电平,持续480-960微秒,意味着单片机向ds18b20发送了一个复位信号,询问其是否存在。主机再将电平拉高,等待15-60微秒。若引脚一直为高电平,则表示ds18b20不存在,若电平被ds18b20拉低,则表示其存在。
根据时序图,我们可以写出复位函数:
cs
#include <reg51.h>
#include "delay.h"
#define DQ_HIGH ((P3 |= (1 << 7)))//P37置高电平
#define DQ_DOWN ((P3 &= ~(1 << 7)))
#define DQ_CHECK ((P3 & (1 << 7)) != 0)
// ds18b20 复位函数
int ds18b20_Reset(void)
{
int t = 0;
DQ_DOWN;
Delay10us(70);
DQ_HIGH;
Delay10us(5);
// 等待ds18b20发送存在脉冲:低电平到来
while (DQ_CHECK && t < 30)
{
Delay10us(1);
t++;
}
if (t >= 30)
{
return 0;
}
// 等待ds18b20将DQ引脚拉高: 高电平到来
t = 0;
while (!DQ_CHECK && t < 30)
{
Delay10us(1);
t++;
}
if (t >= 30)
{
return 0;
}
return 1;
}
1.2.2写时序

(写0和写1)
写0:单片机将电平拉低,ds18b20采样到低电平,说明单片机向传感器写入1
写1:单片机先将电平拉低至少1us后再缓慢拉高,ds18b20检测到高电平,说明单片机向传感器写入0
由写时序编写代码:
cs
// 向ds18b20发送一个字节数据
void write_ds18b20(unsigned char dat)
{
int i = 0;
// 循环判断要发送的数据中的8bit是1还是0
for (i = 0; i < 8; i++)
{
if (dat & 1) //bit1
{
DQ_DOWN;
_nop_();
_nop_();
DQ_HIGH;
Delay10us(5);
}
else // bit0
{
DQ_DOWN;
Delay10us(5);
DQ_HIGH;
}
dat >>= 1;
}
}
1.2.3读时序

(读0和写0)
读0:单片机将高电平拉低,15us内单片机采样,若检测到低电平,则单片机读取到0
读1:单片机将高电平拉为低电平至少1us,再将电平拉高,15us内单片机采样,若检测到高电平则读取到1
由读时序编写代码:
cs
// 从ds18b20读取一个字节数据
unsigned char read_ds18b20(void)
{
int i = 0;
unsigned char ret = 0;
for (i = 0; i < 8; i++)
{
DQ_DOWN;
_nop_();
_nop_();
DQ_HIGH;
_nop_();
_nop_();
_nop_();
if (DQ_CHECK) // ds18b20发送一个bit1
{
ret |= (1 << i);
}
Delay10us(5);
}
return ret;
}
1.2.4获取ds18b20采集到的温度:
cs
// 获取ds18b20采集到的温度
float get_temp(void)
{
short ret = 0;
unsigned char tl = 0;
unsigned char th = 0;
ds18b20_Reset();
write_ds18b20(0xCC);
write_ds18b20(0x44);
Delay1ms(1000);
ds18b20_Reset();
write_ds18b20(0xCC);
write_ds18b20(0xBE);
tl = read_ds18b20();
th = read_ds18b20();
ret = th << 8;
ret |= tl;
return ret * 0.0625;//分辨率0.0625
}
我们在主函数中调用看看结果:
cs
#include <reg51.h>
#include <stdio.h>
#include "ds18b20.h"
#include "delay.h"
#include "uart.h"
int main(void)
{
float ret = 0;
xdata char s[20];
Uart_Init();
while (1)
{
ret = get_temp();
sprintf(s, "%f\n", ret);
Uart_SendStr(s);
}
return 0;
}

可以接收到温度