Merge branch 'feature/ledc' into 'master'
driver: ledc update 1. add fading functions. 2. clear up ledc.h 3. update api doc. 4. add ledc example See merge request !347
This commit is contained in:
commit
ad1d4500f9
|
@ -16,9 +16,6 @@
|
|||
#define _DRIVER_LEDC_H_
|
||||
#include "esp_err.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/ledc_reg.h"
|
||||
#include "soc/ledc_reg.h"
|
||||
#include "soc/ledc_struct.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
|
@ -68,6 +65,7 @@ typedef enum {
|
|||
LEDC_CHANNEL_5, /*!< LEDC channel 5 */
|
||||
LEDC_CHANNEL_6, /*!< LEDC channel 6 */
|
||||
LEDC_CHANNEL_7, /*!< LEDC channel 7 */
|
||||
LEDC_CHANNEL_MAX,
|
||||
} ledc_channel_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -79,6 +77,11 @@ typedef enum {
|
|||
LEDC_TIMER_15_BIT = 15, /*!< LEDC PWM depth 15Bit */
|
||||
} ledc_timer_bit_t;
|
||||
|
||||
typedef enum {
|
||||
LEDC_FADE_NO_WAIT = 0, /*!< LEDC fade function will return immediately */
|
||||
LEDC_FADE_WAIT_DONE, /*!< LEDC fade function will block until fading to the target duty*/
|
||||
LEDC_FADE_MAX,
|
||||
} ledc_fade_mode_t;
|
||||
/**
|
||||
* @brief Configuration parameters of LEDC channel for ledc_channel_config function
|
||||
*/
|
||||
|
@ -104,43 +107,39 @@ typedef struct {
|
|||
typedef intr_handle_t ledc_isr_handle_t;
|
||||
|
||||
/**
|
||||
* @brief LEDC channel configuration
|
||||
* @brief LEDC channel configuration
|
||||
* Configure LEDC channel with the given channel/output gpio_num/interrupt/source timer/frequency(Hz)/LEDC depth
|
||||
*
|
||||
* User this Function, configure LEDC channel with the given channel/output gpio_num/interrupt/source timer/frequency(Hz)/LEDC depth
|
||||
* @param ledc_conf Pointer of LEDC channel configure struct
|
||||
*
|
||||
* @param ledc_conf Pointer of LEDC channel configure struct
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*
|
||||
*/
|
||||
esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf);
|
||||
|
||||
/**
|
||||
* @brief LEDC timer configuration
|
||||
*
|
||||
* User this Function, configure LEDC timer with the given source timer/frequency(Hz)/bit_num
|
||||
* @brief LEDC timer configuration
|
||||
* Configure LEDC timer with the given source timer/frequency(Hz)/bit_num
|
||||
*
|
||||
* @param timer_conf Pointer of LEDC timer configure struct
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_FAIL Can not find a proper pre-divider number base on the given frequency and the current bit_num.
|
||||
*
|
||||
*/
|
||||
esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf);
|
||||
|
||||
/**
|
||||
* @brief LEDC update channel parameters
|
||||
* @brief LEDC update channel parameters
|
||||
* Call this function to activate the LEDC updated parameters.
|
||||
* After ledc_set_duty, ledc_set_fade, we need to call this function to update the settings.
|
||||
*
|
||||
* Call this function to activate the LEDC updated parameters.
|
||||
* After ledc_set_duty, ledc_set_fade, we need to call this function to update the settings.
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param channel LEDC channel(0-7), select from ledc_channel_t
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode,
|
||||
* now we only support high-speed mode.
|
||||
* We will access low-speed mode in next version
|
||||
* @param channel LEDC channel(0-7), select from ledc_channel_t
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
|
@ -150,14 +149,11 @@ esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf);
|
|||
esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
|
||||
|
||||
/**
|
||||
* @brief LEDC stop
|
||||
*
|
||||
* Disable LEDC output, and set idle level
|
||||
* @brief LEDC stop.
|
||||
* Disable LEDC output, and set idle level
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param channel LEDC channel(0-7), select from ledc_channel_t
|
||||
*
|
||||
* @param idle_level Set output idle level after LEDC stops.
|
||||
*
|
||||
* @return
|
||||
|
@ -167,14 +163,10 @@ esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
|
|||
esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_level);
|
||||
|
||||
/**
|
||||
* @brief LEDC set channel frequency(Hz)
|
||||
*
|
||||
* Set LEDC frequency(Hz)
|
||||
* @brief LEDC set channel frequency(Hz)
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param timer_num LEDC timer index(0-3), select from ledc_timer_t
|
||||
*
|
||||
* @param freq_hz Set the LEDC frequency
|
||||
*
|
||||
* @return
|
||||
|
@ -188,25 +180,20 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t
|
|||
* @brief LEDC get channel frequency(Hz)
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param timer_num LEDC timer index(0-3), select from ledc_timer_t
|
||||
*
|
||||
* @return
|
||||
* - 0 error
|
||||
* - Others Current LEDC frequency
|
||||
*
|
||||
*/
|
||||
uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num);
|
||||
|
||||
/**
|
||||
* @brief LEDC set duty
|
||||
*
|
||||
* Set LEDC duty, After the function calls the ledc_update_duty function, the function can take effect.
|
||||
* @brief LEDC set duty
|
||||
* Only after calling ledc_update_duty will the duty update.
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param channel LEDC channel(0-7), select from ledc_channel_t
|
||||
*
|
||||
* @param duty Set the LEDC duty, the duty range is [0, (2**bit_num) - 1]
|
||||
*
|
||||
* @return
|
||||
|
@ -216,37 +203,27 @@ uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num);
|
|||
esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty);
|
||||
|
||||
/**
|
||||
* @brief LEDC get duty
|
||||
* @brief LEDC get duty
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param channel LEDC channel(0-7), select from ledc_channel_t
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* - (-1) parameter error
|
||||
* - Others Current LEDC duty
|
||||
*
|
||||
*/
|
||||
int ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
|
||||
|
||||
/**
|
||||
* @brief LEDC set gradient
|
||||
*
|
||||
* Set LEDC gradient, After the function calls the ledc_update_duty function, the function can take effect.
|
||||
* @brief LEDC set gradient
|
||||
* Set LEDC gradient, After the function calls the ledc_update_duty function, the function can take effect.
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param channel LEDC channel(0-7), select from ledc_channel_t
|
||||
*
|
||||
* @param duty Set the start of the gradient duty, the duty range is [0, (2**bit_num) - 1]
|
||||
*
|
||||
* @param gradule_direction Set the direction of the gradient
|
||||
*
|
||||
* @param step_num Set the number of the gradient
|
||||
*
|
||||
* @param duty_cyle_num Set how many LEDC tick each time the gradient lasts
|
||||
*
|
||||
* @param duty_scale Set gradient change amplitude
|
||||
*
|
||||
* @return
|
||||
|
@ -257,16 +234,16 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
|
|||
uint32_t step_num, uint32_t duty_cyle_num, uint32_t duty_scale);
|
||||
|
||||
/**
|
||||
* @brief register LEDC interrupt handler, the handler is an ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
* @brief Register LEDC interrupt handler, the handler is an ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
*
|
||||
* @param fn Interrupt handler function.
|
||||
* @param arg User-supplied argument passed to the handler function.
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
* @param arg Parameter for handler function
|
||||
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
|
||||
* be returned here.
|
||||
* @param fn Interrupt handler function.
|
||||
* @param arg User-supplied argument passed to the handler function.
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
* @param arg Parameter for handler function
|
||||
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
|
||||
* be returned here.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
|
@ -275,48 +252,38 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
|
|||
esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, ledc_isr_handle_t *handle);
|
||||
|
||||
/**
|
||||
* @brief configure LEDC settings
|
||||
* @brief Configure LEDC settings
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param timer_sel Timer index(0-3), there are 4 timers in LEDC module
|
||||
*
|
||||
* @param div_num Timer clock divide number, the timer clock is divided from the selected clock source
|
||||
*
|
||||
* @param bit_num The count number of one period, counter range is 0 ~ ((2 ** bit_num) - 1)
|
||||
*
|
||||
* @param clk_src Select LEDC source clock.
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
* @param timer_sel Timer index(0-3), there are 4 timers in LEDC module
|
||||
* @param div_num Timer clock divide number, the timer clock is divided from the selected clock source
|
||||
* @param bit_num The count number of one period, counter range is 0 ~ ((2 ** bit_num) - 1)
|
||||
* @param clk_src Select LEDC source clock.
|
||||
*
|
||||
* @return
|
||||
* - (-1) Parameter error
|
||||
* - Other Current LEDC duty
|
||||
*
|
||||
*/
|
||||
esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t div_num, uint32_t bit_num, ledc_clk_src_t clk_src);
|
||||
|
||||
/**
|
||||
* @brief reset LEDC timer
|
||||
* @brief Reset LEDC timer
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param timer_sel LEDC timer index(0-3), select from ledc_timer_t
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_OK Success
|
||||
*
|
||||
*/
|
||||
esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel);
|
||||
|
||||
/**
|
||||
* @brief pause LEDC timer counter
|
||||
* @brief Pause LEDC timer counter
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param timer_sel LEDC timer index(0-3), select from ledc_timer_t
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_OK Success
|
||||
|
@ -325,104 +292,96 @@ esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel);
|
|||
esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel);
|
||||
|
||||
/**
|
||||
* @brief pause LEDC timer resume
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param timer_sel LEDC timer index(0-3), select from ledc_timer_t
|
||||
* @brief Resume LEDC timer
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
* @param timer_sel LEDC timer index(0-3), select from ledc_timer_t
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_OK Success
|
||||
*
|
||||
*/
|
||||
esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel);
|
||||
|
||||
/**
|
||||
* @brief bind LEDC channel with the selected timer
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
*
|
||||
* @param channel LEDC channel index(0-7), select from ledc_channel_t
|
||||
*
|
||||
* @param timer_idx LEDC timer index(0-3), select from ledc_timer_t
|
||||
* @brief Bind LEDC channel with the selected timer
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version
|
||||
* @param channel LEDC channel index(0-7), select from ledc_channel_t
|
||||
* @param timer_idx LEDC timer index(0-3), select from ledc_timer_t
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint32_t timer_idx);
|
||||
|
||||
/**
|
||||
* @brief Set LEDC fade function. Should call ledc_fade_func_install() before calling this function.
|
||||
* Call ledc_fade_start() after this to start fading.
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode,
|
||||
* For now we only support high-speed mode. We will access low-speed mode soon.
|
||||
* @param channel LEDC channel index(0-7), select from ledc_channel_t
|
||||
* @param target_duty Target duty of fading.( 0 - (2 ** bit_num - 1)))
|
||||
* @param scale Controls the increase or decrease step scale.
|
||||
* @param cycle_num increase or decrease the duty every cycle_num cycles
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE Fade function not installed.
|
||||
*/
|
||||
esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int scale, int cycle_num);
|
||||
|
||||
/**
|
||||
* @brief Set LEDC fade function, with a limited time. Should call ledc_fade_func_install() before calling this function.
|
||||
* Call ledc_fade_start() after this to start fading.
|
||||
*
|
||||
* @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode,
|
||||
* For now we only support high-speed mode. We will access low-speed mode soon.
|
||||
* @param channel LEDC channel index(0-7), select from ledc_channel_t
|
||||
* @param target_duty Target duty of fading.( 0 - (2 ** bit_num - 1)))
|
||||
* @param max_fade_time_ms The maximum time of the fading ( ms ).
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE Fade function not installed.
|
||||
*/
|
||||
esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int max_fade_time_ms);
|
||||
|
||||
/**
|
||||
* @brief Install ledc fade function. This function will occupy interrupt of LEDC module.
|
||||
*
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_NO_MEM No enough memory
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE Fade function already installed.
|
||||
*/
|
||||
esp_err_t ledc_fade_func_install(int intr_alloc_flags);
|
||||
|
||||
/**
|
||||
* @brief Uninstall LEDC fade function.
|
||||
*
|
||||
*/
|
||||
esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t timer_idx);
|
||||
void ledc_fade_func_uninstall();
|
||||
|
||||
/***************************EXAMPLE**********************************
|
||||
/**
|
||||
* @brief Start LEDC fading.
|
||||
*
|
||||
* @param channel LEDC channel number
|
||||
* @param wait_done Whether to block until fading done.
|
||||
*
|
||||
* ----------------EXAMPLE OF LEDC SETTING ---------------------
|
||||
* @code{c}
|
||||
* //1. enable LEDC
|
||||
* //enable LEDC module, or you can not set any register of it.
|
||||
* periph_module_enable(PERIPH_LEDC_MODULE);
|
||||
* @endcode
|
||||
*
|
||||
* @code{c}
|
||||
* //2. set LEDC timer
|
||||
* ledc_timer_config_t timer_conf = {
|
||||
* .bit_num = LEDC_TIMER_12_BIT, //set timer counter bit number
|
||||
* .freq_hz = 1000, //set frequency of pwm, here, 1000Hz
|
||||
* .speed_mode = LEDC_HIGH_SPEED_MODE, //timer mode,
|
||||
* .timer_num = LEDC_TIMER_0, //timer number
|
||||
* };
|
||||
* ledc_timer_config(&timer_conf); //setup timer.
|
||||
* @endcode
|
||||
*
|
||||
* @code{c}
|
||||
* //3. set LEDC channel
|
||||
* ledc_channel_config_t ledc_conf = {
|
||||
* .channel = LEDC_CHANNEL_0; //set LEDC channel 0
|
||||
* .duty = 1000; //set the duty for initialization.(duty range is 0 ~ ((2**bit_num)-1)
|
||||
* .gpio_num = 16; //GPIO number
|
||||
* .intr_type = LEDC_INTR_FADE_END; //GPIO INTR TYPE, as an example, we enable fade_end interrupt here.
|
||||
* .speed_mode = LEDC_HIGH_SPEED_MODE; //set LEDC mode, from ledc_mode_t
|
||||
* .timer_sel = LEDC_TIMER_0; //set LEDC timer source, if different channel use one timer, the frequency and bit_num of these channels should be the same
|
||||
* }
|
||||
* ledc_channel_config(&ledc_conf); //setup the configuration
|
||||
*
|
||||
* ----------------EXAMPLE OF SETTING DUTY --- -----------------
|
||||
* @code{c}
|
||||
* ledc_channel_t ledc_channel = LEDC_CHANNEL_0; //LEDC channel(0-73)
|
||||
* uint32_t duty = 2000; //duty range is 0 ~ ((2**bit_num)-1)
|
||||
* LEDC_set_duty(LEDC_HIGH_SPEED_MODE, ledc_channel, duty); //set speed mode, channel, and duty.
|
||||
* ledc_update_duty(LEDC_HIGH_SPEED_MODE, ledc_channel); //after set duty, we need to call ledc_update_duty to update the settings.
|
||||
* @endcode
|
||||
*
|
||||
* ----------------EXAMPLE OF LEDC INTERRUPT ------------------
|
||||
* @code{c}
|
||||
* //we have fade_end interrupt and counter overflow interrupt. we just give an example of fade_end interrupt here.
|
||||
* ledc_isr_register(ledc_isr_handler, NULL, 0); //hook the isr handler for LEDC interrupt
|
||||
* @endcode
|
||||
*
|
||||
* ----------------EXAMPLE OF INTERRUPT HANDLER ---------------
|
||||
* @code{c}
|
||||
* #include "esp_attr.h"
|
||||
* void IRAM_ATTR ledc_isr_handler(void* arg) //we should add 'IRAM_ATTR' attribution when we declare the isr function
|
||||
* {
|
||||
* uint32_t intr_st = LEDC.int_st.val; //read LEDC interrupt status.
|
||||
*
|
||||
* //you will find which channels have triggered fade_end interrupt here,
|
||||
* //then, you can post some event to RTOS queue to process the event.
|
||||
* //later we will add a queue in the driver code.
|
||||
*
|
||||
* LEDC.int_clr.val = intr_st; //clear LEDC interrupt status.
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
*--------------------------END OF EXAMPLE --------------------------
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_STATE Fade function not installed.
|
||||
* - ESP_ERR_INVALID_ARG Parameter error.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
esp_err_t ledc_fade_start(ledc_channel_t channel, ledc_fade_mode_t wait_done);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "freertos/xtensa_api.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "soc/ledc_reg.h"
|
||||
#include "soc/ledc_struct.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char* LEDC_TAG = "ledc";
|
||||
|
@ -29,26 +31,56 @@ static portMUX_TYPE ledc_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
|||
return (ret_val); \
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint16_t speed_mode;
|
||||
uint16_t direction;
|
||||
int target_duty;
|
||||
int cycle_num;
|
||||
int scale;
|
||||
ledc_fade_mode_t mode;
|
||||
xSemaphoreHandle ledc_fade_sem;
|
||||
xSemaphoreHandle ledc_fade_mux;
|
||||
} ledc_fade_t;
|
||||
static ledc_fade_t* s_ledc_fade_rec = NULL;
|
||||
static ledc_isr_handle_t s_ledc_fade_isr_handle = NULL;
|
||||
|
||||
#define LEDC_VAL_NO_CHANGE (-1)
|
||||
#define LEDC_STEP_NUM_MAX (1023)
|
||||
#define LEDC_DUTY_DECIMAL_BIT_NUM (4)
|
||||
|
||||
#define LEDC_MODE_ERR_STR "LEDC mode error"
|
||||
#define LEDC_TIMER_ERR_STR "LEDC timer error"
|
||||
#define LEDC_CHANNEL_ERR_STR "LEDC channel error"
|
||||
#define LEDC_GPIO_OUT_ERR_STR "LEDC GPIO output number error"
|
||||
#define LEDC_FADE_DIR_ERR_STR "LEDC fade direction error"
|
||||
#define LEDC_FADE_SERVICE_ERR_STR "LEDC fade service not installed"
|
||||
#define LEDC_FADE_TARGET_ERR_STR "LEDC fade target duty error"
|
||||
#define LEDC_FADE_INSTALLED_ERR_STR "LEDC fade service already installed"
|
||||
#define LEDC_FADE_MODE_ERR_STR "LEDC fade mode error"
|
||||
|
||||
|
||||
esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t div_num, uint32_t bit_num, ledc_clk_src_t clk_src)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(timer_sel <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
LEDC.timer_group[speed_mode].timer[timer_sel].conf.div_num = div_num;
|
||||
LEDC.timer_group[speed_mode].timer[timer_sel].conf.tick_sel = clk_src;
|
||||
LEDC.timer_group[speed_mode].timer[timer_sel].conf.bit_num = bit_num;
|
||||
if(speed_mode != LEDC_HIGH_SPEED_MODE) {
|
||||
if (speed_mode != LEDC_HIGH_SPEED_MODE) {
|
||||
LEDC.timer_group[speed_mode].timer[timer_sel].conf.low_speed_update = 1;
|
||||
}
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t hpoint_val, uint32_t duty_val,
|
||||
static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel_t channel_num, int hpoint_val, uint32_t duty_val,
|
||||
uint32_t duty_direction, uint32_t duty_num, uint32_t duty_cycle, uint32_t duty_scale)
|
||||
{
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
LEDC.channel_group[speed_mode].channel[channel_num].hpoint.hpoint = hpoint_val;
|
||||
if (hpoint_val >= 0) {
|
||||
LEDC.channel_group[speed_mode].channel[channel_num].hpoint.hpoint = hpoint_val;
|
||||
}
|
||||
LEDC.channel_group[speed_mode].channel[channel_num].duty.duty = duty_val;
|
||||
LEDC.channel_group[speed_mode].channel[channel_num].conf1.val = ((duty_direction & LEDC_DUTY_INC_HSCH0_V) << LEDC_DUTY_INC_HSCH0_S) |
|
||||
((duty_num & LEDC_DUTY_NUM_HSCH0_V) << LEDC_DUTY_NUM_HSCH0_S) |
|
||||
|
@ -60,8 +92,8 @@ static esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel_t channel
|
|||
|
||||
esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t timer_idx)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(timer_idx <= LEDC_TIMER_3, "ledc timer error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(timer_idx <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel = timer_idx;
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
|
@ -70,8 +102,8 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel
|
|||
|
||||
esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(timer_sel <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
LEDC.timer_group[speed_mode].timer[timer_sel].conf.rst = 1;
|
||||
LEDC.timer_group[speed_mode].timer[timer_sel].conf.rst = 0;
|
||||
|
@ -81,8 +113,8 @@ esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel)
|
|||
|
||||
esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(timer_sel <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
LEDC.timer_group[speed_mode].timer[timer_sel].conf.pause = 1;
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
|
@ -91,8 +123,8 @@ esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel)
|
|||
|
||||
esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(timer_sel <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
LEDC.timer_group[speed_mode].timer[timer_sel].conf.pause = 0;
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
|
@ -101,15 +133,15 @@ esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel)
|
|||
|
||||
static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, uint32_t channel, ledc_intr_type_t type)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
uint32_t value;
|
||||
uint32_t intr_type = type;
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
value = LEDC.int_ena.val;
|
||||
if(intr_type == LEDC_INTR_FADE_END) {
|
||||
if (intr_type == LEDC_INTR_FADE_END) {
|
||||
LEDC.int_ena.val = value | BIT(LEDC_DUTY_CHNG_END_HSCH0_INT_ENA_S + channel);
|
||||
} else {
|
||||
LEDC.int_ena.val = (value & (~(BIT(LEDC_DUTY_CHNG_END_HSCH0_INT_ENA_S + channel))));
|
||||
LEDC.int_ena.val = ( value & ( ~( BIT(LEDC_DUTY_CHNG_END_HSCH0_INT_ENA_S + channel) ) ) );
|
||||
}
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
return ESP_OK;
|
||||
|
@ -120,7 +152,7 @@ esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags,
|
|||
esp_err_t ret;
|
||||
LEDC_CHECK(fn, "ledc isr null", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
ret=esp_intr_alloc(ETS_LEDC_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
|
||||
ret = esp_intr_alloc(ETS_LEDC_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
return ret;
|
||||
}
|
||||
|
@ -131,32 +163,35 @@ esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf)
|
|||
int bit_num = timer_conf->bit_num;
|
||||
int timer_num = timer_conf->timer_num;
|
||||
int speed_mode = timer_conf->speed_mode;
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
|
||||
if(freq_hz == 0 || bit_num == 0 || bit_num > LEDC_TIMER_15_BIT) {
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
periph_module_enable(PERIPH_LEDC_MODULE);
|
||||
if (freq_hz == 0 || bit_num == 0 || bit_num > LEDC_TIMER_15_BIT) {
|
||||
ESP_LOGE(LEDC_TAG, "freq_hz=%u bit_num=%u", freq_hz, bit_num);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if(timer_num > LEDC_TIMER_3) {
|
||||
if (timer_num > LEDC_TIMER_3) {
|
||||
ESP_LOGE(LEDC_TAG, "invalid timer #%u", timer_num);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
esp_err_t ret = ESP_OK;
|
||||
uint32_t precision = (0x1 << bit_num); // 2**depth
|
||||
uint32_t precision = ( 0x1 << bit_num ); // 2**depth
|
||||
// Try calculating divisor based on LEDC_APB_CLK
|
||||
ledc_clk_src_t timer_clk_src = LEDC_APB_CLK;
|
||||
// div_param is a Q10.8 fixed point value
|
||||
uint64_t div_param = ((uint64_t) LEDC_APB_CLK_HZ << 8) / freq_hz / precision;
|
||||
uint64_t div_param = ( (uint64_t) LEDC_APB_CLK_HZ << 8 ) / freq_hz / precision;
|
||||
if (div_param < 256) {
|
||||
// divisor is too low
|
||||
ESP_LOGE(LEDC_TAG, "requested frequency and bit depth can not be achieved, try reducing freq_hz or bit_num. div_param=%d", (uint32_t) div_param);
|
||||
ESP_LOGE(LEDC_TAG, "requested frequency and bit depth can not be achieved, try reducing freq_hz or bit_num. div_param=%d",
|
||||
(uint32_t ) div_param);
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
if (div_param > LEDC_DIV_NUM_HSTIMER0_V) {
|
||||
// APB_CLK results in divisor which too high. Try using REF_TICK as clock source.
|
||||
timer_clk_src = LEDC_REF_TICK;
|
||||
div_param = ((uint64_t) LEDC_REF_CLK_HZ << 8) / freq_hz / precision;
|
||||
if(div_param < 256 || div_param > LEDC_DIV_NUM_HSTIMER0_V) {
|
||||
ESP_LOGE(LEDC_TAG, "requested frequency and bit depth can not be achieved, try increasing freq_hz or bit_num. div_param=%d", (uint32_t) div_param);
|
||||
div_param = ( (uint64_t) LEDC_REF_CLK_HZ << 8 ) / freq_hz / precision;
|
||||
if (div_param < 256 || div_param > LEDC_DIV_NUM_HSTIMER0_V) {
|
||||
ESP_LOGE(LEDC_TAG, "requested frequency and bit depth can not be achieved, try increasing freq_hz or bit_num. div_param=%d",
|
||||
(uint32_t ) div_param);
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
@ -169,12 +204,12 @@ esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf)
|
|||
|
||||
esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc_channel)
|
||||
{
|
||||
LEDC_CHECK(ledc_channel <= LEDC_CHANNEL_7, "ledc channel error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "ledc GPIO output number error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(ledc_channel <= LEDC_CHANNEL_7, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), LEDC_GPIO_OUT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
|
||||
gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);
|
||||
if(speed_mode == LEDC_HIGH_SPEED_MODE) {
|
||||
if (speed_mode == LEDC_HIGH_SPEED_MODE) {
|
||||
gpio_matrix_out(gpio_num, LEDC_HS_SIG_OUT0_IDX + ledc_channel, 0, 0);
|
||||
} else {
|
||||
ESP_LOGE(LEDC_TAG, "low speed mode is not implemented");
|
||||
|
@ -191,10 +226,10 @@ esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf)
|
|||
uint32_t timer_select = ledc_conf->timer_sel;
|
||||
uint32_t intr_type = ledc_conf->intr_type;
|
||||
uint32_t duty = ledc_conf->duty;
|
||||
LEDC_CHECK(ledc_channel <= LEDC_CHANNEL_7, "ledc channel error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "ledc GPIO output number error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(timer_select <= LEDC_TIMER_3, "ledc timer error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(ledc_channel <= LEDC_CHANNEL_7, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), LEDC_GPIO_OUT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(timer_select <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
periph_module_enable(PERIPH_LEDC_MODULE);
|
||||
esp_err_t ret = ESP_OK;
|
||||
/*set channel parameters*/
|
||||
|
@ -207,7 +242,7 @@ esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf)
|
|||
ledc_bind_channel_timer(speed_mode, ledc_channel, timer_select);
|
||||
/*set interrupt type*/
|
||||
ledc_enable_intr_type(speed_mode, ledc_channel, intr_type);
|
||||
ESP_LOGI(LEDC_TAG, "LEDC_PWM CHANNEL %1u|GPIO %02u|Duty %04u|Time %01u",
|
||||
ESP_LOGD(LEDC_TAG, "LEDC_PWM CHANNEL %1u|GPIO %02u|Duty %04u|Time %01u",
|
||||
ledc_channel, gpio_num, duty, timer_select
|
||||
);
|
||||
/*set LEDC signal in gpio matrix*/
|
||||
|
@ -219,8 +254,8 @@ esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf)
|
|||
|
||||
esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(channel <= LEDC_CHANNEL_7, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 1;
|
||||
LEDC.channel_group[speed_mode].channel[channel].conf1.duty_start = 1;
|
||||
|
@ -230,8 +265,8 @@ esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel)
|
|||
|
||||
esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_level)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(channel <= LEDC_CHANNEL_7, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
LEDC.channel_group[speed_mode].channel[channel].conf0.idle_lv = idle_level & 0x1;
|
||||
LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 0;
|
||||
|
@ -239,16 +274,20 @@ esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idl
|
|||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, ledc_duty_direction_t fade_direction,
|
||||
uint32_t step_num, uint32_t duty_cyle_num, uint32_t duty_scale)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(fade_direction <= LEDC_DUTY_DIR_INCREASE, "ledc fade direction error", ESP_ERR_INVALID_ARG);
|
||||
if(step_num > LEDC_DUTY_NUM_HSCH0_V || duty_cyle_num > LEDC_DUTY_CYCLE_HSCH0_V || duty_scale > LEDC_DUTY_SCALE_HSCH0_V) {
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(channel <= LEDC_CHANNEL_7, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(fade_direction <= LEDC_DUTY_DIR_INCREASE, LEDC_FADE_DIR_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
if (step_num > LEDC_DUTY_NUM_HSCH0_V || duty_cyle_num > LEDC_DUTY_CYCLE_HSCH0_V || duty_scale > LEDC_DUTY_SCALE_HSCH0_V) {
|
||||
ESP_LOGE(LEDC_TAG, "step_num=%u duty_cyle_num=%u duty_scale=%u", step_num, duty_cyle_num, duty_scale);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (s_ledc_fade_rec) {
|
||||
ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_DISABLE);
|
||||
}
|
||||
ledc_duty_config(speed_mode,
|
||||
channel, //uint32_t chan_num,
|
||||
0, //uint32_t hpoint_val,
|
||||
|
@ -263,8 +302,11 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
|
|||
|
||||
esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(channel <= LEDC_CHANNEL_7, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
if (s_ledc_fade_rec) {
|
||||
ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_DISABLE);
|
||||
}
|
||||
ledc_duty_config(speed_mode,
|
||||
channel, //uint32_t chan_num,
|
||||
0, //uint32_t hpoint_val,
|
||||
|
@ -279,26 +321,26 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
|
|||
|
||||
int ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", (-1));
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, (-1));
|
||||
uint32_t duty = (LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> 4);
|
||||
return duty;
|
||||
}
|
||||
|
||||
esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t freq_hz)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
esp_err_t ret = ESP_OK;
|
||||
uint32_t div_num = 0;
|
||||
uint32_t bit_num = LEDC.timer_group[speed_mode].timer[timer_num].conf.bit_num;
|
||||
uint32_t timer_source_clk = LEDC.timer_group[speed_mode].timer[timer_num].conf.tick_sel;
|
||||
uint32_t precision = (0x1 << bit_num);
|
||||
if(timer_source_clk == LEDC_APB_CLK) {
|
||||
div_num = ((uint64_t) LEDC_APB_CLK_HZ << 8) / freq_hz / precision;
|
||||
uint32_t precision = ( 0x1 << bit_num );
|
||||
if (timer_source_clk == LEDC_APB_CLK) {
|
||||
div_num = ( (uint64_t) LEDC_APB_CLK_HZ << 8 ) / freq_hz / precision;
|
||||
} else {
|
||||
div_num = ((uint64_t) LEDC_REF_CLK_HZ << 8) / freq_hz / precision;
|
||||
div_num = ( (uint64_t) LEDC_REF_CLK_HZ << 8 ) / freq_hz / precision;
|
||||
}
|
||||
if(div_num <= 256 || div_num > LEDC_DIV_NUM_HSTIMER0) {
|
||||
if (div_num <= 256 || div_num > LEDC_DIV_NUM_HSTIMER0) {
|
||||
ESP_LOGE(LEDC_TAG, "div param err,div_param=%u", div_num);
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
@ -309,18 +351,217 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t
|
|||
|
||||
uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num)
|
||||
{
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", (0));
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ( 0 ));
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
uint32_t freq = 0;
|
||||
uint32_t timer_source_clk = LEDC.timer_group[speed_mode].timer[timer_num].conf.tick_sel;
|
||||
uint32_t bit_num = LEDC.timer_group[speed_mode].timer[timer_num].conf.bit_num;
|
||||
uint32_t div_num = LEDC.timer_group[speed_mode].timer[timer_num].conf.div_num;
|
||||
uint32_t precision = (0x1 << bit_num);
|
||||
if(timer_source_clk == LEDC_APB_CLK) {
|
||||
freq = ((uint64_t) LEDC_APB_CLK_HZ << 8) / precision / div_num;
|
||||
uint32_t precision = ( 0x1 << bit_num );
|
||||
if (timer_source_clk == LEDC_APB_CLK) {
|
||||
freq = ( (uint64_t) LEDC_APB_CLK_HZ << 8 ) / precision / div_num;
|
||||
} else {
|
||||
freq = ((uint64_t) LEDC_REF_CLK_HZ << 8) / precision / div_num;
|
||||
freq = ( (uint64_t) LEDC_REF_CLK_HZ << 8 ) / precision / div_num;
|
||||
}
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
return freq;
|
||||
}
|
||||
|
||||
void IRAM_ATTR ledc_fade_isr()
|
||||
{
|
||||
int i;
|
||||
portBASE_TYPE HPTaskAwoken = pdFALSE;
|
||||
uint32_t intr_status = LEDC.int_st.val; //read LEDC interrupt status.
|
||||
LEDC.int_clr.val = intr_status; //clear LEDC interrupt status.
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (intr_status & BIT(LEDC_DUTY_CHNG_END_HSCH0_INT_ST_S + i)) {
|
||||
int speed_mode = s_ledc_fade_rec[i].speed_mode;
|
||||
int duty_cur = LEDC.channel_group[speed_mode].channel[i].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM;
|
||||
if (duty_cur == s_ledc_fade_rec[i].target_duty) {
|
||||
if(s_ledc_fade_rec[i].mode == LEDC_FADE_WAIT_DONE) {
|
||||
xSemaphoreGiveFromISR(s_ledc_fade_rec[i].ledc_fade_sem, &HPTaskAwoken);
|
||||
if(HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR() ;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
int duty_tar = s_ledc_fade_rec[i].target_duty;
|
||||
int scale = s_ledc_fade_rec[i].scale;
|
||||
if (scale == 0) {
|
||||
continue;
|
||||
}
|
||||
int cycle = s_ledc_fade_rec[i].cycle_num;
|
||||
int delta = s_ledc_fade_rec[i].direction == LEDC_DUTY_DIR_DECREASE ? duty_cur - duty_tar : duty_tar - duty_cur;
|
||||
int step = delta / scale > LEDC_STEP_NUM_MAX ? LEDC_STEP_NUM_MAX : delta / scale;
|
||||
|
||||
if (delta > scale) {
|
||||
ledc_duty_config(
|
||||
speed_mode,
|
||||
i,
|
||||
LEDC_VAL_NO_CHANGE,
|
||||
duty_cur << LEDC_DUTY_DECIMAL_BIT_NUM,
|
||||
s_ledc_fade_rec[i].direction,
|
||||
step,
|
||||
cycle,
|
||||
scale);
|
||||
} else {
|
||||
ledc_duty_config(
|
||||
speed_mode,
|
||||
i,
|
||||
LEDC_VAL_NO_CHANGE,
|
||||
duty_tar << LEDC_DUTY_DECIMAL_BIT_NUM,
|
||||
s_ledc_fade_rec[i].direction,
|
||||
1,
|
||||
1,
|
||||
0);
|
||||
}
|
||||
LEDC.channel_group[speed_mode].channel[i].conf1.duty_start = 1;
|
||||
}
|
||||
}
|
||||
LEDC.int_clr.val = intr_status; //clear LEDC interrupt status.
|
||||
}
|
||||
|
||||
esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int max_fade_time_ms)
|
||||
{
|
||||
int timer_sel = LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel;
|
||||
int max_duty = ( 1 << ( LEDC.timer_group[speed_mode].timer[timer_sel].conf.bit_num ) ) - 1;
|
||||
LEDC_CHECK(target_duty <= max_duty, LEDC_FADE_TARGET_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
uint32_t freq = ledc_get_freq(speed_mode, timer_sel);
|
||||
int duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM;
|
||||
int duty_delta = target_duty > duty_cur ? target_duty - duty_cur : duty_cur - target_duty;
|
||||
|
||||
if (duty_delta == 0) {
|
||||
return ESP_OK;
|
||||
}
|
||||
int total_cycles = max_fade_time_ms * freq / 1000;
|
||||
int scale, cycle_num;
|
||||
if (total_cycles > duty_delta) {
|
||||
scale = 1;
|
||||
cycle_num = total_cycles / duty_delta;
|
||||
} else {
|
||||
cycle_num = 1;
|
||||
scale = ( duty_delta + total_cycles - 1 ) / total_cycles;
|
||||
}
|
||||
return ledc_set_fade_with_step(speed_mode, channel, target_duty, scale, cycle_num);
|
||||
}
|
||||
|
||||
esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int scale, int cycle_num)
|
||||
{
|
||||
LEDC_CHECK(s_ledc_fade_rec != NULL, LEDC_FADE_SERVICE_ERR_STR, ESP_ERR_INVALID_STATE);
|
||||
LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
LEDC_CHECK(channel < LEDC_CHANNEL_MAX, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
int timer_sel = LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel;
|
||||
int max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.bit_num)) - 1;
|
||||
LEDC_CHECK(target_duty <= max_duty, LEDC_FADE_TARGET_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
//disable the interrupt, so the operation will not mess up
|
||||
ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_DISABLE);
|
||||
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
int duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM;
|
||||
int duty_delta = target_duty > duty_cur ? target_duty - duty_cur : duty_cur - target_duty;
|
||||
if (duty_delta == 0) {
|
||||
return ESP_OK;
|
||||
}
|
||||
s_ledc_fade_rec[channel].speed_mode = speed_mode;
|
||||
s_ledc_fade_rec[channel].target_duty = target_duty;
|
||||
s_ledc_fade_rec[channel].cycle_num = cycle_num;
|
||||
s_ledc_fade_rec[channel].scale = scale;
|
||||
int step_num;
|
||||
if (duty_cur > target_duty) {
|
||||
s_ledc_fade_rec[channel].direction = LEDC_DUTY_DIR_DECREASE;
|
||||
step_num = ( duty_cur - target_duty ) / scale;
|
||||
step_num = step_num > LEDC_STEP_NUM_MAX ? LEDC_STEP_NUM_MAX : step_num;
|
||||
} else {
|
||||
s_ledc_fade_rec[channel].direction = LEDC_DUTY_DIR_INCREASE;
|
||||
step_num = ( target_duty - duty_cur ) / scale;
|
||||
step_num = step_num > LEDC_STEP_NUM_MAX ? LEDC_STEP_NUM_MAX : step_num;
|
||||
}
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
|
||||
ledc_set_fade(
|
||||
speed_mode,
|
||||
channel,
|
||||
duty_cur,
|
||||
s_ledc_fade_rec[channel].direction,
|
||||
step_num,
|
||||
s_ledc_fade_rec[channel].cycle_num,
|
||||
s_ledc_fade_rec[channel].scale
|
||||
);
|
||||
ESP_LOGD(LEDC_TAG, "cur duty: %d; target: %d, step: %d, cycle: %d; scale: %d\n",
|
||||
LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM,
|
||||
target_duty,
|
||||
step_num,
|
||||
s_ledc_fade_rec[channel].cycle_num,
|
||||
s_ledc_fade_rec[channel].scale
|
||||
);
|
||||
LEDC.int_clr.val |= BIT(LEDC_DUTY_CHNG_END_HSCH0_INT_ENA_S + channel);
|
||||
ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_FADE_END);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t ledc_fade_func_install(int intr_alloc_flags)
|
||||
{
|
||||
LEDC_CHECK(s_ledc_fade_rec == NULL, LEDC_FADE_INSTALLED_ERR_STR, ESP_ERR_INVALID_STATE);
|
||||
s_ledc_fade_rec = (ledc_fade_t*) calloc(LEDC_CHANNEL_MAX, sizeof(ledc_fade_t));
|
||||
if (s_ledc_fade_rec == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
int i = 0;
|
||||
for (i = 0; i < LEDC_CHANNEL_MAX; i++) {
|
||||
s_ledc_fade_rec[i].ledc_fade_sem = xSemaphoreCreateBinary();
|
||||
s_ledc_fade_rec[i].ledc_fade_mux = xSemaphoreCreateMutex();
|
||||
if (s_ledc_fade_rec[i].ledc_fade_sem == NULL || s_ledc_fade_rec[i].ledc_fade_mux == NULL) {
|
||||
ledc_fade_func_uninstall();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
//OR intr_alloc_flags with ESP_INTR_FLAG_IRAM because the fade isr is in IRAM
|
||||
ledc_isr_register(ledc_fade_isr, NULL, intr_alloc_flags | ESP_INTR_FLAG_IRAM, &s_ledc_fade_isr_handle);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void ledc_fade_func_uninstall()
|
||||
{
|
||||
if (s_ledc_fade_rec == NULL) {
|
||||
return;
|
||||
}
|
||||
if(s_ledc_fade_isr_handle) {
|
||||
esp_intr_free(s_ledc_fade_isr_handle);
|
||||
s_ledc_fade_isr_handle = NULL;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < LEDC_CHANNEL_MAX; i++) {
|
||||
if (s_ledc_fade_rec[i].ledc_fade_sem) {
|
||||
xSemaphoreHandle sem_tmp = s_ledc_fade_rec[i].ledc_fade_sem;
|
||||
s_ledc_fade_rec[i].ledc_fade_sem = NULL;
|
||||
vSemaphoreDelete(sem_tmp);
|
||||
}
|
||||
if (s_ledc_fade_rec[i].ledc_fade_mux) {
|
||||
xSemaphoreHandle mux_tmp = s_ledc_fade_rec[i].ledc_fade_mux;
|
||||
s_ledc_fade_rec[i].ledc_fade_mux = NULL;
|
||||
vSemaphoreDelete(mux_tmp);
|
||||
}
|
||||
}
|
||||
free(s_ledc_fade_rec);
|
||||
s_ledc_fade_rec = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
esp_err_t ledc_fade_start(ledc_channel_t channel, ledc_fade_mode_t wait_done)
|
||||
{
|
||||
LEDC_CHECK(s_ledc_fade_rec != NULL, LEDC_FADE_SERVICE_ERR_STR, ESP_ERR_INVALID_STATE);
|
||||
LEDC_CHECK(wait_done < LEDC_FADE_MAX, LEDC_FADE_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
int speed_mode = s_ledc_fade_rec[channel].speed_mode;
|
||||
xSemaphoreTake(s_ledc_fade_rec[channel].ledc_fade_mux, portMAX_DELAY);
|
||||
if (wait_done == LEDC_FADE_WAIT_DONE) {
|
||||
s_ledc_fade_rec[channel].mode = LEDC_FADE_WAIT_DONE;
|
||||
ledc_update_duty(speed_mode, channel);
|
||||
xSemaphoreTake(s_ledc_fade_rec[channel].ledc_fade_sem, portMAX_DELAY);
|
||||
} else {
|
||||
s_ledc_fade_rec[channel].mode = LEDC_FADE_NO_WAIT;
|
||||
ledc_update_duty(speed_mode, channel);
|
||||
}
|
||||
xSemaphoreGive(s_ledc_fade_rec[channel].ledc_fade_mux);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
|
|
@ -4,20 +4,19 @@ LED Control
|
|||
Overview
|
||||
--------
|
||||
|
||||
`Instructions`_
|
||||
The LED control module is primarily designed to control the intensity of LEDs, although it can be used to generate PWM signals for other purposes as well.
|
||||
It has 16 channels which can generate independent waveforms that can be used to drive e.g. RGB LED devices. For maximum flexibility, the high-speed as well
|
||||
as the low-speed channels can be driven from one of four high-speed/low-speed timers. The PWM controller also has the ability to automatically increase or
|
||||
decrease the duty cycle gradually, allowing for fades without any processor interference.
|
||||
|
||||
Application Example
|
||||
-------------------
|
||||
|
||||
`Instructions`_
|
||||
LEDC change duty cycle and fading control example: `examples/29_ledc <https://github.com/espressif/esp-idf/tree/master/examples/29_ledc>`_.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
`Instructions`_
|
||||
|
||||
.. _Instructions: template.html
|
||||
|
||||
Header Files
|
||||
^^^^^^^^^^^^
|
||||
|
||||
|
@ -38,6 +37,11 @@ Macros
|
|||
.. doxygendefine:: LEDC_APB_CLK_HZ
|
||||
.. doxygendefine:: LEDC_REF_CLK_HZ
|
||||
|
||||
Type Definitions
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. doxygentypedef:: ledc_isr_handle_t
|
||||
|
||||
Enumerations
|
||||
^^^^^^^^^^^^
|
||||
|
||||
|
@ -49,6 +53,16 @@ Enumerations
|
|||
.. doxygenenum:: ledc_channel_t
|
||||
.. doxygenenum:: ledc_timer_bit_t
|
||||
|
||||
Structures
|
||||
^^^^^^^^^^
|
||||
|
||||
.. doxygenstruct:: ledc_channel_config_t
|
||||
:members:
|
||||
|
||||
.. doxygenstruct:: ledc_timer_config_t
|
||||
:members:
|
||||
|
||||
|
||||
Functions
|
||||
^^^^^^^^^
|
||||
|
||||
|
@ -67,3 +81,9 @@ Functions
|
|||
.. doxygenfunction:: ledc_timer_pause
|
||||
.. doxygenfunction:: ledc_timer_resume
|
||||
.. doxygenfunction:: ledc_bind_channel_timer
|
||||
.. doxygenfunction:: ledc_set_fade_with_step
|
||||
.. doxygenfunction:: ledc_set_fade_with_time
|
||||
.. doxygenfunction:: ledc_fade_func_install
|
||||
.. doxygenfunction:: ledc_fade_func_uninstall
|
||||
.. doxygenfunction:: ledc_fade_start
|
||||
|
||||
|
|
9
examples/29_ledc/Makefile
Normal file
9
examples/29_ledc/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := ledc
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
16
examples/29_ledc/README.md
Normal file
16
examples/29_ledc/README.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
# LEDC(LED control) Example
|
||||
|
||||
###This example shows:
|
||||
|
||||
* init LEDC module:
|
||||
|
||||
a. You need to set the timer of LEDC first, this decide the frequency and resolution of PWM.
|
||||
|
||||
b. You need to set the LEDC channel you want to use, and bind the channel with one of the timers.
|
||||
|
||||
* You can install a default fade function, then you can use fade APIs.
|
||||
|
||||
* You can also set a target duty directly without fading.
|
||||
|
||||
* This example use GPIO18/19/4/5 as LEDC ouput, and it will change the duty repeatedly.
|
||||
|
3
examples/29_ledc/main/component.mk
Normal file
3
examples/29_ledc/main/component.mk
Normal file
|
@ -0,0 +1,3 @@
|
|||
#
|
||||
# Main Makefile. This is basically the same as a component makefile.
|
||||
#
|
131
examples/29_ledc/main/ledc_fade.c
Normal file
131
examples/29_ledc/main/ledc_fade.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
/* Ledc fade 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 "freertos/xtensa_api.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
/*
|
||||
* About this example
|
||||
* 1. init LEDC module:
|
||||
* a. You need to set the timer of LEDC first, this decide the frequency and resolution of PWM.
|
||||
* b. You need to set the LEDC channel you want to use, and bind with one of the timers.
|
||||
*
|
||||
* 2. You can install a default fade function, then you can use fade APIs.
|
||||
*
|
||||
* 3. You can also set a target duty directly without fading.
|
||||
*
|
||||
* 4. This example use GPIO18/19/4/5 as LEDC ouput, and it will change the duty repeatedly.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#define LEDC_IO_0 (18)
|
||||
#define LEDC_IO_1 (19)
|
||||
#define LEDC_IO_2 (4)
|
||||
#define LEDC_IO_3 (5)
|
||||
|
||||
esp_err_t app_main()
|
||||
{
|
||||
ledc_timer_config_t ledc_timer = {
|
||||
//set timer counter bit number
|
||||
.bit_num = LEDC_TIMER_13_BIT,
|
||||
//set frequency of pwm
|
||||
.freq_hz = 5000,
|
||||
//timer mode,
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
||||
//timer index
|
||||
.timer_num = LEDC_TIMER_0
|
||||
};
|
||||
ledc_timer_config(&ledc_timer);
|
||||
|
||||
ledc_channel_config_t ledc_channel = {
|
||||
//set LEDC channel 0
|
||||
.channel = LEDC_CHANNEL_0,
|
||||
//set the duty for initialization.(duty range is 0 ~ ((2**bit_num)-1)
|
||||
.duty = 100,
|
||||
//GPIO number
|
||||
.gpio_num = LEDC_IO_0,
|
||||
//GPIO INTR TYPE, as an example, we enable fade_end interrupt here.
|
||||
.intr_type = LEDC_INTR_FADE_END,
|
||||
//set LEDC mode, from ledc_mode_t
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
||||
//set LEDC timer source, if different channel use one timer,
|
||||
//the frequency and bit_num of these channels should be the same
|
||||
.timer_sel = LEDC_TIMER_0
|
||||
};
|
||||
//set the configuration
|
||||
ledc_channel_config(&ledc_channel);
|
||||
|
||||
//config ledc channel1
|
||||
ledc_channel.channel = LEDC_CHANNEL_1;
|
||||
ledc_channel.gpio_num = LEDC_IO_1;
|
||||
ledc_channel_config(&ledc_channel);
|
||||
//config ledc channel2
|
||||
ledc_channel.channel = LEDC_CHANNEL_2;
|
||||
ledc_channel.gpio_num = LEDC_IO_2;
|
||||
ledc_channel_config(&ledc_channel);
|
||||
//config ledc channel3
|
||||
ledc_channel.channel = LEDC_CHANNEL_3;
|
||||
ledc_channel.gpio_num = LEDC_IO_3;
|
||||
ledc_channel_config(&ledc_channel);
|
||||
|
||||
//initialize fade service.
|
||||
ledc_fade_func_install(0);
|
||||
|
||||
while(1) {
|
||||
printf("LEDC fade up\n");
|
||||
ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 1000, 2000);
|
||||
ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 7000, 2000);
|
||||
ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 5000, 2000);
|
||||
ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_3, 3000, 2000);
|
||||
ledc_fade_start(LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT);
|
||||
ledc_fade_start(LEDC_CHANNEL_1, LEDC_FADE_NO_WAIT);
|
||||
ledc_fade_start(LEDC_CHANNEL_2, LEDC_FADE_NO_WAIT);
|
||||
ledc_fade_start(LEDC_CHANNEL_3, LEDC_FADE_NO_WAIT);
|
||||
vTaskDelay(3000 / portTICK_PERIOD_MS);
|
||||
|
||||
printf("LEDC fade down\n");
|
||||
ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 100, 2000);
|
||||
ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 300, 2000);
|
||||
ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 500, 2000);
|
||||
ledc_set_fade_with_time(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_3, 700, 2000);
|
||||
ledc_fade_start(LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT);
|
||||
ledc_fade_start(LEDC_CHANNEL_1, LEDC_FADE_NO_WAIT);
|
||||
ledc_fade_start(LEDC_CHANNEL_2, LEDC_FADE_NO_WAIT);
|
||||
ledc_fade_start(LEDC_CHANNEL_3, LEDC_FADE_NO_WAIT);
|
||||
vTaskDelay(3000 / portTICK_PERIOD_MS);
|
||||
|
||||
printf("LEDC set duty without fade\n");
|
||||
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 1000);
|
||||
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 7000);
|
||||
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 5000);
|
||||
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_3, 3000);
|
||||
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
|
||||
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1);
|
||||
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2);
|
||||
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_3);
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
|
||||
printf("LEDC set duty without fade\n");
|
||||
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 0);
|
||||
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 0);
|
||||
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 0);
|
||||
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_3, 0);
|
||||
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
|
||||
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1);
|
||||
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2);
|
||||
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_3);
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue