当前位置:   article > 正文

day07 51单片机-18B20温度检测

day07 51单片机-18B20温度检测

18B20温度检测

1.1 需求描述

本案例讲解如何从18B20传感器获取温度信息并显示在LCD上。

1.2 硬件设计

1.2.1 硬件原理图

在这里插入图片描述

1.2.3 18B20工作原理

可以看到18B20有两根引脚负责供电,一根引脚负责数据交换。18B20就是通过数据线和单片机进行数据交换的。

1)18B20工作时序

在这里插入图片描述

2)初始化信号

在这里插入图片描述

#define DQ P44

/**
 * @brief 初始化方法
 *
 * @return 1代表存在,0代表不存在
 */
static bit Int_DS18B20_Init()
{
    bit result;

    // 主机拉低
    DQ = 0;
    Delay60us(8);

    // 主机释放DQ
    DQ = 1;
    Delay60us(1);

    // 查看18B20状态
    result = ~DQ;
    Delay60us(7);

    return result;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

3)写数据时序

写‘1’时序

在这里插入图片描述

写‘0’时序

在这里插入图片描述

写字节

在这里插入图片描述

让18B20测量温度,并将温度保存在RAM中。

根据说明书第五节“温度测量”,我们需要向18B20发送功能指令0x44,可以触发温度测量动作,根据上面的事件序列,我们可以得知,这一步的通信流程如下:

发送初始化信号。

发送跳过ROM命令的指令(因为我们不需要ROM命令),查询ROM命令列表可得知,我们需要向18B20发送0xCC。

发送温度测量指令,查询功能命令列表可得知,我们需要向18B20发送0x44。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

4)读数据时序

在这里插入图片描述

在这里插入图片描述

5)从18B20中读取刚刚测量的温度。

查询说明书的命令指令可得知,如果我们想读取18B20寄存器,需要向18B20发送功能指令0xBE,再从18B20中连续接收9字节数据。这9字节数据中,只有前两个字节是我们需要的温度数据。所以我们在接收两个字节后,需要再发送一次复位(初始化)信号,打断接下来的数据传输。整个通信流程如下:

 发送初始化信号。

 发送跳过ROM命令的指令0xCC。

 发送读取寄存器的命令0xBE。

 接收两个字节。

 发送初始化信号打断传输。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

1.3软件设计

1)Util.h

在Util.h中加入新的延时函数声明。

/**
 * @brief 延时10us
 *
 */
void Delay10us();

/**
 * @brief 延时50us
 *
 */
void Delay50us();

/**
 * @brief 延时60us
 *
 * @param n 倍数
 */
void Delay60us(u8 n);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

2)Util.c

void Delay60us(u8 n) //@11.0592MHz
{
    unsigned char data i;

    while (n--)
    {
        i = 25;
        while (--i)
            ;
    }
}

void Delay10us() //@11.0592MHz
{
    unsigned char data i;

    i = 2;
    while (--i)
        ;
}

void Delay50us() //@11.0592MHz
{
    unsigned char data i;

    _nop_();
    i = 20;
    while (--i)
        ;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

3)Int_DS18B20.h

在Int目录下创建Int_DS18B20.h,写入以下内容。

#ifndef __INT_DS18B20_H__
#define __INT_DS18B20_H__
#include <STC89C5xRC.H>
#include "Util.h"

/**
 * @brief 获取温度
 *
 * @return u8
 */
u8 Int_DS18B20_GetTemperature();

#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

4)Int_DS18B20.c

在Int目录下创建Int_DS18B20.c,写入以下内容。

#include "Int_DS18B20.h"

#define DQ P44

/**
 * @brief 初始化方法
 *
 * @return 1代表存在,0代表不存在
 */
static bit Int_DS18B20_Init()
{
    bit result;

    // 主机拉低
    DQ = 0;
    Delay60us(8);

    // 主机释放DQ
    DQ = 1;
    Delay60us(1);

    // 查看18B20状态
    result = ~DQ;
    Delay60us(7);

    return result;
}

/**
 * @brief 向18B20发送字节
 *
 * @param dat 要发送的字节
 */
static void Int_DS18B20_SendByte(u8 dat)
{
    u8 i;

    for (i = 0; i < 8; i++)
    {
        // 首先拉低总线
        DQ = 0;
        // 延时10us
        Delay10us();
        // 根据要发送的bit决定是高是低
        DQ = dat & 0x1;
        dat >>= 1;
        // 延时50us
        Delay50us();
        // 释放总线
        DQ = 1;
    }
}

/**
 * @brief 从18B20读取字节
 *
 * @return u8 读取的字节
 */
static u8 Int_DS18B20_RecvByte()
{
    u8 i, result = 0;

    // 8个bit
    for (i = 0; i < 8; i++)
    {
        // 主机初始化读时段
        DQ = 0;
        result >>= 1;
        DQ = 1;
        // 等待10us
        Delay10us();

        // 采样
        if (DQ == 1)
        {
            result |= 0x80;
        }
        // 等待整个读时段过去
        Delay50us();
    }

    return result;
}

u8 Int_DS18B20_GetTemperature()
{
    u8 ls_byte, ms_byte;

    // 初始化
    Int_DS18B20_Init();
    // 发送跳过ROM指令的指令(0xCC)
    Int_DS18B20_SendByte(0xCC);
    // 发送温度转换指令(0x44)
    Int_DS18B20_SendByte(0x44);

    // 初始化
    Int_DS18B20_Init();
    // 发送0xCC
    Int_DS18B20_SendByte(0xCC);
    // 发送读取暂存器指令(0xBE)
    Int_DS18B20_SendByte(0xBE);
    // 收字节,总共9个,只要两个
    ls_byte = Int_DS18B20_RecvByte();
    ms_byte = Int_DS18B20_RecvByte();
    // 初始化
    Int_DS18B20_Init();

    // 将读取到的两字节转化成温度返回
    ls_byte >>= 4;
    ms_byte <<= 4;

    return ms_byte | ls_byte;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113

5)Main.c

在Main.c文件中,写入以下内容。

#include <STC89C5xRC.H>
#include "Int_LCD1602.h"
#include "Int_DS18B20.h"

void main()
{
    Int_LCD1602_Init();

    while (1)
    {
        Int_LCD1602_ShowNum(0, 0, Int_DS18B20_GetTemperature());
        Delay1ms(500);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

s_byte | ls_byte;
}


**5)Main.c**

在Main.c文件中,写入以下内容。

```c
#include <STC89C5xRC.H>
#include "Int_LCD1602.h"
#include "Int_DS18B20.h"

void main()
{
    Int_LCD1602_Init();

    while (1)
    {
        Int_LCD1602_ShowNum(0, 0, Int_DS18B20_GetTemperature());
        Delay1ms(500);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/482358
推荐阅读
相关标签
  

闽ICP备14008679号