OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 23|回复: 0

《ESP32-P4开发指南— V1.0》第三十一章 DS18B20实验

[复制链接]

1233

主题

1247

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
5304
金钱
5304
注册时间
2019-5-8
在线时间
1361 小时
发表于 昨天 09:07 | 显示全部楼层 |阅读模式
第三十一章 DS18B20实验

1)实验平台:正点原子DNESP32P4开发板

2)章节摘自【正点原子】ESP32-P4开发指南— V1.0

3)购买链接:https://detail.tmall.com/item.htm?id=873309579825

4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/esp32/ATK-DNESP32P4.html

5)正点原子官方B站:https://space.bilibili.com/394620890

6)正点原子DNESP32S3开发板技术交流群:132780729


2.jpg

3.png

本章,我们将介绍ESP32-P4如何读取外部温度传感器的温度,来得到较为准确的环境温度。我们将学习单总线技术,通过它来实现ESP32-P4和外部温度传感器DS18B20的通信,并把从温度传感器得到的温度显示在LCD上。
本章分为如下几个小节:
31.1 DS18B20介绍
31.2 硬件设计
31.3 程序设计
31.4 下载验证


31.1 DS18B20介绍

31.1.1 DS18B20简介
DS18B20是由DALLAS半导体公司推出的一种“单总线”接口的温度传感器,实物图如下图所示。

第三十一章 DS18B20实验267.png
图31.1.1.1 DS18B20实物图

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

第三十一章 DS18B20实验576.png
图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,复位脉冲和应答脉冲

第三十一章 DS18B20实验966.png
图31.1.2.1 复位脉冲和应答脉冲时序图

单总线上的所有通信都是以初始化序列开始。主机输出低电平,保持低电平时间至少要在480us,以产生复位脉冲。接着主机释放总线,4.7K的上拉电阻将单总线拉高,延时时间要在15~60us,并进入接收模式(Rx)。接着DS18B20拉低总线60~240us,以产生低电平应答脉冲。
2,写时序


第三十一章 DS18B20实验1135.png
图31.1.2.2 写时序图

写时序包括写0时序和写1时序。所有写时序至少需要60us,且在两次独立的写时序之间至少需要1us的恢复时间,两种写时序均起始于主机拉低总线。写1时序:主机输出低电平,延时2us,然后释放总线,延时60us。写0时序:主机输出低电平,延时60us,然后释放总线延时2us。
3,读时序


第三十一章 DS18B20实验1294.png
图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器件相关原理图,如下图所示。

第三十一章 DS18B20实验1920.png
图31.2.3.1 DS18B20原理图

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


第三十一章 DS18B20实验2109.png
图31.2.3.2 DS18B20与开发板连接图

从上图可以看出,DS18B20的平面部分(有字的那面)应该朝内,而曲面部分朝外。

31.3 程序设计
本例程主要用到的是GPIO函数,GPIO函数已在11.3.1章节中详细阐述,为避免重复,此处不再赘述。建议读者查阅第十一章的函数解析章节,以获取更多关于GPIO函数的信息。

31.3.1 程序流程图

第三十一章 DS18B20实验2314.png
图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. <font size="3">#define DS18B20_DQ_IN              gpio_get_level(DS18B20_DQ_GPIO_PIN)        /* IO操作 */</font>

  2. <font size="3">#define DS18B20_DQ_OUT(x)         do { x ?                                    \</font>
  3. <font size="3">                                      gpio_set_level(DS18B20_DQ_GPIO_PIN, 1): \</font>
  4. <font size="3">                                     gpio_set_level(DS18B20_DQ_GPIO_PIN, 0); \</font>
  5. <font size="3">                                  } while(0)                                        /* DS18B20端口定义 */</font>
复制代码
接下来,解析一下ds18b20.c的程序,首先来看一下DS18B20的初始化函数ds18b20_init,代码如下:
  1. <font size="3">/**</font>
  2. <font size="3"> * @brief             初始化DS18B20</font>
  3. <font size="3"> * [url=home.php?mod=space&uid=271674]@param[/url]             无</font>
  4. <font size="3"> * @retval            0, 正常; 1, 不存在/不正常</font>
  5. <font size="3"> */</font>
  6. <font size="3">uint8_t ds18b20_init(void)</font>
  7. <font size="3">{</font>
  8. <font size="3">    gpio_config_t gpio_init_struct;</font>

  9. <font size="3">    gpio_init_struct.intr_type = GPIO_INTR_DISABLE;                   /* 失能引脚中断 */</font>
  10. <font size="3">    gpio_init_struct.mode = GPIO_MODE_INPUT_OUTPUT_OD;         /* 开漏的输入和输出 */</font>
  11. <font size="3">    gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE;                            /* 使能上拉 */</font>
  12. <font size="3">    gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE;                   /* 失能下拉 */</font>
  13. <font size="3">    gpio_init_struct.pin_bit_mask = 1ull << DS18B20_DQ_GPIO_PIN;        /* 设置位掩码 */</font>
  14. <font size="3">    gpio_config(&gpio_init_struct);                            /* 配置DS18B20引脚 */</font>

  15. <font size="3">    ds18b20_reset();                        /* 复位DS18B20 */</font>
  16. <font size="3">    return ds18b20_check();                /* 等待DS18B20回应 */</font>
  17. <font size="3">}</font>
复制代码
在DS18B20初始化函数中,首先对数据引脚初始化,然后通过调用复位函数和自检函数,可以知道DS18B20是否正常。
下面介绍一下在前面提及的几个信号类型。
  1. <font size="3">/**</font>
  2. <font size="3"> * @brief            复位DS18B20</font>
  3. <font size="3"> * @param            无</font>
  4. <font size="3"> * @retval            无</font>
  5. <font size="3"> */</font>
  6. <font size="3">void ds18b20_reset(void)</font>
  7. <font size="3">{</font>
  8. <font size="3">    DS18B20_DQ_OUT(0);                     /* 拉低DQ,复位 */</font>
  9. <font size="3">    esp_rom_delay_us(750);          /* 拉低至少750μs */</font>
  10. <font size="3">    DS18B20_DQ_OUT(1);              /* DQ=1,释放复位 */</font>
  11. <font size="3">    esp_rom_delay_us(15);           /* 主机拉高10~35us */</font>
  12. <font size="3">}</font>

  13. <font size="3">/**</font>
  14. <font size="3"> * @brief             等待DS18B20的回应</font>
  15. <font size="3"> * @param            无</font>
  16. <font size="3"> * @retval            0, DS18B20正常; 1, DS18B20异常/不存在</font>
  17. <font size="3"> */</font>
  18. <font size="3">uint8_t ds18b20_check(void)</font>
  19. <font size="3">{</font>
  20. <font size="3">    uint8_t retry = 0;</font>
  21. <font size="3">    uint8_t rval = 0;</font>

  22. <font size="3">    while (DS18B20_DQ_IN && retry < 200)                 /* DS18B20会拉低200us */</font>
  23. <font size="3">    {</font>
  24. <font size="3">        retry++;</font>
  25. <font size="3">        esp_rom_delay_us(1);</font>
  26. <font size="3">    }</font>

  27. <font size="3">    if (retry >= 200)</font>
  28. <font size="3">    {</font>
  29. <font size="3">        rval = 1;</font>
  30. <font size="3">    }</font>
  31. <font size="3">    else</font>
  32. <font size="3">    {</font>
  33. <font size="3">        retry = 0;</font>

  34. <font size="3">        while (!DS18B20_DQ_IN && retry < 240)        /* DS18B20拉低后会再次拉高240us */</font>
  35. <font size="3">        {</font>
  36. <font size="3">            retry++;</font>
  37. <font size="3">            esp_rom_delay_us(1);</font>
  38. <font size="3">        }</font>
  39. <font size="3">        if (retry >= 240)</font>
  40. <font size="3">        {</font>
  41. <font size="3">            rval = 1;</font>
  42. <font size="3">        }</font>
  43. <font size="3">    }</font>
  44. <font size="3">    </font>
  45. <font size="3">    return rval;</font>
  46. <font size="3">}</font>
复制代码
以上两个函数分别代表着前面所说的复位脉冲与应答信号,大家可以对比前面的时序图进行理解。由于复位脉冲比较简单,所以这里不做展开。现在看一下应答信号函数,函数主要是对于DS18B20传感器的回应信号进行检测,对此判断其是否存在。函数的实现也是依据时序图进行逻辑判断,例如当主机发送了复位信号之后,按照时序,DS18B20会拉低数据线60~240us,同时主机接收最小时间为480us,我们就依据这两个硬性条件进行判断,首先需要设置一个时限等待DS18B20响应,后面也设置一个时限等待DS18B20释放数据线拉高,满足这两个条件即DS18B20成功响应。
下面介绍的是写函数,其定义如下:
  1. <font size="3">/**</font>
  2. <font size="3"> * @brief              写一个字节到DS18B20</font>
  3. <font size="3"> * @param              data: 要写入的字节</font>
  4. <font size="3"> * @retval             无</font>
  5. <font size="3"> */</font>
  6. <font size="3">void ds18b20_write_byte(uint8_t data)</font>
  7. <font size="3">{</font>
  8. <font size="3">    uint8_t j;</font>

  9. <font size="3">    for (j = 1; j <= 8; j++)</font>
  10. <font size="3">    {</font>
  11. <font size="3">        if (data & 0x01)</font>
  12. <font size="3">        {</font>
  13. <font size="3">            DS18B20_DQ_OUT(0);          /* 写0 */</font>
  14. <font size="3">            esp_rom_delay_us(2);</font>
  15. <font size="3">            DS18B20_DQ_OUT(1);          /* 写1 */</font>
  16. <font size="3">            esp_rom_delay_us(60);</font>
  17. <font size="3">        }</font>
  18. <font size="3">        else</font>
  19. <font size="3">        {</font>
  20. <font size="3">            DS18B20_DQ_OUT(0);          /* 写0 */</font>
  21. <font size="3">            esp_rom_delay_us(60);</font>
  22. <font size="3">            DS18B20_DQ_OUT(1);          /* 写1 */</font>
  23. <font size="3">            esp_rom_delay_us(2);</font>
  24. <font size="3">        }</font>

  25. <font size="3">        data >>= 1;                     /* 右移,获取高一位数据 */</font>
  26. <font size="3">    }</font>
  27. <font size="3">}</font>
复制代码
通过形参决定是写1还是写0,按照前面对写时序的分析,我们可以很清晰知道写函数的逻辑处理。
有写函数肯定就有读函数,下面看一下读函数:
  1. <font size="3">/**</font>
  2. <font size="3"> * @brief            从DS18B20读取一个位</font>
  3. <font size="3"> * @param             无</font>
  4. <font size="3"> * @retval            读取到的位值: 0 / 1</font>
  5. <font size="3"> */</font>
  6. <font size="3">uint8_t ds18b20_read_bit(void)</font>
  7. <font size="3">{</font>
  8. <font size="3">    uint8_t data = 0;</font>
  9. <font size="3">    DS18B20_DQ_OUT(0);</font>
  10. <font size="3">    esp_rom_delay_us(2);</font>
  11. <font size="3">    DS18B20_DQ_OUT(1);</font>
  12. <font size="3">    esp_rom_delay_us(12);</font>

  13. <font size="3">    if (DS18B20_DQ_IN)</font>
  14. <font size="3">    {</font>
  15. <font size="3">        data = 1;</font>
  16. <font size="3">    }</font>

  17. <font size="3">    esp_rom_delay_us(50);</font>
  18. <font size="3">    return data;</font>
  19. <font size="3">}</font>

  20. <font size="3">/**</font>
  21. <font size="3"> * @brief            从DS18B20读取一个字节</font>
  22. <font size="3"> * @param             无</font>
  23. <font size="3"> * @retval            读到的数据</font>
  24. <font size="3"> */</font>
  25. <font size="3">uint8_t ds18b20_read_byte(void)</font>
  26. <font size="3">{</font>
  27. <font size="3">    uint8_t i, b, data = 0;</font>

  28. <font size="3">    for (i = 0; i < 8; i++)     /* 循环读取8位数据 */</font>
  29. <font size="3">    {</font>
  30. <font size="3">        b = ds18b20_read_bit(); /* DS18B20先输出低位数据,高位数据后输出 */</font>
  31. <font size="3">        data |= b << i;         /* 填充data的每一位 */</font>
  32. <font size="3">    }</font>

  33. <font size="3">    return data;</font>
  34. <font size="3">}</font>
复制代码
在这里,ds18b20_read_bit函数从DS18B20处读取1位数据,在前面已经对读时序也进行了详细的分析,所以这里也不展开解释了。而ds18b20_read_byte便是调用ds18b20_read_bit函数实现1个字节数据的获取。
下面介绍读取温度函数,其定义如下:
  1. <font size="3">/**</font>
  2. <font size="3"> * @brief             开始温度转换</font>
  3. <font size="3"> * @param             无</font>
  4. <font size="3"> * @retval             无</font>
  5. <font size="3"> */</font>
  6. <font size="3">void ds18b20_start(void)</font>
  7. <font size="3">{</font>
  8. <font size="3">    ds18b20_reset();</font>
  9. <font size="3">    ds18b20_check();</font>
  10. <font size="3">    ds18b20_write_byte(0xcc);   /* 跳过rom */</font>
  11. <font size="3">    ds18b20_write_byte(0x44);   /* 转换 */</font>
  12. <font size="3">}</font>

  13. <font size="3">/**</font>
  14. <font size="3"> * @brief                  从ds18b20得到温度值(精度:0.1C)</font>
  15. <font size="3"> * @param           无</font>
  16. <font size="3"> * @retval          温度值 (-550~1250)</font>
  17. <font size="3"> *   [url=home.php?mod=space&uid=60778]@note[/url]                 返回的温度值放大了10倍.</font>
  18. <font size="3"> *                  实际使用的时候,要除以10才是实际温度.</font>
  19. <font size="3"> */</font>
  20. <font size="3">short ds18b20_get_temperature(void)</font>
  21. <font size="3">{</font>
  22. <font size="3">    uint8_t flag = 1;                   /* 默认温度为正数 */</font>
  23. <font size="3">    uint8_t TL, TH;</font>
  24. <font size="3">    short temp;</font>

  25. <font size="3">    ds18b20_start();                    /*  ds1820 start convert */</font>
  26. <font size="3">    ds18b20_reset();</font>
  27. <font size="3">    ds18b20_check();</font>
  28. <font size="3">    ds18b20_write_byte(0xcc);                 /*  skip rom */</font>
  29. <font size="3">    ds18b20_write_byte(0xbe);           /*  convert */</font>
  30. <font size="3">    TL = ds18b20_read_byte();           /*  LSB */</font>
  31. <font size="3">    TH = ds18b20_read_byte();           /*  MSB */</font>

  32. <font size="3">    if (TH > 7)</font>
  33. <font size="3">    { /* 温度为负,查看DS18B20的温度表示法与计算机存储正负数据的原理一致:</font>
  34. <font size="3">        正数补码为寄存器存储的数据自身,负数补码为寄存器存储值按位取反后+1</font>
  35. <font size="3">        所以我们直接取它实际的负数部分,但负数的补码为取反后加一,但考虑到</font>
  36. <font size="3">        低位可能+1后有进位和代码冗余,我们这里先暂时没有作+1的处理,这里需要留意  */</font>
  37. <font size="3">        TH = ~TH;</font>
  38. <font size="3">        TL = ~TL;</font>
  39. <font size="3">        flag = 0;        /* 温度为负 */</font>
  40. <font size="3">    }</font>

  41. <font size="3">    temp = TH;              /* 获得高八位 */</font>
  42. <font size="3">    temp <<= 8;</font>
  43. <font size="3">    temp += TL;             /* 获得底八位 */</font>

  44. <font size="3">    /* 转换成实际温度 */</font>
  45. <font size="3">    if (flag == 0)</font>
  46. <font size="3">    {   /* 将温度转换成负温度,这里的+1参考前面的说明 */</font>
  47. <font size="3">        temp = (double)(temp + 1) * 0.625;</font>
  48. <font size="3">        temp = -temp;   </font>
  49. <font size="3">    }</font>
  50. <font size="3">    else</font>
  51. <font size="3">    {</font>
  52. <font size="3">        temp = (double)temp * 0.625;                </font>
  53. <font size="3">    }</font>

  54. <font size="3">    return temp;</font>
  55. <font size="3">}</font>
复制代码
在这里简单介绍一下上面用到的RAM指令:
跳过ROM(0xCC),该指令只适合总线只有一个节点,它通过允许总线上的主机不提供64位ROM序列号而直接访问RAM,节省了操作时间。
温度转换(0x44),启动DS18B20进行温度转换,结果存入内部RAM。
读暂存器(0xBE),读暂存器9个字节内容,该指令从RAM的第一个字节(字节0)开始读取,直到九个字节(字节8,CRC值)被读出为止。如果不需要读出所有字节的内容,那么主机可以在任何时候发出复位信号以中止读操作。
2. CMakeLists.txt文件
本例程的功能实现主要依靠DS18B20驱动。要在main函数中,成功调用DS18B20文件中的内容,就得需要修改BSP文件夹下的CMakeLists.txt文件,修改如下:
  1. <font size="3">set(src_dirs</font>
  2. <font size="3">                   LED</font>
  3. <font size="3">                        LCD</font>
  4. <font size="3">                  DS18B20)</font>

  5. <font size="3">set(include_dirs</font>
  6. <font size="3">                  LED</font>
  7. <font size="3">                        LCD</font>
  8. <font size="3">                  DS18B20)</font>

  9. <font size="3">set(requires</font>
  10. <font size="3">                   driver</font>
  11. <font size="3">                   esp_lcd</font>
  12. <font size="3">                   esp_common)</font>

  13. <font size="3">idf_component_register(        SRC_DIRS ${src_dirs} INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})</font>

  14. <font size="3">component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)</font>
复制代码
3. main.c驱动代码
在main.c里面编写如下代码。
  1. <font size="3">void app_main(void)</font>
  2. <font size="3">{</font>
  3. <font size="3">    esp_err_t ret;</font>
  4. <font size="3">    uint8_t t = 0;</font>
  5. <font size="3">    short temperature = 0;</font>
  6. <font size="3">    </font>
  7. <font size="3">    ret = nvs_flash_init();           /* 初始化NVS */</font>
  8. <font size="3">    if(ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)</font>
  9. <font size="3">    {</font>
  10. <font size="3">        ESP_ERROR_CHECK(nvs_flash_erase());</font>
  11. <font size="3">        ESP_ERROR_CHECK(nvs_flash_init());</font>
  12. <font size="3">    }</font>

  13. <font size="3">    led_init();                             /* LED初始化 */</font>
  14. <font size="3">    lcd_init();                             /* LCD屏初始化 */</font>

  15. <font size="3">    lcd_show_string(30, 50, 200, 16, 16, "ESP32-P4", RED);</font>
  16. <font size="3">    lcd_show_string(30, 70, 200, 16, 16, "DS18B20 TEST", RED);</font>
  17. <font size="3">    lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);</font>
  18. <font size="3">    </font>
  19. <font size="3">    while (ds18b20_init())                /* 初始化DS18B20数字温度传感器 */</font>
  20. <font size="3">    {</font>
  21. <font size="3">        lcd_show_string(30, 110, 200, 16, 16, "DS18B20 Error", RED);</font>
  22. <font size="3">        vTaskDelay(pdMS_TO_TICKS(200));</font>
  23. <font size="3">        lcd_fill(30, 110, 239, 126, WHITE);</font>
  24. <font size="3">        vTaskDelay(pdMS_TO_TICKS(200));</font>
  25. <font size="3">    }</font>

  26. <font size="3">    lcd_show_string(30, 110, 200, 16, 16, "DS18B20 OK", RED);</font>
  27. <font size="3">    lcd_show_string(30, 130, 200, 16, 16, "Temp: 00.0C", BLUE);</font>

  28. <font size="3">    while (1)</font>
  29. <font size="3">    {</font>
  30. <font size="3">        if (t % 10 == 0)                /* 每100ms读取一次温度 */</font>
  31. <font size="3">        {</font>
  32. <font size="3">            temperature = ds18b20_get_temperature();</font>

  33. <font size="3">            if (temperature < 0)</font>
  34. <font size="3">            {</font>
  35. <font size="3">                lcd_show_char(70, 130, '-', 16, 0, BLUE);   /* 显示负号 */</font>
  36. <font size="3">                temperature = -temperature;                 /* 转为正数 */</font>
  37. <font size="3">            }</font>
  38. <font size="3">            else</font>
  39. <font size="3">            {</font>
  40. <font size="3">                lcd_show_char(70, 130, ' ', 16, 0, BLUE);   /* 无符号 */</font>
  41. <font size="3">            }</font>

  42. <font size="3">            lcd_show_num(78,  130, temperature / 10, 2, 16, BLUE);  /* 显示整数 */</font>
  43. <font size="3">            lcd_show_num(102, 130, temperature % 10, 1, 16, BLUE);  /* 显示小数 */</font>
  44. <font size="3">        }</font>

  45. <font size="3">        vTaskDelay(pdMS_TO_TICKS(10));</font>
  46. <font size="3">        t++;</font>

  47. <font size="3">        if (t == 20)</font>
  48. <font size="3">        {</font>
  49. <font size="3">            t = 0;</font>
  50. <font size="3">            LED0_TOGGLE();</font>
  51. <font size="3">        }</font>
  52. <font size="3">    }</font>
  53. <font size="3">}</font>
复制代码
在app_main函数中,设置一个while循环去初始化DS18B20,若DS18B20成功被初始化,程序便可往下执行。在while循环中每隔100毫秒调用一次ds18b20_get_temperature函数获取一下温度数据,并在LCD上显示。LED灯每隔200毫秒状态翻转,实现闪烁效果。

31.4 下载验证
假定DS18B20传感器已经接上去正确的位置,将程序下载到开发板后,可以看到LED0不停的闪烁,提示程序已经在运行了。LCD显示当前的温度值的内容如下图所示:

第三十一章 DS18B20实验10624.png
图31.4.1 DS18B20实验程序运行效果图

该程序还可以读取并显示负温度值,具备零下温度条件可以测试一下。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


关闭

原子哥极力推荐上一条 /1 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2026-1-11 11:39

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表