/* * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ #include #include #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "driver/gpio.h" #include "driver/gptimer.h" #include "driver/dac_oneshot.h" #include "esp_log.h" #include "dac_continuous_example.h" #define EXAMPLE_TIMER_RESOLUTION 1000000 // 1MHz,1个tick = 1us #define EXAMPLE_WAVE_FREQ_HZ 50 // 默认波形频率50Hz,不能太高 #define EXAMPLE_CONVERT_FREQ_HZ (EXAMPLE_ARRAY_LEN * EXAMPLE_WAVE_FREQ_HZ) // DAC转换波形数组中每个数据的频率 #define EXAMPLE_TIMER_ALARM_COUNT (EXAMPLE_TIMER_RESOLUTION / EXAMPLE_CONVERT_FREQ_HZ) // 触发定时器报警回调的计数值 static const char *TAG = "dac continuous(timer)"; static const char wav_name[DAC_WAVE_MAX][15] = {"sine", "triangle", "sawtooth", "square"}; static dac_oneshot_handle_t chan0_handle; static dac_oneshot_handle_t chan1_handle; extern uint8_t sin_wav[EXAMPLE_ARRAY_LEN]; // 用于存储正弦波值 extern uint8_t tri_wav[EXAMPLE_ARRAY_LEN]; // 用于存储三角波值 extern uint8_t saw_wav[EXAMPLE_ARRAY_LEN]; // 用于存储锯齿波值 extern uint8_t squ_wav[EXAMPLE_ARRAY_LEN]; // 用于存储方波值 /* 定时器中断服务例程 */ static bool IRAM_ATTR on_timer_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data) { static uint32_t point_cnt = 0; // 用于计算一个波形的输出点数 static uint32_t index = 0; // 波形缓冲区的当前索引 static dac_example_wave_type_t wav_sel = DAC_SINE_WAVE; // 从正弦波开始 // 每CONFIG_EXAMPLE_WAVE_PERIOD_SEC秒切换波形 if (point_cnt < EXAMPLE_CONVERT_FREQ_HZ * CONFIG_EXAMPLE_WAVE_PERIOD_SEC) { switch (wav_sel) { case DAC_SINE_WAVE: ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, sin_wav[index])); ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, sin_wav[index])); break; case DAC_TRIANGLE_WAVE: ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, tri_wav[index])); ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, tri_wav[index])); break; case DAC_SAWTOOTH_WAVE: ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, saw_wav[index])); ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, saw_wav[index])); break; case DAC_SQUARE_WAVE: ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan0_handle, squ_wav[index])); ESP_ERROR_CHECK(dac_oneshot_output_voltage(chan1_handle, squ_wav[index])); break; default: break; } point_cnt++; index++; index %= EXAMPLE_ARRAY_LEN; } else { wav_sel++; wav_sel %= DAC_WAVE_MAX; point_cnt = 0; index = 0; ESP_EARLY_LOGI(TAG, "%s wave start", wav_name[wav_sel]); } return false; } void example_dac_continuous_by_timer(void) { gptimer_handle_t gptimer = NULL; gptimer_config_t timer_config = { .clk_src = GPTIMER_CLK_SRC_DEFAULT, .direction = GPTIMER_COUNT_UP, .resolution_hz = EXAMPLE_TIMER_RESOLUTION, // 1MHz,1个tick = 1us }; ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer)); dac_oneshot_config_t dac0_cfg = { .chan_id = DAC_CHAN_0, }; ESP_ERROR_CHECK(dac_oneshot_new_channel(&dac0_cfg, &chan0_handle)); dac_oneshot_config_t dac1_cfg = { .chan_id = DAC_CHAN_1, }; ESP_ERROR_CHECK(dac_oneshot_new_channel(&dac1_cfg, &chan1_handle)); example_log_info(EXAMPLE_CONVERT_FREQ_HZ, EXAMPLE_WAVE_FREQ_HZ); gptimer_alarm_config_t alarm_config = { .reload_count = 0, .alarm_count = EXAMPLE_TIMER_ALARM_COUNT, .flags.auto_reload_on_alarm = true, }; gptimer_event_callbacks_t cbs = { .on_alarm = on_timer_alarm_cb, }; ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, NULL)); ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config)); ESP_ERROR_CHECK(gptimer_enable(gptimer)); ESP_ERROR_CHECK(gptimer_start(gptimer)); }