From bb6feca7a9495ddcb4fb3ba75f235d717f0e99d4 Mon Sep 17 00:00:00 2001 From: Cai Xinying Date: Tue, 8 Aug 2023 11:46:12 +0800 Subject: [PATCH] docs: provide CN translation for api-reference/peripherals/adc_continuous.rst --- .../peripherals/adc_continuous.rst | 219 ++++++----- .../peripherals/adc_continuous.rst | 360 +++++++++++++++++- 2 files changed, 487 insertions(+), 92 deletions(-) diff --git a/docs/en/api-reference/peripherals/adc_continuous.rst b/docs/en/api-reference/peripherals/adc_continuous.rst index e88a0f4c6659..a22c733430bc 100644 --- a/docs/en/api-reference/peripherals/adc_continuous.rst +++ b/docs/en/api-reference/peripherals/adc_continuous.rst @@ -1,27 +1,29 @@ Analog to Digital Converter (ADC) Continuous Mode Driver ======================================================== +:link_to_translation:`zh_CN:[中文]` + {IDF_TARGET_ADC_NUM:default="two", esp32c2="one", esp32c6="one", esp32h2="one"} Introduction ------------ -The Analog to Digital Converter is an on-chip sensor which is able to measure analog signals from specific analog IO pads. +The Analog to Digital Converter is integrated on the chip and is capable of measuring analog signals from specific analog IO pads. Additionally, the Direct Memory Access (DMA) functionality is utilized to efficiently retrieve ADC conversion results. -{IDF_TARGET_NAME} has {IDF_TARGET_ADC_NUM} ADC unit(s), which can be used in scenario(s) like: +{IDF_TARGET_NAME} has {IDF_TARGET_ADC_NUM} ADC unit(s), which can be used in scenarios like: - Generate one-shot ADC conversion result - Generate continuous ADC conversion results -This guide will introduce ADC continuous mode conversion. +This guide introduces ADC continuous mode conversion. Driver Concepts ^^^^^^^^^^^^^^^ -ADC continuous mode conversion is made up with multiple Conversion Frames. +ADC continuous mode conversion is made up of multiple conversion frames. -- Conversion Frame: One Conversion Frame contains multiple Conversion Results. Conversion Frame size is configured in :cpp:func:`adc_continuous_new_handle`, in bytes. -- Conversion Result: One Conversion Result contains multiple bytes (see :c:macro:`SOC_ADC_DIGI_RESULT_BYTES`). Its structure is :cpp:type:`adc_digi_output_data_t`, including ADC unit, ADC channel and raw data. +- Conversion Frame: One conversion frame contains multiple conversion results. Conversion frame size is configured in :cpp:func:`adc_continuous_new_handle` in bytes. +- Conversion Result: One conversion result contains multiple bytes, see :c:macro:`SOC_ADC_DIGI_RESULT_BYTES`. Its structure is :cpp:type:`adc_digi_output_data_t`, including ADC unit, ADC channel, and raw data. .. image:: /../_static/diagrams/adc/adc_conversion_frame.png :scale: 100 % @@ -30,40 +32,44 @@ ADC continuous mode conversion is made up with multiple Conversion Frames. Functional Overview ------------------- -The following sections of this document cover the typical steps to install the ADC continuous mode driver, and read ADC conversion results from group of ADC channels continuously: +The following sections of this document cover the typical steps to install the ADC continuous mode driver, and read ADC conversion results from a group of ADC channels continuously: + +- :ref:`adc-continuous-resource-allocation`: covers which parameters should be set up to initialize the ADC continuous mode driver and how to deinitialize it. +- :ref:`adc-continuous-adc-configurations`: describes how to configure the ADC(s) to make it work under continuous mode. +- :ref:`adc-continuous-adc-control`: describes ADC control functions. +- :ref:`adc-continuous-register-event-callbacks`: describes how to hook user-specific code to an ADC continuous mode event callback function. +- :ref:`adc-continuous-read-conversion-result`: covers how to get ADC conversion result. +- :ref:`adc-continuous-hardware-limitations`: describes the ADC-related hardware limitations. +- :ref:`adc-continuous-power-management`: covers power management-related information. +- :ref:`adc-continuous-iram-safe`: covers the IRAM safe functions. +- :ref:`adc-continuous-thread-safety`: lists which APIs are guaranteed to be thread-safe by the driver. -- `Resource Allocation <#resource-allocation>`__ - covers which parameters should be set up to initialize the ADC continuous mode driver and how to deinitialize it. -- `ADC Configurations <#adc-configurations>`__ - describes how to configure the ADC(s) to make it work under continuous mode. -- `ADC Control <#adc-control>`__ - describes ADC control functions. -- `Register Event Callbacks <#register-event-callbacks>`__ - describes how to hook user specific code to an ADC continuous mode event callback function. -- `Read Conversion Result <#read-conversion-result>`__ - covers how to get ADC conversion result. -- `Hardware Limitations <#hardware-limitations>`__ - describes the ADC related hardware limitations. -- `Power Management <#power-management>`__ - covers power management related. -- `IRAM Safe <#iram-safe>`__ - covers the IRAM safe functions. -- `Thread Safety <#thread-safety>`__ - lists which APIs are guaranteed to be thread safe by the driver. +.. _adc-continuous-resource-allocation: Resource Allocation ^^^^^^^^^^^^^^^^^^^ -The ADC continuous mode driver is implemented based on {IDF_TARGET_NAME} SAR ADC module. Different ESP targets might have different number of independent ADCs. +The ADC continuous mode driver is implemented based on {IDF_TARGET_NAME} SAR ADC module. Different ESP targets might have different numbers of independent ADCs. To create an ADC continuous mode driver handle, set up the required configuration structure :cpp:type:`adc_continuous_handle_cfg_t`: -- :cpp:member:`adc_continuous_handle_cfg_t::max_store_buf_size` set the maximum size (in bytes) of the pool that the driver saves ADC conversion result into. If this pool is full, new conversion results will be lost. -- :cpp:member:`adc_continuous_handle_cfg_t::conv_frame_size` set the size of the ADC conversion frame, in bytes. -- :cpp:member:`adc_continuous_handle_cfg_t::flags` set the flags that can change the driver behaviour. +- :cpp:member:`adc_continuous_handle_cfg_t::max_store_buf_size`: set the maximum size of the pool in bytes, and the driver saves ADC conversion result into the pool. If this pool is full, new conversion results will be lost. +- :cpp:member:`adc_continuous_handle_cfg_t::conv_frame_size`: set the size of the ADC conversion frame, in bytes. +- :cpp:member:`adc_continuous_handle_cfg_t::flags`: set the flags that can change the driver's behavior. + + - ``flush_pool``: auto flush the pool when it's full. -After setting up above configurations for the ADC, call :cpp:func:`adc_continuous_new_handle` with the prepared :cpp:type:`adc_continuous_handle_cfg_t`. This function may fail due to various errors such as invalid argumemts, insufficient memory, etc. +After setting up the above configurations for the ADC, call :cpp:func:`adc_continuous_new_handle` with the prepared :cpp:type:`adc_continuous_handle_cfg_t`. This function may fail due to various errors such as invalid arguments, insufficient memory, etc. .. only:: esp32 - Especially, when this function returns :c:macro:`ESP_ERR_NOT_FOUND`, this means the I2S0 peripheral is in use. See `Hardware Limitations <#hardware-limitations>`__ for more information. + Especially, when this function returns :c:macro:`ESP_ERR_NOT_FOUND`, this means the I2S0 peripheral is in use. See :ref:`adc-continuous-hardware-limitations` for more information. .. only:: esp32s2 - Especially, when this function returns :c:macro:`ESP_ERR_NOT_FOUND`, this means the SPI3 peripheral is in use. See `Hardware Limitations <#hardware-limitations>`__ for more information. + Especially, when this function returns :c:macro:`ESP_ERR_NOT_FOUND`, this means the SPI3 peripheral is in use. See :ref:`adc-continuous-hardware-limitations` for more information. .. only:: SOC_GDMA_SUPPORTED @@ -77,15 +83,15 @@ If the ADC continuous mode driver is no longer used, you should deinitialize the IIR filter ~~~~~~~~~~ - Two IIR filters are available when ADC is working under continuous mode. To create an ADC IIR filter, you should set up the :cpp:type:`adc_continuous_iir_filter_config_t`, and call :cpp:func:`adc_new_continuous_iir_filter`. + Two IIR filters are available when ADC is working in continuous mode. To create an ADC IIR filter, you should set up :cpp:type:`adc_continuous_iir_filter_config_t` and call :cpp:func:`adc_new_continuous_iir_filter`. - - :cpp:member:`adc_digi_filter_config_t::unit`, ADC unit. - - :cpp:member:`adc_digi_filter_config_t::channel`, ADC channel to be filtered. - - :cpp:member:`adc_digi_filter_config_t::coeff`, filter coefficient. + - :cpp:member:`adc_digi_filter_config_t::unit`: ADC unit. + - :cpp:member:`adc_digi_filter_config_t::channel`: ADC channel to be filtered. + - :cpp:member:`adc_digi_filter_config_t::coeff`: Filter coefficient. .. only:: SOC_ADC_DIG_IIR_FILTER_UNIT_BINDED - On ESP32S2, the filter is per ADC unit. Once a filter is enabled, all the enabled ADC channels in this ADC unit will be filtered. However, we suggest only enabling one ADC channel per unit, when using the filter feature. Because the filtered results depend on the previous filtered result. So you should not enable multiple ADC channels, to avoid mixing the filtered results. + On {IDF_TARGET_NAME}, the filter is per ADC unit. Once a filter is enabled, all the enabled ADC channels in this ADC unit will be filtered. However, we suggest only enabling one ADC channel per unit, when using the filter feature. Because the filtered results depend on the previous filtered result. So you should not enable multiple ADC channels, to avoid mixing the filtered results. To recycle a filter, you should call :cpp:func:`adc_del_continuous_iir_filter`. @@ -93,34 +99,35 @@ If the ADC continuous mode driver is no longer used, you should deinitialize the .. note:: - If you use both the filters on a same ADC channel, then only the first one will take effect. + If you use both filters on the same ADC channel, then only the first one will take effect. .. only:: SOC_ADC_MONITOR_SUPPORTED Monitor ~~~~~~~ - {IDF_TARGET_SOC_ADC_DIGI_MONITOR_NUM} monitors are available when ADC is working under continuous mode, you can set one or two threshold(s) of a monitor on a working ADC channel, then monitor will invoke interrupts every sample loop if converted value outranges of the threshold. To create an ADC monitor, you need setup the :cpp:type:`adc_monitor_config_t` and call :cpp:func:`adc_new_continuous_monitor`. - - :cpp:member:`adc_monitor_config_t::adc_unit`, What ADC unit the channel you want to monit belongs to. - - :cpp:member:`adc_monitor_config_t::channel`, The channel you want to monit. - - :cpp:member:`adc_monitor_config_t::h_threshold`, The high threshold, convert value lager than this value will invoke interrupt, set to -1 if don't use. - - :cpp:member:`adc_monitor_config_t::l_threshold`, The low threshold, convert value less than this value will invoke interrupt, set to -1 if don't use. + {IDF_TARGET_SOC_ADC_DIGI_MONITOR_NUM} monitors are available when ADC is working under continuous mode, you can set one or two threshold(s) of a monitor on a working ADC channel, then the monitor will invoke interrupts every sample loop if conversion result outranges of the threshold. To create an ADC monitor, you need to set up the :cpp:type:`adc_monitor_config_t` and call :cpp:func:`adc_new_continuous_monitor`. + + - :cpp:member:`adc_monitor_config_t::adc_unit`: Configures which ADC unit the channel you want to monitor belongs to. + - :cpp:member:`adc_monitor_config_t::channel`: The channel you want to monitor. + - :cpp:member:`adc_monitor_config_t::h_threshold`: The high threshold, conversion result larger than this value invokes interrupt, set to -1 if do not use. + - :cpp:member:`adc_monitor_config_t::l_threshold`: The low threshold, conversion result less than this value invokes interrupt, set to -1 if do not use. Once a monitor is created, you can operate it by following APIs to construct your apps. - - :cpp:func:`adc_continuous_monitor_enable`, Enable a monitor. - - :cpp:func:`adc_continuous_monitor_disable`, Disable a monitor. - - :cpp:func:`adc_monitor_register_callbacks`, Register user callbacks to do something when ADC value outrange of the threshold. - - :cpp:func:`adc_del_continuous_monitor`, Delete a created monitor, free resources. + - :cpp:func:`adc_continuous_monitor_enable`: Enable a monitor. + - :cpp:func:`adc_continuous_monitor_disable`: Disable a monitor. + - :cpp:func:`adc_monitor_register_callbacks`: register user callbacks to take action when the ADC value exceeds of the threshold. + - :cpp:func:`adc_del_continuous_monitor`: Delete a created monitor and free resources. .. only:: esp32s2 .. NOTE:: - There are some hardware limitations on ESP32S2: - 1. Only one threshold supported for one monitor. - 2. Only one monitor supported for one adc unit. - 3. All enabled channel(s) of a certain adc unit in adc continuous mode driver will be monitored, param :cpp:member:`adc_monitor_config_t::channel` will not used. + There are some hardware limitations on {IDF_TARGET_NAME}: + 1. Only one threshold is supported for one monitor. + 2. Only one monitor is supported for one ADC unit. + 3. All enabled channel(s) of a certain ADC unit in ADC continuous mode driver will be monitored. The :cpp:member:`adc_monitor_config_t::channel` parameter will not be used. Initialize the ADC Continuous Mode Driver ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -142,38 +149,44 @@ Recycle the ADC Unit ESP_ERROR_CHECK(adc_continuous_deinit()); +.. _adc-continuous-adc-configurations: + ADC Configurations ^^^^^^^^^^^^^^^^^^ After the ADC continuous mode driver is initialized, set up the :cpp:type:`adc_continuous_config_t` to configure ADC IOs to measure analog signal: -- :cpp:member:`adc_continuous_config_t::pattern_num`, number of ADC channels that will be used. -- :cpp:member:`adc_continuous_config_t::adc_pattern`, list of configs for each ADC channel that will be used, see below description. -- :cpp:member:`adc_continuous_config_t::sample_freq_hz`, expected ADC sampling frequency in Hz. -- :cpp:member:`adc_continuous_config_t::conv_mode`, continuous conversion mode. -- :cpp:member:`adc_continuous_config_t::format`, conversion output format. +- :cpp:member:`adc_continuous_config_t::pattern_num`: number of ADC channels that will be used. +- :cpp:member:`adc_continuous_config_t::adc_pattern`: list of configs for each ADC channel that will be used, see the description below. +- :cpp:member:`adc_continuous_config_t::sample_freq_hz`: expected ADC sampling frequency in Hz. +- :cpp:member:`adc_continuous_config_t::conv_mode`: continuous conversion mode. +- :cpp:member:`adc_continuous_config_t::format`: conversion output format. -For :cpp:type:`adc_digi_pattern_config_t`: +Set :cpp:type:`adc_digi_pattern_config_t` with the following process: -- :cpp:member:`adc_digi_pattern_config_t::atten`, ADC attenuation. Refer to the On-Chip Sensor chapter in `TRM <{IDF_TARGET_TRM_EN_URL}>`__. -- :cpp:member:`adc_digi_pattern_config_t::channel`, the IO corresponding ADC channel number. See below note. -- :cpp:member:`adc_digi_pattern_config_t::unit`, the ADC that the IO is subordinate to. -- :cpp:member:`adc_digi_pattern_config_t::bit_width`, the bitwidth of the raw conversion result. +- :cpp:member:`adc_digi_pattern_config_t::atten`: ADC attenuation. Refer to the On-Chip Sensor and Analog Signal Processing chapter in `TRM <{IDF_TARGET_TRM_EN_URL}>`__. +- :cpp:member:`adc_digi_pattern_config_t::channel`: the IO corresponding ADC channel number. See the note below. +- :cpp:member:`adc_digi_pattern_config_t::unit`: the ADC that the IO is subordinate to. +- :cpp:member:`adc_digi_pattern_config_t::bit_width`: the bitwidth of the raw conversion result. .. note:: - For the IO corresponding ADC channel number. Check `datasheet <{IDF_TARGET_TRM_EN_URL}>`__ to acquire the ADC IOs. - On the other hand, :cpp:func:`adc_continuous_io_to_channel` and :cpp:func:`adc_continuous_channel_to_io` can be used to acquire the ADC channels and ADC IOs. + For the IO corresponding ADC channel number, check `TRM <{IDF_TARGET_TRM_EN_URL}#sensor>`__ to acquire the ADC IOs. Besides, :cpp:func:`adc_continuous_io_to_channel` and :cpp:func:`adc_continuous_channel_to_io` can be used to acquire the ADC channels and ADC IOs. -To make these settings take effect, call :cpp:func:`adc_continuous_config` with the configuration structure above. -This API may fail due to reasons like :c:macro:`ESP_ERR_INVALID_ARG`. When it returns :c:macro:`ESP_ERR_INVALID_STATE`, this means the ADC continuous mode driver is started, you shouldn't call this API at this moment. +To make these settings take effect, call :cpp:func:`adc_continuous_config` with the configuration structure above. This API may fail due to reasons like :c:macro:`ESP_ERR_INVALID_ARG`. When it returns :c:macro:`ESP_ERR_INVALID_STATE`, this means the ADC continuous mode driver is started, you should not call this API at this moment. See ADC continuous mode example :example:`peripherals/adc/continuous_read` to see configuration codes. .. only:: SOC_ADC_DIG_IIR_FILTER_SUPPORTED - To enable / disable the ADC IIR filter, you should call :cpp:func:`adc_continuous_iir_filter_enable` / :cpp:func:`adc_continuous_iir_filter_disable`. + To enable/disable the ADC IIR filter, you should call :cpp:func:`adc_continuous_iir_filter_enable` / :cpp:func:`adc_continuous_iir_filter_disable`. + +.. only:: SOC_ADC_MONITOR_SUPPORTED + + To enable/disable the ADC monitor, you should call :cpp:func:`adc_continuous_monitor_enable` / :cpp:func:`adc_continuous_monitor_disable`. + +.. _adc-continuous-adc-control: ADC Control ^^^^^^^^^^^ @@ -181,8 +194,9 @@ ADC Control Start and Stop ~~~~~~~~~~~~~~ -Calling :cpp:func:`adc_continuous_start` will make the ADC start to measure analog signals from the configured ADC channels, and generate the conversion results. -On the contrary, calling :cpp:func:`adc_continuous_stop` will stop the ADC conversion. +Calling :cpp:func:`adc_continuous_start` makes the ADC start to measure analog signals from the configured ADC channels, and generate the conversion results. + +On the contrary, calling :cpp:func:`adc_continuous_stop` stops the ADC conversion. .. code::c @@ -193,24 +207,27 @@ On the contrary, calling :cpp:func:`adc_continuous_stop` will stop the ADC conve ESP_ERROR_CHECK(adc_continuous_stop()); +.. _adc-continuous-register-event-callbacks: + Register Event Callbacks ^^^^^^^^^^^^^^^^^^^^^^^^ -By calling :cpp:func:`adc_continuous_register_event_callbacks`, you can hook your own function to the driver ISR. Supported event callbacks are listed in :cpp:type:`adc_continuous_evt_cbs_t` -- :cpp:member:`adc_continuous_evt_cbs_t::on_conv_done`, this is invoked when one conversion frame finishes. -- :cpp:member:`adc_continuous_evt_cbs_t::on_pool_ovf`, this is invoked when internal pool is full. Newer conversion results will be discarded. +By calling :cpp:func:`adc_continuous_register_event_callbacks`, you can hook your own function to the driver ISR. Supported event callbacks are listed in :cpp:type:`adc_continuous_evt_cbs_t`. + +- :cpp:member:`adc_continuous_evt_cbs_t::on_conv_done`: this is invoked when one conversion frame finishes. +- :cpp:member:`adc_continuous_evt_cbs_t::on_pool_ovf`: this is invoked when the internal pool is full. Newer conversion results will be discarded. -As above callbacks are called in an ISR context, you should always ensure the callback function is suitable for an ISR context. Blocking logics should not appear in these callbacks. Callback function prototype is declared in :cpp:type:`adc_continuous_callback_t`. +As the above callbacks are called in an ISR context, you should always ensure the callback function is suitable for an ISR context. Blocking logic should not appear in these callbacks. The callback function prototype is declared in :cpp:type:`adc_continuous_callback_t`. -You can also register your own context when calling :cpp:func:`adc_continuous_register_event_callbacks`, by the parameter ``user_data``. This user data will be passed to the callback functions directly. +You can also register your own context when calling :cpp:func:`adc_continuous_register_event_callbacks` by the parameter ``user_data``. This user data will be passed to the callback functions directly. -This function may fail due to reasons like :c:macro:`ESP_ERR_INVALID_ARG`. Specially, when :ref:`CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE` is enabled, this error may indicate that the callback functions aren't in internal RAM. Check error log to know this. Besides, when it fails due to :c:macro:`ESP_ERR_INVALID_STATE`, this means the ADC continuous mode driver is started, you shouldn't add callback at this moment. +This function may fail due to reasons like :c:macro:`ESP_ERR_INVALID_ARG`. Especially, when :ref:`CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE` is enabled, this error may indicate that the callback functions are not in the internal RAM. Check the error log for more details. Besides, when it fails due to :c:macro:`ESP_ERR_INVALID_STATE`, it indicates that the ADC continuous mode driver is started, and you should not add a callback at this moment. Conversion Done Event ~~~~~~~~~~~~~~~~~~~~~ -The driver will fill in the event data of a :cpp:member:`adc_continuous_evt_cbs_t::on_conv_done` event. Event data contains a buffer pointer to a conversion frame buffer, together with the size. Refer to :cpp:type:`adc_continuous_evt_data_t` to know the event data structure. +When the driver completes a conversion, it triggers the :cpp:member:`adc_continuous_evt_cbs_t::on_conv_done` event and fills the event data. Event data contains a buffer pointer to a conversion frame buffer, together with the size. Refer to :cpp:type:`adc_continuous_evt_data_t` to know the event data structure. .. note:: @@ -223,23 +240,25 @@ The driver will fill in the event data of a :cpp:member:`adc_continuous_evt_cbs_ Pool Overflow Event ~~~~~~~~~~~~~~~~~~~ -The ADC continuous mode driver has an internal pool to save the conversion results. When the pool is full, a pool overflow event will emerge. Under this condition, the driver won't fill in the event data. This usually happens the speed to read data from the pool (by calling :cpp:func:`adc_continuous_read`) is much slower than the ADC conversion speed. +The ADC continuous mode driver has an internal pool to save the conversion results. When the pool is full, a pool overflow event will emerge. Under this condition, the driver will not fill in the event data. This usually happens because the speed to read data from the pool by calling :cpp:func:`adc_continuous_read` is much slower than the ADC conversion speed. + +.. _adc-continuous-read-conversion-result: Read Conversion Result ^^^^^^^^^^^^^^^^^^^^^^ After calling :cpp:func:`adc_continuous_start`, the ADC continuous conversion starts. Call :cpp:func:`adc_continuous_read` to get the conversion results of the ADC channels. You need to provide a buffer to get the raw results. -This function will try to read the expected length of conversion results each time. +Function :cpp:func:`adc_continuous_read` tries to read the expected length of conversion results each time. -- If the requested length isn't reached, the function will still move the data from the internal pool to the buffer you prepared. Therefore, check the `out_length` to know the actual size of conversion results. -- If there is no conversion result generated in the internal pool, the function will block for `timeout_ms` until the conversion results are generated. If there is still no generated results, the function will return :c:macro:`ESP_ERR_TIMEOUT`. -- If the generated results fill up the internal pool, new generated results will be lost. Next time when the :cpp:func:`adc_continuous_read` is called, this function will return :c:macro:`ESP_ERR_INVALID_STATE` indicating this situation. +- When calling :cpp:func:`adc_continuous_read`, you can request to read a conversion result of the specified length. Sometimes, however, the actual available conversion results may be less than the requested length, in which case the function still moves the data from the internal pool into the buffer you provided. Therefore, to learn the number of conversion results actually moved into the buffer, please check the value of ``out_length``. +- If there is no conversion result generated in the internal pool, the function will block for ``timeout_ms`` until the conversion results are generated. If there are still no generated results, the function will return :c:macro:`ESP_ERR_TIMEOUT`. +- If the generated results fill up the internal pool, newly generated results will be lost. Next time when :cpp:func:`adc_continuous_read` is called, this function will return :c:macro:`ESP_ERR_INVALID_STATE` to indicate this situation. This API aims to give you a chance to read all the ADC continuous conversion results. -The ADC conversion results read from above function are raw data. To calculate the voltage based on the ADC raw results, this formula can be used: +The ADC conversion results read from the above function are raw data. To calculate the voltage based on the ADC raw results, this formula can be used: .. parsed-literal:: @@ -247,67 +266,85 @@ The ADC conversion results read from above function are raw data. To calculate t where: -====== ============================================================= -Vout Digital output result, standing for the voltage. -Dout ADC raw digital reading result. -Vmax Maximum measurable input analog voltage, this is related to the ADC attenuation, please refer to the On-Chip Sensor chapter in `TRM <{IDF_TARGET_TRM_EN_URL}>`__. -Dmax Maximum of the output ADC raw digital reading result, which is 2^bitwidth, where bitwidth is the :cpp:member::`adc_digi_pattern_config_t:bit_width` configured before. -====== ============================================================= +.. list-table:: + :header-rows: 1 + :widths: 20 80 + :align: center + + * - Vout + - Digital output result, standing for the voltage. + * - Dout + - ADC raw digital reading result. + * - Vmax + - Maximum measurable input analog voltage, this is related to the ADC attenuation, please refer to the On-Chip Sensor and Analog Signal Processing chapter in `TRM <{IDF_TARGET_TRM_EN_URL}>`__. + * - Dmax + - Maximum of the output ADC raw digital reading result, which is 2^bitwidth, where the bitwidth is the :cpp:member:`adc_digi_pattern_config_t::bit_width` configured before. -To do further calbration to convert the ADC raw result to voltage in mV, please refer to calibration doc :doc:`adc_calibration`. +To do further calibration to convert the ADC raw result to voltage in mV, please refer to :doc:`adc_calibration`. + +.. _adc-continuous-hardware-limitations: .. _hardware_limitations_adc_continuous: Hardware Limitations ^^^^^^^^^^^^^^^^^^^^ -- A specific ADC unit can only work under one operating mode at any one time, either continuous mode or oneshot mode. :cpp:func:`adc_continuous_start` has provided the protection. +- A specific ADC unit can only work under one operating mode at any one time, either continuous mode or one-shot mode. :cpp:func:`adc_continuous_start` has provided the protection. -- Random Number Generator uses ADC as an input source. When ADC continuous mode driver works, the random number generated from RNG will be less random. +- Random Number Generator (RNG) uses ADC as an input source. When ADC continuous mode driver works, the random number generated from RNG will be less random. .. only:: esp32 or esp32s2 - - ADC2 is also used by the Wi-Fi. :cpp:func:`adc_continuous_start` has provided the protection between Wi-Fi driver and ADC continuous mode driver. + - ADC2 is also used by Wi-Fi. :cpp:func:`adc_continuous_start` has provided the protection between Wi-Fi driver and ADC continuous mode driver. .. only:: esp32 - - ADC continuous mode driver uses I2S0 peripheral as hardware DMA fifo. Therefore, if I2S0 is in use already, the :cpp:func:`adc_continuous_new_handle` will return :c:macro:`ESP_ERR_NOT_FOUND`. + - ADC continuous mode driver uses I2S0 peripheral as hardware DMA FIFO. Therefore, if I2S0 is in use already, the :cpp:func:`adc_continuous_new_handle` will return :c:macro:`ESP_ERR_NOT_FOUND`. - ESP32 DevKitC: GPIO 0 cannot be used due to external auto program circuits. - - ESP-WROVER-KIT: GPIO 0, 2, 4 and 15 cannot be used due to external connections for different purposes. + - ESP-WROVER-KIT: GPIO 0, 2, 4, and 15 cannot be used due to external connections for different purposes. .. only:: esp32s2 - - ADC continuous mode driver uses SPI3 peripheral as hardware DMA fifo. Therefore, if SPI3 is in use already, the :cpp:func:`adc_continuous_new_handle` will return :c:macro:`ESP_ERR_NOT_FOUND`. + - ADC continuous mode driver uses SPI3 peripheral as hardware DMA FIFO. Therefore, if SPI3 is in use already, the :cpp:func:`adc_continuous_new_handle` will return :c:macro:`ESP_ERR_NOT_FOUND`. .. only:: esp32c3 - - ADC2 continuous mode is no longer supported, due to hardware limitation. The results are not stable. This issue can be found in `ESP32C3 Errata `_. For compatibility, you can enable :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3` to force use ADC2. + - ADC2 DMA functionality is no longer supported to retrieve ADC conversion results due to hardware limitations, as unstable results have been observed. This issue can be found in `ESP32C3 Errata `_. For compatibility, you can enable :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3` to force use ADC2. .. only:: esp32s3 - - ADC2 continuous mode is no longer supported, due to hardware limitation. The results are not stable. This issue can be found in `ESP32S3 Errata `_. For compatibility, you can enable :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3` to force use ADC2. + - ADC2 DMA functionality is no longer supported to retrieve ADC conversion results due to hardware limitations, as unstable results have been observed. This issue can be found in `ESP32S3 Errata `_. For compatibility, you can enable :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3` to force use ADC2. + + .. _adc-continuous-power-management: + +.. only:: not esp32s3 + .. _adc-continuous-power-management: Power Management ^^^^^^^^^^^^^^^^ -When power management is enabled (i.e. :ref:`CONFIG_PM_ENABLE` is on), the APB clock frequency may be adjusted when the system is in an idle state, thus potentially changing the behavior of ADC continuous conversion. +When power management is enabled, i.e., :ref:`CONFIG_PM_ENABLE` is on, the APB clock frequency may be adjusted when the system is in an idle state, thus potentially changing the behavior of ADC continuous conversion. -However, the continuous mode driver can prevent this change by acquiring a power management lock of type :cpp:enumerator:`ESP_PM_APB_FREQ_MAX`. The lock is acquired after the continuous conversion is started by :cpp:func:`adc_continuous_start`. Similarly, the lock will be released after :cpp:func:`adc_continuous_stop`. Therefore, :cpp:func:`adc_continuous_start` and :cpp:func:`adc_continuous_stop` should appear in pairs, otherwise the power management will be out of action. +However, the continuous mode driver can prevent this change by acquiring a power management lock of type :cpp:enumerator:`ESP_PM_APB_FREQ_MAX`. The lock is acquired after the continuous conversion is started by :cpp:func:`adc_continuous_start`. Similarly, the lock will be released after :cpp:func:`adc_continuous_stop`. Therefore, :cpp:func:`adc_continuous_start` and :cpp:func:`adc_continuous_stop` should appear in pairs, otherwise, the power management will be out of action. +.. _adc-continuous-iram-safe: + IRAM Safe ^^^^^^^^^ -All the ADC continuous mode driver APIs are not IRAM-safe. They are not supposed to be run when the Cache is disabled. By enabling the Kconfig option :ref:`CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE`, driver internal ISR handler is IRAM-safe, which means even when the Cache is disabled, the driver will still save the conversion results into its internal pool. +All the ADC continuous mode driver APIs are not IRAM-safe. They are not supposed to be run when the Cache is disabled. By enabling the Kconfig option :ref:`CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE`, the driver's internal ISR handler is IRAM-safe, which means even when the Cache is disabled, the driver will still save the conversion results into its internal pool. + +.. _adc-continuous-thread-safety: Thread Safety ^^^^^^^^^^^^^ -ADC continuous mode driver APIs are not guaranteed to be thread safe. However, the share hardware mutual exclusion is provided by the driver. See `Hardware Limitations <#hardware-limitations>`__ for more details. +ADC continuous mode driver APIs are not guaranteed to be thread-safe. However, the share hardware mutual exclusion is provided by the driver. See :ref:`adc-continuous-hardware-limitations` for more details. Application Examples diff --git a/docs/zh_CN/api-reference/peripherals/adc_continuous.rst b/docs/zh_CN/api-reference/peripherals/adc_continuous.rst index 890cb0cf7f1e..3e3ccdcc7140 100644 --- a/docs/zh_CN/api-reference/peripherals/adc_continuous.rst +++ b/docs/zh_CN/api-reference/peripherals/adc_continuous.rst @@ -1 +1,359 @@ -.. include:: ../../../en/api-reference/peripherals/adc_continuous.rst \ No newline at end of file +模数转换器 (ADC) 连续转换模式驱动 +======================================================== + +:link_to_translation:`en:[English]` + +{IDF_TARGET_ADC_NUM:default="两", esp32c2="一", esp32c6="一", esp32h2="一"} + +简介 +------------ + +{IDF_TARGET_NAME} 芯片集成了模数转换器 (ADC),支持测量特定模拟 IO 管脚的模拟信号。此外,ADC 还支持直接内存访问 (DMA) 功能,高效获取 ADC 转换结果。 + +{IDF_TARGET_NAME} 具有 {IDF_TARGET_ADC_NUM} 个 ADC 单元,可应用于以下场景: + +- 生成单次 ADC 转换结果 +- 生成连续 ADC 转换结果 + +本指南介绍了 ADC 连续转换模式。 + +ADC 连续转换模式驱动概念 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +ADC 连续转换模式驱动由多个转换帧组成。 + +- 转换帧:一个转换帧包含多个转换结果。转换帧大小以字节为单位,在 :cpp:func:`adc_continuous_new_handle` 中配置。 +- 转换结果:一个转换结果包含多个字节,即 :c:macro:`SOC_ADC_DIGI_RESULT_BYTES`。转换结果的数据结构由 :cpp:type:`adc_digi_output_data_t` 定义,包括 ADC 单元、ADC 通道以及原始数据。 + +.. image:: /../_static/diagrams/adc/adc_conversion_frame.png + :scale: 100 % + :align: center + +功能概述 +------------------- + +下文将分节概述安装 ADC 连续转换模式驱动、并从一组 ADC 通道连续读取 ADC 转换结果的基本步骤: + +- :ref:`adc-continuous-resource-allocation`:介绍初始化 ADC 连续转换模式驱动所需设置的参数,以及如何将驱动去初始化。 +- :ref:`adc-continuous-adc-configurations`:介绍如何将 ADC 配置为在连续转换模式下工作。 +- :ref:`adc-continuous-adc-control`:介绍 ADC 控制函数。 +- :ref:`adc-continuous-register-event-callbacks`:介绍如何将特定用户代码链接到 ADC 连续转换模式事件回调函数。 +- :ref:`adc-continuous-read-conversion-result`:介绍如何获取 ADC 转换结果。 +- :ref:`adc-continuous-hardware-limitations`:介绍与 ADC 相关的硬件限制。 +- :ref:`adc-continuous-power-management`:介绍电源管理的相关内容。 +- :ref:`adc-continuous-iram-safe`:介绍与 IRAM 安全相关的函数。 +- :ref:`adc-continuous-thread-safety`:介绍由驱动程序认证为线程安全的 API。 + + +.. _adc-continuous-resource-allocation: + +资源分配 +^^^^^^^^^^^^^^^^^^^ + +ADC 连续转换模式驱动基于 {IDF_TARGET_NAME} SAR ADC 模块实现,不同的 ESP 目标芯片可能拥有不同数量的独立 ADC。 + +请按照以下步骤设置配置结构体 :cpp:type:`adc_continuous_handle_cfg_t`,创建 ADC 连续转换模式驱动的句柄: + +- :cpp:member:`adc_continuous_handle_cfg_t::max_store_buf_size`:以字节为单位设置最大缓冲池的大小,驱动程序将 ADC 转换结果保存到该缓冲池中。缓冲池已满时,新的转换将丢失。 +- :cpp:member:`adc_continuous_handle_cfg_t::conv_frame_size`:以字节为单位设置 ADC 转换帧大小。 +- :cpp:member:`adc_continuous_handle_cfg_t::flags`:设置可以改变驱动程序行为的标志。 + + - ``flush_pool``:缓冲池满时自动清空缓冲池。 + + +完成以上 ADC 配置后,使用已设置的配置结构体 :cpp:type:`adc_continuous_handle_cfg_t` 调用 :cpp:func:`adc_continuous_new_handle`。该函数可能将在特定情况下返回错误值,如无效参数、内存不足等。 + +.. only:: esp32 + + 函数返回 :c:macro:`ESP_ERR_NOT_FOUND` 时,表明 I2S0 外设正在使用中,详情请参阅 :ref:`adc-continuous-hardware-limitations`。 + +.. only:: esp32s2 + + 函数返回 :c:macro:`ESP_ERR_NOT_FOUND` 时,表明 SPI3 外设正在使用中,详情请参阅 :ref:`adc-continuous-hardware-limitations`。 + +.. only:: SOC_GDMA_SUPPORTED + + 函数返回 :c:macro:`ESP_ERR_NOT_FOUND` 时,表明 GDMA 空闲通道不足。 + +如果不再使用 ADC 连续转换模式驱动,请调用 :cpp:func:`adc_continuous_deinit` 将驱动去初始化。 + + +.. only:: SOC_ADC_DIG_IIR_FILTER_SUPPORTED + + IIR 滤波器 + ~~~~~~~~~~ + + ADC 连续转换模式下支持使用两个 IIR 滤波器。请设置 :cpp:type:`adc_continuous_iir_filter_config_t` 结构体并调用 :cpp:func:`adc_new_continuous_iir_filter`,以创建 ADC IIR 滤波器。 + + - :cpp:member:`adc_digi_filter_config_t::unit`:ADC 单元。 + - :cpp:member:`adc_digi_filter_config_t::channel`:将进行滤波的 ADC 通道。 + - :cpp:member:`adc_digi_filter_config_t::coeff`:滤波器系数。 + + .. only:: SOC_ADC_DIG_IIR_FILTER_UNIT_BINDED + + 在 {IDF_TARGET_NAME} 上,滤波器按 ADC 单元设置。一旦启用了滤波器,将对当前 ADC 单元中所有启用的 ADC 通道进行滤波。每个通道的滤波结果取决于前一次的滤波结果,因此为避免混淆滤波结果,建议在使用滤波器功能时,每个 ADC 单元只启用一条 ADC 通道,请勿同时启用多条 ADC 通道。 + + 调用 :cpp:func:`adc_del_continuous_iir_filter` 可以回收滤波器。 + + .. only:: not SOC_ADC_DIG_IIR_FILTER_UNIT_BINDED + + .. note:: + + 在一个 ADC 通道上同时使用两个滤波器时,只有第一个滤波器会生效。 + +.. only:: SOC_ADC_MONITOR_SUPPORTED + + 监视器 + ~~~~~~~ + + 当 ADC 在连续转换模式下运行时,支持使用 {IDF_TARGET_SOC_ADC_DIGI_MONITOR_NUM} 个监视器。你可以在运行中的 ADC 通道上设置一到两个监视器阈值,一旦转换结果超出阈值,监视器将在每个采样循环中触发中断。请设置 :cpp:type:`adc_monitor_config_t`,并调用 :cpp:func:`adc_new_continuous_monitor` 以创建 ADC 监视器。 + + - :cpp:member:`adc_monitor_config_t::adc_unit`:配置要监视的 ADC 通道所属的 ADC 单元。 + - :cpp:member:`adc_monitor_config_t::channel`:要监视的 ADC 通道。 + - :cpp:member:`adc_monitor_config_t::h_threshold`:高阈值,转换结果大于此值将触发中断,如果不使用此阈值,则将其设置为 -1。 + - :cpp:member:`adc_monitor_config_t::l_threshold`:低阈值,转换结果小于此值将触发中断,如果不使用此阈值,则将其设置为 -1。 + + 创建监视器后,可以使用以下 API 操作监视器,构建你的应用程序。 + + - :cpp:func:`adc_continuous_monitor_enable`:启用监视器。 + - :cpp:func:`adc_continuous_monitor_disable`:禁用监视器. + - :cpp:func:`adc_monitor_register_callbacks`:注册用户回调函数,在 ADC 转换结果超出阈值时,执行相应操作。 + - :cpp:func:`adc_del_continuous_monitor`:删除监视器,释放资源。 + + .. only:: esp32s2 + + .. NOTE:: + + {IDF_TARGET_NAME} 上存在以下硬件限制: + 1. 每个监视器仅支持一个阈值。 + 2. 每个 ADC 单元仅支持一个监视器。 + 3. ADC 连续转换模式驱动中,如果启用了监视器,无需使用参数 :cpp:member:`adc_monitor_config_t::channel` 指定,某个 ADC 单元中所有已启用的通道都会受监视。 + +初始化 ADC 连续转换模式驱动 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code:: c + + adc_continuous_handle_cfg_t adc_config = { + .max_store_buf_size = 1024, + .conv_frame_size = 100, + }; + ESP_ERROR_CHECK(adc_continuous_new_handle(&adc_config)); + + +回收 ADC 单元 +~~~~~~~~~~~~~~~~~~~~ + +.. code:: c + + ESP_ERROR_CHECK(adc_continuous_deinit()); + + +.. _adc-continuous-adc-configurations: + +配置 ADC +^^^^^^^^^^^^^^^^^^ + +初始化 ADC 连续转换模式驱动后,设置 :cpp:type:`adc_continuous_config_t` 配置 ADC IO,测量模拟信号: + +- :cpp:member:`adc_continuous_config_t::pattern_num`:要使用的 ADC 通道数量。 +- :cpp:member:`adc_continuous_config_t::adc_pattern`:每个要使用的 ADC 通道的配置列表,请参阅下文描述。 +- :cpp:member:`adc_continuous_config_t::sample_freq_hz`:期望的 ADC 采样频率,单位为 Hz。 +- :cpp:member:`adc_continuous_config_t::conv_mode`:连续转换模式。 +- :cpp:member:`adc_continuous_config_t::format`:转换模式结果的输出格式。 + +按照以下步骤设置 :cpp:type:`adc_digi_pattern_config_t`: + +- :cpp:member:`adc_digi_pattern_config_t::atten`:ADC 衰减。请参阅 `技术参考手册 <{IDF_TARGET_TRM_CN_URL}#sensor>`__ 中的片上传感器与模拟信号处理章节。 +- :cpp:member:`adc_digi_pattern_config_t::channel`:IO 对应的 ADC 通道号,请参阅下文注意事项。 +- :cpp:member:`adc_digi_pattern_config_t::unit`:IO 所属的 ADC 单元。 +- :cpp:member:`adc_digi_pattern_config_t::bit_width`:原始转换结果的位宽。 + +.. note:: + + 对于 IO 对应的 ADC 通道号,请参阅 `技术参考手册 <{IDF_TARGET_TRM_CN_URL}#sensor>`__ 获取 ADC IO 管脚的详细信息。另外,可以使用 :cpp:func:`adc_continuous_io_to_channel` 和 :cpp:func:`adc_continuous_channel_to_io` 获取 ADC 通道和 ADC IO 的对应关系。 + +为使这些设置生效,请使用上述配置结构体,调用 :cpp:func:`adc_continuous_config`。此 API 可能由于 :c:macro:`ESP_ERR_INVALID_ARG` 等原因返回错误。当它返回 :c:macro:`ESP_ERR_INVALID_STATE` 时,意味着 ADC 连续转换模式驱动已经启动,此时不应调用此 API。 + +请参考 ADC 连续转换模式示例 :example:`peripherals/adc/continuous_read`,查看相应配置代码。 + + +.. only:: SOC_ADC_DIG_IIR_FILTER_SUPPORTED + + 请调用 :cpp:func:`adc_continuous_iir_filter_enable` 或 :cpp:func:`adc_continuous_iir_filter_disable`,以启用或禁用 ADC IIR 滤波器。 + +.. only:: SOC_ADC_MONITOR_SUPPORTED + + 请调用 :cpp:func:`adc_continuous_monitor_enable` 或 :cpp:func:`adc_continuous_monitor_disable`,以启用或禁用 ADC 监视器。 + +.. _adc-continuous-adc-control: + +ADC 控制 +^^^^^^^^^^^ + +启动和停止 +~~~~~~~~~~~~~~ + +调用 :cpp:func:`adc_continuous_start`,将使 ADC 开始从配置好的 ADC 通道测量模拟信号,并生成转换结果。 + +相反,调用 :cpp:func:`adc_continuous_stop` 则会停止 ADC 转换。 + +.. code::c + + ESP_ERROR_CHECK(adc_continuous_start()); + +.. code:: c + + ESP_ERROR_CHECK(adc_continuous_stop()); + + +.. _adc-continuous-register-event-callbacks: + +注册事件回调 +^^^^^^^^^^^^^^^^^^^^^^^^ + +调用 :cpp:func:`adc_continuous_register_event_callbacks`,可以将自己的函数链接到驱动程序的 ISR 中。通过 :cpp:type:`adc_continuous_evt_cbs_t` 可查看所有支持的事件回调。 + +- :cpp:member:`adc_continuous_evt_cbs_t::on_conv_done`:当一个转换帧完成时,触发此事件。 +- :cpp:member:`adc_continuous_evt_cbs_t::on_pool_ovf`:当内部缓冲池已满时,触发此事件,新的转换结果将丢失。 + +由于上述回调函数在 ISR 中调用,请确保回调函数适合在 ISR 上下文中运行,且这些回调不应涉及阻塞逻辑。回调函数的原型在 :cpp:type:`adc_continuous_callback_t` 中声明。 + +在调用 :cpp:func:`adc_continuous_register_event_callbacks` 时,还可以通过参数 ``user_data`` 注册自己的上下文,该用户数据将直接传递给回调函数。 + +此回调函数可能由于 :c:macro:`ESP_ERR_INVALID_ARG` 等原因返回错误。启用 :ref:`CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE` 时,如果回调函数失败并报错,可能是因为回调函数不在内部 RAM 中,请查看错误日志了解详情。此外,如果回调函数出现 :c:macro:`ESP_ERR_INVALID_STATE` 错误,表明 ADC 连续转换模式驱动已经启动,此时不应添加回调。 + + +转换完成事件 +~~~~~~~~~~~~~~~~~~~~~ + +当驱动程序完成一次转换后,会触发 :cpp:member:`adc_continuous_evt_cbs_t::on_conv_done` 事件,并填充事件数据。事件数据包含一个指向转换帧缓冲区的指针,以及转换帧缓冲区大小。要了解事件数据结构,请参阅 :cpp:type:`adc_continuous_evt_data_t`。 + +.. note:: + + 注意,数据缓冲区 :cpp:member:`adc_continuous_evt_data_t::conv_frame_buffer` 由驱动程序本身维护,请勿释放此内存。 + +.. note:: + + 启用 Kconfig 选项 :ref:`CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE` 时,注册的回调函数以及回调函数中调用的函数应放置在 IRAM 中,涉及的变量也应放置在内部 RAM 中。 + +缓冲池溢出事件 +~~~~~~~~~~~~~~~~~~~ + +ADC 连续转换模式驱动使用内部缓冲池保存转换结果,缓冲池满时将发生缓冲池溢出事件。此时,驱动程序不会继续填充事件数据。缓冲池溢出通常是因为调用 :cpp:func:`adc_continuous_read` 从池中读取数据的速度远低于 ADC 转换的速度。 + + +.. _adc-continuous-read-conversion-result: + +读取转换结果 +^^^^^^^^^^^^^^^^^^^^^^ + +调用 :cpp:func:`adc_continuous_start` 启动 ADC 连续转换,调用 :cpp:func:`adc_continuous_read` 可以获取 ADC 通道的转换结果。注意提供缓冲区,获取原始结果。 + +函数 :cpp:func:`adc_continuous_read` 每次都会尝试以期望长度读取转换结果。 + +- 调用 :cpp:func:`adc_continuous_read` 可以请求读取指定长度的转换结果。但有时实际可用的转换结果可能少于请求长度,此时,函数仍会将数据从内部池移动到你提供的缓冲区中。因此,请查看 ``out_length`` 的值,了解实际移动到缓冲区中的转换结果数量。 +- 如果内部池中没有生成转换结果,函数将会阻塞一段时间,即 ``timeout_ms``,直到转换结果生成。如果始终没有转换结果生成,函数将返回 :c:macro:`ESP_ERR_TIMEOUT`。 +- 如果 ADC 连续转换生成的结果填满了内部池,新产生的结果将丢失。下次调用 :cpp:func:`adc_continuous_read` 时,将返回 :c:macro:`ESP_ERR_INVALID_STATE`,提示此情况发生。 + +此 API 提供了一个读取所有 ADC 连续转换结果的机会。 + +从上述函数读取的 ADC 转换结果为原始数据。要根据 ADC 原始结果计算电压,可以使用以下公式: + +.. parsed-literal:: + + Vout = Dout * Vmax / Dmax (1) + +其中: + +.. list-table:: + :header-rows: 1 + :widths: 20 80 + :align: center + + * - Vout + - 数据输出结果,代表电压。 + * - Dout + - ADC 原始数据读取结果。 + * - Vmax + - 可测量的最大模拟输入电压,与 ADC 衰减相关,请参考 `技术参考手册 <{IDF_TARGET_TRM_CN_URL}#sensor>`__ 中的片上传感器与模拟信号处理章节。 + * - Dmax + - 输出 ADC 原始数据读取结果的最大值,即 2^位宽,位宽即之前配置的 :cpp:member:`adc_digi_pattern_config_t::bit_width`。 + +若需进一步校准,将 ADC 原始结果转换为以 mV 为单位的电压数据,请参考 :doc:`adc_calibration`。 + +.. _adc-continuous-hardware-limitations: + +.. _hardware_limitations_adc_continuous: + +硬件限制 +^^^^^^^^^^^^^^^^^^^^ + +- 一个 ADC 单元一次只能运行一种操作模式,即连续模式或单次模式。:cpp:func:`adc_continuous_start` 提供了保护措施。 + +- 随机数生成器 (RNG) 以 ADC 为输入源。使用 ADC 连续转换模式驱动从 RNG 生成随机数时,随机性会减弱。 + +.. only:: esp32 or esp32s2 + + - Wi-Fi 也使用 ADC2,:cpp:func:`adc_continuous_start` 提供了 Wi-Fi 驱动和 ADC 连续转换模式驱动之间的保护。 + +.. only:: esp32 + + - ADC 连续转换模式驱动使用 I2S0 外设作为硬件 DMA FIFO。因此,如果 I2S0 已在使用中,:cpp:func:`adc_continuous_new_handle` 将返回 :c:macro:`ESP_ERR_NOT_FOUND`。 + + - ESP32 DevKitC:由于存在外部自动烧录电路,GPIO 0 不能用于 ADC 连续转换模式。 + + - ESP-WROVER-KIT:由于部分 GPIO 管脚可能已经用于其他目的,GPIO 0、2、4 和 15 不能用于 ADC 连续转换模式。 + +.. only:: esp32s2 + + - ADC 连续转换模式驱动使用 SPI3 外设作为硬件 DMA FIFO。因此,如果 SPI3 已在使用中,:cpp:func:`adc_continuous_new_handle` 将返回 :c:macro:`ESP_ERR_NOT_FOUND`。 + +.. only:: esp32c3 + + - 由于硬件限制,现已不再支持使用 ADC2 DMA 功能获取 ADC 转换结果。使用 ADC2 连续转换的结果可能不稳定,具体可参考 `ESP32-C3 系列芯片勘误表 `__。出于兼容性考虑,可以启用 :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3`,强制使用 ADC2。 + +.. only:: esp32s3 + + - 由于硬件限制,现已不再支持使用 ADC2 DMA 功能获取 ADC 转换结果。使用 ADC2 连续转换的结果可能不稳定,具体可参考 `ESP32-S3 系列芯片勘误表 `__。出于兼容性考虑,可以启用 :ref:`CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3`,强制使用 ADC2。 + + .. _adc-continuous-power-management: + +.. only:: not esp32s3 + + .. _adc-continuous-power-management: + +电源管理 +^^^^^^^^^^^^^^^^ + +启用电源管理,即启用 :ref:`CONFIG_PM_ENABLE` 时,系统在空闲状态下,可能会调整 APB 时钟频率,这可能会改变 ADC 连续转换的行为。 + +然而,通过获取类型为 :cpp:enumerator:`ESP_PM_APB_FREQ_MAX` 的电源管理锁,ADC 连续转换模式驱动可以阻止这种改变。调用 :cpp:func:`adc_continuous_start` 启动连续转换后即可获取该锁。同样,调用 :cpp:func:`adc_continuous_stop` 停止转换后将释放该锁。因此,必须确保 :cpp:func:`adc_continuous_start` 和 :cpp:func:`adc_continuous_stop` 成对出现,否则电源管理将失效。 + + +.. _adc-continuous-iram-safe: + +IRAM 安全 +^^^^^^^^^ + +ADC 连续转换模式驱动的所有 API 均非 IRAM 安全。禁用 cache 时,不应运行这类 API。启用 Kconfig 选项 :ref:`CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE` 可确保驱动的内部 ISR 处理程序为 IRAM 安全,此时即使禁用 cache,驱动仍然会将转换结果保存到其内部缓冲池中。 + + +.. _adc-continuous-thread-safety: + +线程安全 +^^^^^^^^^^^^^ + +ADC 连续转换模式驱动的 API 不一定线程安全,但驱动程序提供了共享硬件互斥,详情请参阅 :ref:`adc-continuous-hardware-limitations`。 + + +应用示例 +-------------------- + +* ADC 连续转换模式示例::example:`peripherals/adc/continuous_read`。 + + +API 参考 +------------- + +.. include-build-file:: inc/adc_continuous.inc