TP3 TPF - nachocarballeda/embebidos_fiuba GitHub Wiki

TPF Funciones utilizadas en ESP32 para UART, ADC y DAC

DAC

Para habilitar un DAC en algun GPIO se debe llamar a la siguiente funcion:

esp_err_t dac_output_enable(dac_channel_t channel)

La misma utiliza el channel como parametro para llama a

dac_rtc_pad_init(channel);

La cual configura el pad para utilizarse como DAC:

static esp_err_t dac_rtc_pad_init(dac_channel_t channel)
{
    DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG);

    gpio_num_t gpio_num = 0;
    dac_pad_get_io_num(channel, &gpio_num);
    rtc_gpio_init(gpio_num);
    rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED);
    rtc_gpio_pullup_dis(gpio_num);
    rtc_gpio_pulldown_dis(gpio_num);

    return ESP_OK;
}

DAC_CHECK es un macro:

#define DAC_CHECK(a, str, ret_val) ({                                               \
    if (!(a)) {                                                                     \
        ESP_LOGE(DAC_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str);   \
        return (ret_val);                                                           \
    }                                                                               \
})

Donde se checkea que el canal seleccionado sea menor que el canal maximo, definido en un enum (vale 3 ya que solo hay dos DACs):

typedef enum {
    DAC_CHANNEL_1 = 0,    /*!< DAC channel 1 is GPIO25(ESP32) / GPIO17(ESP32S2) */
    DAC_CHANNEL_2 = 1,    /*!< DAC channel 2 is GPIO26(ESP32) / GPIO18(ESP32S2) */
    DAC_CHANNEL_MAX,
} dac_channel_t;

finalmente podemos setear el nivel de tension requerido (255 valores) en el GPIO con la función:

esp_err_t dac_output_voltage(dac_channel_t channel, uint8_t dac_value)

ADC

Primero debemos configurar el ADC a utilizar . En ESP32 wrover tenemos 2 canales, pero el segundo canal no se puede utilizar si estamos utilizando wifi.

La referencia de tension utilizada para comparar se selecciona via efuse.

Elegimos la resolución (12 bits como máximo)

esp_err_t adc1_config_width(adc_bits_width_t width_bit)

Seleccionamos la atenuación (maxima atenuación 11 db)

adc1_config_channel_atten(channel, atten);

y finalmente obtenemos la medición deseada

adc1_get_raw((adc1_channel_t)channel);

UART

Para analizar la UART lo mejor es desmenuzar una tarea basica como es la que realiza un "echo" sobre el puerto serie

static void echo_task(void *arg)
{
    /* Configure parameters of an UART driver,
     * communication pins and install the driver */
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity    = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };
    uart_driver_install(UART_NUM_1, BUF_SIZE * 2, 0, 0, NULL, 0);
    uart_param_config(UART_NUM_1, &uart_config);
    uart_set_pin(UART_NUM_1, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS);

    // Configure a temporary buffer for the incoming data
    uint8_t *data = (uint8_t *) malloc(BUF_SIZE);

    while (1) {
        // Read data from the UART
        int len = uart_read_bytes(UART_NUM_1, data, BUF_SIZE, 20 / portTICK_RATE_MS);
        // Write data back to the UART
        uart_write_bytes(UART_NUM_1, (const char *) data, len);
    }
}

Como se puede observar primero debemos configurar la UART a utilizar

uart_config_t uart_config = {
    .baud_rate = 115200,
    .data_bits = UART_DATA_8_BITS,
    .parity    = UART_PARITY_DISABLE,
    .stop_bits = UART_STOP_BITS_1,
    .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
    .source_clk = UART_SCLK_APB,
}

En la estructura uart_config_t debemos seleccionar el baudrate, cantidad de bits de datos, bit de paridad, control de flujo y la fuente de clock para la UART.

Llamamos a uart_driver_install para instalar el driver UART, inicializandolo por defecto y adozandolo al core del MCU deseado.

uart_driver_install(UART_NUM_1, BUF_SIZE * 2, 0, 0, NULL, 0);

Una vez instalado, lo configuramos con los parametros seteados en uart_config_t

uart_param_config(UART_NUM_1, &uart_config);

Seteamos los pines de salida y finalmente leemos o escribimos del puerto serie

uart_set_pin(UART_NUM_1, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS);

Lectura

uart_read_bytes(UART_NUM_1, data, BUF_SIZE, 20 / portTICK_RATE_MS);

Escritura

uart_write_bytes(UART_NUM_1, (const char *) data, len);