DS18B20介绍

  • DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点
  • 测温范围:-55°C到 +125°C
  • 通信接口:1-Wire(单总线)
  • 其它特征:可形成总线结构、内置温度报警功能、可寄生供电

引脚及应用电路

内部结构框图

  • 64-BIT ROM:作为器件地址,用于总线通信的寻址
  • SCRATCHPAD(暂存器):用于总线的数据交互
  • EEPROM:用于保存温度触发阈值和配置参数

存储器结构

单总线介绍

  • 单总线(1-Wire BUS)是由Dallas公司开发的一种通用数据总线
  • 一根通信线:DQ
  • 异步、半双工
  • 单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线。

单总线电路规范

  • 设备的DQ均要配置成开漏输出模式
  • DQ添加一个上拉电阻,阻值一般为4.7KΩ左右
  • 若此总线的从机采取寄生供电,则主机还应配一个强上拉输出电路

单总线时序结构

  • 初始化:主机将总线拉低至少480us,然后释放总线,等待15-60us后,存在的从机会拉低总线60~240us以响应主机,之后从机将释放总线。

  • 发送一位:主机将总线拉低60-120us,然后释放总线,表示发送0;主机将总线拉低1~15us,然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us。

  • 接收一位:主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾),读取为低电平则为接收0,读取为高电平则为接收1,整个时间片应大于60us。

  • 发送一个字节:连续调用8次发送一位的时序,依次发送一个字节的8位(低位在前)

  • 接收一个字节:连续调用8次接收一位的时序,依次接收一个字节的8位(低位在前)

DS18B20操作流程

  • 初始化:从机复位,主机判断从机是否响应
  • ROM操作:ROM指令+本指令需要的读写操作
  • 功能操作:功能指令+本指令需要的读写操作

DS18B20数据帧

  • 温度变换:初始化→跳过ROM→开始温度变换

  • 温度读取:初始化→跳过ROM→读暂存器→连续的读操作

温度存储格式

DS18B20温度读取

main.c

#include <REGX52.H>
#include "LCD1602.h"
#include "DS18B20.h"
#include "Delay.h"

float T;

void main()
{
    DS18B20_ConvertT();        //上电先转换一次温度,防止第一次读数据错误
    Delay(1000);            //等待转换完成
    LCD_Init();
    LCD_ShowString(1,1,"Temperature:");
    while(1)
    {
        DS18B20_ConvertT();    //转换温度
        T=DS18B20_ReadT();    //读取温度
        if(T<0)                //如果温度小于0
        {
            LCD_ShowChar(2,1,'-');    //显示负号
            T=-T;            //将温度变为正数
        }
        else                //如果温度大于等于0
        {
            LCD_ShowChar(2,1,'+');    //显示正号
        }
        LCD_ShowNum(2,2,T,3);        //显示温度整数部分
        LCD_ShowChar(2,5,'.');        //显示小数点
        LCD_ShowNum(2,6,(unsigned long)(T*10000)%10000,4);//显示温度小数部分
    }
}

OneWire.c

#include <REGX52.H>

//引脚定义
sbit OneWire_DQ=P3^7;

/**
  * @brief  单总线初始化
  * @param  无
  * @retval 从机响应位,0为响应,1为未响应
  */
unsigned char OneWire_Init(void)
{
    unsigned char i;
    unsigned char AckBit;
    OneWire_DQ=1;
    OneWire_DQ=0;
    i = 247;while (--i);        //Delay 500us
    OneWire_DQ=1;
    i = 32;while (--i);            //Delay 70us
    AckBit=OneWire_DQ;
    i = 247;while (--i);        //Delay 500us
    return AckBit;
}

/**
  * @brief  单总线发送一位
  * @param  Bit 要发送的位
  * @retval 无
  */
void OneWire_SendBit(unsigned char Bit)
{
    unsigned char i;
    OneWire_DQ=0;
    i = 4;while (--i);            //Delay 10us
    OneWire_DQ=Bit;
    i = 24;while (--i);            //Delay 50us
    OneWire_DQ=1;
}

/**
  * @brief  单总线接收一位
  * @param  无
  * @retval 读取的位
  */
unsigned char OneWire_ReceiveBit(void)
{
    unsigned char i;
    unsigned char Bit;
    OneWire_DQ=0;
    i = 2;while (--i);            //Delay 5us
    OneWire_DQ=1;
    i = 2;while (--i);            //Delay 5us
    Bit=OneWire_DQ;
    i = 24;while (--i);            //Delay 50us
    return Bit;
}

/**
  * @brief  单总线发送一个字节
  * @param  Byte 要发送的字节
  * @retval 无
  */
void OneWire_SendByte(unsigned char Byte)
{
    unsigned char i;
    for(i=0;i<8;i++)
    {
        OneWire_SendBit(Byte&(0x01<<i));
    }
}

/**
  * @brief  单总线接收一个字节
  * @param  无
  * @retval 接收的一个字节
  */
unsigned char OneWire_ReceiveByte(void)
{
    unsigned char i;
    unsigned char Byte=0x00;
    for(i=0;i<8;i++)
    {
        if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}
    }
    return Byte;
}

OneWire.h

#ifndef __ONEWIRE_H__
#define __ONEWIRE_H__

unsigned char OneWire_Init(void);
void OneWire_SendBit(unsigned char Bit);
unsigned char OneWire_ReceiveBit(void);
void OneWire_SendByte(unsigned char Byte);
unsigned char OneWire_ReceiveByte(void);

#endif

DS18B20.c

#include <REGX52.H>
#include "OneWire.h"

//DS18B20指令
#define DS18B20_SKIP_ROM            0xCC
#define DS18B20_CONVERT_T            0x44
#define DS18B20_READ_SCRATCHPAD     0xBE

/**
  * @brief  DS18B20开始温度变换
  * @param  无
  * @retval 无
  */
void DS18B20_ConvertT(void)
{
    OneWire_Init();
    OneWire_SendByte(DS18B20_SKIP_ROM);
    OneWire_SendByte(DS18B20_CONVERT_T);
}

/**
  * @brief  DS18B20读取温度
  * @param  无
  * @retval 温度数值
  */
float DS18B20_ReadT(void)
{
    unsigned char TLSB,TMSB;
    int Temp;
    float T;
    OneWire_Init();
    OneWire_SendByte(DS18B20_SKIP_ROM);
    OneWire_SendByte(DS18B20_READ_SCRATCHPAD);
    TLSB=OneWire_ReceiveByte();
    TMSB=OneWire_ReceiveByte();
    Temp=(TMSB<<8)|TLSB;
    T=Temp/16.0;
    return T;
}

DS18B20.h

#ifndef __DS18B20_H__
#define __DS18B20_H__

void DS18B20_ConvertT(void);
float DS18B20_ReadT(void);

#endif

DS18B20温度报警器

参考资料

51单片机入门教程-2020版 程序全程纯手打 从零开始入门\_哔哩哔哩\_bilibili

最后修改:2023 年 10 月 21 日
如果觉得我的文章对你有用,请随意赞赏