mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'refactor/cleanup_mcpwm_examples' into 'master'
mcpwm: more clean up (example + LL + doc) Closes IDF-3295 See merge request espressif/esp-idf!12798
This commit is contained in:
commit
f907009056
@ -11,7 +11,6 @@
|
||||
#include "esp_err.h"
|
||||
#include "soc/soc.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "hal/mcpwm_types.h"
|
||||
|
||||
@ -46,8 +45,7 @@ typedef enum {
|
||||
} mcpwm_io_signals_t;
|
||||
|
||||
/**
|
||||
* @brief MCPWM pin number for
|
||||
*
|
||||
* @brief pin number for MCPWM
|
||||
*/
|
||||
typedef struct {
|
||||
int mcpwm0a_out_num; /*!<MCPWM0A out pin*/
|
||||
@ -71,9 +69,9 @@ typedef struct {
|
||||
* @brief Select MCPWM unit
|
||||
*/
|
||||
typedef enum {
|
||||
MCPWM_UNIT_0 = 0, /*!<MCPWM unit0 selected*/
|
||||
MCPWM_UNIT_1, /*!<MCPWM unit1 selected*/
|
||||
MCPWM_UNIT_MAX, /*!<Num of MCPWM units on ESP32*/
|
||||
MCPWM_UNIT_0, /*!<MCPWM unit0 selected*/
|
||||
MCPWM_UNIT_1, /*!<MCPWM unit1 selected*/
|
||||
MCPWM_UNIT_MAX, /*!<Max number of MCPWM units*/
|
||||
} mcpwm_unit_t;
|
||||
|
||||
_Static_assert(MCPWM_UNIT_MAX == SOC_MCPWM_GROUPS, "MCPWM unit number not equal to chip capabilities");
|
||||
@ -82,19 +80,19 @@ _Static_assert(MCPWM_UNIT_MAX == SOC_MCPWM_GROUPS, "MCPWM unit number not equal
|
||||
* @brief Select MCPWM timer
|
||||
*/
|
||||
typedef enum {
|
||||
MCPWM_TIMER_0 = 0, /*!<Select MCPWM timer0*/
|
||||
MCPWM_TIMER_1, /*!<Select MCPWM timer1*/
|
||||
MCPWM_TIMER_2, /*!<Select MCPWM timer2*/
|
||||
MCPWM_TIMER_MAX, /*!<Num of MCPWM timers on ESP32*/
|
||||
MCPWM_TIMER_0, /*!<Select MCPWM timer0*/
|
||||
MCPWM_TIMER_1, /*!<Select MCPWM timer1*/
|
||||
MCPWM_TIMER_2, /*!<Select MCPWM timer2*/
|
||||
MCPWM_TIMER_MAX, /*!<Max number of timers in a unit*/
|
||||
} mcpwm_timer_t;
|
||||
|
||||
/**
|
||||
* @brief Select MCPWM operator
|
||||
*/
|
||||
typedef enum {
|
||||
MCPWM_GEN_A = 0, /*!<Select MCPWMXA, where 'X' is operator number*/
|
||||
MCPWM_GEN_B, /*!<Select MCPWMXB, where 'X' is operator number*/
|
||||
MCPWM_GEN_MAX, /*!<Num of generators to each operator of MCPWM*/
|
||||
MCPWM_GEN_A, /*!<Select MCPWMXA, where 'X' is operator number*/
|
||||
MCPWM_GEN_B, /*!<Select MCPWMXB, where 'X' is operator number*/
|
||||
MCPWM_GEN_MAX, /*!<Num of generators to each operator of MCPWM*/
|
||||
} mcpwm_generator_t;
|
||||
|
||||
//definitions and macros to be back-compatible before IDFv4.1
|
||||
@ -107,25 +105,25 @@ typedef mcpwm_generator_t mcpwm_operator_t; ///< @deprecated
|
||||
* @brief MCPWM carrier oneshot mode, in this mode the width of the first pulse of carrier can be programmed
|
||||
*/
|
||||
typedef enum {
|
||||
MCPWM_ONESHOT_MODE_DIS = 0, /*!<Enable oneshot mode*/
|
||||
MCPWM_ONESHOT_MODE_EN, /*!<Disable oneshot mode*/
|
||||
MCPWM_ONESHOT_MODE_DIS, /*!<Enable oneshot mode*/
|
||||
MCPWM_ONESHOT_MODE_EN, /*!<Disable oneshot mode*/
|
||||
} mcpwm_carrier_os_t;
|
||||
|
||||
/**
|
||||
* @brief MCPWM carrier output inversion, high frequency carrier signal active with MCPWM signal is high
|
||||
*/
|
||||
typedef enum {
|
||||
MCPWM_CARRIER_OUT_IVT_DIS = 0, /*!<Enable carrier output inversion*/
|
||||
MCPWM_CARRIER_OUT_IVT_EN, /*!<Disable carrier output inversion*/
|
||||
MCPWM_CARRIER_OUT_IVT_DIS, /*!<Enable carrier output inversion*/
|
||||
MCPWM_CARRIER_OUT_IVT_EN, /*!<Disable carrier output inversion*/
|
||||
} mcpwm_carrier_out_ivt_t;
|
||||
|
||||
/**
|
||||
* @brief MCPWM select fault signal input
|
||||
*/
|
||||
typedef enum {
|
||||
MCPWM_SELECT_F0 = 0, /*!<Select F0 as input*/
|
||||
MCPWM_SELECT_F1, /*!<Select F1 as input*/
|
||||
MCPWM_SELECT_F2, /*!<Select F2 as input*/
|
||||
MCPWM_SELECT_F0, /*!<Select F0 as input*/
|
||||
MCPWM_SELECT_F1, /*!<Select F1 as input*/
|
||||
MCPWM_SELECT_F2, /*!<Select F2 as input*/
|
||||
} mcpwm_fault_signal_t;
|
||||
|
||||
/**
|
||||
@ -141,8 +139,8 @@ typedef enum {
|
||||
* @brief MCPWM select triggering level of fault signal
|
||||
*/
|
||||
typedef enum {
|
||||
MCPWM_LOW_LEVEL_TGR = 0, /*!<Fault condition occurs when fault input signal goes from high to low, currently not supported*/
|
||||
MCPWM_HIGH_LEVEL_TGR, /*!<Fault condition occurs when fault input signal goes low to high*/
|
||||
MCPWM_LOW_LEVEL_TGR, /*!<Fault condition occurs when fault input signal goes from high to low, currently not supported*/
|
||||
MCPWM_HIGH_LEVEL_TGR, /*!<Fault condition occurs when fault input signal goes low to high*/
|
||||
} mcpwm_fault_input_level_t;
|
||||
|
||||
/**
|
||||
@ -189,7 +187,7 @@ typedef enum {
|
||||
MCPWM_ACTIVE_LOW_COMPLIMENT_MODE, /*!<MCPWMXA = compliment of rising edge delay, MCPWMXB = falling edge delay*/
|
||||
MCPWM_ACTIVE_RED_FED_FROM_PWMXA, /*!<MCPWMXA = MCPWMXB = rising edge delay as well as falling edge delay, generated from MCPWMXA*/
|
||||
MCPWM_ACTIVE_RED_FED_FROM_PWMXB, /*!<MCPWMXA = MCPWMXB = rising edge delay as well as falling edge delay, generated from MCPWMXB*/
|
||||
MCPWM_DEADTIME_TYPE_MAX,
|
||||
MCPWM_DEADTIME_TYPE_MAX, /*!<Maximum number of supported dead time modes*/
|
||||
} mcpwm_deadtime_type_t;
|
||||
|
||||
/**
|
||||
@ -220,9 +218,9 @@ typedef mcpwm_output_action_t mcpwm_action_on_pwmxb_t;
|
||||
* @brief MCPWM select capture signal input
|
||||
*/
|
||||
typedef enum {
|
||||
MCPWM_SELECT_CAP0 = 0, /*!<Select CAP0 as input*/
|
||||
MCPWM_SELECT_CAP1, /*!<Select CAP1 as input*/
|
||||
MCPWM_SELECT_CAP2, /*!<Select CAP2 as input*/
|
||||
MCPWM_SELECT_CAP0, /*!<Select CAP0 as input*/
|
||||
MCPWM_SELECT_CAP1, /*!<Select CAP1 as input*/
|
||||
MCPWM_SELECT_CAP2, /*!<Select CAP2 as input*/
|
||||
} mcpwm_capture_signal_t;
|
||||
|
||||
/**
|
||||
@ -237,7 +235,7 @@ typedef struct {
|
||||
} mcpwm_config_t;
|
||||
|
||||
/**
|
||||
* @brief MCPWM config carrier structure
|
||||
* @brief MCPWM carrier configuration structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t carrier_period; /*!<Set carrier period = (carrier_period + 1)*800ns, carrier_period should be < 16*/
|
||||
@ -249,8 +247,8 @@ typedef struct {
|
||||
|
||||
/**
|
||||
* @brief This function initializes each gpio signal for MCPWM
|
||||
* @note
|
||||
* This function initializes one gpio at a time.
|
||||
*
|
||||
* @note This function initializes one gpio at a time.
|
||||
*
|
||||
* @param mcpwm_num set MCPWM unit(0-1)
|
||||
* @param io_signal set MCPWM signals, each MCPWM unit has 6 output(MCPWMXA, MCPWMXB) and 9 input(SYNC_X, FAULT_X, CAP_X)
|
||||
@ -265,8 +263,8 @@ esp_err_t mcpwm_gpio_init(mcpwm_unit_t mcpwm_num, mcpwm_io_signals_t io_signal,
|
||||
|
||||
/**
|
||||
* @brief Initialize MCPWM gpio structure
|
||||
* @note
|
||||
* This function can be used to initialize more then one gpio at a time.
|
||||
*
|
||||
* @note This function initialize a group of MCPWM GPIOs at a time.
|
||||
*
|
||||
* @param mcpwm_num set MCPWM unit(0-1)
|
||||
* @param mcpwm_pin MCPWM pin structure
|
||||
@ -619,20 +617,19 @@ esp_err_t mcpwm_fault_deinit(mcpwm_unit_t mcpwm_num, mcpwm_fault_signal_t fault_
|
||||
/**
|
||||
* @brief Initialize capture submodule
|
||||
*
|
||||
* @note Enabling capture feature could also enable the capture interrupt,
|
||||
* @note Enabling capture feature would also enable the capture interrupt event,
|
||||
* users have to register an interrupt handler by `mcpwm_isr_register`, and in there, query the capture data.
|
||||
* @note The capture timer uses APB_CLK (typically 80MHz) as the count source.
|
||||
*
|
||||
* @param mcpwm_num set MCPWM unit(0-1)
|
||||
* @param cap_edge set capture edge, BIT(0) - negative edge, BIT(1) - positive edge
|
||||
* @param cap_sig capture pin, which needs to be enabled
|
||||
* @param num_of_pulse count time between rising/falling edge between 2 *(pulses mentioned), counter uses APB_CLK
|
||||
* [0~MCPWM_LL_MAX_PRESCALE] (MCPWM_LL_MAX_PRESCALE = 255 on ESP32);
|
||||
* @param num_of_pulse Input capture signal prescaling, num_of_pulse ranges from 0 to 255, representing prescaling from 1 to 256.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
|
||||
esp_err_t mcpwm_capture_enable(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t cap_sig, mcpwm_capture_on_edge_t cap_edge,
|
||||
uint32_t num_of_pulse);
|
||||
|
||||
|
@ -35,7 +35,8 @@ static const char *TAG = "mcpwm";
|
||||
#define MCPWM_GEN_ERROR "MCPWM GENERATOR ERROR"
|
||||
#define MCPWM_DT_ERROR "MCPWM DEADTIME TYPE ERROR"
|
||||
|
||||
#define MCPWM_GROUP_CLK_HZ (SOC_MCPWM_BASE_CLK_HZ / 16)
|
||||
#define MCPWM_GROUP_CLK_PRESCALE (16)
|
||||
#define MCPWM_GROUP_CLK_HZ (SOC_MCPWM_BASE_CLK_HZ / MCPWM_GROUP_CLK_PRESCALE)
|
||||
#define MCPWM_TIMER_CLK_HZ (MCPWM_GROUP_CLK_HZ / 10)
|
||||
|
||||
_Static_assert(SOC_MCPWM_OPERATORS_PER_GROUP >= SOC_MCPWM_TIMERS_PER_GROUP, "This driver assumes the timer num equals to the operator num.");
|
||||
@ -100,12 +101,12 @@ esp_err_t mcpwm_gpio_init(mcpwm_unit_t mcpwm_num, mcpwm_io_signals_t io_signal,
|
||||
esp_rom_gpio_connect_out_signal(gpio_num, mcpwm_periph_signals.groups[mcpwm_num].operators[operator_id].generators[generator_id].pwm_sig, 0, 0);
|
||||
} else if (io_signal <= MCPWM_SYNC_2) { // External sync input signal
|
||||
gpio_set_direction(gpio_num, GPIO_MODE_INPUT);
|
||||
int ext_sync_id = io_signal - MCPWM_SYNC_0;
|
||||
esp_rom_gpio_connect_in_signal(gpio_num, mcpwm_periph_signals.groups[mcpwm_num].ext_syncers[ext_sync_id].sync_sig, 0);
|
||||
int gpio_sync_id = io_signal - MCPWM_SYNC_0;
|
||||
esp_rom_gpio_connect_in_signal(gpio_num, mcpwm_periph_signals.groups[mcpwm_num].gpio_synchros[gpio_sync_id].sync_sig, 0);
|
||||
} else if (io_signal <= MCPWM_FAULT_2) { // Fault input signal
|
||||
gpio_set_direction(gpio_num, GPIO_MODE_INPUT);
|
||||
int fault_id = io_signal - MCPWM_FAULT_0;
|
||||
esp_rom_gpio_connect_in_signal(gpio_num, mcpwm_periph_signals.groups[mcpwm_num].detectors[fault_id].fault_sig, 0);
|
||||
esp_rom_gpio_connect_in_signal(gpio_num, mcpwm_periph_signals.groups[mcpwm_num].gpio_faults[fault_id].fault_sig, 0);
|
||||
} else if (io_signal >= MCPWM_CAP_0 && io_signal <= MCPWM_CAP_2) { // Capture input signal
|
||||
gpio_set_direction(gpio_num, GPIO_MODE_INPUT);
|
||||
int capture_id = io_signal - MCPWM_CAP_0;
|
||||
@ -141,7 +142,7 @@ esp_err_t mcpwm_start(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
|
||||
MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
|
||||
|
||||
mcpwm_critical_enter(mcpwm_num);
|
||||
mcpwm_ll_timer_set_operate_command(context[mcpwm_num].hal.dev, timer_num, MCPWM_TIMER_START_NO_STOP);
|
||||
mcpwm_ll_timer_set_execute_command(context[mcpwm_num].hal.dev, timer_num, MCPWM_TIMER_START_NO_STOP);
|
||||
mcpwm_critical_exit(mcpwm_num);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -151,7 +152,7 @@ esp_err_t mcpwm_stop(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
|
||||
MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
|
||||
|
||||
mcpwm_critical_enter(mcpwm_num);
|
||||
mcpwm_ll_timer_set_operate_command(context[mcpwm_num].hal.dev, timer_num, MCPWM_TIMER_STOP_AT_ZERO);
|
||||
mcpwm_ll_timer_set_execute_command(context[mcpwm_num].hal.dev, timer_num, MCPWM_TIMER_STOP_AT_ZERO);
|
||||
mcpwm_critical_exit(mcpwm_num);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -312,10 +313,10 @@ esp_err_t mcpwm_init(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, const mcpw
|
||||
mcpwm_hal_init(hal, &config);
|
||||
|
||||
mcpwm_critical_enter(mcpwm_num);
|
||||
mcpwm_ll_group_set_clock(hal->dev, MCPWM_GROUP_CLK_HZ);
|
||||
mcpwm_ll_group_set_clock_prescale(hal->dev, MCPWM_GROUP_CLK_PRESCALE);
|
||||
mcpwm_ll_group_enable_shadow_mode(hal->dev);
|
||||
mcpwm_ll_group_flush_shadow(hal->dev);
|
||||
mcpwm_ll_timer_set_clock(hal->dev, timer_num, MCPWM_GROUP_CLK_HZ, MCPWM_TIMER_CLK_HZ);
|
||||
mcpwm_ll_timer_set_clock_prescale(hal->dev, timer_num, MCPWM_GROUP_CLK_HZ / MCPWM_TIMER_CLK_HZ);
|
||||
mcpwm_ll_timer_set_count_mode(hal->dev, timer_num, mcpwm_conf->counter_mode);
|
||||
mcpwm_ll_timer_update_period_at_once(hal->dev, timer_num);
|
||||
mcpwm_ll_timer_set_peak(hal->dev, timer_num, MCPWM_TIMER_CLK_HZ / mcpwm_conf->frequency, false);
|
||||
@ -336,8 +337,8 @@ uint32_t mcpwm_get_frequency(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
|
||||
MCPWM_TIMER_CHECK(mcpwm_num, timer_num);
|
||||
mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
|
||||
mcpwm_critical_enter(mcpwm_num);
|
||||
unsigned long long group_clock = mcpwm_ll_group_get_clock(hal->dev);
|
||||
unsigned long long timer_clock = mcpwm_ll_timer_get_clock(hal->dev, timer_num, group_clock);
|
||||
unsigned int group_clock = SOC_MCPWM_BASE_CLK_HZ / mcpwm_ll_group_get_clock_prescale(hal->dev);
|
||||
unsigned int timer_clock = group_clock / mcpwm_ll_timer_get_clock_prescale(hal->dev, timer_num);
|
||||
mcpwm_critical_exit(mcpwm_num);
|
||||
return (uint32_t)timer_clock;
|
||||
}
|
||||
@ -479,7 +480,8 @@ esp_err_t mcpwm_deadtime_enable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num,
|
||||
|
||||
mcpwm_critical_enter(mcpwm_num);
|
||||
mcpwm_ll_deadtime_enable_update_delay_on_tez(hal->dev, op, true);
|
||||
mcpwm_ll_deadtime_set_resolution_same_to_timer(hal->dev, op, false);
|
||||
// The dead time delay unit equals to MCPWM group resolution
|
||||
mcpwm_ll_deadtime_resolution_to_timer(hal->dev, op, false);
|
||||
mcpwm_ll_deadtime_set_rising_delay(hal->dev, op, red + 1);
|
||||
mcpwm_ll_deadtime_set_falling_delay(hal->dev, op, fed + 1);
|
||||
switch (dt_mode) {
|
||||
@ -611,11 +613,12 @@ esp_err_t mcpwm_fault_set_cyc_mode(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_n
|
||||
|
||||
mcpwm_critical_enter(mcpwm_num);
|
||||
mcpwm_ll_fault_enable_cbc_mode(hal->dev, op, fault_sig, true);
|
||||
mcpwm_ll_fault_enable_cbc_refresh_on_tez(hal->dev, op, true);
|
||||
mcpwm_ll_fault_enable_oneshot_mode(hal->dev, op, fault_sig, false);
|
||||
mcpwm_ll_generator_set_action_on_fault_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_FAULT_REACTION_CBC, action_on_pwmxa);
|
||||
mcpwm_ll_generator_set_action_on_fault_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_UP, MCPWM_FAULT_REACTION_CBC, action_on_pwmxa);
|
||||
mcpwm_ll_generator_set_action_on_fault_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_FAULT_REACTION_CBC, action_on_pwmxb);
|
||||
mcpwm_ll_generator_set_action_on_fault_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_UP, MCPWM_FAULT_REACTION_CBC, action_on_pwmxb);
|
||||
mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TRIP_TYPE_CBC, action_on_pwmxa);
|
||||
mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_UP, MCPWM_TRIP_TYPE_CBC, action_on_pwmxa);
|
||||
mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TRIP_TYPE_CBC, action_on_pwmxb);
|
||||
mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_UP, MCPWM_TRIP_TYPE_CBC, action_on_pwmxb);
|
||||
mcpwm_critical_exit(mcpwm_num);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -632,10 +635,10 @@ esp_err_t mcpwm_fault_set_oneshot_mode(mcpwm_unit_t mcpwm_num, mcpwm_timer_t tim
|
||||
mcpwm_ll_fault_clear_ost(hal->dev, op);
|
||||
mcpwm_ll_fault_enable_oneshot_mode(hal->dev, op, fault_sig, true);
|
||||
mcpwm_ll_fault_enable_cbc_mode(hal->dev, op, fault_sig, false);
|
||||
mcpwm_ll_generator_set_action_on_fault_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_FAULT_REACTION_OST, action_on_pwmxa);
|
||||
mcpwm_ll_generator_set_action_on_fault_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_UP, MCPWM_FAULT_REACTION_OST, action_on_pwmxa);
|
||||
mcpwm_ll_generator_set_action_on_fault_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_FAULT_REACTION_OST, action_on_pwmxb);
|
||||
mcpwm_ll_generator_set_action_on_fault_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_UP, MCPWM_FAULT_REACTION_OST, action_on_pwmxb);
|
||||
mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TRIP_TYPE_OST, action_on_pwmxa);
|
||||
mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 0, MCPWM_TIMER_DIRECTION_UP, MCPWM_TRIP_TYPE_OST, action_on_pwmxa);
|
||||
mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_DOWN, MCPWM_TRIP_TYPE_OST, action_on_pwmxb);
|
||||
mcpwm_ll_generator_set_action_on_trip_event(hal->dev, op, 1, MCPWM_TIMER_DIRECTION_UP, MCPWM_TRIP_TYPE_OST, action_on_pwmxb);
|
||||
mcpwm_critical_exit(mcpwm_num);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -644,7 +647,7 @@ esp_err_t mcpwm_capture_enable(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t ca
|
||||
uint32_t num_of_pulse)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(mcpwm_num < SOC_MCPWM_GROUPS, ESP_ERR_INVALID_ARG, TAG, MCPWM_GROUP_NUM_ERROR);
|
||||
ESP_RETURN_ON_FALSE(num_of_pulse <= MCPWM_LL_MAX_PRESCALE, ESP_ERR_INVALID_ARG, TAG, MCPWM_PRESCALE_ERROR);
|
||||
ESP_RETURN_ON_FALSE(num_of_pulse <= MCPWM_LL_MAX_CAPTURE_PRESCALE, ESP_ERR_INVALID_ARG, TAG, MCPWM_PRESCALE_ERROR);
|
||||
ESP_RETURN_ON_FALSE(cap_sig < SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER, ESP_ERR_INVALID_ARG, TAG, MCPWM_CAPTURE_ERROR);
|
||||
mcpwm_hal_context_t *hal = &context[mcpwm_num].hal;
|
||||
// enable MCPWM module incase user don't use `mcpwm_init` at all
|
||||
@ -654,7 +657,7 @@ esp_err_t mcpwm_capture_enable(mcpwm_unit_t mcpwm_num, mcpwm_capture_signal_t ca
|
||||
};
|
||||
mcpwm_critical_enter(mcpwm_num);
|
||||
mcpwm_hal_init(hal, &init_config);
|
||||
mcpwm_ll_group_set_clock(hal->dev, MCPWM_GROUP_CLK_HZ);
|
||||
mcpwm_ll_group_set_clock_prescale(hal->dev, MCPWM_GROUP_CLK_PRESCALE);
|
||||
mcpwm_ll_capture_enable_timer(hal->dev, true);
|
||||
mcpwm_ll_capture_enable_channel(hal->dev, cap_sig, true);
|
||||
mcpwm_ll_capture_enable_negedge(hal->dev, cap_sig, cap_edge & MCPWM_NEG_EDGE);
|
||||
@ -707,9 +710,9 @@ esp_err_t mcpwm_sync_enable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, mcp
|
||||
uint32_t set_phase = mcpwm_ll_timer_get_peak(hal->dev, timer_num, false) * phase_val / 1000;
|
||||
mcpwm_ll_timer_set_sync_phase_value(hal->dev, timer_num, set_phase);
|
||||
if (sync_sig >= MCPWM_SELECT_SYNC0) {
|
||||
mcpwm_ll_timer_enable_sync_from_external(hal->dev, timer_num, sync_sig - MCPWM_SELECT_SYNC0);
|
||||
mcpwm_ll_timer_set_timer_synchro(hal->dev, timer_num, sync_sig - MCPWM_SELECT_SYNC0);
|
||||
}
|
||||
mcpwm_ll_timer_sync_out_same_in(hal->dev, timer_num);
|
||||
mcpwm_ll_timer_sync_out_penetrate(hal->dev, timer_num);
|
||||
mcpwm_ll_timer_enable_sync_input(hal->dev, timer_num, true);
|
||||
mcpwm_critical_exit(mcpwm_num);
|
||||
return ESP_OK;
|
||||
|
@ -52,12 +52,12 @@ static esp_err_t test_mcpwm_gpio_init(mcpwm_unit_t mcpwm_num, mcpwm_io_signals_t
|
||||
esp_rom_gpio_connect_out_signal(gpio_num, mcpwm_periph_signals.groups[mcpwm_num].operators[operator_id].generators[generator_id].pwm_sig, 0, 0);
|
||||
} else if (io_signal <= MCPWM_SYNC_2) { // External sync input signal
|
||||
gpio_set_direction(gpio_num, GPIO_MODE_INPUT_OUTPUT);
|
||||
int ext_sync_id = io_signal - MCPWM_SYNC_0;
|
||||
esp_rom_gpio_connect_in_signal(gpio_num, mcpwm_periph_signals.groups[mcpwm_num].ext_syncers[ext_sync_id].sync_sig, 0);
|
||||
int gpio_sync_id = io_signal - MCPWM_SYNC_0;
|
||||
esp_rom_gpio_connect_in_signal(gpio_num, mcpwm_periph_signals.groups[mcpwm_num].gpio_synchros[gpio_sync_id].sync_sig, 0);
|
||||
} else if (io_signal <= MCPWM_FAULT_2) { // Fault input signal
|
||||
gpio_set_direction(gpio_num, GPIO_MODE_INPUT_OUTPUT);
|
||||
int fault_id = io_signal - MCPWM_FAULT_0;
|
||||
esp_rom_gpio_connect_in_signal(gpio_num, mcpwm_periph_signals.groups[mcpwm_num].detectors[fault_id].fault_sig, 0);
|
||||
esp_rom_gpio_connect_in_signal(gpio_num, mcpwm_periph_signals.groups[mcpwm_num].gpio_faults[fault_id].fault_sig, 0);
|
||||
} else if (io_signal >= MCPWM_CAP_0 && io_signal <= MCPWM_CAP_2) { // Capture input signal
|
||||
gpio_set_direction(gpio_num, GPIO_MODE_INPUT_OUTPUT);
|
||||
int capture_id = io_signal - MCPWM_CAP_0;
|
||||
|
@ -26,31 +26,36 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/mcpwm_struct.h"
|
||||
#include "hal/mcpwm_types.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// Get the address of peripheral registers
|
||||
#define MCPWM_LL_GET_HW(ID) (((ID) == 0) ? &MCPWM0 : &MCPWM1)
|
||||
#define MCPWM_LL_MAX_PRESCALE 255
|
||||
#define MCPWM_LL_GET_HW(ID) (((ID) == 0) ? &MCPWM0 : &MCPWM1)
|
||||
#define MCPWM_LL_MAX_CAPTURE_PRESCALE 255
|
||||
#define MCPWM_LL_MAX_COMPARE_VALUE 65535
|
||||
#define MCPWM_LL_MAX_DEAD_DELAY 65535
|
||||
#define MCPWM_LL_MAX_PHASE_VALUE 65535
|
||||
|
||||
/********************* Group registers *******************/
|
||||
|
||||
// Set/Get group clock: PWM_clk = CLK_160M / (prescale + 1)
|
||||
static inline void mcpwm_ll_group_set_clock(mcpwm_dev_t *mcpwm, unsigned long long group_clk_hz)
|
||||
static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int pre_scale)
|
||||
{
|
||||
mcpwm->clk_cfg.prescale = (SOC_MCPWM_BASE_CLK_HZ / group_clk_hz) - 1;
|
||||
mcpwm->clk_cfg.prescale = pre_scale - 1;
|
||||
}
|
||||
|
||||
static inline unsigned long long mcpwm_ll_group_get_clock(mcpwm_dev_t *mcpwm)
|
||||
static inline uint32_t mcpwm_ll_group_get_clock_prescale(mcpwm_dev_t *mcpwm)
|
||||
{
|
||||
return SOC_MCPWM_BASE_CLK_HZ / (mcpwm->clk_cfg.prescale + 1);
|
||||
return mcpwm->clk_cfg.prescale + 1;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_group_enable_shadow_mode(mcpwm_dev_t *mcpwm)
|
||||
{
|
||||
mcpwm->update_cfg.global_up_en = 1;
|
||||
// updating of active registers in MCPWM operators should be enabled
|
||||
mcpwm->update_cfg.op0_up_en = 1;
|
||||
mcpwm->update_cfg.op1_up_en = 1;
|
||||
mcpwm->update_cfg.op2_up_en = 1;
|
||||
@ -58,7 +63,8 @@ static inline void mcpwm_ll_group_enable_shadow_mode(mcpwm_dev_t *mcpwm)
|
||||
|
||||
static inline void mcpwm_ll_group_flush_shadow(mcpwm_dev_t *mcpwm)
|
||||
{
|
||||
mcpwm->update_cfg.val ^= (1 << 1);
|
||||
// a toggle can trigger a forced update of all active registers in MCPWM, i.e. shadow->active
|
||||
mcpwm->update_cfg.global_force_up = ~mcpwm->update_cfg.global_force_up;
|
||||
}
|
||||
|
||||
/********************* Interrupt registers *******************/
|
||||
@ -129,47 +135,47 @@ static inline uint32_t mcpwm_ll_intr_get_capture_status(mcpwm_dev_t *mcpwm)
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_timer_stop_status(mcpwm_dev_t *mcpwm, uint32_t timer_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (timer_mask & 0x07) << 0;
|
||||
mcpwm->int_clr.val = (timer_mask & 0x07) << 0;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_timer_tez_status(mcpwm_dev_t *mcpwm, uint32_t timer_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (timer_mask & 0x07) << 3;
|
||||
mcpwm->int_clr.val = (timer_mask & 0x07) << 3;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_timer_tep_status(mcpwm_dev_t *mcpwm, uint32_t timer_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (timer_mask & 0x07) << 6;
|
||||
mcpwm->int_clr.val = (timer_mask & 0x07) << 6;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_fault_enter_status(mcpwm_dev_t *mcpwm, uint32_t fault_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (fault_mask & 0x07) << 9;
|
||||
mcpwm->int_clr.val = (fault_mask & 0x07) << 9;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_fault_exit_status(mcpwm_dev_t *mcpwm, uint32_t fault_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (fault_mask & 0x07) << 12;
|
||||
mcpwm->int_clr.val = (fault_mask & 0x07) << 12;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_compare_status(mcpwm_dev_t *mcpwm, uint32_t operator_mask, uint32_t cmp_id)
|
||||
{
|
||||
mcpwm->int_clr.val |= (operator_mask & 0x07) << (15 + cmp_id * 3);
|
||||
mcpwm->int_clr.val = (operator_mask & 0x07) << (15 + cmp_id * 3);
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_trip_cbc_status(mcpwm_dev_t *mcpwm, uint32_t cbc_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (cbc_mask & 0x07) << 21;
|
||||
mcpwm->int_clr.val = (cbc_mask & 0x07) << 21;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_trip_ost_status(mcpwm_dev_t *mcpwm, uint32_t ost_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (ost_mask & 0x07) << 24;
|
||||
mcpwm->int_clr.val = (ost_mask & 0x07) << 24;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_capture_status(mcpwm_dev_t *mcpwm, uint32_t capture_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (capture_mask & 0x07) << 27;
|
||||
mcpwm->int_clr.val = (capture_mask & 0x07) << 27;
|
||||
}
|
||||
|
||||
//////////// enable interrupt for each event ////////////////
|
||||
@ -201,13 +207,20 @@ static inline void mcpwm_ll_intr_enable_timer_tep(mcpwm_dev_t *mcpwm, uint32_t t
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_enable_fault(mcpwm_dev_t *mcpwm, uint32_t fault_id, bool enable)
|
||||
static inline void mcpwm_ll_intr_enable_fault_enter(mcpwm_dev_t *mcpwm, uint32_t fault_id, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
mcpwm->int_ena.val |= 1 << (9 + fault_id); // enter fault interrupt
|
||||
mcpwm->int_ena.val |= 1 << (12 + fault_id); // exit fault interrupt
|
||||
} else {
|
||||
mcpwm->int_ena.val &= ~(1 << (9 + fault_id));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_enable_fault_exit(mcpwm_dev_t *mcpwm, uint32_t fault_id, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
mcpwm->int_ena.val |= 1 << (12 + fault_id); // exit fault interrupt
|
||||
} else {
|
||||
mcpwm->int_ena.val &= ~(1 << (12 + fault_id));
|
||||
}
|
||||
}
|
||||
@ -221,13 +234,20 @@ static inline void mcpwm_ll_intr_enable_compare(mcpwm_dev_t *mcpwm, uint32_t ope
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_enable_trip(mcpwm_dev_t *mcpwm, uint32_t operator_id, bool enable)
|
||||
static inline void mcpwm_ll_intr_enable_trip_cbc(mcpwm_dev_t *mcpwm, uint32_t operator_id, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
mcpwm->int_ena.val |= (1 << (21 + operator_id));
|
||||
mcpwm->int_ena.val |= (1 << (24 + operator_id));
|
||||
} else {
|
||||
mcpwm->int_ena.val &= ~(1 << (21 + operator_id));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_enable_trip_ost(mcpwm_dev_t *mcpwm, uint32_t operator_id, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
mcpwm->int_ena.val |= (1 << (24 + operator_id));
|
||||
} else {
|
||||
mcpwm->int_ena.val &= ~(1 << (24 + operator_id));
|
||||
}
|
||||
}
|
||||
@ -243,14 +263,14 @@ static inline void mcpwm_ll_intr_enable_capture(mcpwm_dev_t *mcpwm, uint32_t cap
|
||||
|
||||
/********************* Timer registers *******************/
|
||||
|
||||
static inline void mcpwm_ll_timer_set_clock(mcpwm_dev_t *mcpwm, int timer_id, unsigned long long group_clock, unsigned long long timer_clock)
|
||||
static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id, uint32_t prescale)
|
||||
{
|
||||
mcpwm->timer[timer_id].period.prescale = group_clock / timer_clock - 1;
|
||||
mcpwm->timer[timer_id].period.prescale = prescale - 1;
|
||||
}
|
||||
|
||||
static inline unsigned long long mcpwm_ll_timer_get_clock(mcpwm_dev_t *mcpwm, int timer_id, unsigned long long group_clock)
|
||||
static inline uint32_t mcpwm_ll_timer_get_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
{
|
||||
return group_clock / (mcpwm->timer[timer_id].period.prescale + 1);
|
||||
return mcpwm->timer[timer_id].period.prescale + 1;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric)
|
||||
@ -327,9 +347,9 @@ static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_set_operate_command(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_operate_cmd_t mode)
|
||||
static inline void mcpwm_ll_timer_set_execute_command(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_execute_cmd_t cmd)
|
||||
{
|
||||
switch (mode) {
|
||||
switch (cmd) {
|
||||
case MCPWM_TIMER_STOP_AT_ZERO:
|
||||
mcpwm->timer[timer_id].mode.start = 0;
|
||||
break;
|
||||
@ -348,23 +368,14 @@ static inline void mcpwm_ll_timer_set_operate_command(mcpwm_dev_t *mcpwm, int ti
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_set_count_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t value)
|
||||
{
|
||||
// we use software sync to set count value
|
||||
int previous_phase = mcpwm->timer[timer_id].sync.timer_phase;
|
||||
mcpwm->timer[timer_id].sync.timer_phase = value;
|
||||
mcpwm->timer[timer_id].sync.sync_sw = ~mcpwm->timer[timer_id].sync.sync_sw;
|
||||
mcpwm->timer[timer_id].sync.timer_phase = previous_phase;
|
||||
}
|
||||
|
||||
static inline uint32_t mcpwm_ll_timer_get_count_value(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
{
|
||||
return mcpwm->timer[timer_id].status.value;
|
||||
}
|
||||
|
||||
static inline bool mcpwm_ll_is_timer_decreasing(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
static inline mcpwm_timer_direction_t mcpwm_ll_timer_get_count_direction(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
{
|
||||
return mcpwm->timer[timer_id].status.direction;
|
||||
return mcpwm->timer[timer_id].status.direction ? MCPWM_TIMER_DIRECTION_DOWN : MCPWM_TIMER_DIRECTION_UP;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_enable_sync_input(mcpwm_dev_t *mcpwm, int timer_id, bool enable)
|
||||
@ -372,8 +383,9 @@ static inline void mcpwm_ll_timer_enable_sync_input(mcpwm_dev_t *mcpwm, int time
|
||||
mcpwm->timer[timer_id].sync.in_en = enable;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_sync_out_same_in(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
static inline void mcpwm_ll_timer_sync_out_penetrate(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
{
|
||||
// sync_out is selected to sync_in
|
||||
mcpwm->timer[timer_id].sync.out_sel = 0;
|
||||
}
|
||||
|
||||
@ -383,47 +395,51 @@ static inline void mcpwm_ll_timer_sync_out_on_timer_event(mcpwm_dev_t *mcpwm, in
|
||||
mcpwm->timer[timer_id].sync.out_sel = 1;
|
||||
} else if (event == MCPWM_TIMER_EVENT_PEAK) {
|
||||
mcpwm->timer[timer_id].sync.out_sel = 2;
|
||||
} else {
|
||||
HAL_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_disable_sync_out(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
{
|
||||
// sync_out will always be zero
|
||||
mcpwm->timer[timer_id].sync.out_sel = 3;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_trigger_sw_sync(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
static inline void mcpwm_ll_timer_trigger_soft_sync(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
{
|
||||
mcpwm->timer[timer_id].sync.sync_sw = ~mcpwm->timer[timer_id].sync.sync_sw;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_set_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t reload_val)
|
||||
static inline void mcpwm_ll_timer_set_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t phase_value)
|
||||
{
|
||||
mcpwm->timer[timer_id].sync.timer_phase = reload_val;
|
||||
mcpwm->timer[timer_id].sync.timer_phase = phase_value;
|
||||
}
|
||||
|
||||
static inline uint32_t mcpwm_ll_timer_get_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
static inline void mcpwm_ll_timer_set_sync_phase_direction(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_direction_t direction)
|
||||
{
|
||||
return mcpwm->timer[timer_id].sync.timer_phase;
|
||||
mcpwm->timer[timer_id].sync.phase_direct = direction;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_set_sync_phase_direction(mcpwm_dev_t *mcpwm, int timer_id, bool decrease)
|
||||
static inline void mcpwm_ll_timer_set_gpio_synchro(mcpwm_dev_t *mcpwm, int timer, int gpio_sync_id)
|
||||
{
|
||||
mcpwm->timer[timer_id].sync.phase_direct = decrease;
|
||||
mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3));
|
||||
mcpwm->timer_synci_cfg.val |= (gpio_sync_id + 4) << (timer * 3);
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_enable_sync_from_internal_timer(mcpwm_dev_t *mcpwm, int this_timer, int internal_sync_timer)
|
||||
static inline void mcpwm_ll_timer_set_timer_synchro(mcpwm_dev_t *mcpwm, int timer, int timer_sync_id)
|
||||
{
|
||||
mcpwm->timer_synci_cfg.val &= ~(0x07 << (this_timer * 3));
|
||||
mcpwm->timer_synci_cfg.val |= (internal_sync_timer + 1) << (this_timer * 3);
|
||||
mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3));
|
||||
mcpwm->timer_synci_cfg.val |= (timer_sync_id + 1) << (timer * 3);
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_enable_sync_from_external(mcpwm_dev_t *mcpwm, int this_timer, int extern_syncer)
|
||||
static inline void mcpwm_ll_timer_set_soft_synchro(mcpwm_dev_t *mcpwm, int timer)
|
||||
{
|
||||
mcpwm->timer_synci_cfg.val &= ~(0x07 << (this_timer * 3));
|
||||
mcpwm->timer_synci_cfg.val |= (extern_syncer + 4) << (this_timer * 3);
|
||||
// no sync input is selected, but software sync can still work
|
||||
mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3));
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_invert_external_syncer(mcpwm_dev_t *mcpwm, int sync_id, bool invert)
|
||||
static inline void mcpwm_ll_invert_gpio_synchro(mcpwm_dev_t *mcpwm, int sync_id, bool invert)
|
||||
{
|
||||
if (invert) {
|
||||
mcpwm->timer_synci_cfg.val |= 1 << (sync_id + 9);
|
||||
@ -524,6 +540,19 @@ static inline void mcpwm_ll_operator_enable_update_action_on_sync(mcpwm_dev_t *m
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_operator_set_trigger_gpio_fault(mcpwm_dev_t *mcpwm, int operator_id, int trig_id, int fault_id)
|
||||
{
|
||||
mcpwm->channel[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id));
|
||||
mcpwm->channel[operator_id].gen_cfg0.val |= (fault_id << (4 + 3 * trig_id));
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_operator_set_trigger_timer_sync(mcpwm_dev_t *mcpwm, int operator_id, int trig_id)
|
||||
{
|
||||
// the timer here is not selectable, must be the one connected with the operator
|
||||
mcpwm->channel[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id));
|
||||
mcpwm->channel[operator_id].gen_cfg0.val |= (3 << (4 + 3 * trig_id));
|
||||
}
|
||||
|
||||
/********************* Generator registers *******************/
|
||||
|
||||
static inline void mcpwm_ll_generator_reset_actions(mcpwm_dev_t *mcpwm, int operator_id, int generator_id)
|
||||
@ -567,31 +596,58 @@ static inline void mcpwm_ll_generator_set_action_on_trigger_event(mcpwm_dev_t *m
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_gen_set_onetime_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int action)
|
||||
static inline void mcpwm_ll_gen_trigger_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id)
|
||||
{
|
||||
if (generator_id == 0) {
|
||||
mcpwm->channel[operator_id].gen_force.a_nciforce_mode = action;
|
||||
mcpwm->channel[operator_id].gen_force.a_nciforce = ~mcpwm->channel[operator_id].gen_force.a_nciforce;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].gen_force.b_nciforce_mode = action;
|
||||
mcpwm->channel[operator_id].gen_force.b_nciforce = ~mcpwm->channel[operator_id].gen_force.b_nciforce;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_gen_set_continuous_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int action)
|
||||
static inline void mcpwm_ll_gen_disable_continue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id)
|
||||
{
|
||||
mcpwm->channel[operator_id].gen_force.cntu_force_upmethod = 0; // force action immediately
|
||||
mcpwm->channel[operator_id].gen_force.cntu_force_upmethod = 0; // update force method immediately
|
||||
if (generator_id == 0) {
|
||||
mcpwm->channel[operator_id].gen_force.a_cntuforce_mode = action;
|
||||
mcpwm->channel[operator_id].gen_force.a_cntuforce_mode = 0;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].gen_force.b_cntuforce_mode = action;
|
||||
mcpwm->channel[operator_id].gen_force.b_cntuforce_mode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_gen_disable_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id)
|
||||
{
|
||||
if (generator_id == 0) {
|
||||
mcpwm->channel[operator_id].gen_force.a_nciforce_mode = 0;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].gen_force.b_nciforce_mode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_gen_set_continue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level)
|
||||
{
|
||||
mcpwm->channel[operator_id].gen_force.cntu_force_upmethod = 0; // update force method immediately
|
||||
if (generator_id == 0) {
|
||||
mcpwm->channel[operator_id].gen_force.a_cntuforce_mode = level + 1;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].gen_force.b_cntuforce_mode = level + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level)
|
||||
{
|
||||
if (generator_id == 0) {
|
||||
mcpwm->channel[operator_id].gen_force.a_nciforce_mode = level + 1;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].gen_force.b_nciforce_mode = level + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/********************* Dead time registers *******************/
|
||||
|
||||
static inline void mcpwm_ll_deadtime_set_resolution_same_to_timer(mcpwm_dev_t *mcpwm, int operator_id, bool same)
|
||||
static inline void mcpwm_ll_deadtime_resolution_to_timer(mcpwm_dev_t *mcpwm, int operator_id, bool same)
|
||||
{
|
||||
// whether to make the resolution of dead time delay module the same to the timer connected with operator
|
||||
mcpwm->channel[operator_id].db_cfg.clk_sel = same;
|
||||
}
|
||||
|
||||
@ -637,7 +693,7 @@ static inline void mcpwm_ll_deadtime_enable_deb(mcpwm_dev_t *mcpwm, int operator
|
||||
mcpwm->channel[operator_id].db_cfg.deb_mode = enable;
|
||||
}
|
||||
|
||||
static inline uint32_t mcpwm_ll_deadtime_get_topology_code(mcpwm_dev_t *mcpwm, int operator_id)
|
||||
static inline uint32_t mcpwm_ll_deadtime_get_switch_topology(mcpwm_dev_t *mcpwm, int operator_id)
|
||||
{
|
||||
return (mcpwm->channel[operator_id].db_cfg.deb_mode << 8) | (mcpwm->channel[operator_id].db_cfg.b_outswap << 7) |
|
||||
(mcpwm->channel[operator_id].db_cfg.a_outswap << 6) | (mcpwm->channel[operator_id].db_cfg.fed_insel << 5) |
|
||||
@ -781,25 +837,32 @@ static inline void mcpwm_ll_fault_clear_ost(mcpwm_dev_t *mcpwm, int operator_id)
|
||||
|
||||
static inline void mcpwm_ll_fault_enable_oneshot_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable)
|
||||
{
|
||||
if (fault_sig == 0) {
|
||||
mcpwm->channel[operator_id].tz_cfg0.f0_ost = enable;
|
||||
} else if (fault_sig == 1) {
|
||||
mcpwm->channel[operator_id].tz_cfg0.f1_ost = enable;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].tz_cfg0.f2_ost = enable;
|
||||
}
|
||||
mcpwm->channel[operator_id].tz_cfg0.val &= ~(1 << (7 - fault_sig));
|
||||
mcpwm->channel[operator_id].tz_cfg0.val |= (enable << (7 - fault_sig));
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_fault_enable_cbc_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable)
|
||||
{
|
||||
if (fault_sig == 0) {
|
||||
mcpwm->channel[operator_id].tz_cfg0.f0_cbc = enable;
|
||||
} else if (fault_sig == 1) {
|
||||
mcpwm->channel[operator_id].tz_cfg0.f1_cbc = enable;
|
||||
mcpwm->channel[operator_id].tz_cfg0.val &= ~(1 << (3 - fault_sig));
|
||||
mcpwm->channel[operator_id].tz_cfg0.val |= (enable << (3 - fault_sig));
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
mcpwm->channel[operator_id].tz_cfg1.val |= 1 << 1;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].tz_cfg0.f2_cbc = enable;
|
||||
mcpwm->channel[operator_id].tz_cfg1.val &= ~(1 << 1);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
mcpwm->channel[operator_id].tz_cfg1.val |= 1 << 2;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].tz_cfg1.val &= ~(1 << 2);
|
||||
}
|
||||
mcpwm->channel[operator_id].tz_cfg1.cbcpulse = 1 << 0;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_fault_enable_sw_cbc(mcpwm_dev_t *mcpwm, int operator_id, bool enable)
|
||||
@ -817,20 +880,20 @@ static inline void mcpwm_ll_fault_trigger_sw_cbc(mcpwm_dev_t *mcpwm, int operato
|
||||
mcpwm->channel[operator_id].tz_cfg1.force_cbc = ~mcpwm->channel[operator_id].tz_cfg1.force_cbc;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_fault_trigger_sw_oneshot(mcpwm_dev_t *mcpwm, int operator_id)
|
||||
static inline void mcpwm_ll_fault_trigger_sw_ost(mcpwm_dev_t *mcpwm, int operator_id)
|
||||
{
|
||||
mcpwm->channel[operator_id].tz_cfg1.force_ost = ~mcpwm->channel[operator_id].tz_cfg1.force_ost;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_generator_set_action_on_fault_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id,
|
||||
mcpwm_timer_direction_t direction, mcpwm_fault_reaction_t reaction, int action)
|
||||
static inline void mcpwm_ll_generator_set_action_on_trip_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id,
|
||||
mcpwm_timer_direction_t direction, mcpwm_trip_type_t trip, int action)
|
||||
{
|
||||
if (direction == MCPWM_TIMER_DIRECTION_UP) {
|
||||
mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * reaction + 2));
|
||||
mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * reaction + 2);
|
||||
mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip + 2));
|
||||
mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip + 2);
|
||||
} else if (direction == MCPWM_TIMER_DIRECTION_DOWN) {
|
||||
mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * reaction));
|
||||
mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * reaction);
|
||||
mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip));
|
||||
mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip);
|
||||
}
|
||||
}
|
||||
|
||||
@ -856,12 +919,12 @@ static inline void mcpwm_ll_capture_enable_channel(mcpwm_dev_t *mcpwm, int chann
|
||||
mcpwm->cap_cfg_ch[channel].en = enable;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_capture_set_sync_phase(mcpwm_dev_t *mcpwm, uint32_t phase_value)
|
||||
static inline void mcpwm_ll_capture_set_sync_phase_value(mcpwm_dev_t *mcpwm, uint32_t phase_value)
|
||||
{
|
||||
mcpwm->cap_timer_phase = phase_value;
|
||||
}
|
||||
|
||||
static inline uint32_t mcpwm_ll_capture_get_sync_phase(mcpwm_dev_t *mcpwm)
|
||||
static inline uint32_t mcpwm_ll_capture_get_sync_phase_value(mcpwm_dev_t *mcpwm)
|
||||
{
|
||||
return mcpwm->cap_timer_phase;
|
||||
}
|
||||
@ -871,14 +934,14 @@ static inline void mcpwm_ll_capture_enable_timer_sync(mcpwm_dev_t *mcpwm, bool e
|
||||
mcpwm->cap_timer_cfg.synci_en = enable;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_capture_set_internal_timer_syncer(mcpwm_dev_t *mcpwm, int sync_out_timer)
|
||||
static inline void mcpwm_ll_capture_set_internal_timer_synchro(mcpwm_dev_t *mcpwm, int sync_out_timer)
|
||||
{
|
||||
mcpwm->cap_timer_cfg.synci_sel = sync_out_timer + 1;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_capture_set_external_syncer(mcpwm_dev_t *mcpwm, int extern_syncer)
|
||||
static inline void mcpwm_ll_capture_set_external_synchro(mcpwm_dev_t *mcpwm, int extern_synchro)
|
||||
{
|
||||
mcpwm->cap_timer_cfg.synci_sel = extern_syncer + 4;
|
||||
mcpwm->cap_timer_cfg.synci_sel = extern_synchro + 4;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_capture_trigger_sw_sync(mcpwm_dev_t *mcpwm)
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/mcpwm_struct.h"
|
||||
#include "hal/mcpwm_types.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -33,24 +34,28 @@ extern "C" {
|
||||
|
||||
/// Get the address of peripheral registers
|
||||
#define MCPWM_LL_GET_HW(ID) (((ID) == 0) ? &MCPWM0 : &MCPWM1)
|
||||
#define MCPWM_LL_MAX_PRESCALE 255
|
||||
#define MCPWM_LL_MAX_CAPTURE_PRESCALE 255
|
||||
#define MCPWM_LL_MAX_COMPARE_VALUE 65535
|
||||
#define MCPWM_LL_MAX_DEAD_DELAY 65535
|
||||
#define MCPWM_LL_MAX_PHASE_VALUE 65535
|
||||
|
||||
/********************* Group registers *******************/
|
||||
|
||||
// Set/Get group clock: PWM_clk = CLK_160M / (prescale + 1)
|
||||
static inline void mcpwm_ll_group_set_clock(mcpwm_dev_t *mcpwm, unsigned long long group_clk_hz)
|
||||
static inline void mcpwm_ll_group_set_clock_prescale(mcpwm_dev_t *mcpwm, int pre_scale)
|
||||
{
|
||||
mcpwm->clk_cfg.prescale = (SOC_MCPWM_BASE_CLK_HZ / group_clk_hz) - 1;
|
||||
mcpwm->clk_cfg.prescale = pre_scale - 1;
|
||||
}
|
||||
|
||||
static inline unsigned long long mcpwm_ll_group_get_clock(mcpwm_dev_t *mcpwm)
|
||||
static inline uint32_t mcpwm_ll_group_get_clock_prescale(mcpwm_dev_t *mcpwm)
|
||||
{
|
||||
return SOC_MCPWM_BASE_CLK_HZ / (mcpwm->clk_cfg.prescale + 1);
|
||||
return mcpwm->clk_cfg.prescale + 1;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_group_enable_shadow_mode(mcpwm_dev_t *mcpwm)
|
||||
{
|
||||
mcpwm->update_cfg.global_up_en = 1;
|
||||
// updating of active registers in MCPWM operators should be enabled
|
||||
mcpwm->update_cfg.op0_up_en = 1;
|
||||
mcpwm->update_cfg.op1_up_en = 1;
|
||||
mcpwm->update_cfg.op2_up_en = 1;
|
||||
@ -58,7 +63,8 @@ static inline void mcpwm_ll_group_enable_shadow_mode(mcpwm_dev_t *mcpwm)
|
||||
|
||||
static inline void mcpwm_ll_group_flush_shadow(mcpwm_dev_t *mcpwm)
|
||||
{
|
||||
mcpwm->update_cfg.val ^= (1 << 1);
|
||||
// a toggle can trigger a forced update of all active registers in MCPWM, i.e. shadow->active
|
||||
mcpwm->update_cfg.global_force_up = ~mcpwm->update_cfg.global_force_up;
|
||||
}
|
||||
|
||||
/********************* Interrupt registers *******************/
|
||||
@ -129,47 +135,47 @@ static inline uint32_t mcpwm_ll_intr_get_capture_status(mcpwm_dev_t *mcpwm)
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_timer_stop_status(mcpwm_dev_t *mcpwm, uint32_t timer_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (timer_mask & 0x07) << 0;
|
||||
mcpwm->int_clr.val = (timer_mask & 0x07) << 0;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_timer_tez_status(mcpwm_dev_t *mcpwm, uint32_t timer_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (timer_mask & 0x07) << 3;
|
||||
mcpwm->int_clr.val = (timer_mask & 0x07) << 3;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_timer_tep_status(mcpwm_dev_t *mcpwm, uint32_t timer_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (timer_mask & 0x07) << 6;
|
||||
mcpwm->int_clr.val = (timer_mask & 0x07) << 6;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_fault_enter_status(mcpwm_dev_t *mcpwm, uint32_t fault_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (fault_mask & 0x07) << 9;
|
||||
mcpwm->int_clr.val = (fault_mask & 0x07) << 9;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_fault_exit_status(mcpwm_dev_t *mcpwm, uint32_t fault_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (fault_mask & 0x07) << 12;
|
||||
mcpwm->int_clr.val = (fault_mask & 0x07) << 12;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_compare_status(mcpwm_dev_t *mcpwm, uint32_t operator_mask, uint32_t cmp_id)
|
||||
{
|
||||
mcpwm->int_clr.val |= (operator_mask & 0x07) << (15 + cmp_id * 3);
|
||||
mcpwm->int_clr.val = (operator_mask & 0x07) << (15 + cmp_id * 3);
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_trip_cbc_status(mcpwm_dev_t *mcpwm, uint32_t cbc_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (cbc_mask & 0x07) << 21;
|
||||
mcpwm->int_clr.val = (cbc_mask & 0x07) << 21;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_trip_ost_status(mcpwm_dev_t *mcpwm, uint32_t ost_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (ost_mask & 0x07) << 24;
|
||||
mcpwm->int_clr.val = (ost_mask & 0x07) << 24;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_clear_capture_status(mcpwm_dev_t *mcpwm, uint32_t capture_mask)
|
||||
{
|
||||
mcpwm->int_clr.val |= (capture_mask & 0x07) << 27;
|
||||
mcpwm->int_clr.val = (capture_mask & 0x07) << 27;
|
||||
}
|
||||
|
||||
//////////// enable interrupt for each event ////////////////
|
||||
@ -201,13 +207,20 @@ static inline void mcpwm_ll_intr_enable_timer_tep(mcpwm_dev_t *mcpwm, uint32_t t
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_enable_fault(mcpwm_dev_t *mcpwm, uint32_t fault_id, bool enable)
|
||||
static inline void mcpwm_ll_intr_enable_fault_enter(mcpwm_dev_t *mcpwm, uint32_t fault_id, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
mcpwm->int_ena.val |= 1 << (9 + fault_id); // enter fault interrupt
|
||||
mcpwm->int_ena.val |= 1 << (12 + fault_id); // exit fault interrupt
|
||||
} else {
|
||||
mcpwm->int_ena.val &= ~(1 << (9 + fault_id));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_enable_fault_exit(mcpwm_dev_t *mcpwm, uint32_t fault_id, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
mcpwm->int_ena.val |= 1 << (12 + fault_id); // exit fault interrupt
|
||||
} else {
|
||||
mcpwm->int_ena.val &= ~(1 << (12 + fault_id));
|
||||
}
|
||||
}
|
||||
@ -221,13 +234,20 @@ static inline void mcpwm_ll_intr_enable_compare(mcpwm_dev_t *mcpwm, uint32_t ope
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_enable_trip(mcpwm_dev_t *mcpwm, uint32_t operator_id, bool enable)
|
||||
static inline void mcpwm_ll_intr_enable_trip_cbc(mcpwm_dev_t *mcpwm, uint32_t operator_id, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
mcpwm->int_ena.val |= (1 << (21 + operator_id));
|
||||
mcpwm->int_ena.val |= (1 << (24 + operator_id));
|
||||
} else {
|
||||
mcpwm->int_ena.val &= ~(1 << (21 + operator_id));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_intr_enable_trip_ost(mcpwm_dev_t *mcpwm, uint32_t operator_id, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
mcpwm->int_ena.val |= (1 << (24 + operator_id));
|
||||
} else {
|
||||
mcpwm->int_ena.val &= ~(1 << (24 + operator_id));
|
||||
}
|
||||
}
|
||||
@ -243,14 +263,14 @@ static inline void mcpwm_ll_intr_enable_capture(mcpwm_dev_t *mcpwm, uint32_t cap
|
||||
|
||||
/********************* Timer registers *******************/
|
||||
|
||||
static inline void mcpwm_ll_timer_set_clock(mcpwm_dev_t *mcpwm, int timer_id, unsigned long long group_clock, unsigned long long timer_clock)
|
||||
static inline void mcpwm_ll_timer_set_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id, uint32_t prescale)
|
||||
{
|
||||
mcpwm->timer[timer_id].period.prescale = group_clock / timer_clock - 1;
|
||||
mcpwm->timer[timer_id].period.prescale = prescale - 1;
|
||||
}
|
||||
|
||||
static inline unsigned long long mcpwm_ll_timer_get_clock(mcpwm_dev_t *mcpwm, int timer_id, unsigned long long group_clock)
|
||||
static inline uint32_t mcpwm_ll_timer_get_clock_prescale(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
{
|
||||
return group_clock / (mcpwm->timer[timer_id].period.prescale + 1);
|
||||
return mcpwm->timer[timer_id].period.prescale + 1;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_set_peak(mcpwm_dev_t *mcpwm, int timer_id, uint32_t peak, bool symmetric)
|
||||
@ -327,9 +347,9 @@ static inline mcpwm_timer_count_mode_t mcpwm_ll_timer_get_count_mode(mcpwm_dev_t
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_set_operate_command(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_operate_cmd_t mode)
|
||||
static inline void mcpwm_ll_timer_set_execute_command(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_execute_cmd_t cmd)
|
||||
{
|
||||
switch (mode) {
|
||||
switch (cmd) {
|
||||
case MCPWM_TIMER_STOP_AT_ZERO:
|
||||
mcpwm->timer[timer_id].mode.start = 0;
|
||||
break;
|
||||
@ -348,23 +368,23 @@ static inline void mcpwm_ll_timer_set_operate_command(mcpwm_dev_t *mcpwm, int ti
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_set_count_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t value)
|
||||
{
|
||||
// we use software sync to set count value
|
||||
int previous_phase = mcpwm->timer[timer_id].sync.timer_phase;
|
||||
mcpwm->timer[timer_id].sync.timer_phase = value;
|
||||
mcpwm->timer[timer_id].sync.sync_sw = ~mcpwm->timer[timer_id].sync.sync_sw;
|
||||
mcpwm->timer[timer_id].sync.timer_phase = previous_phase;
|
||||
}
|
||||
|
||||
static inline uint32_t mcpwm_ll_timer_get_count_value(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
{
|
||||
return mcpwm->timer[timer_id].status.value;
|
||||
// status.value saves the "next count value", so need an extra round up here to get the current count value according to count mode
|
||||
// timer is paused
|
||||
if (mcpwm->timer[timer_id].mode.mode == 0) {
|
||||
return mcpwm->timer[timer_id].status.value;
|
||||
}
|
||||
if (mcpwm->timer[timer_id].status.direction) { // down direction
|
||||
return (mcpwm->timer[timer_id].status.value + 1) % (mcpwm->timer[timer_id].period.period + 1);
|
||||
}
|
||||
// up direction
|
||||
return (mcpwm->timer[timer_id].status.value + mcpwm->timer[timer_id].period.period) % (mcpwm->timer[timer_id].period.period + 1);
|
||||
}
|
||||
|
||||
static inline bool mcpwm_ll_is_timer_decreasing(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
static inline mcpwm_timer_direction_t mcpwm_ll_timer_get_count_direction(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
{
|
||||
return mcpwm->timer[timer_id].status.direction;
|
||||
return mcpwm->timer[timer_id].status.direction ? MCPWM_TIMER_DIRECTION_DOWN : MCPWM_TIMER_DIRECTION_UP;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_enable_sync_input(mcpwm_dev_t *mcpwm, int timer_id, bool enable)
|
||||
@ -372,8 +392,9 @@ static inline void mcpwm_ll_timer_enable_sync_input(mcpwm_dev_t *mcpwm, int time
|
||||
mcpwm->timer[timer_id].sync.in_en = enable;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_sync_out_same_in(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
static inline void mcpwm_ll_timer_sync_out_penetrate(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
{
|
||||
// sync_out is selected to sync_in
|
||||
mcpwm->timer[timer_id].sync.out_sel = 0;
|
||||
}
|
||||
|
||||
@ -383,47 +404,51 @@ static inline void mcpwm_ll_timer_sync_out_on_timer_event(mcpwm_dev_t *mcpwm, in
|
||||
mcpwm->timer[timer_id].sync.out_sel = 1;
|
||||
} else if (event == MCPWM_TIMER_EVENT_PEAK) {
|
||||
mcpwm->timer[timer_id].sync.out_sel = 2;
|
||||
} else {
|
||||
HAL_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_disable_sync_out(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
{
|
||||
// sync_out will always be zero
|
||||
mcpwm->timer[timer_id].sync.out_sel = 3;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_trigger_sw_sync(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
static inline void mcpwm_ll_timer_trigger_soft_sync(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
{
|
||||
mcpwm->timer[timer_id].sync.sync_sw = ~mcpwm->timer[timer_id].sync.sync_sw;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_set_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t reload_val)
|
||||
static inline void mcpwm_ll_timer_set_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id, uint32_t phase_value)
|
||||
{
|
||||
mcpwm->timer[timer_id].sync.timer_phase = reload_val;
|
||||
mcpwm->timer[timer_id].sync.timer_phase = phase_value;
|
||||
}
|
||||
|
||||
static inline uint32_t mcpwm_ll_timer_get_sync_phase_value(mcpwm_dev_t *mcpwm, int timer_id)
|
||||
static inline void mcpwm_ll_timer_set_sync_phase_direction(mcpwm_dev_t *mcpwm, int timer_id, mcpwm_timer_direction_t direction)
|
||||
{
|
||||
return mcpwm->timer[timer_id].sync.timer_phase;
|
||||
mcpwm->timer[timer_id].sync.phase_direct = direction;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_set_sync_phase_direction(mcpwm_dev_t *mcpwm, int timer_id, bool decrease)
|
||||
static inline void mcpwm_ll_timer_set_gpio_synchro(mcpwm_dev_t *mcpwm, int timer, int gpio_sync_id)
|
||||
{
|
||||
mcpwm->timer[timer_id].sync.phase_direct = decrease;
|
||||
mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3));
|
||||
mcpwm->timer_synci_cfg.val |= (gpio_sync_id + 4) << (timer * 3);
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_enable_sync_from_internal_timer(mcpwm_dev_t *mcpwm, int this_timer, int internal_sync_timer)
|
||||
static inline void mcpwm_ll_timer_set_timer_synchro(mcpwm_dev_t *mcpwm, int timer, int timer_sync_id)
|
||||
{
|
||||
mcpwm->timer_synci_cfg.val &= ~(0x07 << (this_timer * 3));
|
||||
mcpwm->timer_synci_cfg.val |= (internal_sync_timer + 1) << (this_timer * 3);
|
||||
mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3));
|
||||
mcpwm->timer_synci_cfg.val |= (timer_sync_id + 1) << (timer * 3);
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_timer_enable_sync_from_external(mcpwm_dev_t *mcpwm, int this_timer, int extern_syncer)
|
||||
static inline void mcpwm_ll_timer_set_soft_synchro(mcpwm_dev_t *mcpwm, int timer)
|
||||
{
|
||||
mcpwm->timer_synci_cfg.val &= ~(0x07 << (this_timer * 3));
|
||||
mcpwm->timer_synci_cfg.val |= (extern_syncer + 4) << (this_timer * 3);
|
||||
// no sync input is selected, but software sync can still work
|
||||
mcpwm->timer_synci_cfg.val &= ~(0x07 << (timer * 3));
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_invert_external_syncer(mcpwm_dev_t *mcpwm, int sync_id, bool invert)
|
||||
static inline void mcpwm_ll_invert_gpio_synchro(mcpwm_dev_t *mcpwm, int sync_id, bool invert)
|
||||
{
|
||||
if (invert) {
|
||||
mcpwm->timer_synci_cfg.val |= 1 << (sync_id + 9);
|
||||
@ -524,6 +549,19 @@ static inline void mcpwm_ll_operator_enable_update_action_on_sync(mcpwm_dev_t *m
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_operator_set_trigger_gpio_fault(mcpwm_dev_t *mcpwm, int operator_id, int trig_id, int fault_id)
|
||||
{
|
||||
mcpwm->channel[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id));
|
||||
mcpwm->channel[operator_id].gen_cfg0.val |= (fault_id << (4 + 3 * trig_id));
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_operator_set_trigger_timer_sync(mcpwm_dev_t *mcpwm, int operator_id, int trig_id)
|
||||
{
|
||||
// the timer here is not selectable, must be the one connected with the operator
|
||||
mcpwm->channel[operator_id].gen_cfg0.val &= ~(0x07 << (4 + 3 * trig_id));
|
||||
mcpwm->channel[operator_id].gen_cfg0.val |= (3 << (4 + 3 * trig_id));
|
||||
}
|
||||
|
||||
/********************* Generator registers *******************/
|
||||
|
||||
static inline void mcpwm_ll_generator_reset_actions(mcpwm_dev_t *mcpwm, int operator_id, int generator_id)
|
||||
@ -567,31 +605,58 @@ static inline void mcpwm_ll_generator_set_action_on_trigger_event(mcpwm_dev_t *m
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_gen_set_onetime_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int action)
|
||||
static inline void mcpwm_ll_gen_trigger_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id)
|
||||
{
|
||||
if (generator_id == 0) {
|
||||
mcpwm->channel[operator_id].gen_force.a_nciforce_mode = action;
|
||||
mcpwm->channel[operator_id].gen_force.a_nciforce = ~mcpwm->channel[operator_id].gen_force.a_nciforce;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].gen_force.b_nciforce_mode = action;
|
||||
mcpwm->channel[operator_id].gen_force.b_nciforce = ~mcpwm->channel[operator_id].gen_force.b_nciforce;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_gen_set_continuous_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int action)
|
||||
static inline void mcpwm_ll_gen_disable_continue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id)
|
||||
{
|
||||
mcpwm->channel[operator_id].gen_force.cntu_force_upmethod = 0; // force action immediately
|
||||
mcpwm->channel[operator_id].gen_force.cntu_force_upmethod = 0; // update force method immediately
|
||||
if (generator_id == 0) {
|
||||
mcpwm->channel[operator_id].gen_force.a_cntuforce_mode = action;
|
||||
mcpwm->channel[operator_id].gen_force.a_cntuforce_mode = 0;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].gen_force.b_cntuforce_mode = action;
|
||||
mcpwm->channel[operator_id].gen_force.b_cntuforce_mode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_gen_disable_noncontinue_force_action(mcpwm_dev_t *mcpwm, int operator_id, int generator_id)
|
||||
{
|
||||
if (generator_id == 0) {
|
||||
mcpwm->channel[operator_id].gen_force.a_nciforce_mode = 0;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].gen_force.b_nciforce_mode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_gen_set_continue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level)
|
||||
{
|
||||
mcpwm->channel[operator_id].gen_force.cntu_force_upmethod = 0; // update force method immediately
|
||||
if (generator_id == 0) {
|
||||
mcpwm->channel[operator_id].gen_force.a_cntuforce_mode = level + 1;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].gen_force.b_cntuforce_mode = level + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_gen_set_noncontinue_force_level(mcpwm_dev_t *mcpwm, int operator_id, int generator_id, int level)
|
||||
{
|
||||
if (generator_id == 0) {
|
||||
mcpwm->channel[operator_id].gen_force.a_nciforce_mode = level + 1;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].gen_force.b_nciforce_mode = level + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/********************* Dead time registers *******************/
|
||||
|
||||
static inline void mcpwm_ll_deadtime_set_resolution_same_to_timer(mcpwm_dev_t *mcpwm, int operator_id, bool same)
|
||||
static inline void mcpwm_ll_deadtime_resolution_to_timer(mcpwm_dev_t *mcpwm, int operator_id, bool same)
|
||||
{
|
||||
// whether to make the resolution of dead time delay module the same to the timer connected with operator
|
||||
mcpwm->channel[operator_id].db_cfg.clk_sel = same;
|
||||
}
|
||||
|
||||
@ -637,7 +702,7 @@ static inline void mcpwm_ll_deadtime_enable_deb(mcpwm_dev_t *mcpwm, int operator
|
||||
mcpwm->channel[operator_id].db_cfg.deb_mode = enable;
|
||||
}
|
||||
|
||||
static inline uint32_t mcpwm_ll_deadtime_get_topology_code(mcpwm_dev_t *mcpwm, int operator_id)
|
||||
static inline uint32_t mcpwm_ll_deadtime_get_switch_topology(mcpwm_dev_t *mcpwm, int operator_id)
|
||||
{
|
||||
return (mcpwm->channel[operator_id].db_cfg.deb_mode << 8) | (mcpwm->channel[operator_id].db_cfg.b_outswap << 7) |
|
||||
(mcpwm->channel[operator_id].db_cfg.a_outswap << 6) | (mcpwm->channel[operator_id].db_cfg.fed_insel << 5) |
|
||||
@ -781,25 +846,32 @@ static inline void mcpwm_ll_fault_clear_ost(mcpwm_dev_t *mcpwm, int operator_id)
|
||||
|
||||
static inline void mcpwm_ll_fault_enable_oneshot_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable)
|
||||
{
|
||||
if (fault_sig == 0) {
|
||||
mcpwm->channel[operator_id].tz_cfg0.f0_ost = enable;
|
||||
} else if (fault_sig == 1) {
|
||||
mcpwm->channel[operator_id].tz_cfg0.f1_ost = enable;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].tz_cfg0.f2_ost = enable;
|
||||
}
|
||||
mcpwm->channel[operator_id].tz_cfg0.val &= ~(1 << (7 - fault_sig));
|
||||
mcpwm->channel[operator_id].tz_cfg0.val |= (enable << (7 - fault_sig));
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_fault_enable_cbc_mode(mcpwm_dev_t *mcpwm, int operator_id, int fault_sig, bool enable)
|
||||
{
|
||||
if (fault_sig == 0) {
|
||||
mcpwm->channel[operator_id].tz_cfg0.f0_cbc = enable;
|
||||
} else if (fault_sig == 1) {
|
||||
mcpwm->channel[operator_id].tz_cfg0.f1_cbc = enable;
|
||||
mcpwm->channel[operator_id].tz_cfg0.val &= ~(1 << (3 - fault_sig));
|
||||
mcpwm->channel[operator_id].tz_cfg0.val |= (enable << (3 - fault_sig));
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tez(mcpwm_dev_t *mcpwm, int operator_id, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
mcpwm->channel[operator_id].tz_cfg1.val |= 1 << 1;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].tz_cfg0.f2_cbc = enable;
|
||||
mcpwm->channel[operator_id].tz_cfg1.val &= ~(1 << 1);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_fault_enable_cbc_refresh_on_tep(mcpwm_dev_t *mcpwm, int operator_id, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
mcpwm->channel[operator_id].tz_cfg1.val |= 1 << 2;
|
||||
} else {
|
||||
mcpwm->channel[operator_id].tz_cfg1.val &= ~(1 << 2);
|
||||
}
|
||||
mcpwm->channel[operator_id].tz_cfg1.cbcpulse = 1 << 0;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_fault_enable_sw_cbc(mcpwm_dev_t *mcpwm, int operator_id, bool enable)
|
||||
@ -817,20 +889,20 @@ static inline void mcpwm_ll_fault_trigger_sw_cbc(mcpwm_dev_t *mcpwm, int operato
|
||||
mcpwm->channel[operator_id].tz_cfg1.force_cbc = ~mcpwm->channel[operator_id].tz_cfg1.force_cbc;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_fault_trigger_sw_oneshot(mcpwm_dev_t *mcpwm, int operator_id)
|
||||
static inline void mcpwm_ll_fault_trigger_sw_ost(mcpwm_dev_t *mcpwm, int operator_id)
|
||||
{
|
||||
mcpwm->channel[operator_id].tz_cfg1.force_ost = ~mcpwm->channel[operator_id].tz_cfg1.force_ost;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_generator_set_action_on_fault_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id,
|
||||
mcpwm_timer_direction_t direction, mcpwm_fault_reaction_t reaction, int action)
|
||||
static inline void mcpwm_ll_generator_set_action_on_trip_event(mcpwm_dev_t *mcpwm, int operator_id, int generator_id,
|
||||
mcpwm_timer_direction_t direction, mcpwm_trip_type_t trip, int action)
|
||||
{
|
||||
if (direction == MCPWM_TIMER_DIRECTION_UP) {
|
||||
mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * reaction + 2));
|
||||
mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * reaction + 2);
|
||||
mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip + 2));
|
||||
mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip + 2);
|
||||
} else if (direction == MCPWM_TIMER_DIRECTION_DOWN) {
|
||||
mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * reaction));
|
||||
mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * reaction);
|
||||
mcpwm->channel[operator_id].tz_cfg0.val &= ~(0x03 << (8 + 8 * generator_id + 4 * trip));
|
||||
mcpwm->channel[operator_id].tz_cfg0.val |= action << (8 + 8 * generator_id + 4 * trip);
|
||||
}
|
||||
}
|
||||
|
||||
@ -856,12 +928,12 @@ static inline void mcpwm_ll_capture_enable_channel(mcpwm_dev_t *mcpwm, int chann
|
||||
mcpwm->cap_cfg_ch[channel].en = enable;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_capture_set_sync_phase(mcpwm_dev_t *mcpwm, uint32_t phase_value)
|
||||
static inline void mcpwm_ll_capture_set_sync_phase_value(mcpwm_dev_t *mcpwm, uint32_t phase_value)
|
||||
{
|
||||
mcpwm->cap_timer_phase = phase_value;
|
||||
}
|
||||
|
||||
static inline uint32_t mcpwm_ll_capture_get_sync_phase(mcpwm_dev_t *mcpwm)
|
||||
static inline uint32_t mcpwm_ll_capture_get_sync_phase_value(mcpwm_dev_t *mcpwm)
|
||||
{
|
||||
return mcpwm->cap_timer_phase;
|
||||
}
|
||||
@ -871,14 +943,14 @@ static inline void mcpwm_ll_capture_enable_timer_sync(mcpwm_dev_t *mcpwm, bool e
|
||||
mcpwm->cap_timer_cfg.synci_en = enable;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_capture_set_internal_timer_syncer(mcpwm_dev_t *mcpwm, int sync_out_timer)
|
||||
static inline void mcpwm_ll_capture_set_internal_timer_synchro(mcpwm_dev_t *mcpwm, int sync_out_timer)
|
||||
{
|
||||
mcpwm->cap_timer_cfg.synci_sel = sync_out_timer + 1;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_capture_set_external_syncer(mcpwm_dev_t *mcpwm, int extern_syncer)
|
||||
static inline void mcpwm_ll_capture_set_external_synchro(mcpwm_dev_t *mcpwm, int extern_synchro)
|
||||
{
|
||||
mcpwm->cap_timer_cfg.synci_sel = extern_syncer + 4;
|
||||
mcpwm->cap_timer_cfg.synci_sel = extern_synchro + 4;
|
||||
}
|
||||
|
||||
static inline void mcpwm_ll_capture_trigger_sw_sync(mcpwm_dev_t *mcpwm)
|
||||
|
@ -37,7 +37,7 @@ typedef enum {
|
||||
MCPWM_TIMER_START_NO_STOP, /*!< MCPWM timer starts couting */
|
||||
MCPWM_TIMER_START_STOP_AT_ZERO, /*!< MCPWM timer starts counting and stops when couting to zero */
|
||||
MCPWM_TIMER_START_STOP_AT_PEAK, /*!< MCPWM timer starts counting and stops when counting to peak */
|
||||
} mcpwm_timer_operate_cmd_t;
|
||||
} mcpwm_timer_execute_cmd_t;
|
||||
|
||||
typedef enum {
|
||||
MCPWM_GEN_ACTION_KEEP, /*!< Generator action: Keep the same level */
|
||||
@ -47,6 +47,6 @@ typedef enum {
|
||||
} mcpwm_generator_action_t;
|
||||
|
||||
typedef enum {
|
||||
MCPWM_FAULT_REACTION_CBC, /*!< Reaction on fault signal: recover cycle by cycle */
|
||||
MCPWM_FAULT_REACTION_OST, /*!< Reaction on fault signal: one shot trip */
|
||||
} mcpwm_fault_reaction_t;
|
||||
MCPWM_TRIP_TYPE_CBC, /*!< CBC trip type, shut down the operator cycle by cycle*/
|
||||
MCPWM_TRIP_TYPE_OST, /*!< OST trip type, shut down the operator in one shot */
|
||||
} mcpwm_trip_type_t;
|
||||
|
@ -236,26 +236,8 @@
|
||||
#define PWM1_CAP1_IN_IDX 113
|
||||
#define PWM1_OUT2B_IDX 113
|
||||
#define PWM1_CAP2_IN_IDX 114
|
||||
#define PWM2_OUT1H_IDX 114
|
||||
#define PWM2_FLTA_IDX 115
|
||||
#define PWM2_OUT1L_IDX 115
|
||||
#define PWM2_FLTB_IDX 116
|
||||
#define PWM2_OUT2H_IDX 116
|
||||
#define PWM2_CAP1_IN_IDX 117
|
||||
#define PWM2_OUT2L_IDX 117
|
||||
#define PWM2_CAP2_IN_IDX 118
|
||||
#define PWM2_OUT3H_IDX 118
|
||||
#define PWM2_CAP3_IN_IDX 119
|
||||
#define PWM2_OUT3L_IDX 119
|
||||
#define PWM3_FLTA_IDX 120
|
||||
#define PWM2_OUT4H_IDX 120
|
||||
#define PWM3_FLTB_IDX 121
|
||||
#define PWM2_OUT4L_IDX 121
|
||||
#define PWM3_CAP1_IN_IDX 122
|
||||
#define PWM3_CAP2_IN_IDX 123
|
||||
#define TWAI_TX_IDX 123
|
||||
#define CAN_TX_IDX TWAI_TX_IDX
|
||||
#define PWM3_CAP3_IN_IDX 124
|
||||
#define TWAI_BUS_OFF_ON_IDX 124
|
||||
#define CAN_BUS_OFF_ON_IDX TWAI_BUS_OFF_ON_IDX
|
||||
#define TWAI_CLKOUT_IDX 125
|
||||
@ -369,19 +351,11 @@
|
||||
#define I2S1O_DATA_OUT22_IDX 188
|
||||
#define I2S1O_DATA_OUT23_IDX 189
|
||||
#define I2S0I_H_SYNC_IDX 190
|
||||
#define PWM3_OUT1H_IDX 190
|
||||
#define I2S0I_V_SYNC_IDX 191
|
||||
#define PWM3_OUT1L_IDX 191
|
||||
#define I2S0I_H_ENABLE_IDX 192
|
||||
#define PWM3_OUT2H_IDX 192
|
||||
#define I2S1I_H_SYNC_IDX 193
|
||||
#define PWM3_OUT2L_IDX 193
|
||||
#define I2S1I_V_SYNC_IDX 194
|
||||
#define PWM3_OUT3H_IDX 194
|
||||
#define I2S1I_H_ENABLE_IDX 195
|
||||
#define PWM3_OUT3L_IDX 195
|
||||
#define PWM3_OUT4H_IDX 196
|
||||
#define PWM3_OUT4L_IDX 197
|
||||
#define U2RXD_IN_IDX 198
|
||||
#define U2TXD_OUT_IDX 198
|
||||
#define U2CTS_IN_IDX 199
|
||||
|
@ -158,10 +158,11 @@
|
||||
#define SOC_MCPWM_OPERATORS_PER_GROUP (3) ///< The number of operators that each group has
|
||||
#define SOC_MCPWM_COMPARATORS_PER_OPERATOR (2) ///< The number of comparators that each operator has
|
||||
#define SOC_MCPWM_GENERATORS_PER_OPERATOR (2) ///< The number of generators that each operator has
|
||||
#define SOC_MCPWM_FAULT_DETECTORS_PER_GROUP (3) ///< The number of fault signal detectors that each group has
|
||||
#define SOC_MCPWM_TRIGGERS_PER_OPERATOR (2) ///< The number of triggers that each operator has
|
||||
#define SOC_MCPWM_GPIO_FAULTS_PER_GROUP (3) ///< The number of GPIO fault signals that each group has
|
||||
#define SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP (1) ///< The number of capture timers that each group has
|
||||
#define SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER (3) ///< The number of capture channels that each capture timer has
|
||||
#define SOC_MCPWM_EXT_SYNCERS_PER_GROUP (3) ///< The number of external syncers that each group has
|
||||
#define SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP (3) ///< The number of GPIO synchros that each group has
|
||||
#define SOC_MCPWM_BASE_CLK_HZ (160000000ULL) ///< Base Clock frequency of 160MHz
|
||||
|
||||
/*-------------------------- MPU CAPS ----------------------------------------*/
|
||||
|
@ -53,7 +53,7 @@ const mcpwm_signal_conn_t mcpwm_periph_signals = {
|
||||
}
|
||||
}
|
||||
},
|
||||
.detectors = {
|
||||
.gpio_faults = {
|
||||
[0] = {
|
||||
.fault_sig = PWM0_F0_IN_IDX
|
||||
},
|
||||
@ -75,7 +75,7 @@ const mcpwm_signal_conn_t mcpwm_periph_signals = {
|
||||
.cap_sig = PWM0_CAP2_IN_IDX
|
||||
}
|
||||
},
|
||||
.ext_syncers = {
|
||||
.gpio_synchros = {
|
||||
[0] = {
|
||||
.sync_sig = PWM0_SYNC0_IN_IDX
|
||||
},
|
||||
@ -122,7 +122,7 @@ const mcpwm_signal_conn_t mcpwm_periph_signals = {
|
||||
}
|
||||
}
|
||||
},
|
||||
.detectors = {
|
||||
.gpio_faults = {
|
||||
[0] = {
|
||||
.fault_sig = PWM1_F0_IN_IDX
|
||||
},
|
||||
@ -144,7 +144,7 @@ const mcpwm_signal_conn_t mcpwm_periph_signals = {
|
||||
.cap_sig = PWM1_CAP2_IN_IDX
|
||||
}
|
||||
},
|
||||
.ext_syncers = {
|
||||
.gpio_synchros = {
|
||||
[0] = {
|
||||
.sync_sig = PWM1_SYNC0_IN_IDX
|
||||
},
|
||||
|
@ -71,10 +71,11 @@
|
||||
#define SOC_MCPWM_OPERATORS_PER_GROUP (3) ///< The number of operators that each group has
|
||||
#define SOC_MCPWM_COMPARATORS_PER_OPERATOR (2) ///< The number of comparators that each operator has
|
||||
#define SOC_MCPWM_GENERATORS_PER_OPERATOR (2) ///< The number of generators that each operator has
|
||||
#define SOC_MCPWM_FAULT_DETECTORS_PER_GROUP (3) ///< The number of fault signal detectors that each group has
|
||||
#define SOC_MCPWM_TRIGGERS_PER_OPERATOR (2) ///< The number of triggers that each operator has
|
||||
#define SOC_MCPWM_GPIO_FAULTS_PER_GROUP (3) ///< The number of fault signal detectors that each group has
|
||||
#define SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP (1) ///< The number of capture timers that each group has
|
||||
#define SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER (3) ///< The number of capture channels that each capture timer has
|
||||
#define SOC_MCPWM_EXT_SYNCERS_PER_GROUP (3) ///< The number of external syncers that each group has
|
||||
#define SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP (3) ///< The number of GPIO synchros that each group has
|
||||
#define SOC_MCPWM_BASE_CLK_HZ (160000000ULL) ///< Base Clock frequency of 160MHz
|
||||
|
||||
/*-------------------------- MPU CAPS ----------------------------------------*/
|
||||
|
@ -53,7 +53,7 @@ const mcpwm_signal_conn_t mcpwm_periph_signals = {
|
||||
}
|
||||
}
|
||||
},
|
||||
.detectors = {
|
||||
.gpio_faults = {
|
||||
[0] = {
|
||||
.fault_sig = PWM0_F0_IN_IDX
|
||||
},
|
||||
@ -75,7 +75,7 @@ const mcpwm_signal_conn_t mcpwm_periph_signals = {
|
||||
.cap_sig = PWM0_CAP2_IN_IDX
|
||||
}
|
||||
},
|
||||
.ext_syncers = {
|
||||
.gpio_synchros = {
|
||||
[0] = {
|
||||
.sync_sig = PWM0_SYNC0_IN_IDX
|
||||
},
|
||||
@ -122,7 +122,7 @@ const mcpwm_signal_conn_t mcpwm_periph_signals = {
|
||||
}
|
||||
}
|
||||
},
|
||||
.detectors = {
|
||||
.gpio_faults = {
|
||||
[0] = {
|
||||
.fault_sig = PWM1_F0_IN_IDX
|
||||
},
|
||||
@ -144,7 +144,7 @@ const mcpwm_signal_conn_t mcpwm_periph_signals = {
|
||||
.cap_sig = PWM1_CAP2_IN_IDX
|
||||
}
|
||||
},
|
||||
.ext_syncers = {
|
||||
.gpio_synchros = {
|
||||
[0] = {
|
||||
.sync_sig = PWM1_SYNC0_IN_IDX
|
||||
},
|
||||
|
@ -34,13 +34,13 @@ typedef struct {
|
||||
} operators[SOC_MCPWM_OPERATORS_PER_GROUP];
|
||||
struct {
|
||||
const uint32_t fault_sig;
|
||||
} detectors[SOC_MCPWM_FAULT_DETECTORS_PER_GROUP];
|
||||
} gpio_faults[SOC_MCPWM_GPIO_FAULTS_PER_GROUP];
|
||||
struct {
|
||||
const uint32_t cap_sig;
|
||||
} captures[SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER];
|
||||
struct {
|
||||
const uint32_t sync_sig;
|
||||
} ext_syncers[SOC_MCPWM_EXT_SYNCERS_PER_GROUP];
|
||||
} gpio_synchros[SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP];
|
||||
} groups[SOC_MCPWM_GROUPS];
|
||||
} mcpwm_signal_conn_t;
|
||||
|
||||
|
BIN
docs/_static/mcpwm-bldc-control.png
vendored
BIN
docs/_static/mcpwm-bldc-control.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 45 KiB |
@ -53,7 +53,7 @@ In this case we will describe a simple configuration to control a brushed DC mot
|
||||
|
||||
Configuration covers the following steps:
|
||||
|
||||
1. Selection of a MPWn unit that will be used to drive the motor. There are two units available on-board of {IDF_TARGET_NAME} and enumerated in :cpp:type:`mcpwm_unit_t`.
|
||||
1. Selection of a MCPWM unit that will be used to drive the motor. There are two units available on-board of {IDF_TARGET_NAME} and enumerated in :cpp:type:`mcpwm_unit_t`.
|
||||
2. Initialization of two GPIOs as output signals within selected unit by calling :cpp:func:`mcpwm_gpio_init`. The two output signals are typically used to command the motor to rotate right or left. All available signal options are listed in :cpp:type:`mcpwm_io_signals_t`. To set more than a single pin at a time, use function :cpp:func:`mcpwm_set_pin` together with :cpp:type:`mcpwm_pin_config_t`.
|
||||
3. Selection of a timer. There are three timers available within the unit. The timers are listed in :cpp:type:`mcpwm_timer_t`.
|
||||
4. Setting of the timer frequency and initial duty within :cpp:type:`mcpwm_config_t` structure.
|
||||
@ -146,7 +146,7 @@ The MCPWM has a carrier submodule used if galvanic isolation from the motor driv
|
||||
|
||||
To use the carrier submodule, it should be first initialized by calling :cpp:func:`mcpwm_carrier_init`. The carrier parameters are defined in :cpp:type:`mcpwm_carrier_config_t` structure invoked within the function call. Then the carrier functionality may be enabled by calling :cpp:func:`mcpwm_carrier_enable`.
|
||||
|
||||
The carrier parameters may be then alerted at a runtime by calling dedicated functions to change individual fields of the :cpp:type:`mcpwm_carrier_config_t` structure, like :cpp:func:`mcpwm_carrier_set_period`, :cpp:func:`mcpwm_carrier_set_duty_cycle`, :cpp:func:`mcpwm_carrier_output_invert`, etc.
|
||||
The carrier parameters may be then altered at a runtime by calling dedicated functions to change individual fields of the :cpp:type:`mcpwm_carrier_config_t` structure, like :cpp:func:`mcpwm_carrier_set_period`, :cpp:func:`mcpwm_carrier_set_duty_cycle`, :cpp:func:`mcpwm_carrier_output_invert`, etc.
|
||||
|
||||
This includes enabling and setting duration of the first pulse of the career with :cpp:func:`mcpwm_carrier_oneshot_mode_enable`. For more details, see *{IDF_TARGET_NAME} Technical Reference Manual* > *Motor Control PWM (MCPWM)* > *PWM Carrier Submodule* [`PDF <{IDF_TARGET_TRM_EN_URL}#mcpwm>`__].
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
| Supported Targets | ESP32 |
|
||||
| ----------------- | ----- |
|
||||
| Supported Targets | ESP32 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- |
|
||||
|
||||
# MCPWM BLDC motor control(hall sensor feedback) Example
|
||||
# MCPWM BLDC motor control (hall sensor feedback) Example
|
||||
|
||||
This example will show you how to use MCPWM module to control BLDC motor with hall sensor feedback.
|
||||
|
||||
This example will show you how to use MCPWM module to control bldc motor with hall sensor feedback
|
||||
|
||||
The following examples uses MCPWM module to control bldc motor and vary its speed continuously
|
||||
|
||||
The bldc motor used for testing this code had hall sensor capture sequence of 6-->4-->5-->1-->3-->2-->6-->4--> and so on
|
||||
@ -13,7 +13,7 @@ IR2136 3-ph bridge driver is used for testing this example code
|
||||
|
||||
User needs to make changes according to the motor and gate driver ic used
|
||||
|
||||
|
||||
|
||||
## Step 1: Pin assignment
|
||||
* The gpio init function initializes:
|
||||
* GPIO15 is assigned as the MCPWM signal for 1H(UH)
|
||||
|
@ -215,7 +215,7 @@ static void mcpwm_example_bldc_control(void *arg)
|
||||
//2. initial mcpwm configuration
|
||||
printf("Configuring Initial Parameters of mcpwm bldc control...\n");
|
||||
mcpwm_config_t pwm_config;
|
||||
pwm_config.frequency = 1000; //frequency = 1000Hz
|
||||
pwm_config.frequency = 14400; //frequency = 1000Hz
|
||||
pwm_config.cmpr_a = 50.0; //duty cycle of PWMxA = 50.0%
|
||||
pwm_config.cmpr_b = 50.0; //duty cycle of PWMxb = 50.0%
|
||||
pwm_config.counter_mode = MCPWM_UP_COUNTER;
|
||||
|
@ -1,22 +1,59 @@
|
||||
| Supported Targets | ESP32 |
|
||||
| ----------------- | ----- |
|
||||
| Supported Targets | ESP32 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- |
|
||||
# MCPWM RC Servo Control Example
|
||||
|
||||
# MCPWM servo motor control Example
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example will show you how to use MCPWM module to control servo motor
|
||||
|
||||
Assign pulse width range and the maximum degree, accordingly the servo will move from 0 to maximum degree continuously
|
||||
|
||||
This example illustrates how to drive a typical [RC Servo](https://en.wikipedia.org/wiki/Servo_(radio_control)) by sending a PWM signal using the MCPWM driver. The PWM pulse has a frequency of 50Hz (period of 20ms), and the active-high time (which controls the rotation) ranges from 1ms to 2ms with 1.5ms always being center of range.
|
||||
|
||||
## Step 1: Pin assignment
|
||||
* GPIO18 is assigned as the MCPWM signal for servo motor
|
||||
## How to Use Example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* A development board with any Espressif SoC which features MCPWM peripheral (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.)
|
||||
* A USB cable for Power supply and programming
|
||||
* A RC servo motor, e.g. [SG90](http://www.ee.ic.ac.uk/pcheung/teaching/DE1_EE/stores/sg90_datasheet.pdf)
|
||||
|
||||
Connection :
|
||||
|
||||
```
|
||||
+-------+ +-----------------+
|
||||
| | | |
|
||||
| +-+ GPIO18++ PWM(Orange) +----------+ |
|
||||
| ESP |---5V------+ Vcc(Red) +--------------| Servo Motor |
|
||||
| +---------+ GND(Brown) +----------+ |
|
||||
| | | |
|
||||
+-------+ +-----------------+
|
||||
```
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
|
||||
## Step 2: Connection
|
||||
* connect GPIO18 with servo pwm signal
|
||||
* other two wires of servo motor are VCC and GND
|
||||
## Example Output
|
||||
|
||||
Run the example, you will see the following output log:
|
||||
|
||||
## Step 3: Initialize MCPWM
|
||||
* You need to set the frequency(generally 50 Hz) and duty cycle of MCPWM timer
|
||||
* You need to set the MCPWM channel you want to use, and bind the channel with one of the timers
|
||||
```
|
||||
...
|
||||
I (0) cpu_start: Starting scheduler on APP CPU.
|
||||
I (349) example: Angle of rotation: -90
|
||||
I (449) example: Angle of rotation: -89
|
||||
I (549) example: Angle of rotation: -88
|
||||
I (649) example: Angle of rotation: -87
|
||||
I (749) example: Angle of rotation: -86
|
||||
...
|
||||
```
|
||||
|
||||
The servo will rotate from -90 degree to 90 degree, and then turn back again.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Note that, some kind of servo might need a higher current supply than the development board usually can provide. It's recommended to power the servo separately.
|
||||
|
||||
For any technical queries, please open an [issue] (https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
|
||||
|
@ -1,2 +1,2 @@
|
||||
idf_component_register(SRCS "mcpwm_servo_control_example.c"
|
||||
idf_component_register(SRCS "mcpwm_servo_control_example_main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
|
@ -1,77 +0,0 @@
|
||||
/* servo motor control example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
#include "driver/mcpwm.h"
|
||||
#include "soc/mcpwm_periph.h"
|
||||
|
||||
//You can get these value from the datasheet of servo you use, in general pulse width varies between 1000 to 2000 mocrosecond
|
||||
#define SERVO_MIN_PULSEWIDTH 1000 //Minimum pulse width in microsecond
|
||||
#define SERVO_MAX_PULSEWIDTH 2000 //Maximum pulse width in microsecond
|
||||
#define SERVO_MAX_DEGREE 90 //Maximum angle in degree upto which servo can rotate
|
||||
|
||||
static void mcpwm_example_gpio_initialize(void)
|
||||
{
|
||||
printf("initializing mcpwm servo control gpio......\n");
|
||||
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, 18); //Set GPIO 18 as PWM0A, to which servo is connected
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Use this function to calcute pulse width for per degree rotation
|
||||
*
|
||||
* @param degree_of_rotation the angle in degree to which servo has to rotate
|
||||
*
|
||||
* @return
|
||||
* - calculated pulse width
|
||||
*/
|
||||
static uint32_t servo_per_degree_init(uint32_t degree_of_rotation)
|
||||
{
|
||||
uint32_t cal_pulsewidth = 0;
|
||||
cal_pulsewidth = (SERVO_MIN_PULSEWIDTH + (((SERVO_MAX_PULSEWIDTH - SERVO_MIN_PULSEWIDTH) * (degree_of_rotation)) / (SERVO_MAX_DEGREE)));
|
||||
return cal_pulsewidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure MCPWM module
|
||||
*/
|
||||
void mcpwm_example_servo_control(void *arg)
|
||||
{
|
||||
uint32_t angle, count;
|
||||
//1. mcpwm gpio initialization
|
||||
mcpwm_example_gpio_initialize();
|
||||
|
||||
//2. initial mcpwm configuration
|
||||
printf("Configuring Initial Parameters of mcpwm......\n");
|
||||
mcpwm_config_t pwm_config;
|
||||
pwm_config.frequency = 50; //frequency = 50Hz, i.e. for every servo motor time period should be 20ms
|
||||
pwm_config.cmpr_a = 0; //duty cycle of PWMxA = 0
|
||||
pwm_config.cmpr_b = 0; //duty cycle of PWMxb = 0
|
||||
pwm_config.counter_mode = MCPWM_UP_COUNTER;
|
||||
pwm_config.duty_mode = MCPWM_DUTY_MODE_0;
|
||||
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config); //Configure PWM0A & PWM0B with above settings
|
||||
while (1) {
|
||||
for (count = 0; count < SERVO_MAX_DEGREE; count++) {
|
||||
printf("Angle of rotation: %d\n", count);
|
||||
angle = servo_per_degree_init(count);
|
||||
printf("pulse width: %dus\n", angle);
|
||||
mcpwm_set_duty_in_us(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, angle);
|
||||
vTaskDelay(10); //Add delay, since it takes time for servo to rotate, generally 100ms/60degree rotation at 5V
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
printf("Testing servo motor.......\n");
|
||||
xTaskCreate(mcpwm_example_servo_control, "mcpwm_example_servo_control", 4096, NULL, 5, NULL);
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/* Servo Motor control example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/mcpwm.h"
|
||||
|
||||
static const char *TAG = "example";
|
||||
|
||||
// You can get these value from the datasheet of servo you use, in general pulse width varies between 1000 to 2000 mocrosecond
|
||||
#define SERVO_MIN_PULSEWIDTH_US (1000) // Minimum pulse width in microsecond
|
||||
#define SERVO_MAX_PULSEWIDTH_US (2000) // Maximum pulse width in microsecond
|
||||
#define SERVO_MAX_DEGREE (90) // Maximum angle in degree upto which servo can rotate
|
||||
|
||||
#define SERVO_PULSE_GPIO (18) // GPIO connects to the PWM signal line
|
||||
|
||||
static inline uint32_t example_convert_servo_angle_to_duty_us(int angle)
|
||||
{
|
||||
return (angle + SERVO_MAX_DEGREE) * (SERVO_MAX_PULSEWIDTH_US - SERVO_MIN_PULSEWIDTH_US) / (2 * SERVO_MAX_DEGREE) + SERVO_MIN_PULSEWIDTH_US;
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, SERVO_PULSE_GPIO); // To drive a RC servo, one MCPWM generator is enough
|
||||
|
||||
mcpwm_config_t pwm_config = {
|
||||
.frequency = 50, // frequency = 50Hz, i.e. for every servo motor time period should be 20ms
|
||||
.cmpr_a = 0, // duty cycle of PWMxA = 0
|
||||
.counter_mode = MCPWM_UP_COUNTER,
|
||||
.duty_mode = MCPWM_DUTY_MODE_0,
|
||||
};
|
||||
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config);
|
||||
|
||||
while (1) {
|
||||
for (int angle = -SERVO_MAX_DEGREE; angle < SERVO_MAX_DEGREE; angle++) {
|
||||
ESP_LOGI(TAG, "Angle of rotation: %d", angle);
|
||||
ESP_ERROR_CHECK(mcpwm_set_duty_in_us(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, example_convert_servo_angle_to_duty_us(angle)));
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); //Add delay, since it takes time for servo to rotate, generally 100ms/60degree rotation under 5V power supply
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user