ESP8266接温度传感器18B20时序校准

陈拓 chentuo@ms.xab.ac.cn 2020/06/22-2020/06/25

 

1. 概述

在《ESP8266_SDK发送温度数据到阿里云》

https://blog.csdn.net/chentuo2000/article/details/105592791

https://zhuanlan.zhihu.com/p/132582024

一文中我们将温度传感器DS18B20的温度数据传送到了阿里云物联网平台。

最近由于受疫情和国际局势的影响,美信原厂的DS18B20涨价了。于是在网上买了几种其他厂商的产品做测试,有些样品读取数据正常,有些不正常,这是因为不同产品的时序有差异,对读取不正常的产品要进行时序校准。

为了时序准确,在《ESP8266毫秒微秒延时测量》一文中

https://zhuanlan.zhihu.com/p/150070320

https://blog.csdn.net/chentuo2000/article/details/106914301

我们首先对ESP8266的延时精度进行了测量。

2. 操作18B20的代码

  • ds18b20.c的头文件ds18b20.h
#ifndef __DS18B20_H__
#define __DS18B20_H__
 
#define DSPORT GPIO_ID_PIN(2) //(DS18B20连接ESP8266-01的GPIO2)
 
uint8_t ds18b20_reset(void);
int ds18b20_read_temp(void);
 
#endif
  • 读18B20的c程序代码ds18b20.c

这是用我新买的18B20校正过的程序。

#include "ets_sys.h"
#include "os_type.h"
#include "osapi.h"
#include "mem.h"
#include "user_interface.h"
#include "gpio.h"
#include "ds18b20.h"

void delay_1ms(uint16 y) {
    os_delay_us(y * 1000);
}

/* DS18B20复位 */
uint8_t ICACHE_FLASH_ATTR ds18b20_reset(void) {
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO2); // ESP8266-01的GPIO2连接DS18B20的数据线
    GPIO_OUTPUT_SET(DSPORT, 0);     // 将总线拉低480us-960us ,总线上所有器件都将被复位
    os_delay_us(495);               // 保持低电平,使得MASTER Tx > 480us
    GPIO_OUTPUT_SET(DSPORT, 1);     // 拉高电平,释放总线,如果DS18B20做出反应将在15us~60us后拉低总线
    os_delay_us(80);                // 等待DS18B20拉低总线
    uint8_t ack = GPIO_INPUT_GET(DSPORT);   // 获取总线状态
    os_delay_us(380);               // 调节MASTER TR > 480us

    return(ack);                    // 成功返回0,失败返回1
}

/* 写一位数据 */
void ICACHE_FLASH_ATTR write_bit(uint8_t bit) {
    if (bit) {
        GPIO_OUTPUT_SET(DSPORT, 0);     // 拉低总线
        os_delay_us(1);                 // 延时>1us
        GPIO_OUTPUT_SET(DSPORT, 1);     // 主机输出高电平
        os_delay_us(80);                // 60us < Tx “1”
    } else {
        GPIO_OUTPUT_SET(DSPORT, 0);     // 主机拉低总线
        os_delay_us(80);                // 60us < Tx “0” < 120us
        GPIO_OUTPUT_SET(DSPORT, 1);     // 主机释放总线,恢复高电平
        os_delay_us(1);					// TREC > 1us
	}
}

/* 写一字节数据 */
void ICACHE_FLASH_ATTR write_byte(uint8_t val) {
    uint8_t i, bit;
    for (i=0;i<8;i++) {     // 写入一个字节的数据,一个时序中写一次
     bit=val>>i;            // 右移i位
     bit&=0x01;             // 复制那位数据到temp
     write_bit(bit);        // 调用write_bit
    }
}

/* 读一位数据 */
uint8_t ICACHE_FLASH_ATTR read_bit(void) {
    uint8_t bit;
    GPIO_OUTPUT_SET(DSPORT, 0);     // 拉低总线,开始读时序
    os_delay_us(1);                 // 读数据之前先把总线拉低>1us
    GPIO_OUTPUT_SET(DSPORT, 1);     // 释放总线
    os_delay_us(11);                // 延时到采样位置
    bit = GPIO_INPUT_GET(DSPORT);   // 获取总线值
    os_delay_us(48);                // 延时以完成此次读时序60us
    return(bit);                    // 返回总线值
}

/* 读一字节数据 */
uint8_t ICACHE_FLASH_ATTR read_byte(void) {
    uint8_t i,value=0;
    for(i=0;i<8;i++) {
        if(read_bit())      // 读一字节数据,一个时序中读一次,并作移位处理
        value|=0x01<<i;
    }
    return(value);
}

/* 读温度 */
int ICACHE_FLASH_ATTR ds18b20_read_temp(void) {
    int temp = 0;
	uint8_t ack;
    uint8_t msb, lsb;

    ack = ds18b20_reset();  // 复位
	os_printf("ack ->:%d\r\n", ack);
	// 18B20内部温度转换
    write_byte(0xcc);       // 仅一个DS18b20,跳过ROM
    write_byte(0x44);       // 温度转换
    delay_1ms(700);         // 延时>600ms
	ds18b20_reset();        // 复位,每一次读写之前都要对DS18B20进行复位操作
	write_byte(0xcc);       // 仅一个DS18b20,跳过ROM
	write_byte(0xbe);       // 读温度数据
    lsb = read_byte();      // 读LSB
    msb = read_byte();      // 读MSB
    temp = msb;
    temp <<= 8;
    temp |= lsb;

    return temp;
}

程序的用法请看《ESP8266_SDK发送温度数据到阿里云》一文。

3. 操作18B20的时序

3.1 逻辑分析仪设置

测试仪器是广州致远的LA1016逻辑分析仪。下面是触发和采样设置。

3.2 初始化时序

  • 复位即应答关系时序图

  • 代码
    GPIO_OUTPUT_SET(DSPORT, 0);     // 将总线拉低480us-960us ,总线上所有器件都将被复位
    os_delay_us(495);               // 保持低电平,使得MASTER Tx > 480us
    GPIO_OUTPUT_SET(DSPORT, 1);     // 拉高电平,释放总线,如果DS18B20做出反应将在15us~60us后拉低总线
    os_delay_us(80);                // 等待DS18B20拉低总线
    uint8_t ack = GPIO_INPUT_GET(DSPORT);   // 获取总线状态
    os_delay_us(380);               // 调节MASTER TR > 480us
    return(ack);                    // 成功返回0,失败返回1
  • 波形

T从第一个下降沿开始采样

M1-T是MASTER Tx,主机拉低总线时间496us > 480us

M1主机拉高,释放总线

M2-M1 DS18B20从总线释放后30.1us开始应答,即拉低总线

M3-M2 DS18B20应答持续时间100.5us,我们在从M1开始的80us处采样即可

M3 DS18B20拉高释放总线

M3-M4延时用来调节MASTER Rx

M4-M1是MASTER Rx=508.4us > 480us

3.3 写操作

3.3.1 写1位和读1位时序图

3.3.2 写1位数据

  • 写“0”
        GPIO_OUTPUT_SET(DSPORT, 0);     // 主机拉低总线
        os_delay_us(80);                // 60us < Tx “0” < 120us
        GPIO_OUTPUT_SET(DSPORT, 1);     // 主机释放总线,恢复高电平
        os_delay_us(1);		  // TREC > 1us

M1主机拉低总线

M2-M1 60us < Tx “0”=80.9us < 120us

M2主机释放总线

M3-M2 TREC > 1us

  • 写“1”
        GPIO_OUTPUT_SET(DSPORT, 0);     // 拉低总线
        os_delay_us(1);                 // 延时 > 1us
        GPIO_OUTPUT_SET(DSPORT, 1);     // 主机输出高电平
        os_delay_us(80);                // 60us < Tx “1”

M1 拉低总线

M2-M1延时 > 1us

M2主机输出高电平

M3-M2 = 81.4us > 60us

3.3.3 写1字节数据0xcc(1100 1100)

注意小端先写,也就是从右向左一位一位写0011 0011。

void ICACHE_FLASH_ATTR write_byte(uint8_t val) {
    uint8_t i, bit;
    for (i=0;i<8;i++) {     // 写入一个字节的数据,一个时序中写一次
     bit=val>>i;            // 右移i位
     bit&=0x01;             // 复制那位数据到temp
     write_bit(bit);        // 调用write_bit
    }
}

3.3.4 发送温度转换命令

    write_byte(0xcc);       // 仅一个DS18b20 ,跳过ROM
    write_byte(0x44);       // 温度变换
    delay_1ms(700);         // 延时>600ms

3.4 读操作

3.4.1 发送读温度命令

    ds18b20_reset();        // 复位,每一次读写之前都要对DS18B20进行复位操作
    write_byte(0xcc);       // 仅一个DS18b20,跳过ROM
    write_byte(0xbe);       // 读温度数据

3.4.2 读1位数据

    uint8_t bit;
    GPIO_OUTPUT_SET(DSPORT, 0);     // 拉低总线,开始读时序
    os_delay_us(1);                 // 读数据之前先把总线拉低>1us
    GPIO_OUTPUT_SET(DSPORT, 1);     // 释放总线
    os_delay_us(11);                // 延时到采样位置
    bit = GPIO_INPUT_GET(DSPORT);   // 获取总线值
    os_delay_us(48);                // 延时以完成此次读时序60us
    return(bit);                    // 返回总线值
  • 读数据“0”

M1主机拉低总线,持续1us后释放总线

M2-M1 DS18B20拉低总线,输出数据0,主机在M1之后12usc处采样

M2 DS18B20释放总线

M3-M2主机上拉,高电平

M3-M1读取周期为62.2us > 60us

  • 读“1”

M1主机拉低总线

M2-M1持续1us后释放总线

M3-M2 DS18B20释放总线,主机上拉到高电平,主机在M1之后12usc处采样

M3-M1读取周期为63.2us > 60us

3.4.3 读1个字节数据

注意低位先读。

    uint8_t i,value=0;
    for(i=0;i<8;i++) {
        if(read_bit())      // 读一字节数据,一个时序中读一次,并作移位处理
        value|=0x01<<i;
    }
    return(value);
  • 读2个字节的温度数据
    lsb = read_byte();      // 读LSB
    msb = read_byte();      // 读MSB

      1     0      1      1      0      0     1      1      1     0      0      0      0     0     0      0     

大小端转换:

0000 0001 1100 1101

前5位是符号位,0表示正数。

001 1100 1101 = 461

转换成温度值:461/16 = 28.81℃

串口显示,请看前面概述中提到的《ESP8266_SDK发送温度数据到阿里云》一文。

 


http://www.niftyadmin.cn/n/1733233.html

相关文章

RabbitMQ第四个实操小案例——DirectExchange

文章目录RabbitMQ第四个实操小案例——DirectExchangeRabbitMQ第四个实操小案例——DirectExchange DirectExchange&#xff1a;这种交换机的模式跟前面的Fouout&#xff08;广播&#xff09;不太一样&#xff0c;DirectExchange 会将接收到的消息根据规则路由到指定的Queue&a…

javascript面向对象技术基础(六)

http://sdcyst.javaeye.com/blog/296492作用域、闭包、模拟私有属性 先来简单说一下变量作用域&#xff0c;这些东西我们都很熟悉了&#xff0c;所以也不详细介绍。 Js代码 var sco "global"; //全局变量 function t() { var sco "local"; //函…

javascript面向对象技术基础(四)

http://sdcyst.javaeye.com/blog/288808类、构造函数、原型 先来说明一点:在上面的内容中提到,每一个函数都包含了一个prototype属性,这个属性指向了一个prototype对象(Every function has a prototype property that refers to a predefined prototype object --section8.6.…

树莓派安装Web服务器Boa和CGIC

树莓派安装Web服务器Boa和CGIC 陈拓 2020/08/01-2020/08/09 1. 树莓派换源 为了加快所需软件的下载&#xff0c;我们需要先换源。 首先查看系统版本&#xff1a;lsb_release -a修改软件更新源 /etc/apt/sources.list sudo nano /etc/apt/sources.list 在下面的语句前面加#注…

树莓派I2C通过Shell操作FDC2214

陈拓 chentuoms.xab.ac.cn 2020/07/21-2020/07/29 FDC2214是Ti公司的一款低功耗高精度的电容传感器芯片。本文讲述用树莓派Linux Shell配置和操作FDC2214&#xff0c;可以快速熟悉并进行原型开发。 1. 树莓派换源 为了加快所需软件的下载&#xff0c;我们需要先换源。 首先查…

界面渐变特效 -- CSS实现 -- 兼容IE8

特别注意&#xff1a;里面的RGB颜色值必须要全写&#xff0c;不能使用缩写。左右&#xff1a;background: -webkit-gradient(linear, 0 0, 0 100%, from(#80c1e7), to(#213c7c)); background: -webkit-linear-gradient(left, #80c1e7, #213c7c); background: -moz-linear-g…

javascript面向对象技术基础(二)

数组 我们已经提到过,对象是无序数据的集合,而数组则是有序数据的集合,数组中的数据(元素)通过索引(从0开始)来访问,数组中的数据可以是任何的数据类 型.数组本身仍旧是对象,但是由于数组的很多特性,通常情况下把数组和对象区别开来分别对待(Throughout this book, objects and…

树莓安装Nginx并支持CGI

陈拓 2020.09.17/2020.09.17 1. 概述 百度百科对Nginx 的介绍&#xff1a; Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器&#xff0c;同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔赛索耶夫为俄罗斯访问量第二的Rambler.ru站点&#xff08;俄文&#xff1a;…