ana_cmpr_example_intr.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /*
  2. * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Unlicense OR CC0-1.0
  5. */
  6. #include <stdio.h>
  7. #include "freertos/FreeRTOS.h"
  8. #include "freertos/task.h"
  9. #include "driver/gpio.h"
  10. #include "driver/ana_cmpr.h"
  11. #include "esp_log.h"
  12. #include "ana_cmpr_example_main.h"
  13. static const char *TAG = "ana_cmpr_example";
  14. static bool example_ana_cmpr_on_cross_callback(ana_cmpr_handle_t cmpr,
  15. const ana_cmpr_cross_event_data_t *edata,
  16. void *user_ctx)
  17. {
  18. #if CONFIG_EXAMPLE_HYSTERESIS_COMPARATOR
  19. static ana_cmpr_internal_ref_config_t ref_cfg = {
  20. .ref_volt = ANA_CMPR_REF_VOLT_70_PCT_VDD,
  21. };
  22. bool is_70p = ref_cfg.ref_volt == ANA_CMPR_REF_VOLT_70_PCT_VDD;
  23. /* Toggle the GPIO, monitor the gpio on an oscilloscope. */
  24. gpio_set_level(EXAMPLE_MONITOR_GPIO_NUM, is_70p);
  25. /* Set the internal reference voltage to 30% VDD and 70 %VDD alternately */
  26. ana_cmpr_set_internal_reference(cmpr, &ref_cfg);
  27. ref_cfg.ref_volt = is_70p ? ANA_CMPR_REF_VOLT_30_PCT_VDD : ANA_CMPR_REF_VOLT_70_PCT_VDD;
  28. #else
  29. static int lvl = 0;
  30. /* Toggle the GPIO, monitor the gpio on a oscilloscope. */
  31. gpio_set_level(EXAMPLE_MONITOR_GPIO_NUM, lvl);
  32. lvl = !lvl;
  33. #endif
  34. return false;
  35. }
  36. void example_init_analog_comparator_intr(void)
  37. {
  38. /* Step 0: Show the source channel and reference channel GPIO */
  39. int src_gpio = -1;
  40. int ext_ref_gpio = -1;
  41. ESP_ERROR_CHECK(ana_cmpr_get_gpio(EXAMPLE_ANA_CMPR_UNIT, ANA_CMPR_SOURCE_CHAN, &src_gpio));
  42. ESP_ERROR_CHECK(ana_cmpr_get_gpio(EXAMPLE_ANA_CMPR_UNIT, ANA_CMPR_EXT_REF_CHAN, &ext_ref_gpio));
  43. ESP_LOGI(TAG, "Analog Comparator source gpio %d, external reference gpio %d", src_gpio, ext_ref_gpio);
  44. ana_cmpr_handle_t cmpr = NULL;
  45. #if CONFIG_EXAMPLE_INTERNAL_REF
  46. /* Step 1: Allocate the new analog comparator unit */
  47. ana_cmpr_config_t config = {
  48. .unit = EXAMPLE_ANA_CMPR_UNIT,
  49. .clk_src = ANA_CMPR_CLK_SRC_DEFAULT,
  50. .ref_src = ANA_CMPR_REF_SRC_INTERNAL,
  51. .cross_type = ANA_CMPR_CROSS_ANY,
  52. };
  53. ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr));
  54. ESP_LOGI(TAG, "Allocate Analog Comparator with internal reference");
  55. /* Step 1.1: As we are using the internal reference source, we need to configure the internal reference */
  56. ana_cmpr_internal_ref_config_t ref_cfg = {
  57. #if CONFIG_EXAMPLE_HYSTERESIS_COMPARATOR
  58. /* Set the initial internal reference voltage to 70% VDD, it will be updated in the callback every time the interrupt triggered */
  59. .ref_volt = ANA_CMPR_REF_VOLT_70_PCT_VDD
  60. #else
  61. .ref_volt = ANA_CMPR_REF_VOLT_50_PCT_VDD,
  62. #endif
  63. };
  64. ESP_ERROR_CHECK(ana_cmpr_set_internal_reference(cmpr, &ref_cfg));
  65. #else
  66. /* Step 1: Allocate the new analog comparator unit */
  67. ana_cmpr_config_t config = {
  68. .unit = EXAMPLE_ANA_CMPR_UNIT,
  69. .clk_src = ANA_CMPR_CLK_SRC_DEFAULT,
  70. .ref_src = ANA_CMPR_REF_SRC_EXTERNAL,
  71. .cross_type = ANA_CMPR_CROSS_ANY,
  72. };
  73. ESP_ERROR_CHECK(ana_cmpr_new_unit(&config, &cmpr));
  74. ESP_LOGI(TAG, "Allocate Analog Comparator with external reference");
  75. #endif
  76. /* Step 2: (Optional) Set the debounce configuration
  77. * It's an optional configuration, if the wait time is set in debounce configuration,
  78. * the cross interrupt will be disabled temporary after it is triggered, and it will be enabled
  79. * automatically enabled after `wait_us`, so that the duplicate interrupts
  80. * can be suppressed while the source signal crossing the reference signal. */
  81. ana_cmpr_debounce_config_t dbc_cfg = {
  82. /* Normally the `wait_us` is related to the relative frequency between the source and reference signal
  83. * comparing to another one. This example adopts an approximate frequency as the relative signal
  84. * frequency, and set the default wait time to EXAMPLE_WAIT_TIME_PROP of the relative signal period.
  85. * We need to estimate an appropriate `freq_approx` and EXAMPLE_WAIT_TIME_PROP
  86. * to make sure the interrupt neither triggers duplicate interrupts, nor misses the next crossing interrupt.
  87. * Here we take 1 KHz for example */
  88. .wait_us = EXAMPLE_WAITE_TIME_US(1000),
  89. };
  90. ESP_ERROR_CHECK(ana_cmpr_set_debounce(cmpr, &dbc_cfg));
  91. /* Step 3: Register the event callbacks */
  92. ana_cmpr_event_callbacks_t cbs = {
  93. .on_cross = example_ana_cmpr_on_cross_callback,
  94. };
  95. ESP_ERROR_CHECK(ana_cmpr_register_event_callbacks(cmpr, &cbs, NULL));
  96. /* Step 4: Enable the analog comparator unit */
  97. ESP_ERROR_CHECK(ana_cmpr_enable(cmpr));
  98. #if CONFIG_EXAMPLE_INTERNAL_REF
  99. ESP_LOGI(TAG, "Analog comparator enabled, reference voltage: %d%% * VDD", (int)ref_cfg.ref_volt * 10);
  100. #else
  101. ESP_LOGI(TAG, "Analog comparator enabled, external reference selected");
  102. #endif
  103. }
  104. void example_analog_comparator_intr_app(void)
  105. {
  106. /* Initialize GPIO to monitor the comparator interrupt */
  107. example_init_monitor_gpio();
  108. /* Initialize Analog Comparator */
  109. example_init_analog_comparator_intr();
  110. }