DS18B20 电路及驱动笔记

image

工作流程

  • 1.初始化DS18B20
  • 2.执行ROM指令
  • 3.执行DS18B20功能指令

温度数据关系

image

存储器

DS18B20的存储器结构如图7所示。存储器有一个暂存器SRAM和一个存储底稿报警阈值THTL的非易失性电可擦除EEOROM组成。注意当报警功能不能使用时,THTL寄存器可以被当作普通寄存器使用。所有的存储器指令被详述于DS18B20功能指令节。

存储器的byte 0byte 1字节分别为温度寄存器的LSBMSB,这两个字节的存储器为只读存储器。第2和第3字节是THTL。第4字节是配置寄存器数据,器被详述于配置寄存器节。第5字节被器件保留,禁止写入;第6和第7字节用户可以使用。

存储器的第8字节是只读的,包含以上八个字节的CRC码,CRC的执行方式如CRC发生器节所述。

数据通过写寄存器指令[4Eh]写入存储器的2,3,4,67位;数据必须以第2个字节为最低有效位开始传送。为了完整的验证数据,存储器能够在数据写入后被读取(使用读寄存器指令[BEh])。在读寄存器时,数据以字节0为最低有效位从单总线移出。总线控制器从寄存器到EEPROM传递THTL和配置数据时必须发出拷贝寄存器指令[48h]。

EEPROM存储器中的数据在器件掉电后仍然保持;上电时,数据被载入寄存器。数据也可以通过召回EEPROM

令从寄存器载入到EEPROM中。总线控制器在发出这条命令后发出读时序,DS18B20返回0表示正在召回中,返回1表示操作结束。

image

复位和存在信号

复位要先把 DQ拉低480us ,然后把 DQ 拉高并保持 15~60us,这时如果 DS18B20 存在,那么 DS 将会被 DS18B20 拉低 60~240us,如果超过 240us 没有被拉低则可能 DS18B20 不存在。

image

读写时序

DS18B20的数据读写是通过时序处理来进行信息交换的,每个时序传输1位数据。

写时序

image

写0:拉低 60us~120us,然后拉高

写1:拉低大于 1us,然后拉高

static void write_byte(uint8_t byte) {
  uint8_t i;
  uint8_t first_bit;

  for (i=1; i<=8; i++) {
    first_bit = byte & 0x01;
    byte = byte >> 1;
    if (first_bit) { // 写 1
      ds18b20_io_set(LOW);
      delay_us(2);
      ds18b20_io_set(HIGH);
      delay_us(60);
    } else { // 写 0
      ds18b20_io_set(LOW);
      delay_us(60);
      ds18b20_io_set(HIGH);
      delay_us(2);
    }
  }
}

复位

static void ds18b20_rst(void)
{
    ds18b20_io_set(LOW);
    delay_us(750);
    ds18b20_io_set(HIGH);
    delay_us(15);
}

存在检测

/*******************************************************************************
 * @biref  检测存在信号
 * @retval result [1: 不存在,0: 存在]
 *******************************************************************************
 */
static uint8_t ds18b20_check(void)
{
    uint8_t result = 1;
    uint8_t retry = 0;

    // 如果没有检测到存在信号(一直为高电平) 并且没有超过 200 us 则执行循环
    while (ds18b20_io_get() && retry < 200)
    {
        retry++;
        delay_us(1);
    }

    // 如果 retry 超过 200 则说明 DS18B20 不存在
    if (retry>=  200)
    {
        result = 1;
    }
    else
    {
        retry = 0;

        while (!ds18b20_io_get() && retry < 240)
        {
            retry++;
            delay_us(1);
        }

        if (retry >= 240)
        {
            result = 1;
        }
        else
        {
            result = 0;
        }
    }

    return result;
}

写字节

static void ds18b20_write_byte(uint8_t byte)
{
    uint8_t i;
    uint8_t first_bit;

    for (i = 1; i <= 8; i++)
    {
        first_bit = byte & 0x01;
        byte = byte >> 1;
        if (first_bit)
        { // 写 1
            ds18b20_io_set(LOW);
            delay_us(2);
            ds18b20_io_set(HIGH);
            delay_us(60);
        }
        else
        { // 写 0
            ds18b20_io_set(LOW);
            delay_us(60);
            ds18b20_io_set(HIGH);
            delay_us(2);
        }
    }
}

读一位

static uint8_t ds18b20_read_bit(void)
{
    uint8_t result;
    ds18b20_io_set(LOW);
    delay_us(2);
    ds18b20_io_set(HIGH);
    delay_us(12);
    if (ds18b20_io_get())
    {
        result = 1;
    }
    else
    {
        result = 0;
    }
    delay_us(50);

    return result;
}

读字节

这段代码比较有意思:dat = (j << 7) | dat >> 1; dat 的初始值为 0 ,第一次执行把读到的 j 左移7位再与 dat 右移1位按位或,就是把 j 保存到 dat 的最高位,每执行一遍dat 中的数据就右移一位,这样就把读到的8位数据从低到高的保存的 dat 中了。

static uint8_t ds18b20_read_byte(void)
{
    uint8_t i, j, dat;
    dat = 0;
    for (i = 1; i <= 8; i++)
    {
        j = ds18b20_read_bit();
        dat = (j << 7) | dat >> 1;
    }

    return dat;
}

开始转换温度

static void ds18b20_start(void)
{
    ds18b20_rst();
    ds18b20_check();
    ds18b20_write_byte(0xcc); // skip rom
    ds18b20_write_byte(0x44); // convert
}

获取温度

void ds18b20_get_temp(void)
{
    uint8_t temp;
    uint8_t TL, TH;
    short tem;
    ds18b20_start();
    ds18b20_rst();
    ds18b20_check();
    ds18b20_write_byte(0xcc);
    ds18b20_write_byte(0xbe);
    TL = ds18b20_read_byte(); // LSB
    TH = ds18b20_read_byte(); // MSB

    if (TH > 7)
    {
        TH = ~TH;
        TL = ~TL;
        temp = 0;
    }
    else
    {
        temp = 1;
    }

    tem = TH;
    tem <<= 8;
    tem += TL;

    Ds18b20.temp = (float)tem * 0.0625;
}
posted @ 2023-05-05 01:14  小土坡  阅读(317)  评论(0编辑  收藏  举报