feat(ana_cmpr): support multi-channel scan on esp32s31

This commit is contained in:
morris
2026-05-06 09:39:48 +08:00
parent 05b5dc8938
commit 47863cb651
64 changed files with 1622 additions and 524 deletions
+2 -2
View File
@@ -28,9 +28,9 @@ examples/peripherals/adc/oneshot_read:
reason: no runners for esp32h4 ADC test
<<: *adc_dependencies
examples/peripherals/analog_comparator:
examples/peripherals/analog_comparator/auto_scan:
disable:
- if: SOC_ANA_CMPR_SUPPORTED != 1
- if: SOC_ANA_CMPR_SUPPORT_AUTO_SCAN != 1
depends_components:
- esp_driver_gpio
- esp_driver_ana_cmpr
@@ -8,4 +8,4 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
idf_build_set_property(MINIMAL_BUILD ON)
project(analog_comparator_example)
project(ana_cmpr_auto_scan)
@@ -1,17 +1,17 @@
| Supported Targets | ESP32-C5 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 |
| ----------------- | -------- | --------- | -------- | --------- | -------- |
# Analog Comparator Example
# Analog Comparator Auto Scan Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example is going to show how to use the Analog Comparator. The example toggles a GPIO to monitor the positive and negative crosses on the analog comparator unit.
This example shows how to use the Analog Comparator auto scan mode. After enabling the comparator unit, hardware keeps scanning source channels automatically and updates comparator outputs continuously. The example toggles a GPIO to monitor positive and negative crossing results in real time.
## Realization
- If the target supports generating the analog comparator events (like ESP32-P4), the example can toggle the monitoring GPIO via Event Task Matrix (ETM). ETM can bind the analog comparator cross events (positive and negative events) with the GPIO tasks (to set or clear a GPIO), so that every event happens, hardware will execute the corresponding task without CPU involved.
- If the target supports generating analog comparator events (like ESP32-P4), the example toggles the monitoring GPIO via Event Task Matrix (ETM). ETM binds comparator cross events (positive and negative) to GPIO tasks (set/clear), so each auto-scan crossing result can drive hardware actions without CPU involvement.
- If the target does not support to generate the analog comparator events (like ESP32-H2). The example will register an event callback on the analog comparator, and toggle the GPIO in the callback. It requires the CPU to process every event ISR, thus it is not effective as ETM and can't achieve a high resolution.
- If the target does not support generating analog comparator events (like ESP32-H2), the example registers an interrupt callback and toggles the GPIO in the callback. This still relies on auto scan for continuous output updates, but every crossing ISR must be handled by CPU, so it is less efficient than ETM.
## How to Use Example

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

@@ -52,8 +52,7 @@ static void example_etm_bind_ana_cmpr_event_with_gpio_task(ana_cmpr_handle_t cmp
static void example_init_analog_comparator_etm(void)
{
ana_cmpr_handle_t cmpr = NULL;
int src_gpio = -1;
ESP_ERROR_CHECK(ana_cmpr_get_gpio(EXAMPLE_ANA_CMPR_UNIT, ANA_CMPR_SOURCE_CHAN, &src_gpio));
gpio_num_t src_gpio = -1;
#if CONFIG_EXAMPLE_REF_FROM_INTERNAL
/* Step 1: Allocate the new analog comparator unit */
@@ -64,6 +63,7 @@ static void example_init_analog_comparator_etm(void)
.cross_type = ANA_CMPR_CROSS_ANY,
};
ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr));
ESP_ERROR_CHECK(ana_cmpr_get_channel_gpio(cmpr, ANA_CMPR_SOURCE_CHAN, 0, &src_gpio));
/* Step 1.1: As we are using the internal reference source, we need to configure the internal reference */
ana_cmpr_internal_ref_config_t ref_cfg = {
@@ -81,8 +81,9 @@ static void example_init_analog_comparator_etm(void)
.cross_type = ANA_CMPR_CROSS_ANY,
};
ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr));
int ext_ref_gpio = -1;
ESP_ERROR_CHECK(ana_cmpr_get_gpio(EXAMPLE_ANA_CMPR_UNIT, ANA_CMPR_EXT_REF_CHAN, &ext_ref_gpio));
ESP_ERROR_CHECK(ana_cmpr_get_channel_gpio(cmpr, ANA_CMPR_SOURCE_CHAN, 0, &src_gpio));
gpio_num_t ext_ref_gpio = -1;
ESP_ERROR_CHECK(ana_cmpr_get_channel_gpio(cmpr, ANA_CMPR_EXT_REF_CHAN, 0, &ext_ref_gpio));
ESP_LOGI(TAG, "Allocate Analog Comparator with external reference from GPIO %d, source from GPIO %d", ext_ref_gpio, src_gpio);
#endif // CONFIG_EXAMPLE_REF_FROM_INTERNAL
@@ -35,8 +35,7 @@ static bool example_ana_cmpr_on_cross_callback(ana_cmpr_handle_t cmpr,
static void example_init_analog_comparator_intr(void)
{
ana_cmpr_handle_t cmpr = NULL;
int src_gpio = -1;
ESP_ERROR_CHECK(ana_cmpr_get_gpio(EXAMPLE_ANA_CMPR_UNIT, ANA_CMPR_SOURCE_CHAN, &src_gpio));
gpio_num_t src_gpio = -1;
#if CONFIG_EXAMPLE_REF_FROM_INTERNAL
/* Step 1: Allocate the new analog comparator unit */
@@ -47,6 +46,7 @@ static void example_init_analog_comparator_intr(void)
.cross_type = ANA_CMPR_CROSS_ANY,
};
ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr));
ESP_ERROR_CHECK(ana_cmpr_get_channel_gpio(cmpr, ANA_CMPR_SOURCE_CHAN, 0, &src_gpio));
/* Step 1.1: As we are using the internal reference source, we need to configure the internal reference */
ana_cmpr_internal_ref_config_t ref_cfg = {
@@ -69,8 +69,9 @@ static void example_init_analog_comparator_intr(void)
.cross_type = ANA_CMPR_CROSS_ANY,
};
ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr));
int ext_ref_gpio = -1;
ESP_ERROR_CHECK(ana_cmpr_get_gpio(EXAMPLE_ANA_CMPR_UNIT, ANA_CMPR_EXT_REF_CHAN, &ext_ref_gpio));
ESP_ERROR_CHECK(ana_cmpr_get_channel_gpio(cmpr, ANA_CMPR_SOURCE_CHAN, 0, &src_gpio));
gpio_num_t ext_ref_gpio = -1;
ESP_ERROR_CHECK(ana_cmpr_get_channel_gpio(cmpr, ANA_CMPR_EXT_REF_CHAN, 0, &ext_ref_gpio));
ESP_LOGI(TAG, "Allocate Analog Comparator with external reference from GPIO %d, source from GPIO %d", ext_ref_gpio, src_gpio);
#endif // CONFIG_EXAMPLE_REF_FROM_INTERNAL
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -1,8 +1,9 @@
# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
from pytest_embedded_idf.utils import soc_filtered_targets
@pytest.mark.generic
@@ -14,8 +15,12 @@ from pytest_embedded_idf.utils import idf_parametrize
],
indirect=True,
)
@idf_parametrize('target', ['esp32h2', 'esp32p4', 'esp32c5', 'esp32c61'], indirect=['target'])
def test_ana_cmpr_example(dut: Dut) -> None:
@idf_parametrize(
'target',
soc_filtered_targets('SOC_ANA_CMPR_SUPPORT_AUTO_SCAN == 1'),
indirect=['target'],
)
def test_ana_cmpr_auto_scan(dut: Dut) -> None:
sdkconfig = dut.app.sdkconfig
if sdkconfig['EXAMPLE_REF_FROM_INTERNAL']:
dut.expect_exact('Allocate Analog Comparator with internal reference voltage')

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB