[Arduino] DS18B20 温度传感器

DS18B20是一款低成本低开销的数字温度传感器,它的测量范围在-55℃ ~ 125℃之间,固有误差为1摄氏度,在-10℃ ~ 85℃之间的精度为0.5℃,能够满足日常测温需求。
DS18B20采用OneWire(单线)通信协议,只需要一根信号线就可以完成数据的读写。供电也允许有独立供电和数据寄生供电两种模式,在寄生供电模式下电源线接地,电源从数据线上获取,可以节省一根连接线。

连线方式

DS18B20有三个引脚:

  • VDD,外部电源,如果使用寄生供电模式,该端接地
  • DQ,数据引脚,需要上拉电阻拉高
  • GND,接地端,提供参考低电平

独立供电模式

需要给DQ提供一个5kΩ的弱上拉电阻


[Arduino] DS18B20 温度传感器_第1张图片
独立供电电路

寄生供电模式

需要给DQ提供一个5kΩ的弱上拉电阻,在DS18B20工作时,需要给DQ提供一个强上拉。如果DS18B20工作在超过100℃的环境下,漏电流会比较大,寄生供电的工作方式可能无法正常为DS18B20供电,此时需要设计为独立供电模式。


[Arduino] DS18B20 温度传感器_第2张图片
寄生供电电路

驱动代码

DS18B20采用OneWire协议通信,OneWire通信协议的实现这里就不详细说明了,对于Arduino来说已经内建了OneWire库,可以直接使用。

寄存器结构

DS18B20内建有三种寄存器:

  • 高速缓存,测量的环境温度会缓存在此
  • 暂存器,上电后对DS18B20的配置以及温度转换后的数值都存放在此,以备读写
  • EEPROM,配置都可转储到这里做永久保存,也可从这里读取配置到暂存器上去使用,详见指令寄存转储寄存恢复
[Arduino] DS18B20 温度传感器_第3张图片
寄存器结构

指令集

指令 类型 功能 描述
0x33 ROM指令 读取ROM 读取64位只读唯一识别码,其中第一个字节为固定识别符0x28,最后一个字节为CRC检验码
0x55 ROM指令 查询ROM 查找总线上是否有指定识别码的DS18B20存在
0xF0 ROM指令 枚举ROM 枚举总线上DS18B20的数量和固定标识符
0xCC ROM指令 忽略ROM 跳过ROM查询流程
0xEC ROM指令 枚举告警 枚举总线上处于告警状态的DS18B20的标识符
0x44 功能指令 温度转换 开始探测环境温度并存储到寄存器上
0xBE 功能指令 读取数据 读取RAM中的数据
0x4E 功能指令 设置阈值 设置高温告警温度TH和低温告警温度TL
0x48 功能指令 寄存转储 把RAM中TH、TL和配置转储到EEPROM中
0xB8 功能指令 寄存恢复 把EEPROM中的数据恢复到RAM中的TH、TL和配置位上
0xB4 功能指令 查询供电方式 查询供电方式

和DS18B20通信要遵循一定的访问时序:

  • 主机下拉DQ脚至少480μs做复位操作,然后恢复上拉等待15-60μs
  • DS18B20下拉DQ脚60~240μs做"存在"应答
  • 主机发送ROM指令,然后拉高DQ
  • [读取DS18B20的回复]
  • 主机发送功能指令,然后拉高DQ
  • [读取DS18B20的回复]

DS18B20是指令严格流程化的,如果通信指令的时序不正确,DS18B20会不应答主机的请求。每次访问DS18B20都要重复上面的所有步骤,否则只有不完整的流程时序会得不到DS18B20的应答。

CRC校验

CRC = X8+X5+X4+1

枚举ROM

#define DS18B20_PIN 2

OneWire onewire(DS18B20_PIN);
byte    address[8];
int     count = 0;

void enumerateROM() {
    while (onewire.search(address)) {
        count++;
        for (byte i = 0; i < 8; i++) {
            Serial.print(count);
            Serial.print(": 0x");
            if (address[i] < 0x10) Serial.print("0"); Serial.println(address[i], HEX);
        }
    }
}

温度读取

#define STARTCONVERT 0x44 
#define READDATA     0xBE
#define DS18B20_PIN  2

OneWire onewire(DS18B20_PIN);
byte    address[8]; // 枚举ROM时可获得
bool    isParasite = true; // 是否为寄生供电模式

float readTemperature() {
    byte temperature[2];
    byte highAlarmTemperature;
    byte lowAlarmTemperature;
    byte configuration;
    byte crc;

    // 请求温度转换
    onewire.reset();
    onewire.select(address);
    onewire.wirte(STARTCONVERT, isParasite);

    // 等待DS18B20完成温度转换
    delay(delayForResolution(bitResolution));
    
    // 开始读取DS18B20的数据
    int result = onewire.reset();
    if (result == 0) {
        // DS18B20正在做温度转换,忙
        return;
    }

    onewire.select(address);
    onewire.write(READDATA);

    // byte 0: temperature LSB
    // byte 1: temperature MSB
    // byte 2: high alarm temp
    // byte 3: low alarm temp
    // byte 4: configuration register
    // byte 5: internal use
    // byte 6: internal use
    // byte 7: internal use
    // byte 8: CRC
    for (byte pos = 0; pos < 9; pos++) {
        switch (pos) {
            case 0: temperature[0]       = onewire.read(); break;
            case 1: temperature[1]       = onewire.read(); break;
            case 2: highAlarmTemperature = onewire.read(); break;
            case 3: lowAlarmTemperature  = onewire.read(); break;
            case 4: configuration        = onewire.read(); break;
            case 8: crc                  = onewire.read(); break;
        }
    }

    onewire.reset();

    // 计算温度值
    return (((unsigned int) temperature[1]) << 11) |
           (((unsigned int) temperature[0]) << 3);
}

/**
 * 根据DS18B20的说明文档所述,不同精度的温度转换需要的时间不同
 * 需要等待DS18B20完成温度转换后再读取温度,否则得到的温度为0℃
 */
unsigned int delayForResolution(byte bitResolution) {
    switch (bitResolution) {
        case  9: return  94; // 9位精度等待94ms
        case 10: return 188; // 10位精度等待188ms
        case 11: return 375; // 11位精度等待375ms
        default:
            return 750; // 默认等待750ms
    }
}
代码还没验证过,大概是这样啦~→_→←_←

你可能感兴趣的:([Arduino] DS18B20 温度传感器)