本章学习 ESP32-S3 的内部温度传感器并使用它来读取温度值,然后在 LCD 模块上显示出来。本章分为如下几个小节:
28.1 IIC 简介
28.2 硬件设计
28.3 程序设计
28.4 下载验证

28.1 内部温度传感器简介

        ESP32-S3内部温度传感器是一个模拟电路,用于测量芯片的内部温度。该传感器的输出是一个模拟电压,这个电压与芯片的温度成正比。内部 ADC 会将这个模拟电压转换为数字值,然后通过特定的转换公式计算出实际的温度值 (单位: °C)。 ESP32-S3温度传感器相关内容,请看《esp32-s3_technical_reference_manual_cn.pdf》 技术手册 39.4 章节。以下是关于该传感器的核心信息概要:

​特性项目​

​说明​

​测量原理​

传感器产生与温度成正比的模拟电压,由内部ADC转换为数字值,再通过公式转换为摄氏度 (°C)。

​测量范围​

-40°C 至 125°C。

​精度与误差​

精度取决于设定的测量范围,范围越窄通常精度越高。例如,在-10°C ~ 80°C范围内,误差可小于±1°C。

​主要用途​

监测芯片内部温度变化,评估系统负荷和散热情况,​​而非精确测量环境温度​

​核心API​

包括temperature_sensor_install()temperature_sensor_enable()

temperature_sensor_get_celsius()temperature_sensor_disable()

​重要注意事项​

芯片温度通常高于环境温度,且受时钟频率和I/O负载影响显著。

表28.1.1 ESP32-S3内部温度传感器核心信息

        温度传感器的输出值需要使用转换公式转换成实际的温度值 (° C)。转换公式如下:

                    T(°C) = 0.4386 * VALUE –27.88 * offset –20.52

        其中 VALUE 即温度传感器的输出值, offset 由温度偏移决定。温度传感器在不同的实际使用环境(测量温度范围)下,温度偏移不同,见下表所示。

测量范围(° C) 温度偏移(° C)
50 ~ 110 -2
20 ~ 100 -1
-10 ~ 80 0
-15 ~ 50 1
-20 ~ 20 2

表 28.1.2 温度传感器的温度偏移

重要注意事项:
​​        芯片温度 vs 环境温度​​:该传感器测量的是​​芯片内部的温度​​,由于电路运行产生的热量,其读数通常会高于周围的环境温度。芯片温度会随着微控制器时钟频率或IO负载的变化而变化;
​​        适用场景​​:适用于监测芯片内部温度的变化,评估系统负荷和散热情况。若需测量环境温度,建议使用外部专用温度传感器(如DS18B20、DHT11、LM75等)。

    28.2 硬件设计

    28.2.1 例程功能

            本章实验功能简介:通过 ADC 的通道读取 ESP32-S3 内部温度传感器的电压值,并将其转
    换为温度值,显示在 SPILCD 屏上。
    28.2.2 硬件资源
            1. XL9555
                    IIC_SDA-IO41
                    IIC_SCL-IO42
            2. SPILCD
                    CS-IO21
                    SCK-IO12
                    SDA-IO11
                    DC-IO40(在 P5 端口,使用跳线帽将 IO_SET 和 LCD_DC 相连)
                    PWR- IO1_3(XL9555)
                    RST- IO1_2(XL9555)
            3. 内部温度传感器

    28.2.3 原理图

            本章实验使用的 ADC 为 ESP32-S3 的片上资源,因此并没有相应的连接原理图。

    28.3 程序设计

    28.3.1 程序流程图

            本实验的程序流程图:

    图 28.3.1.1 温度传感器实验程序流程图

    28.3.2 内部温度传感器函数解析

            使用 ESP32-S3 的内部温度传感器通常包含以下步骤,这些步骤通过 ESP-IDF 提供的 API 实现:

            1)安装与配置传感器​​:使用 temperature_sensor_install()函数,并提供一个 temperature_sensor_config_t结构体来设置期望的测量范围(range_min和 range_max)。这会返回一个传感器句柄;
            2)使能传感器​​:通过 temperature_sensor_enable()函数启动温度测量;
            3)读取温度值​​:调用 temperature_sensor_get_celsius()函数即可获取当前的温度值(单位为摄氏度);
            4)失能传感器​​(可选):当不需要测量时,可通过 temperature_sensor_disable()函数停止传感器工作,有助于降低功耗。

            下来看ESP-IDF 提供的相关 API 并配置温度传感器。要使用此功能,需要导入必要的头文件:

    #include "driver/temperature_sensor.h"

    (1)设置测试温度的最大与最小值
            该函数用于配置测试温度的大小范围,其函数原型如下:

    esp_err_t temperature_sensor_install(const temperature_sensor_config_t
                                         *tsens_config,
                                         temperature_sensor_handle_t
                                         *ret_tsens);

            该函数的形参描述,如下表所示:

    形参 描述
    tsens_config 指向温度配置结构的指针
    ret_tsens 返回温度传感器句柄的指针

    表 28.3.2.1 函数 temperature_sensor_install()形参描述

    该函数的返回值描述,如下表所示:

    返回值 描述
    ESP_OK 返回: 0,表示配置成功

    表 28.3.2.2 函数 temperature_sensor_install()返回值描述

    该函数使用 temperature_sensor_config_t 类型的结构体变量传入,该结构体的定义如下:

    结构体 成员变量 可选参数
    temperature_sensor_config_t range_min:
    要测试的温度的最小值
    例程设置了 20
    range_max:
    要测试的温度的最大值
    例程设置了 50

    表 28.3.2.3 temperature_sensor_config_t 结构体参数值描述

            完成上述结构体参数配置之后,可以将结构传递给 temperature_sensor_install () 函数,用以
    实例化温度传感器。

    (2)使能温度传感器
            该函数用于使能温度传感器,其函数原型如下:

    esp_err_t temperature_sensor_enable(temperature_sensor_handle_t tsens);

    该函数的形参描述,如下表所示:

    形参 描述
    tsens 由 temperature_sensor_install()创建的句柄

    表 28.3.2.3 函数 temperature_sensor_enable ()形参描述
    该函数的返回值描述,如下表所示:

    返回值 描述
    ESP_OK 返回: 0,表示配置成功
    ESP_ERR_INVALID_STATE 如果温度传感器已经使能

    表 28.3.2.4 函数 temperature_sensor_enable ()返回值描述

    (3)获取传输的传感器数据
            该函数用于获取传输的传感器数据,其函数原型如下:

    esp_err_t temperature_sensor_get_celsius(temperature_sensor_handle_t tsens,
                                             float *out_celsius);

    该函数的形参描述,如下表所示:

    形参 描述
    tsens 由 temperature_sensor_install()创建的句柄
    out_celsius 度量值输出值

    表 28.3.2.5 函数 temperature_sensor_get_celsius ()形参描述

    该函数的返回值描述,如下表所示:

    返回值 描述
    ESP_OK 返回: 0,配置成功
    ESP_ERR_NOT_STATE 温度传感器未使能

    表 28.3.2.6 函数 temperature_sensor_get_celsius ()返回值描述

    (4)失能温度传感器
            该函数用于获取传输的传感器数据,其函数原型如下:

    esp_err_t temperature_sensor_disable(temperature_sensor_handle_t tsens);

            该函数的形参描述,如下表所示:

    形参 描述
    tsens 由 temperature_sensor_install()创建的句柄

    表 28.3.2.7 函数 temperature_sensor_disable ()形参描述

    该函数的返回值描述,如下表所示:

    返回值 描述
    ESP_OK 返回: 0,配置成功
    ESP_ERR_NOT_STATE 温度传感器未使能

    表 28.3.2.8 函数 temperature_sensor_disable ()返回值描述

    28.3.3 内部温度传感器驱动解析

            在 IDF 版 18_internal_Temperature 例程中,在18_internal_Temperature\components\BSP路径下新增了一个 SENSOR 文件夹,分别用于存放 sensor.c、 sensor.h 这两个文件。其中,sensor.h 文件负责声明温度传感器相关的函数和变量,而 sensor.c 文件则实现了温度传感器的驱动代码。下面,我们将详细解析这两个文件的实现内容。

    (1)sensor.h 文件

    /* 参数定义 */
    #define SENSOR_RANGE_MIN    20      /* 要测试温度的最小值 */
    #define SENSOR_RANGE_MAX    50      /* 要测试温度的最大值 */
    
    /* 函数声明 */
    void temperature_sensor_init(void); /* 初始化内部温度传感器 */
    float sensor_get_temperature(void); /* 获取内部温度传感器温度值 */

    (2)sensor.c 文件

    esp_err_t rev_flag;
    temperature_sensor_handle_t temp_handle = NULL; /* 温度传感器句柄 */
    
    /**
     * @brief       初始化内部温度传感器
     * @param       无
     * @retval      无
     */
    void temperature_sensor_init(void)
    {
        temperature_sensor_config_t temp_sensor;
        
        temp_sensor.range_min = SENSOR_RANGE_MIN;   /* 要测试温度的最小值 */
        temp_sensor.range_max = SENSOR_RANGE_MAX;   /* 要测试温度的最大值 */
    
        rev_flag |= temperature_sensor_install(&temp_sensor, &temp_handle);
        ESP_ERROR_CHECK(rev_flag);
    }
    
    /**
     * @brief       获取内部温度传感器温度值
     * @param       无
     * @retval      返回内部温度值
     */
    float sensor_get_temperature(void)
    {
        float temp = 0;
    
        /* 启用温度传感器 */
        rev_flag |= temperature_sensor_enable(temp_handle);
    
        /* 获取传输的传感器数据 */ 
        rev_flag |= temperature_sensor_get_celsius(temp_handle, &temp);
    
        /* 温度传感器使用完毕后,禁用温度传感器,节约功耗 */
        rev_flag |= temperature_sensor_disable(temp_handle);
        ESP_ERROR_CHECK(rev_flag);
    
        return temp;
    }
    

    28.3.4 CMakeLists.txt 文件

            打开本实验 BSP 下的 CMakeLists.txt 文件,其内容如下所示:

    set(src_dirs
                IIC
                LCD
                LED
                SENSOR
                SPI
                XL9555)
    
    set(include_dirs
                IIC
                LCD
                LED
                SENSOR
                SPI
                XL9555)
    
    set(requires
                driver)
    
    idf_component_register(SRC_DIRS ${src_dirs} INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})
    
    component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)

    28.3.5 实验应用代码

            打开 main/main.c 文件,该文件定义了工程入口函数,名为 app_main。该函数代码如下。

    i2c_obj_t i2c0_master;
    
    /**
     * @brief       程序入口
     * @param       无
     * @retval      无
     */
    void app_main(void)
    {
        float temp = 0;
    	uint8_t intVal = 0;
    	uint8_t decVal = 0;
        esp_err_t ret;
    
        ret = nvs_flash_init();                                                     /* 初始化NVS */
    
        if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
        {
            ESP_ERROR_CHECK(nvs_flash_erase());
            ret = nvs_flash_init();
        }
    
        led_init();                                                                 /* 初始化LED */
        i2c0_master = iic_init(I2C_NUM_0);                                          /* 初始化IIC0 */
        spi2_init();                                                                /* 初始化SPI2 */
        xl9555_init(i2c0_master);                                                   /* 初始化XL9555 */
        lcd_init();                                                                 /* 初始化LCD */
        temperature_sensor_init();                                                  /* 初始化内部温度传感器 */
        
        lcd_show_string(30, 50, 200, 16, 16, "ESP32", RED);
        lcd_show_string(30, 70, 200, 16, 16, "Temperature TEST", RED);
        lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
        lcd_show_string(30, 120, 200, 16, 16, "TEMPERATE: 00.00C", BLUE);
    
        while(1)
        {
            temp = sensor_get_temperature();                                        /* 得到温度值 */
    
            if (temp < 0)
            {
                temp = -temp;
                lcd_show_string(30 + 10 * 8, 120, 16, 16, 16, "-", BLUE);           /* 显示符号 */
            }
            else
            {
                lcd_show_string(30 + 10 * 8, 120, 16, 16, 16, " ", BLUE);           /* 无符号 */
            }
    
    		intVal = (uint8_t)temp;
    		decVal = (uint8_t)(temp * 100) % 100;
            lcd_show_xnum(30 + 11 * 8, 120, intVal, 2, 16, 0, BLUE);                  /* 显示整数部分 */
            lcd_show_xnum(30 + 14 * 8, 120, decVal, 2, 16, 0x80, BLUE);   /* 显示小数部分 */
            
            LED_TOGGLE();                                                           /* LED闪烁,提示程序运行 */
            vTaskDelay(250);
        }
    }
    28.4 下载验证

            将程序下载到开发板后, LCD 显示的内容如下图所示:

    图28.4.1 程序烧录后运行温度

    图28.4.1 程序长时间运行后温度

            可以明显看到芯片温度会随着微控制器运行市场变化而变化,最终会稳定到某一个温度值。

    Logo

    码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

    更多推荐