mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
Merge branch 'refactor/driver_dac_common_v6.1' into 'release/v6.1'
refactor(dac): improve the DAC driver (v6.1) See merge request espressif/esp-idf!50237
This commit is contained in:
@@ -44,6 +44,43 @@ DAC channels can convert digital data continuously via the DMA. There are three
|
||||
2. Cyclical writing: A piece of data can be converted cyclically without blocking, and no more operation is needed after the data are loaded into the DMA buffer. But note that the inputted buffer size is limited by the number of descriptors and the DMA buffer size. It is usually used to transport short signals that need to be repeated, e.g., a sine wave. To achieve cyclical writing, call :cpp:func:`dac_continuous_write_cyclically` after the DAC continuous mode is enabled. Refer to :example:`peripherals/dac/dac_continuous/signal_generator` for examples.
|
||||
3. Asynchronous writing: Data can be transmitted asynchronously based on the event callback. :cpp:member:`dac_event_callbacks_t::on_convert_done` must be registered to use asynchronous mode. Users can get the :cpp:type:`dac_event_data_t` in the callback which contains the DMA buffer address and length, allowing them to load the data into the buffer directly. To use the asynchronous writing, call :cpp:func:`dac_continuous_register_event_callback` to register the :cpp:member:`dac_event_callbacks_t::on_convert_done` before enabling, and then :cpp:func:`dac_continuous_start_async_writing` to start the asynchronous writing. Note that once the asynchronous writing is started, the callback function will be triggered continuously. Call :cpp:func:`dac_continuous_write_asynchronously` to load the data either in a separate task or in the callback directly. Refer to :example:`peripherals/dac/dac_continuous/dac_audio` for examples.
|
||||
|
||||
The following diagram illustrates the life cycle of the DAC continuous driver and the state transitions associated with each API:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
flowchart TD
|
||||
NC(["Idle (Initial State)"]) -->|"new_channels()"| REG[Registered]
|
||||
REG -->|"del_channels()"| NC
|
||||
REG -->|"enable()"| EN[Enabled]
|
||||
EN -->|"disable()"| REG
|
||||
|
||||
EN -->|"start_async_writing()"| ASYNC[Async Writing]
|
||||
ASYNC -->|"stop_async_writing()"| EN
|
||||
|
||||
EN -->|"write_cyclically()"| CYCLIC[Cyclic Writing]
|
||||
CYCLIC -->|"stop_cyclically()"| EN
|
||||
|
||||
EN -->|"write()"| SYNC[Sync Writing]
|
||||
SYNC -->|"write()"| SYNC
|
||||
SYNC -->|"on transmission complete"| EN
|
||||
|
||||
subgraph REG_APIS [Registered State APIs]
|
||||
REGCB["register_event_callbacks()"]
|
||||
end
|
||||
|
||||
subgraph ASYNC_APIS [Async Writing State APIs]
|
||||
AWRITE["write_asynchronously()"]
|
||||
end
|
||||
|
||||
REG -. can call .-> REGCB
|
||||
ASYNC -. when receiving a callback .-> AWRITE
|
||||
|
||||
.. note::
|
||||
|
||||
- For brevity, the prefix ``dac_continuous_`` is omitted from all function names in the diagram.
|
||||
- For backward compatibility, calling :cpp:func:`dac_continuous_stop_cyclically` to exit cyclic writing is optional — any API that transitions away from the Enabled state will automatically stop an ongoing cyclic conversion. However, explicitly calling :cpp:func:`dac_continuous_stop_cyclically` is recommended.
|
||||
- Sync writing requires no explicit exit — any API that transitions away from the Enabled state will automatically stop the ongoing sync writing immediately (the data not yet converted is discarded).
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
On ESP32, the DAC digital controller can be connected internally to the I2S0 and use its DMA for continuous conversion. Although the DAC only needs 8-bit data for conversion, it has to be the left-shifted 8 bits (i.e., the high 8 bits in a 16-bit slot) to satisfy the I2S communication format. By default, the driver helps to expand the data to 16-bit wide automatically. To expand manually, please disable :ref:`CONFIG_DAC_DMA_AUTO_16BIT_ALIGN` in the menuconfig.
|
||||
|
||||
@@ -44,6 +44,43 @@ DAC 通道可以通过 DMA 连续转换数字信号,这种模式下有三种
|
||||
2. 循环写入:在数据载入 DMA 缓冲区后,缓冲区中的数据将以非阻塞的方式被循环转换。但要注意,输入的缓冲区大小受 DMA 描述符数量和 DMA 缓冲区大小的限制。该模式通常用于传输如正弦波等需要重复的短信号。为了启用循环写入,需要在启用 DAC 连续模式后调用 :cpp:func:`dac_continuous_write_cyclically`。示例可参考 :example:`peripherals/dac/dac_continuous/signal_generator`。
|
||||
3. 异步写入。可根据事件回调异步传输数据。需要调用 :cpp:member:`dac_event_callbacks_t::on_convert_done` 以启用异步模式。用户在回调中可得到 :cpp:type:`dac_event_data_t`,其中包含 DMA 缓冲区的地址和长度,即允许用户直接将数据载入 DMA 缓冲区。启用异步写入前需要调用 :cpp:func:`dac_continuous_register_event_callback`、 :cpp:member:`dac_event_callbacks_t::on_convert_done` 和 :cpp:func:`dac_continuous_start_async_writing`。注意,异步写入一旦开始,回调函数将被持续触发。调用 :cpp:func:`dac_continuous_write_asynchronously` 可以在某个单独任务中或直接在回调函数中载入数据。示例可参考 :example:`peripherals/dac/dac_continuous/dac_audio`。
|
||||
|
||||
下图展示了连续模式驱动的生命周期,以及各 API 对应的状态转移:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
flowchart TD
|
||||
NC([空闲(初始状态)]) -->|"new_channels()"| REG[已注册]
|
||||
REG -->|"del_channels()"| NC
|
||||
REG -->|"enable()"| EN[已启用]
|
||||
EN -->|"disable()"| REG
|
||||
|
||||
EN -->|"start_async_writing()"| ASYNC[异步写入]
|
||||
ASYNC -->|"stop_async_writing()"| EN
|
||||
|
||||
EN -->|"write_cyclically()"| CYCLIC[循环写入]
|
||||
CYCLIC -->|"stop_cyclically()"| EN
|
||||
|
||||
EN -->|"write()"| SYNC[同步写入]
|
||||
SYNC -->|"write()"| SYNC
|
||||
SYNC -->|"传输完成后"| EN
|
||||
|
||||
subgraph REG_APIS [已注册状态可用 API]
|
||||
REGCB["register_event_callbacks()"]
|
||||
end
|
||||
|
||||
subgraph ASYNC_APIS [异步写入可用 API]
|
||||
AWRITE["write_asynchronously()"]
|
||||
end
|
||||
|
||||
REG -. 可调用 .-> REGCB
|
||||
ASYNC -. 收到回调通知后调用 .-> AWRITE
|
||||
|
||||
.. note::
|
||||
|
||||
- 为了简洁,图中省略了各函数名的前缀 ``dac_continuous_``。
|
||||
- 为了向后兼容,循环写入的退出函数 :cpp:func:`dac_continuous_stop_cyclically` 是可选的,所有从已启用状态出发的函数会自动检查并停止任何正在进行的循环写入。推荐显式调用 :cpp:func:`dac_continuous_stop_cyclically` 来停止循环写入。
|
||||
- 同步写入无需显式退出,所有从已启用状态出发的函数会自动立即停止任何正在进行的同步写入(尚未转换的数据将被丢弃)。
|
||||
|
||||
.. only:: esp32
|
||||
|
||||
在 ESP32 上,DAC 的数字控制器可以在内部连接到 I2S0,并借用其 DMA 进行连续转换。虽然 DAC 转换仅需 8 位数据,但它必须是左移的 8 位(即 16 位中的高 8 位),以满足 I2S 通信格式。默认状态下驱动程序将自动扩充数据至 16 位,如需手动扩充,请在 menuconfig 中禁用 :ref:`CONFIG_DAC_DMA_AUTO_16BIT_ALIGN`。
|
||||
|
||||
Reference in New Issue
Block a user