MCPWM 比较器:将比例转换为边沿
当定时器计数达到 cmp_ticks 时,比较器产生事件;生成器再将该事件转换为 GPIO 电平变化。通常在向上计数 PWM 中,比较 Tick 数就是高电平时间。
比较器的实际意义是把"我想要多宽、多晚、多早出现一个边沿"转换成硬件里的具体时刻。运行中的占空比调节,通常就是不断更新比较器阈值。
设置 30% 占空比
从已有操作器创建比较器,再设置阈值。对 定时器 中 50 Tick 的周期,15 Tick 即为 30%。下图展示了比较事件在 Tick 15 处触发——生成器可用此事件结束高电平脉冲。
定时器向上计数;比较器在 Tick 15 触发。生成器将其转换为下降沿。
mcpwm_cmpr_handle_t comparator = NULL;
mcpwm_comparator_config_t comparator_config = {
.flags.update_cmp_on_tez = true, // 仅在周期边界改变占空比
};
ESP_ERROR_CHECK(mcpwm_new_comparator(oper, &comparator_config, &comparator));
ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparator, 15));
比较器配置除 flags 外只有一个字段:
intr_priority—on_reach回调使用的中断优先级。不设置(0)时由驱动选择较低优先级;当回调需要抢占其他中断时可适当提高。flags— 即下文介绍的更新点。示例启用了update_cmp_on_tez,这也是在周期边界改变占空比的常见做法。
运行时百分比占空比的计算公式为 period_ticks * percent / 100,结果必须不超过定时器周期。
这也是为什么改变占空比应优先改比较器,而不是改生成器动作:动作定义的是波形规则,比较器定义的是当前边沿位置。前者更像拓扑,后者更像运行参数。
为何要推迟更新
立即更新比较器可能改变当前周期中的边沿。update_cmp_on_tez 会等待计数归零,update_cmp_on_tep 会等待计数到达峰值,update_cmp_on_sync 则等待同步事件。在向上计数或向下计数模式下,峰值即周期边界,与归零点几乎重合,因此 tez 与 tep 对应同一个更新点;仅在向上-向下计数模式下,峰值处于周期中点,tez 与 tep 才是两个不同的更新点。电机和电源转换通常应使用推迟更新。
两个比较器实现脉冲放置
一个比较器每周期产生一个边沿。在同一操作器中使用两个比较器,可在周期内任意位置放置脉冲——一个比较器打开脉冲,另一个关闭。适用于采样窗口、触发信号或非对称死区补偿。
这类需求在电机控制里很常见,例如想把 ADC 采样窗口放在开关噪声较小的位置,或者给外部器件输出一个不位于 PWM 边界的同步脉冲。
mcpwm_cmpr_handle_t cmp_a, cmp_b;
mcpwm_new_comparator(oper, &comparator_config, &cmp_a);
mcpwm_new_comparator(oper, &comparator_config, &cmp_b);
mcpwm_comparator_set_compare_value(cmp_a, 10);
mcpwm_comparator_set_compare_value(cmp_b, 30);
比较事件也可用于精确的软件时间标记
on_reach 回调在比较值到达时触发,适用于软件需要观察 PWM 周期中精确位置的场景。应在启动时间关键型工作前注册。回调在 ISR 上下文运行,应保持简短。
static bool IRAM_ATTR on_compare(mcpwm_cmpr_handle_t cmpr,
const mcpwm_compare_event_data_t *edata,
void *user_ctx)
{
// 通知任务或仅执行 ISR 安全工作
return false;
}
mcpwm_comparator_event_callbacks_t callbacks = { .on_reach = on_compare };
ESP_ERROR_CHECK(mcpwm_comparator_register_event_callbacks(comparator,
&callbacks, NULL));
比较器的种类
操作器比较器 通过 mcpwm_new_comparator() 创建,其比较事件驱动生成器,从而塑造 PWM 输出。
API 参考
MCPWM 比较器驱动函数
Header File
This header file can be included with:
#include "driver/mcpwm_cmpr.h"
This header file is a part of the API provided by the
esp_driver_mcpwmcomponent. To declare that your component depends onesp_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_comparator(mcpwm_oper_handle_t oper, const mcpwm_comparator_config_t *config, mcpwm_cmpr_handle_t *ret_cmpr)
Create MCPWM comparator.
- 参数:
oper -- [in] MCPWM operator, allocated by
mcpwm_new_operator(), the new comparator will be allocated from this operatorconfig -- [in] MCPWM comparator configuration
ret_cmpr -- [out] Returned MCPWM comparator
- 返回:
ESP_OK: Create MCPWM comparator successfully
ESP_ERR_INVALID_ARG: Create MCPWM comparator failed because of invalid argument
ESP_ERR_NO_MEM: Create MCPWM comparator failed because out of memory
ESP_ERR_NOT_FOUND: Create MCPWM comparator failed because can't find free resource
ESP_FAIL: Create MCPWM comparator failed because of other error
-
esp_err_t mcpwm_del_comparator(mcpwm_cmpr_handle_t cmpr)
Delete MCPWM comparator.
- 参数:
cmpr -- [in] MCPWM comparator handle, allocated by
mcpwm_new_comparator()- 返回:
ESP_OK: Delete MCPWM comparator successfully
ESP_ERR_INVALID_ARG: Delete MCPWM comparator failed because of invalid argument
ESP_FAIL: Delete MCPWM comparator failed because of other error
-
esp_err_t mcpwm_comparator_register_event_callbacks(mcpwm_cmpr_handle_t cmpr, const mcpwm_comparator_event_callbacks_t *cbs, void *user_data)
Set event callbacks for MCPWM comparator.
备注
User can deregister a previously registered callback by calling this function and setting the callback member in the
cbsstructure to NULL.- 参数:
cmpr -- [in] MCPWM comparator handle, allocated by
mcpwm_new_comparator()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_FAIL: Set event callbacks failed because of other error
-
esp_err_t mcpwm_comparator_set_compare_value(mcpwm_cmpr_handle_t cmpr, uint32_t cmp_ticks)
Set MCPWM comparator's compare value.
- 参数:
cmpr -- [in] MCPWM comparator handle, allocated by
mcpwm_new_comparator()cmp_ticks -- [in] The new compare value
- 返回:
ESP_OK: Set MCPWM compare value successfully
ESP_ERR_INVALID_ARG: Set MCPWM compare value failed because of invalid argument (e.g. the cmp_ticks is out of range)
ESP_ERR_INVALID_STATE: Set MCPWM compare value failed because the operator doesn't have a timer connected
ESP_FAIL: Set MCPWM compare value failed because of other error
Structures
-
struct mcpwm_comparator_config_t
MCPWM comparator configuration.
Public Members
-
int intr_priority
MCPWM comparator interrupt priority, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3)
-
struct mcpwm_comparator_config_t::extra_mcpwm_comparator_flags flags
Extra configuration flags for comparator
-
struct extra_mcpwm_comparator_flags
Extra configuration flags for comparator.
-
int intr_priority
-
struct mcpwm_comparator_event_callbacks_t
Group of supported MCPWM compare event callbacks.
备注
The callbacks are all running under ISR environment
Public Members
-
mcpwm_compare_event_cb_t on_reach
ISR callback function which would be invoked when counter reaches compare value
-
mcpwm_compare_event_cb_t on_reach