feat(MCPWM): Add mcpwm carrier clk source

The MCPWM carrier is part of the operator and can work independently
without the MCPWM timer being enabled. This commit add the MCPWM
carrier clk source.
This commit is contained in:
Chen Jichang
2023-08-14 14:10:50 +08:00
parent 06a4943e41
commit c240a1f46b
14 changed files with 101 additions and 35 deletions

View File

@@ -135,6 +135,7 @@ esp_err_t mcpwm_operator_register_event_callbacks(mcpwm_oper_handle_t oper, cons
* @brief MCPWM carrier configuration structure
*/
typedef struct {
mcpwm_carrier_clock_source_t clk_src; /*!< MCPWM carrier clock source */
uint32_t frequency_hz; /*!< Carrier frequency in Hz */
uint32_t first_pulse_duration_us; /*!< The duration of the first PWM pulse, in us */
float duty_cycle; /*!< Carrier duty cycle */

View File

@@ -182,9 +182,14 @@ esp_err_t mcpwm_operator_apply_carrier(mcpwm_oper_handle_t oper, const mcpwm_car
float real_duty = 0.0;
if (config && config->frequency_hz) {
uint8_t pre_scale = group->resolution_hz / 8 / config->frequency_hz;
mcpwm_ll_carrier_set_prescale(hal->dev, oper_id, pre_scale);
real_frequency = group->resolution_hz / 8 / pre_scale;
// select the clock source
mcpwm_carrier_clock_source_t clk_src = config->clk_src ? config->clk_src : MCPWM_CARRIER_CLK_SRC_DEFAULT;
ESP_RETURN_ON_ERROR(mcpwm_select_periph_clock(group, (soc_module_clk_t)clk_src), TAG, "set group clock failed");
uint8_t prescale = group->resolution_hz / 8 / config->frequency_hz;
ESP_RETURN_ON_FALSE(prescale > 0 && prescale <= MCPWM_LL_MAX_CARRIER_PRESCALE, ESP_ERR_INVALID_STATE, TAG, "group clock cannot match the frequency");
mcpwm_ll_carrier_set_prescale(hal->dev, oper_id, prescale);
real_frequency = group->resolution_hz / 8 / prescale;
uint8_t duty = (uint8_t)(config->duty_cycle * 8);
mcpwm_ll_carrier_set_duty(hal->dev, oper_id, duty);

View File

@@ -106,6 +106,7 @@ esp_err_t mcpwm_new_timer(const mcpwm_timer_config_t *config, mcpwm_timer_handle
mcpwm_hal_timer_reset(hal, timer_id);
// set timer resolution
uint32_t prescale = group->resolution_hz / config->resolution_hz;
ESP_RETURN_ON_FALSE(prescale > 0 && prescale <= MCPWM_LL_MAX_TIMER_PRESCALE, ESP_ERR_INVALID_STATE, TAG, "group clock cannot match the resolution");
mcpwm_ll_timer_set_clock_prescale(hal->dev, timer_id, prescale);
timer->resolution_hz = group->resolution_hz / prescale;
if (timer->resolution_hz != config->resolution_hz) {

View File

@@ -64,22 +64,11 @@ TEST_CASE("mcpwm_operator_install_uninstall", "[mcpwm]")
TEST_CASE("mcpwm_operator_carrier", "[mcpwm]")
{
mcpwm_timer_config_t timer_config = {
.group_id = 0,
.clk_src = MCPWM_TIMER_CLK_SRC_DEFAULT,
.resolution_hz = 1000000, // 1MHz, 1us per tick
.period_ticks = 20000,
.count_mode = MCPWM_TIMER_COUNT_MODE_UP,
};
mcpwm_timer_handle_t timer = NULL;
TEST_ESP_OK(mcpwm_new_timer(&timer_config, &timer));
mcpwm_operator_config_t operator_config = {
.group_id = 0,
};
mcpwm_oper_handle_t oper = NULL;
TEST_ESP_OK(mcpwm_new_operator(&operator_config, &oper));
TEST_ESP_OK(mcpwm_operator_connect_timer(oper, timer));
mcpwm_generator_config_t generator_config = {
.gen_gpio_num = 0,
@@ -87,36 +76,34 @@ TEST_CASE("mcpwm_operator_carrier", "[mcpwm]")
mcpwm_gen_handle_t generator = NULL;
TEST_ESP_OK(mcpwm_new_generator(oper, &generator_config, &generator));
TEST_ESP_OK(mcpwm_generator_set_action_on_timer_event(generator,
MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_TOGGLE)));
printf("add carrier to PWM wave\r\n");
mcpwm_carrier_config_t carrier_config = {
.clk_src = MCPWM_CARRIER_CLK_SRC_DEFAULT,
.frequency_hz = 1000000, // 1MHz carrier
.duty_cycle = 0.5,
.first_pulse_duration_us = 10,
};
TEST_ESP_OK(mcpwm_operator_apply_carrier(oper, &carrier_config));
TEST_ESP_OK(mcpwm_timer_enable(timer));
TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_START_NO_STOP));
vTaskDelay(pdMS_TO_TICKS(100));
TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_STOP_EMPTY));
vTaskDelay(pdMS_TO_TICKS(100));
TEST_ESP_OK(mcpwm_generator_set_force_level(generator, 1, true));
vTaskDelay(pdMS_TO_TICKS(10));
TEST_ESP_OK(mcpwm_generator_set_force_level(generator, 0, true));
vTaskDelay(pdMS_TO_TICKS(10));
TEST_ESP_OK(mcpwm_generator_set_force_level(generator, 1, true));
vTaskDelay(pdMS_TO_TICKS(10));
printf("remove carrier from PWM wave\r\n");
carrier_config.frequency_hz = 0;
TEST_ESP_OK(mcpwm_operator_apply_carrier(oper, &carrier_config));
TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_START_NO_STOP));
vTaskDelay(pdMS_TO_TICKS(200));
TEST_ESP_OK(mcpwm_timer_start_stop(timer, MCPWM_TIMER_STOP_EMPTY));
vTaskDelay(pdMS_TO_TICKS(100));
TEST_ESP_OK(mcpwm_generator_set_force_level(generator, 1, true));
vTaskDelay(pdMS_TO_TICKS(10));
TEST_ESP_OK(mcpwm_generator_set_force_level(generator, 0, true));
vTaskDelay(pdMS_TO_TICKS(10));
TEST_ESP_OK(mcpwm_generator_set_force_level(generator, 1, true));
vTaskDelay(pdMS_TO_TICKS(10));
TEST_ESP_OK(mcpwm_timer_disable(timer));
TEST_ESP_OK(mcpwm_del_generator(generator));
TEST_ESP_OK(mcpwm_del_operator(oper));
TEST_ESP_OK(mcpwm_del_timer(timer));
}
static bool IRAM_ATTR test_cbc_brake_on_gpio_fault_callback(mcpwm_oper_handle_t oper, const mcpwm_brake_event_data_t *edata, void *user_data)