# MCPWM 捕获：测量输入脉冲

捕获是独立的 MCPWM 路径：捕获定时器为捕获通道 GPIO 的边沿打时间戳，不需要 PWM 定时器、操作器、比较器或生成器，适用于回波脉冲、转速计、霍尔传感器和 RC 接收机。

它适合"把外部世界发生的时刻带进芯片里"。当你关心的是脉宽、周期、相位差或转速，而不是输出 PWM，本页就是 MCPWM 的另一条主线入口。

## 测量脉宽

同时捕获两个边沿，保存上升沿时间戳，再用下降沿时间戳减去它。1 MHz 分辨率下，差值的单位直接是微秒。

    mcpwm_cap_timer_handle_t cap_timer = NULL;
    mcpwm_cap_channel_handle_t cap_channel = NULL;
    ESP_ERROR_CHECK(mcpwm_new_capture_timer(
        &(mcpwm_capture_timer_config_t) {
            .group_id = 0,
            .clk_src = MCPWM_CAPTURE_CLK_SRC_DEFAULT,
            .resolution_hz = 1000000,
        }, &cap_timer));
    ESP_ERROR_CHECK(mcpwm_new_capture_channel(cap_timer,
        &(mcpwm_capture_channel_config_t) {
            .gpio_num = 6,
            .prescale = 1,
            .flags.pos_edge = true,
            .flags.neg_edge = true,
        }, &cap_channel));

仅分配对象并不会开始测量。还需要使能通道并启动捕获定时器：

    ESP_ERROR_CHECK(mcpwm_capture_channel_enable(cap_channel));
    ESP_ERROR_CHECK(mcpwm_capture_timer_enable(cap_timer));
    ESP_ERROR_CHECK(mcpwm_capture_timer_start(cap_timer));

`mcpwm_capture_channel_enable()` 和 `mcpwm_capture_timer_enable()` 负责捕获所需的系统服务准备，二者都尚未开始测量。`mcpwm_capture_timer_start()` 才真正启动计数器，边沿开始被打上时间戳。

捕获到的边沿值通过回调送达应用，详见下一节。

捕获上升沿和下降沿时间戳，相减得到高电平脉宽。

两个配置结构体分开讲解：

### 捕获定时器配置

- `group_id` — 捕获定时器从哪个 MCPWM 组分配。

- `clk_src` — 捕获定时器的时钟源。`MCPWM_CAPTURE_CLK_SRC_DEFAULT` 适合绝大多数应用。当默认时钟源可能被关闭时需要显式选择其他源——例如低功耗场景下，若所选时钟被关断，捕获定时器会停止，时间戳就会失真。

- `resolution_hz` — 捕获定时器的 Tick 频率。一个 Tick 持续 `1 / resolution_hz` 秒，1 MHz 即微秒级分辨率，直接决定每次捕获时间戳的精度。

- `allow_pd` — 允许睡眠时关闭 MCPWM 电源域，在睡眠前后备份并恢复捕获寄存器，代价是额外占用 RAM。

### 捕获通道配置

- `gpio_num` — 承载输入信号的 GPIO。

- `prescale` — 捕获前对输入信号分频，有效输入频率为捕获时钟除以 `prescale`。提高它可扩展可测周期范围，但会降低时间分辨率。

- `pos_edge` 和 `neg_edge` — 捕获哪些边沿。示例同时捕获两个边沿，这正是脉宽测量所需的。

- `invert_cap_signal` — 捕获前反相输入信号，让引脚上的逻辑 `1` 在捕获外设看来是 `0`，反之亦然。

- `intr_priority` — 捕获回调使用的中断优先级。不设置（`0`）时由驱动选择较低优先级。

备注

捕获驱动会把 GPIO 配置为输入，但不会设置任何上拉或下拉电阻。如果输入信号并非主动驱动到两个电平，请调用 `gpio_set_pull_mode()` 选择上拉或下拉方向，让引脚空闲时保持在你期望的电平。

## 捕获事件回调

事件数据告知边沿类型和锁存计数值。真实应用中应将耗时工作留给任务。

    static uint32_t rise_tick;
    static bool IRAM_ATTR on_capture(mcpwm_cap_channel_handle_t channel,
                                     const mcpwm_capture_event_data_t *edata,
                                     void *user_data)
    {
        if (edata->cap_edge == MCPWM_CAP_EDGE_POS) {
            rise_tick = edata->cap_value;
        } else {
            uint32_t width_ticks = edata->cap_value - rise_tick;
            // 使用 ISR 安全方式将 width_ticks 通知任务
        }
        return false;
    }

    ESP_ERROR_CHECK(mcpwm_capture_channel_register_event_callbacks(cap_channel,
        &(mcpwm_capture_event_callbacks_t) { .on_cap = on_capture }, NULL));

通过 `mcpwm_capture_timer_get_resolution()` 获取实际分辨率后，再将 Tick 转换为时间。在捕获时钟与 MCPWM 组时钟共享的芯片上，应保持一致的请求分辨率顺序创建捕获和 PWM 定时器。

若要测转速或周期，可记录两次同类边沿（例如两次上升沿）的时间戳，相减得到周期 Tick 数，再结合实际分辨率换算为频率或转速。

## 实用控制

`mcpwm_capture_channel_trigger_soft_catch()` 生成软件捕获事件，常用于测试，也可借此把重要软件事件的发生时刻落到捕获时间轴上，与硬件边沿时间戳对齐；该调用同样会触发回调。`mcpwm_capture_get_latched_value()` 在不注册回调的情况下也能读取最新时间戳。

`mcpwm_capture_timer_stop()` 使计数器停止，`mcpwm_capture_channel_disable()` 可关闭单个输入，停止定时器则关闭整个测量引擎。删除对象前，先调用 `mcpwm_capture_timer_disable()` 撤销 `mcpwm_capture_timer_enable()` 做的准备工作。

## 捕获定时器同步

捕获定时器默认自由运行，计数值的“零点”是任意的，时间戳只能互相比较。同步让运行中的捕获定时器在同步边沿到来时加载一个指定计数值，从而把时间戳对应到有意义的参考系。

最常见的场景是让捕获定时器与 PWM 定时器对齐相位：以 PWM 定时器每周期零（TEZ）发出的同步为源、计数值设为 0，捕获定时器每个周期归零，捕获时间戳就直接表示周期内的相位。这在电机控制或功率变换中尤为重要——霍尔、编码器或电流检测的反馈边沿只有落在 PWM 周期的具体相位才有意义。

同步源与 PWM 定时器共用（GPIO、软件、定时器三种，须与捕获定时器同组），接收端用 `mcpwm_capture_timer_set_phase_on_sync()` 配置：

    ESP_ERROR_CHECK(mcpwm_capture_timer_set_phase_on_sync(cap_timer,
        &(mcpwm_capture_timer_sync_phase_config_t) {
            .sync_src = timer_a_sync,  // 由 mcpwm_new_timer_sync_src() 创建的同步源
            .count_value = 0,
            .direction = MCPWM_TIMER_DIRECTION_UP,
        }));

- `sync_src` — 同步源，设为 `NULL` 可解除同步。

- `count_value` — 同步边沿到达时加载的计数值。

- `direction` — 加载后的计数方向，捕获定时器只向上计数，固定为 `MCPWM_TIMER_DIRECTION_UP`。

软件同步与 GPIO 同步源也可让捕获定时器建立已知起点或对齐外部参考，同步源的创建与其余用法详见 同步。

## API 参考

### MCPWM 捕获驱动函数

#### Header File

- components/esp_driver_mcpwm/include/driver/mcpwm_cap.h

- This header file can be included with:

  >     #include "driver/mcpwm_cap.h"

- This header file is a part of the API provided by the `esp_driver_mcpwm` component. To declare that your component depends on `esp_driver_mcpwm`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_mcpwm

  > or

  >     PRIV_REQUIRES esp_driver_mcpwm

#### Functions

esp_err_t mcpwm_new_capture_timer(const mcpwm_capture_timer_config_t *config, mcpwm_cap_timer_handle_t *ret_cap_timer)

  Create MCPWM capture timer.

  参数:

    - config -- [in] MCPWM capture timer configuration

    - ret_cap_timer -- [out] Returned MCPWM capture timer handle

  返回:

    - ESP_OK: Create MCPWM capture timer successfully

    - ESP_ERR_INVALID_ARG: Create MCPWM capture timer failed because of invalid argument

    - ESP_ERR_NO_MEM: Create MCPWM capture timer failed because out of memory

    - ESP_ERR_NOT_FOUND: Create MCPWM capture timer failed because can't find free resource

    - ESP_FAIL: Create MCPWM capture timer failed because of other error

esp_err_t mcpwm_del_capture_timer(mcpwm_cap_timer_handle_t cap_timer)

  Delete MCPWM capture timer.

  参数:

    cap_timer -- [in] MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`

  返回:

    - ESP_OK: Delete MCPWM capture timer successfully

    - ESP_ERR_INVALID_ARG: Delete MCPWM capture timer failed because of invalid argument

    - ESP_FAIL: Delete MCPWM capture timer failed because of other error

esp_err_t mcpwm_capture_timer_enable(mcpwm_cap_timer_handle_t cap_timer)

  Enable MCPWM capture timer.

  参数:

    cap_timer -- [in] MCPWM capture timer handle, allocated by `mcpwm_new_capture_timer()`

  返回:

    - ESP_OK: Enable MCPWM capture timer successfully

    - ESP_ERR_INVALID_ARG: Enable MCPWM capture timer failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Enable MCPWM capture timer failed because timer is enabled already

    - ESP_FAIL: Enable MCPWM capture timer failed because of other error

esp_err_t mcpwm_capture_timer_disable(mcpwm_cap_timer_handle_t cap_timer)

  Disable MCPWM capture timer.

  参数:

    cap_timer -- [in] MCPWM capture timer handle, allocated by `mcpwm_new_capture_timer()`

  返回:

    - ESP_OK: Disable MCPWM capture timer successfully

    - ESP_ERR_INVALID_ARG: Disable MCPWM capture timer failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Disable MCPWM capture timer failed because timer is disabled already

    - ESP_FAIL: Disable MCPWM capture timer failed because of other error

esp_err_t mcpwm_capture_timer_start(mcpwm_cap_timer_handle_t cap_timer)

  Start MCPWM capture timer.

  参数:

    cap_timer -- [in] MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`

  返回:

    - ESP_OK: Start MCPWM capture timer successfully

    - ESP_ERR_INVALID_ARG: Start MCPWM capture timer failed because of invalid argument

    - ESP_FAIL: Start MCPWM capture timer failed because of other error

esp_err_t mcpwm_capture_timer_stop(mcpwm_cap_timer_handle_t cap_timer)

  Stop MCPWM capture timer.

  参数:

    cap_timer -- [in] MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`

  返回:

    - ESP_OK: Stop MCPWM capture timer successfully

    - ESP_ERR_INVALID_ARG: Stop MCPWM capture timer failed because of invalid argument

    - ESP_FAIL: Stop MCPWM capture timer failed because of other error

esp_err_t mcpwm_capture_timer_get_resolution(mcpwm_cap_timer_handle_t cap_timer, uint32_t *out_resolution)

  Get MCPWM capture timer resolution, in Hz.

  参数:

    - cap_timer -- [in] MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`

    - out_resolution -- [out] Returned capture timer resolution, in Hz

  返回:

    - ESP_OK: Get capture timer resolution successfully

    - ESP_ERR_INVALID_ARG: Get capture timer resolution failed because of invalid argument

    - ESP_FAIL: Get capture timer resolution failed because of other error

esp_err_t mcpwm_capture_timer_set_phase_on_sync(mcpwm_cap_timer_handle_t cap_timer, const mcpwm_capture_timer_sync_phase_config_t *config)

  Set sync phase for MCPWM capture timer.

  参数:

    - cap_timer -- [in] MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`

    - config -- [in] MCPWM capture timer sync phase configuration

  返回:

    - ESP_OK: Set sync phase for MCPWM capture timer successfully

    - ESP_ERR_INVALID_ARG: Set sync phase for MCPWM capture timer failed because of invalid argument

    - ESP_FAIL: Set sync phase for MCPWM capture timer failed because of other error

esp_err_t mcpwm_new_capture_channel(mcpwm_cap_timer_handle_t cap_timer, const mcpwm_capture_channel_config_t *config, mcpwm_cap_channel_handle_t *ret_cap_channel)

  Create MCPWM capture channel.

  备注

  The created capture channel won't be enabled until calling `mcpwm_capture_channel_enable`

  参数:

    - cap_timer -- [in] MCPWM capture timer, allocated by `mcpwm_new_capture_timer()`, will be connected to the new capture channel

    - config -- [in] MCPWM capture channel configuration

    - ret_cap_channel -- [out] Returned MCPWM capture channel

  返回:

    - ESP_OK: Create MCPWM capture channel successfully

    - ESP_ERR_INVALID_ARG: Create MCPWM capture channel failed because of invalid argument

    - ESP_ERR_NO_MEM: Create MCPWM capture channel failed because out of memory

    - ESP_ERR_NOT_FOUND: Create MCPWM capture channel failed because can't find free resource

    - ESP_FAIL: Create MCPWM capture channel failed because of other error

esp_err_t mcpwm_del_capture_channel(mcpwm_cap_channel_handle_t cap_channel)

  Delete MCPWM capture channel.

  参数:

    cap_channel -- [in] MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`

  返回:

    - ESP_OK: Delete MCPWM capture channel successfully

    - ESP_ERR_INVALID_ARG: Delete MCPWM capture channel failed because of invalid argument

    - ESP_FAIL: Delete MCPWM capture channel failed because of other error

esp_err_t mcpwm_capture_channel_enable(mcpwm_cap_channel_handle_t cap_channel)

  Enable MCPWM capture channel.

  备注

  This function will transit the channel state from init to enable.

  备注

  This function will enable the interrupt service, if it's lazy installed in `mcpwm_capture_channel_register_event_callbacks()`.

  参数:

    cap_channel -- [in] MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`

  返回:

    - ESP_OK: Enable MCPWM capture channel successfully

    - ESP_ERR_INVALID_ARG: Enable MCPWM capture channel failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Enable MCPWM capture channel failed because the channel is already enabled

    - ESP_FAIL: Enable MCPWM capture channel failed because of other error

esp_err_t mcpwm_capture_channel_disable(mcpwm_cap_channel_handle_t cap_channel)

  Disable MCPWM capture channel.

  参数:

    cap_channel -- [in] MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`

  返回:

    - ESP_OK: Disable MCPWM capture channel successfully

    - ESP_ERR_INVALID_ARG: Disable MCPWM capture channel failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Disable MCPWM capture channel failed because the channel is not enabled yet

    - ESP_FAIL: Disable MCPWM capture channel failed because of other error

esp_err_t mcpwm_capture_channel_register_event_callbacks(mcpwm_cap_channel_handle_t cap_channel, const mcpwm_capture_event_callbacks_t *cbs, void *user_data)

  Set event callbacks for MCPWM capture channel.

  备注

  The first call to this function needs to be before the call to `mcpwm_capture_channel_enable`

  备注

  User can deregister a previously registered callback by calling this function and setting the callback member in the `cbs` structure to NULL.

  参数:

    - cap_channel -- [in] MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`

    - cbs -- [in] Group of callback functions

    - user_data -- [in] User data, which will be passed to callback functions directly

  返回:

    - ESP_OK: Set event callbacks successfully

    - ESP_ERR_INVALID_ARG: Set event callbacks failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Set event callbacks failed because the channel is not in init state

    - ESP_FAIL: Set event callbacks failed because of other error

esp_err_t mcpwm_capture_channel_trigger_soft_catch(mcpwm_cap_channel_handle_t cap_channel)

  Trigger a catch by software.

  参数:

    cap_channel -- [in] MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`

  返回:

    - ESP_OK: Trigger software catch successfully

    - ESP_ERR_INVALID_ARG: Trigger software catch failed because of invalid argument

    - ESP_ERR_INVALID_STATE: Trigger software catch failed because the channel is not enabled yet

    - ESP_FAIL: Trigger software catch failed because of other error

esp_err_t mcpwm_capture_get_latched_value(mcpwm_cap_channel_handle_t cap_channel, uint32_t *value)

  Get the last captured value of the MCPWM capture channel.

  备注

  To convert the count value to a time, user can use `mcpwm_capture_timer_get_resolution` to get the resolution of the capture timer.

  参数:

    - cap_channel -- [in] MCPWM capture channel handle, allocated by `mcpwm_new_capture_channel()`

    - value -- [out] Returned capture value

  返回:

    - ESP_OK: Get capture value successfully

    - ESP_ERR_INVALID_ARG: Get capture value failed because of invalid argument

    - ESP_FAIL: Get capture value failed because of other error

#### Structures

struct mcpwm_capture_timer_config_t

  MCPWM capture timer configuration structure.

  Public Members

  int group_id

    Specify from which group to allocate the capture timer

  mcpwm_capture_clock_source_t clk_src

    MCPWM capture timer clock source

  uint32_t resolution_hz

    Resolution of capture timer

  struct mcpwm_capture_timer_config_t::extra_mcpwm_capture_timer_flags flags

    Extra configuration flags for timer

  struct extra_mcpwm_capture_timer_flags

    Extra configuration flags for capture timer.

    Public Members

    uint32_t allow_pd

      Set to allow power down. When this flag set, the driver will backup/restore the MCPWM registers before/after entering/exist sleep mode. By this approach, the system can power off MCPWM's power domain. This can save power, but at the expense of more RAM being consumed.

struct mcpwm_capture_timer_sync_phase_config_t

  MCPWM Capture timer sync phase configuration.

  Public Members

  mcpwm_sync_handle_t sync_src

    The sync event source

  uint32_t count_value

    The count value that should lock to upon sync event

  mcpwm_timer_direction_t direction

    The count direction that should lock to upon sync event

struct mcpwm_capture_channel_config_t

  MCPWM capture channel configuration structure.

  Public Members

  int gpio_num

    GPIO used capturing input signal

  int intr_priority

    MCPWM capture interrupt priority, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3)

  uint32_t prescale

    Prescale of input signal, effective frequency = cap_input_clk/prescale

  struct mcpwm_capture_channel_config_t::extra_capture_channel_flags flags

    Extra configuration flags for capture channel

  struct extra_capture_channel_flags

    Extra configuration flags for capture channel.

    Public Members

    uint32_t pos_edge

      Whether to capture on positive edge

    uint32_t neg_edge

      Whether to capture on negative edge

    uint32_t invert_cap_signal

      Invert the input capture signal

struct mcpwm_capture_event_callbacks_t

  Group of supported MCPWM capture event callbacks.

  备注

  The callbacks are all running under ISR environment

  Public Members

  mcpwm_capture_event_cb_t on_cap

    Callback function that would be invoked when capture event occurred

此文档对您有帮助吗？

- 反馈已收到，谢谢！
- 如果您有其他意见，欢迎填写乐鑫文档反馈表。

- 我们重视您的反馈。
- 您可以填写乐鑫文档反馈表告诉我们如何改进该文档。