| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- /* MCPWM sync 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.
- */
- /*
- * This example will show you how to use capture function to read HC-SR04 sonar sensor.
- */
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "freertos/queue.h"
- #include "esp_rom_gpio.h"
- #include "soc/mcpwm_periph.h"
- #include "hal/gpio_hal.h"
- #include "esp_log.h"
- #include "esp_check.h"
- #include "soc/rtc.h"
- #include "driver/mcpwm.h"
- const static char *TAG = "sync_example";
- #define TARGET_MCPWM_UNIT MCPWM_UNIT_0
- #define TIMER0_OUTPUT_GPIO GPIO_NUM_16
- #define TIMER1_OUTPUT_GPIO GPIO_NUM_17
- #define TIMER2_OUTPUT_GPIO GPIO_NUM_18
- #define SIMU_GPIO_SYNC_SOURCE_GPIO GPIO_NUM_21
- #define SIMU_GPIO_SYNC_SIMULATE_GPIO GPIO_NUM_19
- void app_main(void) {
- ESP_LOGI(TAG, "MCPWM sync example");
- // init MCPWM: 10% duty cycle on all three timers in MCPWM unit 0 (currently not synchronous)
- mcpwm_config_t pwm_config = {
- .frequency = 1000,
- .cmpr_a = 10,
- .cmpr_b = 0,
- .counter_mode = MCPWM_UP_COUNTER,
- .duty_mode = MCPWM_DUTY_MODE_0,
- };
- ESP_ERROR_CHECK(mcpwm_init(TARGET_MCPWM_UNIT, MCPWM_TIMER_0, &pwm_config));
- ESP_ERROR_CHECK(mcpwm_init(TARGET_MCPWM_UNIT, MCPWM_TIMER_1, &pwm_config));
- ESP_ERROR_CHECK(mcpwm_init(TARGET_MCPWM_UNIT, MCPWM_TIMER_2, &pwm_config));
- // bind output to GPIO
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM0A, TIMER0_OUTPUT_GPIO));
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM1A, TIMER1_OUTPUT_GPIO));
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM2A, TIMER2_OUTPUT_GPIO));
- ESP_LOGI(TAG, "PWM started, not synchronized");
- vTaskDelay(pdMS_TO_TICKS(1000));
- // temporarily disable GPIO output, by binding to GenBs which have 0 output
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM0B, TIMER0_OUTPUT_GPIO));
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM1B, TIMER1_OUTPUT_GPIO));
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM2B, TIMER2_OUTPUT_GPIO));
- vTaskDelay(pdMS_TO_TICKS(2000));
- ESP_LOGI(TAG, "Sync timers with GPIO approach");
- // first configure sync source
- mcpwm_sync_config_t sync_conf = {
- .sync_sig = MCPWM_SELECT_GPIO_SYNC0,
- .timer_val = 0,
- .count_direction = MCPWM_TIMER_DIRECTION_UP,
- };
- ESP_ERROR_CHECK(mcpwm_sync_configure(TARGET_MCPWM_UNIT, MCPWM_TIMER_0, &sync_conf));
- ESP_ERROR_CHECK(mcpwm_sync_configure(TARGET_MCPWM_UNIT, MCPWM_TIMER_1, &sync_conf));
- ESP_ERROR_CHECK(mcpwm_sync_configure(TARGET_MCPWM_UNIT, MCPWM_TIMER_2, &sync_conf));
- // then configure GPIO
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM_SYNC_0, SIMU_GPIO_SYNC_SOURCE_GPIO));
- gpio_config_t io_conf = {};
- io_conf.intr_type = GPIO_INTR_DISABLE;
- io_conf.mode = GPIO_MODE_OUTPUT;
- io_conf.pin_bit_mask = BIT64(SIMU_GPIO_SYNC_SIMULATE_GPIO);
- io_conf.pull_down_en = 0;
- io_conf.pull_up_en = 0;
- ESP_ERROR_CHECK(gpio_config(&io_conf));
- ESP_ERROR_CHECK(gpio_set_level(SIMU_GPIO_SYNC_SIMULATE_GPIO, 0));
- ESP_ERROR_CHECK(gpio_set_level(SIMU_GPIO_SYNC_SIMULATE_GPIO, 1));
- // wait for at least one TEP
- vTaskDelay(pdMS_TO_TICKS(10));
- // re-enable GPIO output, to see the result
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM0A, TIMER0_OUTPUT_GPIO));
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM1A, TIMER1_OUTPUT_GPIO));
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM2A, TIMER2_OUTPUT_GPIO));
- ESP_LOGI(TAG, "Output should already be synchronized");
- vTaskDelay(pdMS_TO_TICKS(1000));
- // stop and restart timers to mess them
- ESP_ERROR_CHECK(mcpwm_stop(TARGET_MCPWM_UNIT, MCPWM_TIMER_2));
- ESP_ERROR_CHECK(mcpwm_stop(TARGET_MCPWM_UNIT, MCPWM_TIMER_1));
- ESP_ERROR_CHECK(mcpwm_stop(TARGET_MCPWM_UNIT, MCPWM_TIMER_0));
- vTaskDelay(pdMS_TO_TICKS(2000));
- ESP_ERROR_CHECK(mcpwm_start(TARGET_MCPWM_UNIT, MCPWM_TIMER_0));
- ESP_ERROR_CHECK(mcpwm_start(TARGET_MCPWM_UNIT, MCPWM_TIMER_1));
- ESP_ERROR_CHECK(mcpwm_start(TARGET_MCPWM_UNIT, MCPWM_TIMER_2));
- ESP_LOGI(TAG, "force synchronous lost");
- vTaskDelay(pdMS_TO_TICKS(1000));
- // temporarily disable GPIO output, by binding to GenBs which have 0 output
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM0B, TIMER0_OUTPUT_GPIO));
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM1B, TIMER1_OUTPUT_GPIO));
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM2B, TIMER2_OUTPUT_GPIO));
- vTaskDelay(pdMS_TO_TICKS(2000));
- #ifdef SOC_MCPWM_SWSYNC_CAN_PROPAGATE
- // use the trick that only available on esp32s3
- mcpwm_set_timer_sync_output(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_SWSYNC_SOURCE_SYNCIN);
- sync_conf.sync_sig = MCPWM_SELECT_TIMER0_SYNC;
- mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_0, &sync_conf);
- mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_1, &sync_conf);
- mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_2, &sync_conf);
- // then send soft sync event to timer0
- mcpwm_timer_trigger_soft_sync(MCPWM_UNIT_0, MCPWM_TIMER_0);
- // re-enable GPIO output
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM0A, TIMER0_OUTPUT_GPIO));
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM1A, TIMER1_OUTPUT_GPIO));
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM2A, TIMER2_OUTPUT_GPIO));
- ESP_LOGI(TAG, "Output should already be synchronized on esp32s3");
- vTaskDelay(pdMS_TO_TICKS(1000));
- #endif
- // temporarily disable GPIO output, by binding to GenBs which have 0 output
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM0B, TIMER0_OUTPUT_GPIO));
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM1B, TIMER1_OUTPUT_GPIO));
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM2B, TIMER2_OUTPUT_GPIO));
- vTaskDelay(pdMS_TO_TICKS(2000));
- // create phase between each timer.
- // for this case all timers has 10% of period phase between each other
- sync_conf.sync_sig = MCPWM_SELECT_GPIO_SYNC0;
- sync_conf.timer_val = 0; // no phase applied
- mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_0, &sync_conf);
- sync_conf.timer_val = 900; // fill the counter with 90.0% of period will cause next pulse being delayed 10% period
- mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_1, &sync_conf);
- sync_conf.timer_val = 800; // fill the counter with 80.0% of period will cause next pulse being delayed 20% period
- mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_2, &sync_conf);
- // trigger positive edge
- ESP_ERROR_CHECK(gpio_set_level(SIMU_GPIO_SYNC_SIMULATE_GPIO, 0));
- ESP_ERROR_CHECK(gpio_set_level(SIMU_GPIO_SYNC_SIMULATE_GPIO, 1));
- // wait for at least one TEP
- vTaskDelay(pdMS_TO_TICKS(10));
- // re-enable GPIO output, to see the result
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM0A, TIMER0_OUTPUT_GPIO));
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM1A, TIMER1_OUTPUT_GPIO));
- ESP_ERROR_CHECK(mcpwm_gpio_init(TARGET_MCPWM_UNIT, MCPWM2A, TIMER2_OUTPUT_GPIO));
- ESP_LOGI(TAG, "Each output pulse should be placed with 10 percents of period");
- vTaskDelay(pdMS_TO_TICKS(1000));
- ESP_ERROR_CHECK(mcpwm_stop(TARGET_MCPWM_UNIT, MCPWM_TIMER_2));
- ESP_ERROR_CHECK(mcpwm_stop(TARGET_MCPWM_UNIT, MCPWM_TIMER_1));
- ESP_ERROR_CHECK(mcpwm_stop(TARGET_MCPWM_UNIT, MCPWM_TIMER_0));
- }
|