Simulator_Test/main/dac_continuous_example_main.c

122 lines
5.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include <inttypes.h>
#include <math.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/dac_channel.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_check.h"
#include "dac_continuous_example.h"
/**
* 有两种方式可以连续将数字数据转换为模拟信号:
* - 使用定时器在定时器中断中定期设置DAC电压
* 这种方式DAC可以达到相对较低的转换频率
* 但与使用DMA相比这不是一种高效的方式
* - 使用DMA通过DMA传输数据缓冲区
* 转换频率由DMA传输速度控制
* 这种方式转换频率可以达到几MHz
* 但由于受DMA时钟源限制无法达到很低的转换频率
* 一般来说推荐使用DMA如果DMA外设被占用或所需的转换频率很低
* 则使用定时器代替
*/
/* ADC配置 */
#if CONFIG_IDF_TARGET_ESP32
#define EXAMPLE_DAC_CHAN0_ADC_CHAN ADC_CHANNEL_8 // GPIO25与DAC通道0相同
#define EXAMPLE_DAC_CHAN1_ADC_CHAN ADC_CHANNEL_9 // GPIO26与DAC通道1相同
#define EXAMPLE_ADC_WIDTH ADC_WIDTH_BIT_12
#elif CONFIG_IDF_TARGET_ESP32S2
#define EXAMPLE_DAC_CHAN0_ADC_CHAN ADC_CHANNEL_6 // GPIO17与DAC通道0相同
#define EXAMPLE_DAC_CHAN1_ADC_CHAN ADC_CHANNEL_7 // GPIO18与DAC通道1相同
#define EXAMPLE_ADC_WIDTH ADC_WIDTH_BIT_13
#endif
#define EXAMPLE_DAC_CHAN0_IO DAC_CHAN0_GPIO_NUM // DAC通道0的IO号
#define EXAMPLE_DAC_CHAN1_IO DAC_CHAN1_GPIO_NUM // DAC通道1的IO号
#define EXAMPLE_ADC_ATTEN ADC_ATTEN_DB_12
_Static_assert(EXAMPLE_DAC_AMPLITUDE < 256, "DAC精度为8位不支持超过255的幅度");
static const char *TAG = "dac continuous";
uint8_t sin_wav[EXAMPLE_ARRAY_LEN]; // 用于存储正弦波值
uint8_t tri_wav[EXAMPLE_ARRAY_LEN]; // 用于存储三角波值
uint8_t saw_wav[EXAMPLE_ARRAY_LEN]; // 用于存储锯齿波值
uint8_t squ_wav[EXAMPLE_ARRAY_LEN]; // 用于存储方波值
static void example_generate_wave(void)
{
uint32_t pnt_num = EXAMPLE_ARRAY_LEN;
for (int i = 0; i < pnt_num; i ++) {
sin_wav[i] = (uint8_t)((sin(i * CONST_PERIOD_2_PI / pnt_num) + 1) * (double)(EXAMPLE_DAC_AMPLITUDE) / 2 + 0.5);
tri_wav[i] = (i > (pnt_num / 2)) ? (2 * EXAMPLE_DAC_AMPLITUDE * (pnt_num - i) / pnt_num) : (2 * EXAMPLE_DAC_AMPLITUDE * i / pnt_num);
saw_wav[i] = (i == pnt_num) ? 0 : (i * EXAMPLE_DAC_AMPLITUDE / pnt_num);
squ_wav[i] = (i < (pnt_num / 2)) ? EXAMPLE_DAC_AMPLITUDE : 0;
}
}
void example_log_info(uint32_t conv_freq, uint32_t wave_freq)
{
ESP_LOGI(TAG, "--------------------------------------------------");
#if CONFIG_EXAMPLE_DAC_CONTINUOUS_BY_DMA
ESP_LOGI(TAG, "DAC continuous output by DMA");
#else
ESP_LOGI(TAG, "DAC continuous output by timer");
#endif
ESP_LOGI(TAG, "DAC channel 0 io: GPIO_NUM_%d", EXAMPLE_DAC_CHAN0_IO);
ESP_LOGI(TAG, "DAC channel 1 io: GPIO_NUM_%d", EXAMPLE_DAC_CHAN1_IO);
ESP_LOGI(TAG, "Waveform: SINE -> TRIANGLE -> SAWTOOTH -> SQUARE");
ESP_LOGI(TAG, "DAC conversion frequency (Hz): %"PRIu32, conv_freq);
ESP_LOGI(TAG, "DAC wave frequency (Hz): %"PRIu32, wave_freq);
ESP_LOGI(TAG, "--------------------------------------------------");
}
static void adc_monitor_task(void *args)
{
adc_oneshot_unit_handle_t adc2_handle = (adc_oneshot_unit_handle_t)args;
int chan0_val = 0;
int chan1_val = 0;
while (1) {
/* 读取DAC输出电压 */
ESP_ERROR_CHECK(adc_oneshot_read(adc2_handle, EXAMPLE_DAC_CHAN0_ADC_CHAN, &chan0_val));
ESP_ERROR_CHECK(adc_oneshot_read(adc2_handle, EXAMPLE_DAC_CHAN1_ADC_CHAN, &chan1_val));
printf("DAC channel 0 value: %4d\tDAC channel 1 value: %4d\n", chan0_val, chan1_val);
vTaskDelay(pdMS_TO_TICKS(100));
}
}
void app_main(void)
{
example_generate_wave();
#if CONFIG_EXAMPLE_DAC_CONTINUOUS_BY_DMA
/* 使用DMA输出2kHz波形 */
example_dac_continuous_by_dma();
#else
/* 使用定时器中断输出50Hz波形 */
example_dac_continuous_by_timer();
#endif
/* 设置ADC2通道这些通道内部连接到DAC通道 */
adc_oneshot_unit_handle_t adc2_handle;
adc_oneshot_unit_init_cfg_t adc_cfg = {
.unit_id = ADC_UNIT_2,
.ulp_mode = false,
};
ESP_ERROR_CHECK(adc_oneshot_new_unit(&adc_cfg, &adc2_handle));
adc_oneshot_chan_cfg_t chan_cfg = {
.atten = EXAMPLE_ADC_ATTEN,
.bitwidth = ADC_BITWIDTH_DEFAULT,
};
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc2_handle, EXAMPLE_DAC_CHAN0_ADC_CHAN, &chan_cfg));
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc2_handle, EXAMPLE_DAC_CHAN1_ADC_CHAN, &chan_cfg));
/* 创建ADC监控任务以检测DAC引脚上的电压 */
xTaskCreate(adc_monitor_task, "adc_monitor_task", 4096, adc2_handle, 5, NULL);
}