# 温度传感器

[English]

## 简介

ESP32-H2 内置传感器，用于测量芯片内部的温度。该温度传感器模组包含一个 8 位 Sigma-Delta 模拟-数字转换器 (ADC) 和一个数字-模拟转换器 (DAC)，可以补偿测量结果，减少温度测量的误差。

备注

温度传感器主要用于测量芯片内部的温度变化。温度值可用作衡量温度变化趋势，但无法提供精确的温度数值，因此不建议用作精准测量温度。

## 功能概述

下文将分节概述温度传感器的功能：

- 资源分配 - 介绍了部分参数，设置这些参数可以获取温度传感器句柄；还介绍了在温度传感器完成工作后如何回收资源。

- 启用及禁用温度传感器 - 介绍如何启用及禁用温度传感器。

- 获取测量的温度值 - 介绍如何获取实时温度值。

- 安装温度阈值回调函数 - 介绍如何注册温度阈值回调函数。

- 电源管理 - 介绍更改功耗模式（如 Light-sleep 模式）对温度传感器造成的影响。

- IRAM 安全 - 介绍在禁用 cache 时如何提高温度传感器的性能。

- 线程安全 - 介绍如何使驱动程序具备线程安全性。

- ETM 事件和任务 - 介绍哪些事件和任务可以连接到 ETM 通道。

### 资源分配

ESP32-H2 只有一个内置温度传感器硬件。`temperature_sensor_handle_t` 表示温度传感器模块，该变量也是不同函数之间的纽带。通过使用相同的 `temperature_sensor_handle_t` 变量，可以在不同的函数调用中访问和修改温度传感器属性，以控制和管理温度传感器。该变量会作为温度 API 的参数，携带有关硬件和配置的信息，你只需创建类型为 `temperature_sensor_handle_t` 的指针，并将其传递给所需 API。

请在安装内置温度传感器模块前评估测量环境的温度范围。例如，如果在室内测量，环境温度可能在 10 °C ~ 30 °C；如果在灯泡中测量，环境温度则可能在 60 °C ~ 110 °C。在环境温度范围的基础上，请先根据以下值定义配置结构体 `temperature_sensor_config_t`，再安装内置温度传感器：

- `range_min`：所测量温度范围的最小值。

- `range_max`：所测量温度范围的最大值。

- `allow_pd` 配置驱动程序是否允许系统在睡眠模式下关闭外设电源。在进入睡眠之前，系统将备份温度传感器寄存器上下文，当系统退出睡眠模式时，这些上下文将被恢复。关闭外设可以节省更多功耗，但代价是消耗更多内存来保存寄存器上下文。你需要在功耗和内存消耗之间做权衡。此配置选项依赖于特定的硬件功能，如果在不支持的芯片上启用它，你将看到类似 `not able to power down in light sleep` 的错误消息。

设置好温度范围后，将配置结构体传递给 `temperature_sensor_install()`，该函数将创建温度传感器模块并返回句柄。

如前文所述，不同测量范围对应不同测量误差。然而你无需自行比对测量误差，乐鑫提供了一个内部机制，可以根据所给温度范围选择最小误差。

温度传感器使用完毕后，请调用 `temperature_sensor_uninstall()` 释放相应资源。

#### 创建温度传感器句柄

- 第 1 步：评估测量范围。本示例的温度范围为 20 °C ~ 50 °C。

- 第 2 步：配置测量范围，获取温度传感器句柄。

    temperature_sensor_handle_t temp_handle = NULL;
    temperature_sensor_config_t temp_sensor_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(20, 50);
    ESP_ERROR_CHECK(temperature_sensor_install(&temp_sensor_config, &temp_handle));

### 启用及禁用温度传感器

1. 调用 `temperature_sensor_enable()` 启用温度传感器。此时，内部温度传感器回路开始工作，驱动程序从初始化状态转为启用状态。

2. 调用 `temperature_sensor_disable()` 禁用温度传感器。

### 获取测量的温度值

通过 `temperature_sensor_enable()` 启用温度传感器后，可以调用 `temperature_sensor_get_celsius()` 获取当前测量的温度值。

    // 启用温度传感器
    ESP_ERROR_CHECK(temperature_sensor_enable(temp_handle));
    // 获取传输的传感器数据
    float tsens_out;
    ESP_ERROR_CHECK(temperature_sensor_get_celsius(temp_handle, &tsens_out));
    printf("Temperature in %f °C\n", tsens_out);
    // 温度传感器使用完毕后，禁用温度传感器，节约功耗
    ESP_ERROR_CHECK(temperature_sensor_disable(temp_handle));

### 安装温度阈值回调函数

ESP32-H2 支持自动触发温度传感器，持续监测内部温度，内部温度达到给定阈值时将触发中断。因此，可以安装中断回调函数执行所需操作，如报警、重启等。下文介绍了如何准备阈值回调函数。

- 函数 `temperature_sensor_event_callbacks_t::on_threshold` 在中断服务程序 (ISR) 的上下文中调用，请确保该函数不会涉及 block 操作。为此，可以检查调用 API 的后缀，确保仅从函数内调用具有 `ISR` 后缀的 FreeRTOS API 等。函数原型在 `temperature_thres_cb_t` 中声明。

通过参数 `user_arg` 可以将自定义上下文保存到 `temperature_sensor_register_callbacks()` 中，用户数据将直接传递给回调函数。

    IRAM_ATTR static bool temp_sensor_monitor_cbs(temperature_sensor_handle_t tsens, const temperature_sensor_threshold_event_data_t *edata, void *user_data)
    {
        ESP_DRAM_LOGI("tsens", "Temperature value is higher or lower than threshold, value is %d\n...\n\n", edata->celsius_value);
        return false;
    }

    // 配置回调函数
    temperature_sensor_abs_threshold_config_t threshold_cfg = {
        .high_threshold = 50,
        .low_threshold = -10,
    };
    // 设置监控阈值
    temperature_sensor_set_absolute_threshold(temp_sensor, &threshold_cfg);
    // 注册中断回调函数
    temperature_sensor_event_callbacks_t cbs = {
        .on_threshold = temp_sensor_monitor_cbs,
    };
    // 安装温度回调函数
    temperature_sensor_register_callbacks(temp_sensor, &cbs, NULL);

### 电源管理

由于温度传感器不使用 APB 时钟，无论是否激活 `CONFIG_PM_ENABLE` 启用电源管理，温度传感器仍可以继续工作。

### IRAM 安全

默认情况下，禁用 cache 时，写入/擦除 flash 等原因将导致温度传感器中断延迟，事件回调函数也将延迟执行。在实时应用程序中，应避免此类情况。

因此，可以启用 Kconfig 选项 CONFIG_TEMP_SENSOR_ISR_IRAM_SAFE，该选项：

1. 支持在禁用 cache 时启用所需中断

2. 支持将 ISR 使用的所有函数存放在 IRAM 中

启用该选项可以保证 cache 禁用时的中断运行，但会占用更多的 IRAM。

### 线程安全

温度传感器中并未添加任何确保线程安全的额外保护，因为温度传感器通常只在一个任务中调用。如果要在不同任务中使用该驱动程序，请设置额外的锁进行保护。

### ETM 事件和任务

温度传感器能够生成事件，这些事件可以与 :doc:ETM </api-reference/peripherals/etm> 模块进行交互。:cpp:type:temperature_sensor_etm_event_type_t 中列出了所有支持的事件。可以调用 :cpp:func:temperature_sensor_new_etm_event 来获取相应的 ETM 事件句柄。:cpp:type:temperature_sensor_etm_task_type_t 中列出了所有支持的任务。可以调用 :cpp:func:temperature_sensor_new_etm_task 来获取相应的 ETM 任务句柄。

备注

- 对于 `temperature_sensor_etm_event_type_t::event_type` 的 `TEMPERATURE_SENSOR_EVENT_OVER_LIMIT` 取决于首先设置的阈值类型。如果是通过 `temperature_sensor_set_absolute_threshold()` 设置了绝对阈值，那么 `TEMPERATURE_SENSOR_EVENT_OVER_LIMIT` 将指代绝对阈值。同样，如果是通过 `temperature_sensor_set_delta_threshold()` 设置了增量阈值，那么 `TEMPERATURE_SENSOR_EVENT_OVER_LIMIT` 将指代增量阈值。

有关如何将事件和任务连接到 ETM 通道的详细信息，请参阅 :doc:ETM </api-reference/peripherals/etm> 文档。

## 意外情况

1. 从芯片获取的温度值通常与环境温度不同，因为温度传感器内置于芯片，从某种程度来说，温度传感器测量的是芯片内的温度。

2. 安装温度传感器失败时，如果驱动程序打印的错误信息为 `the boundary you gave cannot meet the range of internal temperature sensor`，说明内置温度传感器温度测量范围的限制影响了安装过程，该错误通常由以下几种不正确的 `temperature_sensor_config_t` 配置造成：

   > 1. 超出温度测量范围，如 200 °C ~ 300 °C。

   > 2. 超过了预定义测量范围的界限，如 40 °C ~ 110 °C。

## 应用示例

> - peripherals/temperature_sensor/temp_sensor 演示了如何使用内置温度传感器，并展示了 DAC 电平和偏移量不同时的测量范围和误差。

- peripherals/temperature_sensor/temp_sensor_monitor 演示了如何使用温度传感器连续自动监测温度值，当温度达到特定值或或两个连续的采样之间的变化大于/小于设置时，触发中断。

## API 参考

### Header File

- components/esp_driver_tsens/include/driver/temperature_sensor.h

- This header file can be included with:

  >     #include "driver/temperature_sensor.h"

- This header file is a part of the API provided by the `esp_driver_tsens` component. To declare that your component depends on `esp_driver_tsens`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_tsens

  > or

  >     PRIV_REQUIRES esp_driver_tsens

### Functions

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

  Install temperature sensor driver.

  参数:

    - tsens_config -- Pointer to config structure.

    - ret_tsens -- Return the pointer of temperature sensor handle.

  返回:

    - ESP_OK if succeed

esp_err_t temperature_sensor_uninstall(temperature_sensor_handle_t tsens)

  Uninstall the temperature sensor driver.

  参数:

    tsens -- The handle created by `temperature_sensor_install()`.

  返回:

    - ESP_OK if succeed.

esp_err_t temperature_sensor_enable(temperature_sensor_handle_t tsens)

  Enable the temperature sensor.

  参数:

    tsens -- The handle created by `temperature_sensor_install()`.

  返回:

    - ESP_OK Success

    - ESP_ERR_INVALID_STATE if temperature sensor is enabled already.

esp_err_t temperature_sensor_disable(temperature_sensor_handle_t tsens)

  Disable temperature sensor.

  参数:

    tsens -- The handle created by `temperature_sensor_install()`.

  返回:

    - ESP_OK Success

    - ESP_ERR_INVALID_STATE if temperature sensor is not enabled yet.

esp_err_t temperature_sensor_get_celsius(temperature_sensor_handle_t tsens, float *out_celsius)

  Read temperature sensor data that is converted to degrees Celsius.

  备注

  Should not be called from interrupt.

  参数:

    - tsens -- The handle created by `temperature_sensor_install()`.

    - out_celsius -- The measure output value.

  返回:

    - ESP_OK Success

    - ESP_ERR_INVALID_ARG invalid arguments

    - ESP_ERR_INVALID_STATE Temperature sensor is not enabled yet.

    - ESP_FAIL Parse the sensor data into ambient temperature failed (e.g. out of the range).

esp_err_t temperature_sensor_set_absolute_threshold(temperature_sensor_handle_t tsens, const temperature_sensor_abs_threshold_config_t *abs_cfg)

  Set temperature sensor absolute mode automatic monitor.

  备注

  This function should not be called with `temperature_sensor_set_delta_threshold`.

  参数:

    - tsens -- The handle created by `temperature_sensor_install()`.

    - abs_cfg -- Configuration of temperature sensor absolute mode interrupt, see `temperature_sensor_abs_threshold_config_t`.

  返回:

    - ESP_OK: Set absolute threshold successfully.

    - ESP_ERR_INVALID_STATE: Set absolute threshold failed because of wrong state.

    - ESP_ERR_INVALID_ARG: Set absolute threshold failed because of invalid argument.

esp_err_t temperature_sensor_set_delta_threshold(temperature_sensor_handle_t tsens, const temperature_sensor_delta_threshold_config_t *delta_cfg)

  Set temperature sensor differential mode automatic monitor.

  备注

  This function should not be called with `temperature_sensor_set_absolute_threshold`

  参数:

    - tsens -- The handle created by `temperature_sensor_install()`.

    - delta_cfg -- Configuration of temperature sensor delta mode interrupt, see `temperature_sensor_delta_threshold_config_t`.

  返回:

    - ESP_OK: Set differential value threshold successfully.

    - ESP_ERR_INVALID_STATE: Set absolute threshold failed because of wrong state.

    - ESP_ERR_INVALID_ARG: Set differential value threshold failed because of invalid argument.

esp_err_t temperature_sensor_register_callbacks(temperature_sensor_handle_t tsens, const temperature_sensor_event_callbacks_t *cbs, void *user_arg)

  Install temperature sensor interrupt callback. Temperature sensor interrupt will be enabled at same time.

  参数:

    - tsens -- The handle created by `temperature_sensor_install()`.

    - cbs -- Pointer to the group of temperature sensor interrupt callbacks.

    - user_arg -- Callback argument.

  返回:

    - ESP_OK: Set event callbacks successfully

    - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument

    - ESP_FAIL: Set event callbacks failed because of other error

### Structures

struct temperature_sensor_config_t

  Configuration of measurement range for the temperature sensor.

  备注

  If you see the log `the boundary you gave cannot meet the range of internal temperature sensor`. You may need to refer to predefined range listed doc `api-reference/peripherals/Temperature sensor`.

  Public Members

  int range_min

    the minimum value of the temperature you want to test

  int range_max

    the maximum value of the temperature you want to test

  temperature_sensor_clk_src_t clk_src

    the clock source of the temperature sensor.

  uint32_t allow_pd

    If set, the driver will backup/restore the temperature sensor registers before/after entering/exist sleep mode. By this approach, the system can power off temperature sensor's power domain. This can save power, but at the expense of more RAM being consumed

  struct temperature_sensor_config_t flags

    Temperature sensor config flags

struct temperature_sensor_threshold_event_data_t

  Temperature sensor event data.

  Public Members

  int celsius_value

    Celsius value in interrupt callback.

  temperature_val_intr_condition_t intr_condition

    Can be used to judge temperature sensor interrupts in which reason

struct temperature_sensor_event_callbacks_t

  Group of temperature sensor callback functions, all of them will be run in ISR.

  Public Members

  temperature_thres_cb_t on_threshold

    Temperature value interrupt callback

struct temperature_sensor_abs_threshold_config_t

  Config options for temperature value absolute interrupt.

  Public Members

  float high_threshold

    High threshold value(Celsius). Interrupt will be triggered if temperature value is higher than this value

  float low_threshold

    Low threshold value(Celsius). Interrupt will be triggered if temperature value is lower than this value

struct temperature_sensor_delta_threshold_config_t

  Config options for temperature value delta interrupt.

  Public Members

  float increase_delta

    Interrupt will be triggered if the temperature increment of two consecutive samplings if larger than `increase_delta`

  float decrease_delta

    Interrupt will be triggered if the temperature decrement of two consecutive samplings if smaller than `decrease_delta`

### Macros

TEMPERATURE_SENSOR_CONFIG_DEFAULT(min, max)

  temperature_sensor_config_t default constructor

### Type Definitions

typedef struct temperature_sensor_obj_t *temperature_sensor_handle_t

  Type of temperature sensor driver handle.

typedef bool (*temperature_thres_cb_t)(temperature_sensor_handle_t tsens, const temperature_sensor_threshold_event_data_t *edata, void *user_data)

  Callback for temperature sensor threshold interrupt.

  Param tsens:

    [in] The handle created by `temperature_sensor_install()`.

  Param edata:

    [in] temperature sensor event data, fed by driver.

  Param user_data:

    [in] User data, set in `temperature_sensor_register_callbacks()`.

  Return:

    Whether a high priority task has been waken up by this function.

### Enumerations

enum temperature_val_intr_condition_t

  Enum for temperature sensor interrupt condition.

  Values:

  enumerator TEMPERATURE_VAL_HIGHER_THAN_HIGH_THRESHOLD

    temperature sensor value is higher than high threshold

  enumerator TEMPERATURE_VAL_LOWER_THAN_LOW_THRESHOLD

    temperature sensor value is lower than low threshold

### Header File

- components/esp_hal_ana_conv/include/hal/temperature_sensor_types.h

- This header file can be included with:

  >     #include "hal/temperature_sensor_types.h"

- This header file is a part of the API provided by the `esp_hal_ana_conv` component. To declare that your component depends on `esp_hal_ana_conv`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_hal_ana_conv

  > or

  >     PRIV_REQUIRES esp_hal_ana_conv

### Type Definitions

typedef soc_periph_temperature_sensor_clk_src_t temperature_sensor_clk_src_t

  temperature sensor clock source

### Enumerations

enum temperature_sensor_etm_event_type_t

  temperature sensor event types enum

  Values:

  enumerator TEMPERATURE_SENSOR_EVENT_OVER_LIMIT

    Temperature sensor over limit event

  enumerator TEMPERATURE_SENSOR_EVENT_MAX

    Maximum number of temperature sensor events

enum temperature_sensor_etm_task_type_t

  temperature sensor task types enum

  Values:

  enumerator TEMPERATURE_SENSOR_TASK_START

    Temperature sensor start task

  enumerator TEMPERATURE_SENSOR_TASK_STOP

    Temperature sensor stop task

  enumerator TEMPERATURE_SENSOR_TASK_MAX

    Maximum number of temperature sensor tasks

### Header File

- components/esp_driver_tsens/include/driver/temperature_sensor_etm.h

- This header file can be included with:

  >     #include "driver/temperature_sensor_etm.h"

- This header file is a part of the API provided by the `esp_driver_tsens` component. To declare that your component depends on `esp_driver_tsens`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_tsens

  > or

  >     PRIV_REQUIRES esp_driver_tsens

### Functions

esp_err_t temperature_sensor_new_etm_event(temperature_sensor_handle_t tsens, const temperature_sensor_etm_event_config_t *config, esp_etm_event_handle_t *out_event)

  Get the ETM event for Temperature Sensor.

  备注

  The created ETM event object can be deleted later by calling `esp_etm_del_event`

  参数:

    - tsens -- [in] Temperature Sensor handle, allocated by `temperature_sensor_install()`

    - config -- [in] Temperature Sensor ETM event configuration

    - out_event -- [out] Returned ETM event handle

  返回:

    - ESP_OK: Get ETM event successfully

    - ESP_ERR_INVALID_ARG: Get ETM event failed because of invalid argument

    - ESP_FAIL: Get ETM event failed because of other error

esp_err_t temperature_sensor_new_etm_task(temperature_sensor_handle_t tsens, const temperature_sensor_etm_task_config_t *config, esp_etm_task_handle_t *out_task)

  Get the ETM task for Temperature Sensor.

  备注

  The created ETM task object can be deleted later by calling `esp_etm_del_task`

  参数:

    - tsens -- [in] Temperature Sensor, allocated by `temperature_sensor_install()`

    - config -- [in] Temperature Sensor ETM task configuration

    - out_task -- [out] Returned ETM task handle

  返回:

    - ESP_OK: Get ETM task successfully

    - ESP_ERR_INVALID_ARG: Get ETM task failed because of invalid argument

    - ESP_FAIL: Get ETM task failed because of other error

### Structures

struct temperature_sensor_etm_event_config_t

  Temperature Sensor ETM event configuration.

  Public Members

  temperature_sensor_etm_event_type_t event_type

    Temperature Sensor ETM event type

struct temperature_sensor_etm_task_config_t

  Temperature Sensor ETM task configuration.

  Public Members

  temperature_sensor_etm_task_type_t task_type

    Temperature Sensor ETM task type

此文档对您有帮助吗？

- 反馈已收到，谢谢！
- 如果您有其他意见，欢迎填写乐鑫文档反馈表。

- 我们重视您的反馈。
- 您可以填写乐鑫文档反馈表告诉我们如何改进该文档。