ESP32 MCPWM 信号同步调试

简介

ESP-IDF版本:V5.1.2

ESP32的MCPWM外设是一个多功能的PWM生成器,集成多个子模块,在电力电子应用(如电机控制、数字电源等)中至关重要。常用于电极控制,H桥转换电路等。

如图,是MCPWM外设的主要子模块

ESP32编程指南中图片
ESP32技术手册中图片

从图中我们可以知道每个定时器都有对应的操作器,每个比较器要有对应的操作器,每个生成器要有对应的操作器,这些都可以从后面的代码得出。

 程序导读(功能)

1.实现两个PWM之间有固定的间隔时间(也称作死区),如图所示。当然,想要实现不同定时器之间生成的PWM同步,也完全没问题,这其实也是同步的另一种方式。

2.实现低频控制,如生成1Hz的PWM波形。如用官方的程序是无法生成1Hz的PWM波的,需要改变MCPWM_TIMER_RESOLUTION_HZ,来变化每个tick的时间。(至于为什么在官方给的1MHz无法实现原理不明)

3.该程序通过改变端口电平来控制同步功能。

4.该程序能实现实时PWM的频率和占空比调节。

程序代码

#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/mcpwm_prelude.h"
#include "driver/gpio.h"
#include "MCPWM_User.h"

const static char *TAG = "example";

uint32_t MCPWM_TIMER_RESOLUTION_HZ = 50000; // 50KHz, 20us per tick
uint32_t MCPWM_TIMER_PERIOD = 5000;         // 5000 ticks, 100ms
uint32_t HB_duty;
#define EXAMPLE_GEN_GPIO1 GPIO_NUM_18   //输出PWM引脚
#define EXAMPLE_GEN_GPIO2 GPIO_NUM_19
#define EXAMPLE_SYNC_GPIO GPIO_NUM_4    //信号同步引脚

mcpwm_timer_handle_t timers[2]; // 创建定时器句柄
// 配置定时器结构体
mcpwm_timer_config_t timer_config = {
    .group_id = 0,                              // 指定MCPWM的组ID
    .clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,     // 设置定时器的时钟源
    .resolution_hz = MCPWM_TIMER_RESOLUTION_HZ, // 设置定时器的预期分辨率
    .count_mode = MCPWM_TIMER_COUNT_MODE_UP,    // 向上计数
    .period_ticks = MCPWM_TIMER_PERIOD,         // 设置定时器的周期,以Tick为单位
};

mcpwm_cmpr_handle_t comparators[2]; // 创建比较器
mcpwm_comparator_config_t compare_config = {
    .flags = {
        .update_cmp_on_tez = true, // 当定时器计数值为0时更新比较阈值
    }};

static void example_setup_sync_strategy(mcpwm_timer_handle_t timers[])
{
    //    +----GPIO----+
    //    |     |      |
    //    |     |      |
    //    v     v      v
    // timer0 timer1 timer2
    ESP_LOGI(TAG, "Create GPIO sync source");
    mcpwm_sync_handle_t gpio_sync_source = NULL;
    mcpwm_gpio_sync_src_config_t gpio_sync_config = {
        .group_id = 0, // GPIO fault should be in the same group of the above timers
        .gpio_num = EXAMPLE_SYNC_GPIO,
        .flags = {
            .active_neg = false,  // by default, a posedge pulse can trigger a sync event
            .io_loop_back = true, // then we can trigger a sync event using `gpio_set_level` on the same GPIO
            .pull_down = true,    // 拉低GPIO电平
        }};
    ESP_ERROR_CHECK(mcpwm_new_gpio_sync_src(&gpio_sync_config, &gpio_sync_source));

    ESP_LOGI(TAG, "Set timers to sync on the GPIO");
    mcpwm_timer_sync_phase_config_t sync_phase_config_timer0 = {
        .sync_src = gpio_sync_source,
        .count_value = 0,   //定时器0从0开始计数
        .direction = MCPWM_TIMER_DIRECTION_UP,
    };
    ESP_ERROR_CHECK(mcpwm_timer_set_phase_on_sync(timers[0], &sync_phase_config_timer0));

    mcpwm_timer_sync_phase_config_t sync_phase_config_timer1 = {
        .sync_src = gpio_sync_source,
        .count_value = 2000,    //定时器1从200开始计数,可调节,但不要小于占空比
        .direction = MCPWM_TIMER_DIRECTION_UP,

    };
    ESP_ERROR_CHECK(mcpwm_timer_set_phase_on_sync(timers[1], &sync_phase_config_timer1));
    ESP_LOGI(TAG, "Trigger a pulse on the GPIO as a sync event");
    gpio_set_level(EXAMPLE_SYNC_GPIO, 0);
    gpio_set_level(EXAMPLE_SYNC_GPIO, 1);
}

void MCPWM_TASK(void)
{
    ESP_LOGI(TAG, "Create timers");
    for (int i = 0; i < 2; i++)
    {
        ESP_ERROR_CHECK(mcpwm_new_timer(&timer_config, &timers[i])); // 分配定时器
    }
    ESP_LOGI(TAG, "Create operators");
    mcpwm_oper_handle_t operators[2]; // 创建操作器句柄
    mcpwm_operator_config_t operator_config = {
        // 操作器的组ID应与定时器的组ID对应
        .group_id = 0, // operator should be in the same group of the above timers
    };
    for (int i = 0; i < 2; ++i)
    {
        ESP_ERROR_CHECK(mcpwm_new_operator(&operator_config, &operators[i])); // 分配操作器
    }

    ESP_LOGI(TAG, "Connect timers and operators with each other");
    for (int i = 0; i < 2; i++)
    {
        ESP_ERROR_CHECK(mcpwm_operator_connect_timer(operators[i], timers[i])); // 连接操作器和定时器
    }

    ESP_LOGI(TAG, "Create comparators");
    for (int i = 0; i < 2; i++)
    {
        // 以MCPWM操作器句柄和配置结构体mcpwm_comparator_config_t为参数
        ESP_ERROR_CHECK(mcpwm_new_comparator(operators[i], &compare_config, &comparators[i]));
        // init compare for each comparator
        ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparators[i], 1000)); // 主要用于调节占空比
    }

    ESP_LOGI(TAG, "Create generators");
    mcpwm_gen_handle_t generators[2]; // 创建生成器句柄
    const int gen_gpios[2] = {EXAMPLE_GEN_GPIO1, EXAMPLE_GEN_GPIO2};
    mcpwm_generator_config_t gen_config = {};
    for (int i = 0; i < 2; i++)
    {
        gen_config.gen_gpio_num = gen_gpios[i];                                          // 设置生成器使用的GPIO编号
        ESP_ERROR_CHECK(mcpwm_new_generator(operators[i], &gen_config, &generators[i])); // 分配生成器
    }

    ESP_LOGI(TAG, "Set generator actions on timer and compare event");
    for (int i = 0; i < 2; i++)
    {
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(
            generators[i],
            // when the timer value is zero, and is counting up, set output to high
            MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP,
                                         MCPWM_TIMER_EVENT_EMPTY,
                                         MCPWM_GEN_ACTION_HIGH))); // 计数值为0时开始输出高电平
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(
            generators[i],
            // when compare event happens, and timer is counting up, set output to low
            MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP,
                                           comparators[i],
                                           MCPWM_GEN_ACTION_LOW))); // 比较事件发生时,输出低电平
    }

    // 逐一启动定时器
    ESP_LOGI(TAG, "Start timers one by one, so they are not synced");
    for (int i = 0; i < 2; i++)
    {
        ESP_ERROR_CHECK(mcpwm_timer_enable(timers[i]));
        // 控制定时器的启动,MCPWM_TIMER_START_NO_STOP是启动后不停止
        ESP_ERROR_CHECK(mcpwm_timer_start_stop(timers[i], MCPWM_TIMER_START_NO_STOP));
        vTaskDelay(pdMS_TO_TICKS(10));
    }

    // 进行同步
    ESP_LOGI(TAG, "Setup sync strategy");
    example_setup_sync_strategy(timers);

    vTaskDelay(pdMS_TO_TICKS(100));
}

//改变MCPWM频率
void MCPWM_Change_period(uint32_t period)
{
    mcpwm_timer_set_period(timers[1], period);
    mcpwm_timer_set_period(timers[0], period);
}

//改变MCPWM占空比
void MCPWM_Change_duty(uint32_t duty)
{
    ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparators[0], duty)); // 主要用于调节占空比
    ESP_ERROR_CHECK(mcpwm_comparator_set_compare_value(comparators[1], duty)); // 主要用于调节占空比
}

  • 13
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ESP32 MCPWM (Motor Control PWM) 模块是 ESP32 的一个硬件模块,用于控制电机或其他设备的 PWM 信号MCPWM 模块还具有捕获功能,可以用于测量输入信号的频率、占空比和脉冲宽度等参数。 要使用 ESP32 MCPWM 模块进行捕获,可以按照以下步骤进行操作: 1. 配置 MCPWM 模块:首先,需要配置 MCPWM 模块的时钟源和其他相关参数。可以使用 `mcpwm_config_t` 结构体来设置这些参数,例如时钟频率、计数器分频系数等。 2. 配置捕获单元:MCPWM 模块包含多个捕获单元,每个捕获单元可以捕获一个输入信号的参数。可以使用 `mcpwm_capture_enable` 函数来启用捕获单元,并设置捕获信号的 GPIO 引脚和触发条件。 3. 设置捕获回调函数:在捕获到输入信号后,可以通过设置回调函数来处理捕获事件。可以使用 `mcpwm_isr_register` 函数来注册回调函数,对捕获事件进行处理。 4. 启动 MCPWM 模块:配置完毕后,可以使用 `mcpwm_start` 函数启动 MCPWM 模块,开始捕获输入信号。 这是一个简单的示例代码,演示了如何使用 ESP32 MCPWM 模块进行捕获: ```c #include <stdio.h> #include "driver/mcpwm.h" #include "soc/mcpwm_periph.h" // 定义捕获回调函数 void capture_handler(void *arg, mcpwm_capture_status_t status, uint32_t capture_value) { if (status == MCPWM_FULL_CAPTURE) { printf("Capture value: %d\n", capture_value); } } void app_main() { // 配置 MCPWM 模块 mcpwm_config_t pwm_config = { .frequency = 1000, // 设置 PWM 频率为 1000Hz .cmpr_a = 0, // 设置占空比为 0 .counter_mode = MCPWM_UP_COUNTER, .duty_mode = MCPWM_DUTY_MODE_0 }; mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config); // 配置捕获单元 mcpwm_capture_enable(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_SELECT_CAP0, 1); // 设置 GPIO 作为捕获信号输入 mcpwm_capture_enable(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_SELECT_CAP1, 1); // 设置 GPIO 作为捕获信号输入 // 设置捕获回调函数 mcpwm_isr_register(MCPWM_UNIT_0, capture_handler, NULL, ESP_INTR_FLAG_IRAM, NULL); // 启动 MCPWM 模块 mcpwm_start(MCPWM_UNIT_0, MCPWM_TIMER_0); } ``` 这个示例代码中,我们配置了一个 MCPWM 模块,并设置了一个捕获单元来捕获输入信号。当捕获到完整的输入信号时,将调用 `capture_handler` 函数进行处理,并打印捕获到的值。 希望这能帮助到你!如果你有任何疑问,请随时问我。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值