/* */ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "esp_log.h" #include "esp_check.h" #include "soc/rtc.h" #include "driver/mcpwm.h" #include "driver/gpio.h" const static char *TAG = "capture"; typedef struct capture_event { int ch; uint32_t val; } capture_event_t; #define FLOW1_PIN_ECHO GPIO_NUM_39 // 捕获GPIO端口 #define FLOW2_PIN_ECHO GPIO_NUM_38 // 捕获GPIO端口 #define TRIGGER_THREAD_PRIORITY 5 typedef struct { uint32_t capture_signal; mcpwm_capture_signal_t sel_cap_signal; } capture; static uint32_t cap_val_begin_of_flow1 = 0; static uint32_t cap_val_end_of_flow1 = 0; static uint32_t cap_val_begin_of_flow2 = 0; static uint32_t cap_val_end_of_flow2 = 0; // static xQueueHandle cap_queue; extern uint32_t rtc_clk_apb_freq; uint32_t volatile t15_ccr[2]; uint16_t volatile t15_ccr_times[2]; static bool flow1_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata, void *arg) { // calculate the interval in the ISR, // so that the interval will be always correct even when cap_queue is not handled in time and overflow. BaseType_t high_task_wakeup = pdFALSE; cap_val_end_of_flow1 = edata->cap_value; capture_event_t cap_event = {.val = 0, .ch = 1}; cap_event.val = cap_val_end_of_flow1 - cap_val_begin_of_flow1; t15_ccr_times[0] = cap_event.val * (1000000.0 / rtc_clk_apb_freq); t15_ccr[0]++; return high_task_wakeup == pdTRUE; } void capture_flow1_init() { ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_1, FLOW1_PIN_ECHO)); // enable pull down CAP0, to reduce noise ESP_ERROR_CHECK(gpio_pullup_en(FLOW1_PIN_ECHO)); // enable both edge capture on CAP0 mcpwm_capture_config_t conf = { .cap_edge = MCPWM_NEG_EDGE, .cap_prescale = 1, .capture_cb = flow1_isr_handler, // 绑定流量捕获中断处理函数 .user_data = NULL}; ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_1, MCPWM_SELECT_CAP1, &conf)); mcpwm_set_frequency(MCPWM_UNIT_1, MCPWM_TIMER_1, 1000000); int value = mcpwm_capture_signal_get_value(MCPWM_UNIT_1, MCPWM_SELECT_CAP1); ESP_LOGI(TAG, "capture_flow_init value=%d", value); } static bool flow2_isr_handler(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_sig, const cap_event_data_t *edata, void *arg) { // calculate the interval in the ISR, // so that the interval will be always correct even when cap_queue is not handled in time and overflow. BaseType_t high_task_wakeup = pdFALSE; cap_val_end_of_flow2 = edata->cap_value; capture_event_t cap_event = {.val = 0, .ch = 2}; cap_event.val = cap_val_end_of_flow2 - cap_val_begin_of_flow2; t15_ccr_times[1] = cap_event.val * (1000000.0 / rtc_clk_apb_freq); t15_ccr[1]++; // send measurement back though queue // xQueueSendFromISR(cap_queue, &cap_event, &high_task_wakeup); return high_task_wakeup == pdTRUE; } void capture_flow2_init() { ESP_ERROR_CHECK(mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_2, FLOW2_PIN_ECHO)); // enable pull down CAP0, to reduce noise ESP_ERROR_CHECK(gpio_pulldown_en(FLOW2_PIN_ECHO)); // enable both edge capture on CAP0 mcpwm_capture_config_t conf = { .cap_edge = MCPWM_NEG_EDGE, .cap_prescale = 1, .capture_cb = flow2_isr_handler, // 绑定流量捕获中断处理函数 .user_data = NULL}; ESP_ERROR_CHECK(mcpwm_capture_enable_channel(MCPWM_UNIT_1, MCPWM_SELECT_CAP2, &conf)); mcpwm_set_frequency(MCPWM_UNIT_1, MCPWM_TIMER_2, 1000000); // ESP_LOGI(TAG, "capture_flow_init"); } // void capture_task(void) // { // while (true) { // capture_event_t cap_event = {.val = 0, .ch = 1}; // uint32_t pulse_width_us = 0; // // block and wait for new measurement // // ESP_LOGI(TAG, "xQueueReceive started"); // xQueueReceive(cap_queue, &cap_event, portMAX_DELAY); // // ESP_LOGI(TAG, "xQueueReceive after"); // // ESP_LOGI(TAG, " cap_event.val: %d, cap_event.ch : %d", cap_event.val, cap_event.ch); // switch (cap_event.ch) // { // case 1: //flow1 capture // pulse_width_us = cap_event.val * (1000000.0 / rtc_clk_apb_freq); // ESP_LOGI(TAG, " (flow1 capture) Pulse width: %uus", pulse_width_us); // break; // case 2: //flow2 capture // pulse_width_us = cap_event.val * (1000000.0 / rtc_clk_apb_freq); // ESP_LOGI(TAG, "(flow2 capture) Pulse width: %uus", pulse_width_us); // break; // default: ESP_LOGI(TAG, " default\n"); // break; // } // } // } // void capture_depth_init(); // void pcnt_rotary_encoder_init(void); void capture_init(void) { // cap_queue = xQueueCreate(3, sizeof(capture_event_t)); // if (cap_queue == NULL) { // ESP_LOGE(TAG, "failed to alloc cap_queue"); // return; // } // capture_depth_init(); capture_flow1_init(); capture_flow2_init(); // start gcapture_task // xTaskCreate(capture_task, "capture_task", 4096, NULL, TRIGGER_THREAD_PRIORITY, NULL); // ESP_LOGI(TAG, "capture_task started"); // pcnt_rotary_encoder_init(); }