[Arduino] DS18B20 温度传感器

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

连线方式

DS18B20有三个引脚:

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

独立供电模式

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


独立供电电路

寄生供电模式

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


寄生供电电路

驱动代码

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

寄存器结构

DS18B20内建有三种寄存器:

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

指令集

指令 类型 功能 描述
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
    }
}
代码还没验证过,大概是这样啦~→_→←_←
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容