# 电机控制脉宽调制器 (MCPWM)

[English]

## 从这里开始

MCPWM 将计数器转换为时序精确的输出边沿。当 LEDC 的简单 PWM 已无法满足需求时，可使用 MCPWM：电机桥需要互补输出和死区，逆变器需要同步相位，传感器则需要精确测量脉宽。

最小可用的 MCPWM 设计由四个对象构成：定时器 提供时间基准，操作器 管理波形资源，比较器 决定边沿位置，生成器 驱动 GPIO。其他模块均在此基础上扩展。

## 构建一路 PWM 输出

初次生成 PWM 输出时，请按下图从左至右创建对象。主线上各阶段按角色配色：时间基准（蓝色）、操作器核心（紫色）、波形配置（青色）、启用与输出（绿色）。琥珀色节点为基础输出正常后按需添加的扩展，红色节点为安全制动。只有在所有输出动作均已配置完成后，才启动定时器。

            flowchart LR
        T1["1. 创建定时器<br/>mcpwm_new_timer"]:::time
        O1["2. 创建操作器<br/>mcpwm_new_operator"]:::core
        LINK["3. 连接时间基准<br/>mcpwm_operator_connect_timer"]:::core
        C1["4. 创建比较器<br/>mcpwm_new_comparator"]:::wave
        G1["5. 创建生成器<br/>mcpwm_new_generator"]:::wave
        A1["6. 描述边沿<br/>mcpwm_generator_set_action_on_*_event"]:::wave
        RUN["7. 启用并启动<br/>mcpwm_timer_enable<br/>mcpwm_timer_start_stop"]:::run
        PIN["GPIO 输出 PWM"]:::output

        T1 --> O1 --> LINK --> C1 --> G1 --> A1 --> RUN --> PIN

        DT["死区<br/>mcpwm_generator_set_dead_time"]:::optional
        BR["故障与制动<br/>mcpwm_new_*_fault<br/>mcpwm_operator_set_brake_on_fault"]:::safety
        SY["相位同步<br/>mcpwm_new_*_sync_src<br/>mcpwm_timer_set_phase_on_sync"]:::optional
        CA["载波调制<br/>mcpwm_operator_apply_carrier"]:::optional

        A1 -. 扩展 .-> DT
        O1 -. 保护 .-> BR
        T1 -. 对齐 .-> SY
        O1 -. 调制 .-> CA

        classDef time fill:#dbeafe,stroke:#2563eb,color:#172554
        classDef core fill:#ede9fe,stroke:#7c3aed,color:#2e1065
        classDef wave fill:#cffafe,stroke:#0891b2,color:#164e63
        classDef run fill:#dcfce7,stroke:#16a34a,color:#14532d
        classDef output fill:#bbf7d0,stroke:#15803d,color:#14532d
        classDef optional fill:#fef3c7,stroke:#d97706,color:#78350f
        classDef safety fill:#fee2e2,stroke:#dc2626,color:#7f1d1d

下面这段代码创建一路 20 kHz、30% 占空比的 PWM 输出，可作为阅读后续各页前的整体参考。它展示了对象的创建顺序，也说明了运行时最常改动的其实是比较器，而不是重新配置整条链路。

    mcpwm_timer_handle_t timer = NULL;
    mcpwm_oper_handle_t oper = NULL;
    mcpwm_cmpr_handle_t comparator = NULL;
    mcpwm_gen_handle_t generator = NULL;

    // 1 MHz → 1 tick = 1 µs
    // 50 ticks → 50 µs 周期 → 20 kHz
    ESP_ERROR_CHECK(mcpwm_new_timer(
        &(mcpwm_timer_config_t) {
            .group_id = 0,
            .clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
            .resolution_hz = 1000000,
            .period_ticks = 50,
            .count_mode = MCPWM_TIMER_COUNT_MODE_UP,
        },
        &timer));

    ESP_ERROR_CHECK(mcpwm_new_operator(
        &(mcpwm_operator_config_t) {
            .group_id = 0,
        },
        &oper));
    ESP_ERROR_CHECK(mcpwm_operator_connect_timer(oper, timer));

    ESP_ERROR_CHECK(mcpwm_new_comparator(
        oper,
        &(mcpwm_comparator_config_t) {
            .flags.update_cmp_on_tez = true,
        },
        &comparator));
    // 15 / 50 = 30% 占空比
    ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparator, 15));

    ESP_ERROR_CHECK(mcpwm_new_generator(
        oper,
        &(mcpwm_generator_config_t) {
            .gen_gpio_num = 18,
        },
        &generator));

    // 定时器归零 → 输出 HIGH；比较器匹配 → 输出 LOW
    ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(
        generator,
        MCPWM_GEN_TIMER_EVENT_ACTION(
            MCPWM_TIMER_DIRECTION_UP,
            MCPWM_TIMER_EVENT_EMPTY,
            MCPWM_GEN_ACTION_HIGH)));
    ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(
        generator,
        MCPWM_GEN_COMPARE_EVENT_ACTION(
            MCPWM_TIMER_DIRECTION_UP,
            comparator,
            MCPWM_GEN_ACTION_LOW)));

    ESP_ERROR_CHECK(mcpwm_timer_enable(timer));
    ESP_ERROR_CHECK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_START_NO_STOP));

    // 运行时修改比较值即可调整占空比，无需重建生成器动作。
    // 25 / 50 = 50% 占空比
    ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparator, 25));

定时器的 `resolution_hz` 和 `period_ticks` 确定时序刻度；比较器的 `compare_value` 在该刻度中选择边沿位置；生成器动作 API 决定在定时器边界或比较器越过阈值时输出何种电平。这种分工也便于调参：改变定时器可调整频率，改变比较器可调整占空比或边沿位置，改变生成器动作可调整极性或波形形状。

波形配置完成后，调用 `mcpwm_timer_enable()` 和 `mcpwm_timer_start_stop()`。运行时应通过 `mcpwm_comparator_set_compare_value()` 更新比较器，而不是重新配置生成器动作。仅在应用需要时添加对应扩展：半桥使用死区，安全路径使用故障与制动，相位对齐使用同步，隔离式驱动使用载波。

## 功能地图

目标 | 先看哪些页 | 关键 API | 典型应用
--- | --- | --- | ---
输出单路 PWM | 定时器 -> 操作器 -> 比较器 生成器 | `mcpwm_new_timer()` `mcpwm_new_comparator()` `mcpwm_generator_set_action_on_*_event` | 舵机、调光、基础功率控制
输出互补半桥 PWM | 生成器 中的死区小节 + 故障 | `mcpwm_generator_set_dead_time()` `mcpwm_operator_set_brake_on_fault()` | 半桥、逆变桥臂
多路同频对齐或移相 | 同步 | `mcpwm_timer_set_phase_on_sync()` `mcpwm_new_timer_sync_src()` | 多相电机、并联变换器
测量输入脉宽或周期 | 捕获 | `mcpwm_new_capture_timer()` `mcpwm_capture_channel_register_event_callbacks()` | HC-SR04、转速计、RC 输入
外设间硬件联动 | ETM | `mcpwm_timer_new_etm_event()` `mcpwm_new_event_comparator()` | ADC 触发、跨外设定时链路

本指南中每个页面介绍一个 MCPWM 模块：

- MCPWM 定时器：设定频率
- MCPWM 操作器：组装输出级
- MCPWM 比较器：将比例转换为边沿
- MCPWM 生成器：生成 PWM 波形
- MCPWM 故障：将保护信号接入 MCPWM
- MCPWM 同步：对齐 PWM 相位
- MCPWM 捕获：测量输入脉冲
- MCPWM ETM：外设间的硬件级联动
- MCPWM 高级主题

## 资源与生命周期

所有对象都属于一个 MCPWM 组。连接的定时器与操作器必须位于同一组；GPIO 故障源和 GPIO 同步源也只能在本组中使用。硬件资源有限，创建时可能返回 `ESP_ERR_NOT_FOUND`。

每个对象都由 `mcpwm_new_*()` 工厂函数创建并返回一个不透明句柄，由对应的 `mcpwm_del_*()` 函数释放，例如 `mcpwm_new_timer()` 与 `mcpwm_del_timer()`。先创建父对象，再创建子对象；释放时按相反顺序执行：先删除生成器/比较器，再删除操作器，最后删除定时器。删除定时器前必须禁用它；删除捕获定时器前必须删除其通道。

组时钟分频器由定时器共享，部分芯片的捕获定时器也共享它。按目标分辨率单调顺序（从高到低或从低到高）创建对象，可避免分频冲突。详见 高级主题。

## 术语速查

- TEZ： Timer equals zero，定时器计数等于零时触发的事件。

- TEP： Timer equals peak，定时器计数达到峰值时触发的事件。

- 定时器（Timer）： MCPWM 的时间基准，决定频率和 Tick 刻度。

- 操作器（Operator）： 连接定时器与输出逻辑的容器，管理比较器、生成器、制动、死区和载波。

- 比较器（Comparator）： 当计数达到阈值时发出事件，常用于决定边沿位置和占空比。

- 生成器（Generator）： 根据定时器/比较器/故障/同步事件输出 GPIO 电平。

- 死区（Dead Time）： 在半桥上下管切换之间插入的非重叠时间，避免直通。

- 故障（Fault）： 进入保护路径的异常源，可来自 GPIO 或软件。

- 制动（Brake）： 故障触发后的输出安全策略。

- CBC： Cycle By Cycle，故障有效时制动，清除后在周期边界自动恢复。

- OST： One Shot，一次制动后保持锁存，需软件显式恢复。

- 同步（Sync）： 在同步边沿把定时器加载到指定计数值和方向，以实现对齐或移相。

- 捕获（Capture）： 对输入边沿打时间戳，用于测脉宽、周期或转速。

## 应用示例

- peripherals/mcpwm/mcpwm_servo_control：RC 舵机的单路 PWM。

- peripherals/mcpwm/mcpwm_bdc_speed_control：有刷直流电机及速度反馈。

- peripherals/mcpwm/mcpwm_bldc_hall_control：使用霍尔传感器反馈进行 BLDC 换相。

- peripherals/mcpwm/mcpwm_capture_hc_sr04：使用 HC-SR04 测量脉宽。

- peripherals/mcpwm/mcpwm_sync：GPIO、定时器和软件同步。

- peripherals/mcpwm/mcpwm_foc_svpwm_open_loop：开环 FOC 的三对互补 PWM。

## API 参考

### 通用类型

#### Header File

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

- This header file can be included with:

  >     #include "driver/mcpwm_types.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

#### Structures

struct mcpwm_timer_event_data_t

  MCPWM timer event data.

  Public Members

  uint32_t count_value

    MCPWM timer count value

  mcpwm_timer_direction_t direction

    MCPWM timer count direction

struct mcpwm_brake_event_data_t

  MCPWM brake event data.

struct mcpwm_fault_event_data_t

  MCPWM fault event data.

struct mcpwm_compare_event_data_t

  MCPWM compare event data.

  Public Members

  uint32_t compare_ticks

    Compare value

  mcpwm_timer_direction_t direction

    Count direction

struct mcpwm_capture_event_data_t

  MCPWM capture event data.

  Public Members

  uint32_t cap_value

    Captured value

  mcpwm_capture_edge_t cap_edge

    Capture edge

#### Type Definitions

typedef struct mcpwm_timer_t *mcpwm_timer_handle_t

  Type of MCPWM timer handle.

typedef struct mcpwm_oper_t *mcpwm_oper_handle_t

  Type of MCPWM operator handle.

typedef struct mcpwm_cmpr_t *mcpwm_cmpr_handle_t

  Type of MCPWM comparator handle.

typedef struct mcpwm_gen_t *mcpwm_gen_handle_t

  Type of MCPWM generator handle.

typedef struct mcpwm_fault_t *mcpwm_fault_handle_t

  Type of MCPWM fault handle.

typedef struct mcpwm_sync_t *mcpwm_sync_handle_t

  Type of MCPWM sync handle.

typedef struct mcpwm_cap_timer_t *mcpwm_cap_timer_handle_t

  Type of MCPWM capture timer handle.

typedef struct mcpwm_cap_channel_t *mcpwm_cap_channel_handle_t

  Type of MCPWM capture channel handle.

typedef bool (*mcpwm_timer_event_cb_t)(mcpwm_timer_handle_t timer, const mcpwm_timer_event_data_t *edata, void *user_ctx)

  MCPWM timer event callback function.

  Param timer:

    [in] MCPWM timer handle

  Param edata:

    [in] MCPWM timer event data, fed by driver

  Param user_ctx:

    [in] User data, set in `mcpwm_timer_register_event_callbacks()`

  Return:

    Whether a high priority task has been waken up by this function

typedef bool (*mcpwm_brake_event_cb_t)(mcpwm_oper_handle_t oper, const mcpwm_brake_event_data_t *edata, void *user_ctx)

  MCPWM operator brake event callback function.

  Param oper:

    [in] MCPWM operator handle

  Param edata:

    [in] MCPWM brake event data, fed by driver

  Param user_ctx:

    [in] User data, set in `mcpwm_operator_register_event_callbacks()`

  Return:

    Whether a high priority task has been waken up by this function

typedef bool (*mcpwm_fault_event_cb_t)(mcpwm_fault_handle_t fault, const mcpwm_fault_event_data_t *edata, void *user_ctx)

  MCPWM fault event callback function.

  Param fault:

    MCPWM fault handle

  Param edata:

    MCPWM fault event data, fed by driver

  Param user_ctx:

    User data, set in `mcpwm_fault_register_event_callbacks()`

  Return:

    whether a task switch is needed after the callback returns

typedef bool (*mcpwm_compare_event_cb_t)(mcpwm_cmpr_handle_t comparator, const mcpwm_compare_event_data_t *edata, void *user_ctx)

  MCPWM comparator event callback function.

  Param comparator:

    MCPWM comparator handle

  Param edata:

    MCPWM comparator event data, fed by driver

  Param user_ctx:

    User data, set in `mcpwm_comparator_register_event_callbacks()`

  Return:

    Whether a high priority task has been waken up by this function

typedef bool (*mcpwm_capture_event_cb_t)(mcpwm_cap_channel_handle_t cap_channel, const mcpwm_capture_event_data_t *edata, void *user_ctx)

  MCPWM capture event callback function.

  Param cap_channel:

    MCPWM capture channel handle

  Param edata:

    MCPWM capture event data, fed by driver

  Param user_ctx:

    User data, set in `mcpwm_capture_channel_register_event_callbacks()`

  Return:

    Whether a high priority task has been waken up by this function

#### Header File

- components/esp_hal_mcpwm/include/hal/mcpwm_types.h

- This header file can be included with:

  >     #include "hal/mcpwm_types.h"

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

  >     REQUIRES esp_hal_mcpwm

  > or

  >     PRIV_REQUIRES esp_hal_mcpwm

#### Type Definitions

typedef soc_periph_mcpwm_timer_clk_src_t mcpwm_timer_clock_source_t

  MCPWM timer clock source.

typedef soc_periph_mcpwm_capture_clk_src_t mcpwm_capture_clock_source_t

  MCPWM capture clock source.

typedef soc_periph_mcpwm_carrier_clk_src_t mcpwm_carrier_clock_source_t

  MCPWM carrier clock source.

#### Enumerations

enum mcpwm_timer_direction_t

  MCPWM timer count direction.

  Values:

  enumerator MCPWM_TIMER_DIRECTION_UP

    Counting direction: Increase

  enumerator MCPWM_TIMER_DIRECTION_DOWN

    Counting direction: Decrease

enum mcpwm_timer_event_t

  MCPWM timer events.

  Values:

  enumerator MCPWM_TIMER_EVENT_EMPTY

    MCPWM timer counts to zero (i.e. counter is empty)

  enumerator MCPWM_TIMER_EVENT_FULL

    MCPWM timer counts to peak (i.e. counter is full)

  enumerator MCPWM_TIMER_EVENT_INVALID

    MCPWM timer invalid event

enum mcpwm_timer_count_mode_t

  MCPWM timer count modes.

  Values:

  enumerator MCPWM_TIMER_COUNT_MODE_PAUSE

    MCPWM timer paused

  enumerator MCPWM_TIMER_COUNT_MODE_UP

    MCPWM timer counting up

  enumerator MCPWM_TIMER_COUNT_MODE_DOWN

    MCPWM timer counting down

  enumerator MCPWM_TIMER_COUNT_MODE_UP_DOWN

    MCPWM timer counting up and down

enum mcpwm_timer_start_stop_cmd_t

  MCPWM timer commands, specify the way to start or stop the timer.

  Values:

  enumerator MCPWM_TIMER_STOP_EMPTY

    MCPWM timer stops when next count reaches zero

  enumerator MCPWM_TIMER_STOP_FULL

    MCPWM timer stops when next count reaches peak

  enumerator MCPWM_TIMER_START_NO_STOP

    MCPWM timer starts counting, and don't stop until received stop command

  enumerator MCPWM_TIMER_START_STOP_EMPTY

    MCPWM timer starts counting and stops when next count reaches zero

  enumerator MCPWM_TIMER_START_STOP_FULL

    MCPWM timer starts counting and stops when next count reaches peak

enum mcpwm_generator_action_t

  MCPWM generator actions.

  Values:

  enumerator MCPWM_GEN_ACTION_KEEP

    Generator action: Keep the same level

  enumerator MCPWM_GEN_ACTION_LOW

    Generator action: Force to low level

  enumerator MCPWM_GEN_ACTION_HIGH

    Generator action: Force to high level

  enumerator MCPWM_GEN_ACTION_TOGGLE

    Generator action: Toggle level

enum mcpwm_operator_brake_mode_t

  MCPWM operator brake mode.

  Values:

  enumerator MCPWM_OPER_BRAKE_MODE_CBC

    Brake mode: CBC (cycle by cycle)

  enumerator MCPWM_OPER_BRAKE_MODE_OST

    Brake mode: OST (one shot)

  enumerator MCPWM_OPER_BRAKE_MODE_INVALID

    MCPWM operator invalid brake mode

enum mcpwm_capture_edge_t

  MCPWM capture edge.

  Values:

  enumerator MCPWM_CAP_EDGE_POS

    Capture on the positive edge

  enumerator MCPWM_CAP_EDGE_NEG

    Capture on the negative edge

enum mcpwm_timer_etm_event_type_t

  MCPWM timer specific events that supported by the ETM module.

  Values:

  enumerator MCPWM_TIMER_ETM_EVENT_TEZ

    The timer reaches zero

  enumerator MCPWM_TIMER_ETM_EVENT_TEP

    The timer reaches peak

  enumerator MCPWM_TIMER_ETM_EVENT_MAX

    Maximum number of timer events

enum mcpwm_comparator_etm_event_type_t

  MCPWM comparator specific events that supported by the ETM module.

  Values:

  enumerator MCPWM_CMPR_ETM_EVENT_EQUAL

    The count value equals the value of comparator

  enumerator MCPWM_CMPR_ETM_EVENT_MAX

    Maximum number of comparator events

此文档对您有帮助吗？

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

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