模拟比较器

[English]

简介

模拟比较器是一种用于比较信号源与内部参考电压或外部参考信号的外设。

当用于比较模拟信号时,集成模拟比较器可以低成本替代运算放大器。不同于运算放大器的连续比较,ESP 模拟比较器由时钟源驱动,其采样频率取决于时钟的频率。

ESP32-P4 上的模拟比较器有 2 个单元,单元中的通道如下:

UNIT0

  • 源通道:GPIO52

  • 外部参考通道:GPIO51

  • 内部参考通道:电压范围是 VDD 的 0% ~ 70%,步长为 VDD 的 10%

UNIT1

  • 源通道:GPIO54

  • 外部参考通道:GPIO53

  • 内部参考通道:电压范围是 VDD 的 0% ~ 70%,步长为 VDD 的 10%

功能概述

本文中的以下章节涵盖了安装及操作模拟比较器单元的基本步骤:

  • 资源分配 - 涵盖了应设置哪些参数以获取单元句柄,以及完成工作后如何回收资源。

  • 进一步配置 - 涵盖了可能需要指定的其他配置及其用途。

  • 启用和禁用单元 - 涵盖了如何启用和禁用单元。

  • 电源管理 - 描述了不同时钟源对功耗的影响。

  • IRAM 安全 - 列出了在 cache 被禁用时也能起效的函数。

  • 线程安全 - 列出了驱动程序中线程安全的 API。

  • Kconfig 选项 - 列出了支持的 Kconfig 选项,这些选项可以对驱动程序产生不同影响。

  • ETM 事件 - 介绍了如何创建一个模拟比较器跨越事件。

资源分配

模拟比较器单元由 ana_cmpr_handle_t 表示,每个单元都可支持内部或外部的参考信号。

通过调用 ana_cmpr_new_unit() 来获取单元句柄以分配资源。在分配单元时需要指定 ana_cmpr_config_t 配置:

函数 ana_cmpr_new_unit() 可能因内存不足、参数无效等各种错误而失败。如果不再需要先前创建的模拟比较器单元,可通过调用 ana_cmpr_del_unit() 来回收资源,从而释放底层硬件通道的资源供其他用途。在删除模拟比较器单元句柄之前,首先应通过 ana_cmpr_disable() 禁用句柄,或者确保尚未通过 ana_cmpr_enable() 启用该单元。

#include "driver/ana_cmpr.h"

ana_cmpr_handle_t cmpr = NULL;
ana_cmpr_config_t config = {
    .unit = 0,
    .clk_src = ANA_CMPR_CLK_SRC_DEFAULT,
    .ref_src = ANA_CMPR_REF_SRC_INTERNAL,
    .cross_type = ANA_CMPR_CROSS_ANY,
};
ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr));
// ...
ESP_ERROR_CHECK(ana_cmpr_del_unit(cmpr));

进一步配置

需要由 ana_cmpr_internal_ref_config_t::ref_volt 来指定电压。该电压受 VDD 电源电压限制,只能支持固定百分比的 VDD。目前在 ESP32-P4 上,内部参考电压范围是 VDD 的 0% ~ 70%,步长为 VDD 的 10%。

#include "driver/ana_cmpr.h"

ana_cmpr_internal_ref_config_t ref_cfg = {
    .ref_volt = ANA_CMPR_REF_VOLT_50_PCT_VDD,
};
ESP_ERROR_CHECK(ana_cmpr_set_internal_reference(cmpr, &ref_cfg));

通过 ana_cmpr_debounce_config_t::wait_us 可设置中断等待时间。跨零中断触发后,中断将暂时禁用 ana_cmpr_debounce_config_t::wait_us 微秒,这样可以避免信号源跨越参考信号时频繁触发中断。因此,等待时间应与信号源和参考信号之间的相对频率成反比。如果中断等待时间设置得太短,则无法完全避免抖动,但如果设置得太长,则可能会错过下一个跨越中断。

#include "driver/ana_cmpr.h"

ana_cmpr_debounce_config_t dbc_cfg = {
    .wait_us = 1,
};
ESP_ERROR_CHECK(ana_cmpr_set_debounce(cmpr, &dbc_cfg));

初始跨越类型在 ana_cmpr_new_unit() 中设置。即便在中断服务程序 (ISR) 的上下文中,此函数也可以更新跨越类型。

#include "driver/ana_cmpr.h"

ESP_ERROR_CHECK(ana_cmpr_set_cross_type(cmpr, ANA_CMPR_CROSS_POS));

目前支持 ana_cmpr_event_callbacks_t::on_cross。当发生跨越事件(由 ana_cmpr_config_t::cross_type 指定)时,将调用该回调函数。

#include "driver/ana_cmpr.h"

static bool IRAM_ATTR example_ana_cmpr_on_cross_callback(ana_cmpr_handle_t cmpr,
                                                     const ana_cmpr_cross_event_data_t *edata,
                                                     void *user_ctx)
{
    // ...
    return false;
}
ana_cmpr_event_callbacks_t cbs = {
    .on_cross = example_ana_cmpr_on_cross_callback,
};
ESP_ERROR_CHECK(ana_cmpr_register_event_callbacks(cmpr, &cbs, NULL));

备注

当启用 CONFIG_ANA_CMPR_ISR_IRAM_SAFE 时,应添加属性 IRAM_ATTR,确保回调上下文和涉及的数据位于内部 RAM 中(详情请参阅 IRAM 安全)。

启用和禁用单元

启用模拟比较器单元与跨越事件中断后,若同时启用了电源管理(详见 电源管理),则将获得电源管理锁。在 启用 状态下,只能调用 ana_cmpr_set_internal_reference()ana_cmpr_set_debounce(),其他函数可在禁用单元后调用。

调用 ana_cmpr_disable() 则会执行与上述过程相反的操作。

电源管理

当启用电源管理时(即开启 CONFIG_PM_ENABLE),系统会在进入 Light-sleep 模式前调整 APB 频率,因此模拟比较器的分辨率也可能随之更改。

通过获取类型为 ESP_PM_NO_LIGHT_SLEEP 的电源管理锁,驱动程序可以防止系统更改 APB 频率。只要驱动程序创建的模拟比较器单元实例选择 ANA_CMPR_CLK_SRC_DEFAULTANA_CMPR_CLK_SRC_XTAL 作为其时钟源,驱动程序会确保通过 ana_cmpr_enable() 启用通道,并获取电源管理锁。同理,当为该通道调用 ana_cmpr_disable() 时,驱动程序会释放锁。

IRAM 安全

默认情况下,当 cache 因写入或擦除 flash 等原因而被禁用时,模拟比较器的中断服务将会延迟,造成警报中断无法及时执行。在实时应用程序中通常需要避免这一情况发生。

Kconfig 选项 CONFIG_ANA_CMPR_ISR_IRAM_SAFE 支持:

  1. 即使 cache 被禁用也能启用中断服务。

  2. 将 ISR 使用的所有函数放入 IRAM。 1

  3. 将驱动程序对象放入 DRAM(以防它被分配到 PSRAM上)。

启用上述 Kconfig 选项以保证在禁用 cache 时可以正常使用函数,但这会增加 IRAM 消耗。

另一个 Kconfig 选项 CONFIG_ANA_CMPR_CTRL_FUNC_IN_IRAM 也支持将常用的 IO 控制函数放入 IRAM 中,以保证在禁用 cache 时可以正常使用函数。IO 控制函数如下所示:

线程安全

驱动程序会确保工厂函数 ana_cmpr_new_unit() 的线程安全。使用时,可以直接从不同的 RTOS 任务中调用此类函数,无需额外锁保护。

驱动程序设置了临界区,以防函数同时在任务和 ISR 中被调用。因此,以下函数支持在 ISR 上下文运行:

其他以 ana_cmpr_handle_t 为第一个位置参数的函数均非线程安全,因此应避免从多个任务中调用这类函数。

Kconfig 选项

ETM 事件

创建一个模拟比较器跨越事件,需要额外包含头文件 driver/ana_cmpr_etm.h,并调用函数 ana_cmpr_new_etm_event() 来分配事件。有关如何将事件连接到任务,请参考 ETM

应用示例

API 参考

Header File

  • components/esp_driver_ana_cmpr/include/driver/ana_cmpr.h

  • This header file can be included with:

    #include "driver/ana_cmpr.h"
    
  • This header file is a part of the API provided by the esp_driver_ana_cmpr component. To declare that your component depends on esp_driver_ana_cmpr, add the following to your CMakeLists.txt:

    REQUIRES esp_driver_ana_cmpr
    

    or

    PRIV_REQUIRES esp_driver_ana_cmpr
    

Functions

esp_err_t ana_cmpr_new_unit(const ana_cmpr_config_t *config, ana_cmpr_handle_t *ret_cmpr)

Allocating a new analog comparator unit handle.

参数
  • config -- [in] The config of the analog comparator unit

  • ret_cmpr -- [out] The returned analog comparator unit handle

返回

  • ESP_OK Allocate analog comparator unit handle success

  • ESP_ERR_NO_MEM No memory for the analog comparator structure

  • ESP_ERR_INVALID_ARG NULL pointer of the parameters or wrong unit number

  • ESP_ERR_INVALID_STATE The unit has been allocated or the clock source has been occupied

esp_err_t ana_cmpr_del_unit(ana_cmpr_handle_t cmpr)

Delete the analog comparator unit handle.

参数

cmpr -- [in] The handle of analog comparator unit

返回

  • ESP_OK Delete analog comparator unit handle success

  • ESP_ERR_INVALID_ARG NULL pointer of the parameters or wrong unit number

  • ESP_ERR_INVALID_STATE The analog comparator is not disabled yet

esp_err_t ana_cmpr_set_internal_reference(ana_cmpr_handle_t cmpr, const ana_cmpr_internal_ref_config_t *ref_cfg)

Set internal reference configuration.

备注

This function only need to be called when ana_cmpr_config_t::ref_src is ANA_CMPR_REF_SRC_INTERNAL.

备注

This function is allowed to run within ISR context including intr callbacks

备注

This function will be placed into IRAM if CONFIG_ANA_CMPR_CTRL_FUNC_IN_IRAM is on, so that it's allowed to be executed when Cache is disabled

参数
  • cmpr -- [in] The handle of analog comparator unit

  • ref_cfg -- [in] Internal reference configuration

返回

  • ESP_OK Set denounce configuration success

  • ESP_ERR_INVALID_ARG NULL pointer of the parameters

  • ESP_ERR_INVALID_STATE The reference source is not ANA_CMPR_REF_SRC_INTERNAL

esp_err_t ana_cmpr_set_debounce(ana_cmpr_handle_t cmpr, const ana_cmpr_debounce_config_t *dbc_cfg)

Set debounce configuration to the analog comparator.

备注

This function is allowed to run within ISR context including intr callbacks

备注

This function will be placed into IRAM if CONFIG_ANA_CMPR_CTRL_FUNC_IN_IRAM is on, so that it's allowed to be executed when Cache is disabled

参数
  • cmpr -- [in] The handle of analog comparator unit

  • dbc_cfg -- [in] Debounce configuration

返回

  • ESP_OK Set denounce configuration success

  • ESP_ERR_INVALID_ARG NULL pointer of the parameters

esp_err_t ana_cmpr_set_cross_type(ana_cmpr_handle_t cmpr, ana_cmpr_cross_type_t cross_type)

Set the source signal cross type.

备注

The initial cross type is configured in ana_cmpr_new_unit, this function can update the cross type

备注

This function is allowed to run within ISR context including intr callbacks

备注

This function will be placed into IRAM if CONFIG_ANA_CMPR_CTRL_FUNC_IN_IRAM is on, so that it's allowed to be executed when Cache is disabled

参数
  • cmpr -- [in] The handle of analog comparator unit

  • cross_type -- [in] The source signal cross type that can trigger the interrupt

返回

  • ESP_OK Set denounce configuration success

  • ESP_ERR_INVALID_ARG NULL pointer of the parameters

esp_err_t ana_cmpr_register_event_callbacks(ana_cmpr_handle_t cmpr, const ana_cmpr_event_callbacks_t *cbs, void *user_data)

Register analog comparator interrupt event callbacks.

备注

This function can only be called before enabling the unit

参数
  • cmpr -- [in] The handle of analog comparator unit

  • cbs -- [in] Group of callback functions

  • user_data -- [in] The user data that will be passed to callback functions directly

返回

  • ESP_OK Register callbacks success

  • ESP_ERR_INVALID_ARG NULL pointer of the parameters

  • ESP_ERR_INVALID_STATE The analog comparator has been enabled

esp_err_t ana_cmpr_enable(ana_cmpr_handle_t cmpr)

Enable the analog comparator unit.

参数

cmpr -- [in] The handle of analog comparator unit

返回

  • ESP_OK Enable analog comparator unit success

  • ESP_ERR_INVALID_ARG NULL pointer of the parameters

  • ESP_ERR_INVALID_STATE The analog comparator has been enabled

esp_err_t ana_cmpr_disable(ana_cmpr_handle_t cmpr)

Disable the analog comparator unit.

参数

cmpr -- [in] The handle of analog comparator unit

返回

  • ESP_OK Disable analog comparator unit success

  • ESP_ERR_INVALID_ARG NULL pointer of the parameters

  • ESP_ERR_INVALID_STATE The analog comparator has disabled already

esp_err_t ana_cmpr_get_gpio(ana_cmpr_unit_t unit, ana_cmpr_channel_type_t chan_type, int *gpio_num)

Get the specific GPIO number of the analog comparator unit.

参数
  • unit -- [in] The handle of analog comparator unit

  • chan_type -- [in] The channel type of analog comparator, like source channel or reference channel

  • gpio_num -- [out] The output GPIO number of this channel

返回

  • ESP_OK Get GPIO success

  • ESP_ERR_INVALID_ARG NULL pointer of the parameters or wrong unit number or wrong channel type

Structures

struct ana_cmpr_config_t

Analog comparator unit configuration.

Public Members

ana_cmpr_unit_t unit

Analog comparator unit

ana_cmpr_clk_src_t clk_src

The clock source of the analog comparator, which decide the resolution of the comparator

ana_cmpr_ref_source_t ref_src

Reference signal source of the comparator, select using ANA_CMPR_REF_SRC_INTERNAL or ANA_CMPR_REF_SRC_EXTERNAL. For internal reference, the reference voltage should be set to internal_ref_volt, for external reference, the reference signal should be connect to ANA_CMPRx_EXT_REF_GPIO

ana_cmpr_cross_type_t cross_type

The crossing types that can trigger interrupt

int intr_priority

The interrupt priority, range 0~7, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) otherwise the larger the higher, 7 is NMI

uint32_t io_loop_back

Enable this field when the other signals that output on the comparison pins are supposed to be fed back. Normally used for debug/test scenario

struct ana_cmpr_config_t::[anonymous] flags

Analog comparator driver flags

struct ana_cmpr_internal_ref_config_t

Analog comparator internal reference configuration.

Public Members

ana_cmpr_ref_voltage_t ref_volt

The internal reference voltage. It can be specified to a certain fixed percentage of the VDD power supply, currently supports 0%~70% VDD with a step 10%

struct ana_cmpr_debounce_config_t

Analog comparator debounce filter configuration.

Public Members

uint32_t wait_us

The wait time of re-enabling the interrupt after the last triggering, it is used to avoid the spurious triggering while the source signal crossing the reference signal. The value should regarding how fast the source signal changes, e.g., a rapid signal requires a small wait time, otherwise the next crosses may be missed. (Unit: micro second)

struct ana_cmpr_event_callbacks_t

Group of Analog Comparator callbacks.

备注

The callbacks are all running under ISR environment

备注

When CONFIG_ANA_CMPR_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM. The variables used in the function should be in the SRAM as well.

Public Members

ana_cmpr_cross_cb_t on_cross

The callback function on cross interrupt

Header File

  • components/esp_driver_ana_cmpr/include/driver/ana_cmpr_types.h

  • This header file can be included with:

    #include "driver/ana_cmpr_types.h"
    
  • This header file is a part of the API provided by the esp_driver_ana_cmpr component. To declare that your component depends on esp_driver_ana_cmpr, add the following to your CMakeLists.txt:

    REQUIRES esp_driver_ana_cmpr
    

    or

    PRIV_REQUIRES esp_driver_ana_cmpr
    

Structures

struct ana_cmpr_cross_event_data_t

Analog comparator cross event data.

Public Members

ana_cmpr_cross_type_t cross_type

The cross type of the target signal to the reference signal. Will either be ANA_CMPR_CROSS_POS or ANA_CMPR_CROSS_NEG Always be ANA_CMPR_CROSS_ANY if target does not support independent interrupt (like ESP32H2)

Macros

ANA_CMPR_UNIT_0

Deprecated:

Analog comparator unit 0

Type Definitions

typedef int ana_cmpr_unit_t

Analog comparator unit.

typedef struct ana_cmpr_t *ana_cmpr_handle_t

Analog comparator unit handle.

typedef soc_periph_ana_cmpr_clk_src_t ana_cmpr_clk_src_t

Analog comparator clock source.

typedef bool (*ana_cmpr_cross_cb_t)(ana_cmpr_handle_t cmpr, const ana_cmpr_cross_event_data_t *edata, void *user_ctx)

Prototype of Analog comparator event callback.

Param cmpr

[in] Analog Comparator handle, created from ana_cmpr_new_unit()

Param edata

[in] Point to Analog Comparator event data. The lifecycle of this pointer memory is inside this function, user should copy it into static memory if used outside this function. (Currently not use)

Param user_ctx

[in] User registered context, passed from ana_cmpr_register_event_callbacks()

Return

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

Enumerations

enum ana_cmpr_ref_source_t

Analog comparator reference source.

Values:

enumerator ANA_CMPR_REF_SRC_INTERNAL

Analog Comparator internal reference source, related to VDD

enumerator ANA_CMPR_REF_SRC_EXTERNAL

Analog Comparator external reference source, from ANA_CMPR0_EXT_REF_GPIO

enum ana_cmpr_channel_type_t

Analog comparator channel type.

Values:

enumerator ANA_CMPR_SOURCE_CHAN

Analog Comparator source channel, which is used to input the signal that to be compared

enumerator ANA_CMPR_EXT_REF_CHAN

Analog Comparator external reference channel, which is used as the reference signal

1

ana_cmpr_event_callbacks_t::on_cross 回调函数,以及由其调用的其他函数也应放置在 IRAM 中,请妥善处理。


此文档对您有帮助吗?