153 lines
5.2 KiB
C
153 lines
5.2 KiB
C
/*
|
|
|
|
*/
|
|
|
|
#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"
|
|
|
|
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();
|
|
}
|