《DNESP32P4开辟指南_V1.0》第三十一章 DS18B20实验

[复制链接]
发表于 2026-6-25 08:56:04 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
第三十一章 DS18B20实验
本章,我们将先容ESP32-P4怎样读取外部温度传感器的温度,来得到较为正确的情况温度。我们将学习单总线技能,通过它来实现ESP32-P4和外部温度传感器DS18B20的通讯,并把从温度传感器得到的温度表如今LCD上。
本章分为如下几个末节:
31.1 DS18B20先容
31.2 硬件计划
31.3 步伐计划
31.4 下载验证
31.1 DS18B20先容
31.1.1 DS18B20简介
DS18B20是由DALLAS半导体公司推出的一种“单总线”接口的温度传感器,实物图如下图所示。

图31.1.1.1 DS18B20实物图
与传统的热敏电阻等测温元件相比,它是一种新型的体积小、实用电压宽、与微处置惩罚器接口简朴的数字化温度传感器。单总线结构具有轻巧且经济的特点,可使用户轻松地组建传感器网络,从而为丈量体系的构建引入全新的概念,测试温度范围为-55+125℃,精度为±0.5℃。现场温度直接以单总线的数字方式传输,大大进步了体系的抗干扰性。它能直接读出被测温度,而且可根据实际要求通过简朴的编程实现912位的数字值读数方式。它工作在3~5.5V的电压范围,采取多种封装情势,从而使体系设置机动、方便,设定分辨率以及用户设定的报警温度存储在EEPROM中,掉电后依然生存。其内部结构如下图所示。

图31.1.1.2 DS18B20内部结构图
ROM中的64位序列号是出厂前被标志好的,它可以看作使该DS18B20的地点序列码,每个DS18B20的64位序列号均不雷同。64位ROM的分列是:前8位是产物家属码,接着48位是DS18B20的序列号,末了8位是前面56位的循环冗余校验码(CRC=X8+X5+X4+1)。ROM作用是使每一个DS18B20都各不雷同,如许计划可以允许一根总线上挂载多个DS18B20模块同时工作且不会引起辩说。
31.1.2 DS18B20时序先容
全部单总线器件要求采取严酷的信号时序,以包管数据的完备性。DS18B20共有6种信号范例:复位脉冲、应答脉冲、写0、写1、读0和读1。全部这些信号,除了应答脉冲以外,都是由主机发出同步信号。而且发送全部的下令和数据都是字节的低位在前。这里我们简朴先容这几个信号的时序。
1,复位脉冲和应答脉冲

图31.1.2.1 复位脉冲和应答脉冲时序图
单总线上的全部通讯都是以初始化序列开始。主机输出低电平,保持低电平常间至少要在480us,以产生复位脉冲。接着主机开释总线,4.7K的上拉电阻将单总线拉高,延时时间要在1560us,并进入吸收模式(Rx)。接着DS18B20拉低总线60240us,以产生低电平应答脉冲。
2,写时序

图31.1.2.2 写时序图
写时序包罗写0时序和写1时序。全部写时序至少须要60us,且在两次独立的写时序之间至少须要1us的规复时间,两种写时序均起始于主机拉低总线。写1时序:主机输出低电平,延时2us,然后开释总线,延时60us。写0时序:主机输出低电平,延时60us,然后开释总线延时2us。
3,读时序

图31.1.2.3 读时序图
单总线器件仅在主机发出读时序时,才向主机传输数据,以是,在主机发出读数据下令后,必须立即产生读时序,以便从性可以大概传输数据。全部读时序至少须要60us,且在2次独立的读时序之间至少须要1us的规复时间。每个读时序都由主机发起,至少拉低总线1us。主机在读时序期间必须开释总线,而且在时序起始后的15us之内采样总线状态。范例的读时序过程为:主机输出低电平延时2us,然后主机转入输入模式延时12us,然后读取单总线当前的电平,然后延时50us。
在相识单总线时序之后,我们来看一下DS18B20的范例温度读取过程,DS18B20的范例温度读取过程为:复位→发SKIP ROM(0xCC)→发开始转换下令(0x44)→延时→复位→发送SKIP ROM下令(0xCC)→发送存储器下令(0xBE)→连续读取两个字节数据(即温度)→竣事。
DS18B20的简介,我们就先容到这里,关于该传感器的具体分析,请各人参考其数据手册。
31.2 硬件计划
31.2.1 例程功能
DS18B20每隔100ms左右读取一次数据,并把温度表如今LCD上。LED0闪耀用于提示步伐正在运行。
31.2.2 硬件资源
1)LED灯
LED        0        - IO51
2)RGBLCD / MIPILCD(引脚太多,不摆列出来)
3)DS18B20
1WIRE_DQ        - IO23
31.2.3 原理图
DS18B20器件干系原理图,如下图所示。

图31.2.3.1 DS18B20原理图
从上图可以看出,使用的是IO23来毗连U4的DQ引脚,图中U10为DHT11(数字温湿度传感器)和DS18B20共用的一个接口,DHT11将在下一章先容。
DS18B20只用到U4的3个引脚(U4的1、2和3脚),将DS18B20传感器插入到这个上面就可以通过ESP32-P4来读取DS18B20的温度了。毗连表示图如下所示。

图31.2.3.2 DS18B20与开辟板毗连图
从上图可以看出,DS18B20的平面部门(有字的那面)应该朝内,而曲面部门朝外。
31.3 步伐计划
本例程重要用到的是GPIO函数,GPIO函数已在11.3.1章节中具体叙述,为克制重复,此处不再赘述。发起读者查阅第十一章的函数分析章节,以获取更多关于GPIO函数的信息。
31.3.1 步伐流程图

图31.3.1.1 DS18B20实验步伐流程图
31.3.2 步伐分析
在22_ds18b20例程中,作者在22_ds18b20\components\BSP路径下新建在¥在¥在¥了1个文件夹DS18B20,而且须要更改CMakeLists.txt内容,以便在其他文件上调用。
1. DS18B20驱动代码
这里我们只讲授核心代码,具体的源码请各人参考光盘本实验对应源码。DS18B20驱动源码包罗两个文件:ds18b20.c和ds18b20.h。
下面先分析ds18b20.h的步伐。对DS18B20的数据引脚做了干系界说。
  1. #define DS18B20_DQ_GPIO_PIN      GPIO_NUM_23
复制代码
由于数据线会存在获取高低电平以及设置高低电平,以是为DS18B20_DQ_GPIO_PIN 做了干系宏函数供单总线时序函数调用。
  1. #define DS18B20_DQ_IN              gpio_get_level(DS18B20_DQ_GPIO_PIN)        /* IO操作 */
  2. #define DS18B20_DQ_OUT(x)         do { x ?                                    \
  3.                                       gpio_set_level(DS18B20_DQ_GPIO_PIN, 1): \
  4.                                      gpio_set_level(DS18B20_DQ_GPIO_PIN, 0); \
  5.                                   } while(0)                                        /* DS18B20端口定义 */
复制代码
接下来,分析一下ds18b20.c的步伐,起首来看一下DS18B20的初始化函数ds18b20_init,代码如下:
  1. /**
  2. * @brief             初始化DS18B20
  3. * @param             无
  4. * @retval            0, 正常; 1, 不存在/不正常
  5. */
  6. uint8_t ds18b20_init(void)
  7. {
  8.     gpio_config_t gpio_init_struct;
  9.     gpio_init_struct.intr_type = GPIO_INTR_DISABLE;                   /* 失能引脚中断 */
  10.     gpio_init_struct.mode = GPIO_MODE_INPUT_OUTPUT_OD;         /* 开漏的输入和输出 */
  11.     gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE;                            /* 使能上拉 */
  12.     gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE;                   /* 失能下拉 */
  13.     gpio_init_struct.pin_bit_mask = 1ull << DS18B20_DQ_GPIO_PIN;        /* 设置位掩码 */
  14.     gpio_config(&gpio_init_struct);                            /* 配置DS18B20引脚 */
  15.     ds18b20_reset();                        /* 复位DS18B20 */
  16.     return ds18b20_check();                /* 等待DS18B20回应 */
  17. }
复制代码
以上两个函数分别代表着前面所说的复位脉冲与应答信号,各人可以对比前面的时序图举行明白。由于复位脉冲比力简朴,以是这里不做睁开。如今看一下应答信号函数,函数重要是对于DS18B20传感器的回应信号举行检测,对此判定其是否存在。函数的实现也是依据时序图举行逻辑判定,比方当主机发送了复位信号之后,按照时序,DS18B20会拉低数据线60~240us,同时主机吸收最小时间为480us,我们就依据这两个硬性条件举行判定,起首须要设置一个时限期待DS18B20相应,背面也设置一个时限期待DS18B20开释数据线拉高,满意这两个条件即DS18B20乐成相应。
下面先容的是写函数,其界说如下:
  1. /**
  2. * @brief            复位DS18B20
  3. * @param            无
  4. * @retval            无
  5. */
  6. void ds18b20_reset(void)
  7. {
  8.     DS18B20_DQ_OUT(0);                     /* 拉低DQ,复位 */
  9.     esp_rom_delay_us(750);          /* 拉低至少750μs */
  10.     DS18B20_DQ_OUT(1);              /* DQ=1,释放复位 */
  11.     esp_rom_delay_us(15);           /* 主机拉高10~35us */
  12. }
  13. /**
  14. * @brief             等待DS18B20的回应
  15. * @param            无
  16. * @retval            0, DS18B20正常; 1, DS18B20异常/不存在
  17. */
  18. uint8_t ds18b20_check(void)
  19. {
  20.     uint8_t retry = 0;
  21.     uint8_t rval = 0;
  22.     while (DS18B20_DQ_IN && retry < 200)                 /* DS18B20会拉低200us */
  23.     {
  24.         retry++;
  25.         esp_rom_delay_us(1);
  26.     }
  27.     if (retry >= 200)
  28.     {
  29.         rval = 1;
  30.     }
  31.     else
  32.     {
  33.         retry = 0;
  34.         while (!DS18B20_DQ_IN && retry < 240)        /* DS18B20拉低后会再次拉高240us */
  35.         {
  36.             retry++;
  37.             esp_rom_delay_us(1);
  38.         }
  39.         if (retry >= 240)
  40.         {
  41.             rval = 1;
  42.         }
  43.     }
  44.    
  45.     return rval;
  46. }
复制代码
通过形参决定是写1还是写0,按照前面临写时序的分析,我们可以很清晰知道写函数的逻辑处置惩罚。
有写函数肯定就有读函数,下面看一下读函数:
[code]/** * @brief            从DS18B20读取一个位 * @param             无 * @retval            读取到的位值: 0 / 1 */uint8_t ds18b20_read_bit(void){    uint8_t data = 0;    DS18B20_DQ_OUT(0);    esp_rom_delay_us(2);    DS18B20_DQ_OUT(1);    esp_rom_delay_us(12);    if (DS18B20_DQ_IN)    {        data = 1;    }    esp_rom_delay_us(50);    return data;}/** * @brief            从DS18B20读取一个字节 * @param             无 * @retval            读到的数据 */uint8_t ds18b20_read_byte(void){    uint8_t i, b, data = 0;    for (i = 0; i < 8; i++)     /* 循环读取8位数据 */    {        b = ds18b20_read_bit(); /* DS18B20先输出低位数据,高位数据后输出 */        data |= b  7)    { /* 温度为负,查察DS18B20的温度表现法与盘算机存储正负数据的原理同等:        正数补码为寄存器存储的数据自身,负数补码为寄存器存储值按位取反后+1        以是我们直接取它实际的负数部门,但负数的补码为取反后加一,但思量到        低位大概+1后有进位和代码冗余,我们这里先暂时没有作+1的处置惩罚,这里须要注意  */        TH = ~TH;        TL = ~TL;        flag = 0;        /* 温度为负 */    }    temp = TH;              /* 得到高八位 */    temp
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表