调用:
ESP_LOGI(TAG, "x:%d, y:%d, sw:%d", rocker_data[0], rocker_data[1], rocker_sw_read());
input_rocker.h
#ifndef _INPUT_ROCKER_H_ #define _INPUT_ROCKER_H_ #include <stdint.h> #include <string.h> void rocker_init(); uint8_t rocker_sw_read(); extern uint16_t rocker_data[2]; #endif
input_rocker.c
#include "input_rocker.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/adc.h" #include "esp_log.h" #define TAG "rocker" /** * X_AXIS: 1 * Y_AXIS: 2 * SW_BTN: 3 */ #define TIMES 128 //每个通道16组数据 #define GET_UNIT(x) ((x >> 3) & 0x1) //support esp32c3 #define ADC_RESULT_BYTE 4 #define ADC_CONV_LIMIT_EN 0 #define ADC_CONV_MODE ADC_CONV_ALTER_UNIT // ESP32C3 only supports alter mode #define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2 static uint16_t adc1_chan_mask = BIT(1) | BIT(2); static adc_channel_t channel[2] = {ADC1_CHANNEL_1, ADC1_CHANNEL_2}; static int16_t sw_pin = 3; uint16_t rocker_data[2]; // X,Y static void continuous_adc_init(uint16_t adc1_chan_mask, adc_channel_t *channel, uint8_t channel_num) { adc_digi_init_config_t adc_dma_config = { .max_store_buf_size = 256, .conv_num_each_intr = TIMES, .adc1_chan_mask = adc1_chan_mask, }; ESP_ERROR_CHECK(adc_digi_initialize(&adc_dma_config)); adc_digi_configuration_t dig_cfg = { .conv_limit_en = ADC_CONV_LIMIT_EN, .conv_limit_num = 250, .sample_freq_hz = 10 * 1000, .conv_mode = ADC_CONV_MODE, .format = ADC_OUTPUT_TYPE, }; adc_digi_pattern_config_t adc_pattern[SOC_ADC_PATT_LEN_MAX] = {0}; dig_cfg.pattern_num = channel_num; for (int i = 0; i < channel_num; i++) { uint8_t unit = GET_UNIT(channel[i]); uint8_t ch = channel[i] & 0x7; adc_pattern[i].atten = ADC_ATTEN_DB_11; adc_pattern[i].channel = ch; adc_pattern[i].unit = unit; adc_pattern[i].bit_width = SOC_ADC_DIGI_MAX_BITWIDTH; ESP_LOGI(TAG, "adc_pattern[%d].atten is :%x", i, adc_pattern[i].atten); ESP_LOGI(TAG, "adc_pattern[%d].channel is :%x", i, adc_pattern[i].channel); ESP_LOGI(TAG, "adc_pattern[%d].unit is :%x", i, adc_pattern[i].unit); } dig_cfg.adc_pattern = adc_pattern; ESP_ERROR_CHECK(adc_digi_controller_configure(&dig_cfg)); } static bool check_valid_data(const adc_digi_output_data_t *data) { const unsigned int unit = data->type2.unit; if (unit > 2) return false; if (data->type2.channel >= SOC_ADC_CHANNEL_NUM(unit)) return false; return true; } static void rocker_sw_init() { gpio_config_t gpio_sw_cfg = { .mode = GPIO_MODE_INPUT, .intr_type = GPIO_INTR_DISABLE, .pull_up_en = 1}; gpio_sw_cfg.pin_bit_mask = ((uint64_t)1UL << sw_pin); gpio_config(&gpio_sw_cfg); } static void adc_read_task() { esp_err_t ret; uint16_t x_data = 0; uint16_t y_data = 0; uint32_t ret_num = 0; uint8_t result[TIMES] = {0}; memset(result, 0xcc, TIMES); memset(rocker_data, 0x0, sizeof(rocker_data)); for (;;) { ret = adc_digi_read_bytes(result, TIMES, &ret_num, ADC_MAX_DELAY); if (ret == ESP_OK || ret == ESP_ERR_INVALID_STATE) { if (ret == ESP_ERR_INVALID_STATE) { /** * @note 1 * Issue: * As an example, we simply print the result out, which is super slow. Therefore the conversion is too * fast for the task to handle. In this condition, some conversion results lost. * * Reason: * When this error occurs, you will usually see the task watchdog timeout issue also. * Because the conversion is too fast, whereas the task calling `adc_digi_read_bytes` is slow. * So `adc_digi_read_bytes` will hardly block. Therefore Idle Task hardly has chance to run. In this * example, we add a `vTaskDelay(1)` below, to prevent the task watchdog timeout. * * Solution: * Either decrease the conversion speed, or increase the frequency you call `adc_digi_read_bytes` */ } //均值滤波 x_data = 0; y_data = 0; for (int i = 0; i < ret_num; i += ADC_RESULT_BYTE) { adc_digi_output_data_t *p = (void *)&result[i]; if (ADC_CONV_MODE == ADC_CONV_BOTH_UNIT || ADC_CONV_MODE == ADC_CONV_ALTER_UNIT) { if (check_valid_data(p)) { if (p->type2.channel == ADC1_CHANNEL_1) x_data += p->type2.data; else y_data += p->type2.data; } else { // abort(); ESP_LOGI(TAG, "Invalid data [%d_%d_%x]", p->type2.unit + 1, p->type2.channel, p->type2.data); } } } if (x_data || y_data) { rocker_data[0] = x_data >> 4; rocker_data[1] = y_data >> 4; } // ESP_LOGI(TAG, "x:%d, y:%d", rocker_data[0], rocker_data[1]); // See `note 1` vTaskDelay(5); } else if (ret == ESP_ERR_TIMEOUT) { /** * ``ESP_ERR_TIMEOUT``: If ADC conversion is not finished until Timeout, you'll get this return error. * Here we set Timeout ``portMAX_DELAY``, so you'll never reach this branch. */ ESP_LOGW(TAG, "No data, increase timeout or reduce conv_num_each_intr"); vTaskDelay(1000); } } vTaskDelete(NULL); } void rocker_init() { rocker_sw_init(); continuous_adc_init(adc1_chan_mask, channel, sizeof(channel) / sizeof(adc_channel_t)); adc_digi_start(); xTaskCreate(&adc_read_task, "ROCKER_TASK", 1024 * 4, NULL, 5, NULL); } uint8_t rocker_sw_read() { return gpio_get_level(sw_pin); }
---
转载请注明本文标题和链接:《ESP32C3使用摇杆--adc dma espidf》
发表评论