Analog Comparator
Introduction
Analog Comparator is a peripheral that can be used to compare a source signal with the internal reference voltage or an external reference signal.
It is a cost effective way to replace an amplifier comparator in some scenarios. But unlike the continuous comparing of the amplifier comparator, ESP Analog Comparator is driven by a source clock, which decides the sampling frequency.
Analog Comparator on ESP32-H2 has 1 unit(s), the channels in the unit(s) are:
UNIT0
Source Channel: GPIO11
External Reference Channel: GPIO10
Internal Reference Channel: Range 0% ~ 70% of the VDD, the step is 10% of the VDD
Functional Overview
The following sections of this document cover the typical steps to install and operate an Analog Comparator unit:
Resource Allocation - covers which parameters should be set up to get a unit handle and how to recycle the resources when it finishes working.
Further Configurations - covers the other configurations that might need to specific and what they are used for.
Enable and Disable Unit - covers how to enable and disable the unit.
Power Management - describes how different source clock selections can affect power consumption.
IRAM Safe - lists which functions are supposed to work even when the cache is disabled.
Thread Safety - lists which APIs are guaranteed to be thread safe by the driver.
Kconfig Options - lists the supported Kconfig options that can be used to make a different effect on driver behavior.
Resource Allocation
An Analog Comparator unit channel is represented by ana_cmpr_handle_t
. Each unit can support either an internal or an external reference.
To allocate the resource of the Analog Comparator unit, ana_cmpr_new_unit()
need to be called to get the handle of the unit. Configurations ana_cmpr_config_t
need to be specified while allocating the unit:
ana_cmpr_config_t::unit
selects the Analog Comparator unit.ana_cmpr_config_t::clk_src
selects the source clock for Analog Comparator, it can affect the sampling frequency. Note that the clock source of the Analog Comparator comes from the io mux, it is shared with GPIO extension peripherals like SDM (Sigma-Delta Modulation) and Glitch Filter. The configuration will fail if you specific different clock sources for multiple GPIO extension peripherals. The default clock sources of these peripherals are same, typically, we selectsoc_periph_ana_cmpr_clk_src_t::ANA_CMPR_CLK_SRC_DEFAULT
as the clock source.ana_cmpr_config_t::ref_src
selects the reference source from internal voltage or external signal.ana_cmpr_config_t::cross_type
selects which kind of cross type can trigger the interrupt.
The function ana_cmpr_new_unit()
can fail due to various errors such as insufficient memory, invalid arguments, etc. If a previously created Analog Comparator unit is no longer required, you should recycle it by calling ana_cmpr_del_unit()
. It allows the underlying HW channel to be used for other purposes. Before deleting an Analog Comparator unit handle, you should disable it by ana_cmpr_unit_disable()
in advance, or make sure it has not enabled yet by ana_cmpr_unit_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));
Further Configurations
ana_cmpr_set_intl_reference()
- Specify the internal reference voltage whenana_cmpr_ref_source_t::ANA_CMPR_REF_SRC_INTERNAL
is selected as reference source.
It requires ana_cmpr_internal_ref_config_t::ref_volt
to specify the voltage. The voltage related to the VDD power supply, which can only support a certain fixed percentage of VDD. Currently on ESP32-H2, the internal reference voltage can be range to 0 ~ 70% VDD with a step 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_set_debounce()
- Set the debounce configuration.
It requires ana_cmpr_debounce_config_t::wait_us
to set the interrupt waiting time. The interrupt is disabled temporarily for ana_cmpr_debounce_config_t::wait_us
micro seconds, so that the frequent triggering can be avoid while the source signal crossing the reference signal. That is, the waiting time is supposed to be inverse ratio to the relative frequency between the source and reference. If the waiting time is set too short, it can not bypass the jitter totally, but if too long, the next crossing interrupt might be missed.
#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_set_cross_type()
- Set the source signal cross type.
The initial cross type is set int ana_cmpr_new_unit()
, this function can update the cross type, even in ISR context.
#include "driver/ana_cmpr.h"
ESP_ERROR_CHECK(ana_cmpr_set_cross_type(cmpr, ANA_CMPR_CROSS_POS));
ana_cmpr_register_event_callbacks()
- Register the callbacks.
Currently it supports ana_cmpr_event_callbacks_t::on_cross
, it will be called when the crossing event (specified by ana_cmpr_config_t::cross_type
) occurs.
#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));
Note
When CONFIG_ANA_CMPR_ISR_IRAM_SAFE is enabled, you should guarantee the callback context and involved data to be in internal RAM by add the attribute IRAM_ATTR
. (See more in IRAM Safe)
Enable and Disable Unit
ana_cmpr_enable()
- Enable the Analog Comparator unit.ana_cmpr_disable()
- Disable the Analog Comparator unit.
After the Analog Comparator unit is enabled and the crossing event interrupt is enabled, a power management lock will be acquired if the power management is enabled (see Power Management). Under the enable state, only ana_cmpr_set_intl_reference()
and ana_cmpr_set_debounce()
can be called, other functions can only be called after the unit is disabled.
Calling ana_cmpr_disable()
does the opposite.
Power Management
When power management is enabled (i.e., CONFIG_PM_ENABLE is on), the system will adjust the APB frequency before going into light sleep, thus potentially changing the resolution of the Analog Comparator.
However, the driver can prevent the system from changing APB frequency by acquiring a power management lock of type ESP_PM_NO_LIGHT_SLEEP
. Whenever the driver creates a Analog Comparator unit instance that has selected the clock source like ANA_CMPR_CLK_SRC_DEFAULT
or ANA_CMPR_CLK_SRC_XTAL
as its clock source, the driver guarantees that the power management lock is acquired when enable the channel by ana_cmpr_enable()
. Likewise, the driver releases the lock when ana_cmpr_disable()
is called for that channel.
IRAM Safe
By default, the Analog Comparator interrupt will be deferred when the Cache is disabled for reasons like programming/erasing Flash. Thus the alarm interrupt will not get executed in time, which is not expected in a real-time application.
There is a Kconfig option CONFIG_ANA_CMPR_ISR_IRAM_SAFE that:
Enables the interrupt being serviced even when cache is disabled
Places all functions that used by the ISR into IRAM 1
Places driver object into DRAM (in case it is allocated on PSRAM)
This allows the interrupt to run while the cache is disabled but comes at the cost of increased IRAM consumption.
There is a Kconfig option CONFIG_ANA_CMPR_CTRL_FUNC_IN_IRAM that can put commonly used IO control functions into IRAM as well. So that these functions can also be executable when the cache is disabled. These IO control functions are listed as follows:
Thread Safety
The factory function ana_cmpr_new_unit()
is guaranteed to be thread safe by the driver, which means, user can call it from different RTOS tasks without protection by extra locks.
The following functions are allowed to run under ISR context, the driver uses a critical section to prevent them being called concurrently in both task and ISR.
Other functions that take the ana_cmpr_handle_t
as the first positional parameter, are not treated as thread safe. Which means the user should avoid calling them from multiple tasks.
Kconfig Options
CONFIG_ANA_CMPR_ISR_IRAM_SAFE controls whether the default ISR handler can work when cache is disabled, see IRAM Safe for more information.
CONFIG_ANA_CMPR_CTRL_FUNC_IN_IRAM controls where to place the Analog Comparator control functions (IRAM or Flash), see IRAM Safe for more information.
CONFIG_ANA_CMPR_ENABLE_DEBUG_LOG is used to enabled the debug log output. Enabling this option increases the firmware binary size.
Application Example
peripherals/analog_comparator shows the basic usage of the analog comparator, and other potential usages like hysteresis comparator and SPWM generator.
API Reference
Header File
components/driver/analog_comparator/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
driver
component. To declare that your component depends ondriver
, add the following to your CMakeLists.txt:REQUIRES driver
or
PRIV_REQUIRES driver
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.
- Parameters
config -- [in] The config of the analog comparator unit
ret_cmpr -- [out] The returned analog comparator unit handle
- Returns
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.
- Parameters
cmpr -- [in] The handle of analog comparator unit
- Returns
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.
Note
This function only need to be called when
ana_cmpr_config_t::ref_src
is ANA_CMPR_REF_SRC_INTERNAL.Note
This function is allowed to run within ISR context including intr callbacks
Note
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- Parameters
cmpr -- [in] The handle of analog comparator unit
ref_cfg -- [in] Internal reference configuration
- Returns
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.
Note
This function is allowed to run within ISR context including intr callbacks
Note
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- Parameters
cmpr -- [in] The handle of analog comparator unit
dbc_cfg -- [in] Debounce configuration
- Returns
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.
Note
The initial cross type is configured in
ana_cmpr_new_unit
, this function can update the cross typeNote
This function is allowed to run within ISR context including intr callbacks
Note
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- Parameters
cmpr -- [in] The handle of analog comparator unit
cross_type -- [in] The source signal cross type that can trigger the interrupt
- Returns
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.
Note
This function can only be called before enabling the unit
- Parameters
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
- Returns
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.
- Parameters
cmpr -- [in] The handle of analog comparator unit
- Returns
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.
- Parameters
cmpr -- [in] The handle of analog comparator unit
- Returns
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.
- Parameters
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
- Returns
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 toANA_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 comparision pins are supposed to be fed back. Normally used for debug/test scenario
-
struct ana_cmpr_config_t::[anonymous] flags
Analog comparator driver flags
-
ana_cmpr_unit_t unit
-
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%
-
ana_cmpr_ref_voltage_t ref_volt
-
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)
-
uint32_t wait_us
-
struct ana_cmpr_event_callbacks_t
Group of Analog Comparator callbacks.
Note
The callbacks are all running under ISR environment
Note
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
-
ana_cmpr_cross_cb_t on_cross
Header File
components/driver/analog_comparator/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
driver
component. To declare that your component depends ondriver
, add the following to your CMakeLists.txt:REQUIRES driver
or
PRIV_REQUIRES driver
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)
-
ana_cmpr_cross_type_t cross_type
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
-
enumerator ANA_CMPR_REF_SRC_INTERNAL
-
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
-
enumerator ANA_CMPR_SOURCE_CHAN
-
enum ana_cmpr_cross_type_t
Analog comparator interrupt type.
Values:
-
enumerator ANA_CMPR_CROSS_DISABLE
Disable the cross event interrupt
-
enumerator ANA_CMPR_CROSS_POS
Positive cross can trigger event interrupt
-
enumerator ANA_CMPR_CROSS_NEG
Negative cross can trigger event interrupt
-
enumerator ANA_CMPR_CROSS_ANY
Any cross can trigger event interrupt
-
enumerator ANA_CMPR_CROSS_DISABLE
-
enum ana_cmpr_ref_voltage_t
Analog comparator internal reference voltage.
Values:
-
enumerator ANA_CMPR_REF_VOLT_0_PCT_VDD
Internal reference voltage equals to 0% VDD
-
enumerator ANA_CMPR_REF_VOLT_10_PCT_VDD
Internal reference voltage equals to 10% VDD
-
enumerator ANA_CMPR_REF_VOLT_20_PCT_VDD
Internal reference voltage equals to 20% VDD
-
enumerator ANA_CMPR_REF_VOLT_30_PCT_VDD
Internal reference voltage equals to 30% VDD
-
enumerator ANA_CMPR_REF_VOLT_40_PCT_VDD
Internal reference voltage equals to 40% VDD
-
enumerator ANA_CMPR_REF_VOLT_50_PCT_VDD
Internal reference voltage equals to 50% VDD
-
enumerator ANA_CMPR_REF_VOLT_60_PCT_VDD
Internal reference voltage equals to 60% VDD
-
enumerator ANA_CMPR_REF_VOLT_70_PCT_VDD
Internal reference voltage equals to 70% VDD
-
enumerator ANA_CMPR_REF_VOLT_0_PCT_VDD
- 1
ana_cmpr_event_callbacks_t::on_cross
callback and the functions invoked by itself should also be placed in IRAM, you need to take care of them by themselves.