110 lines
4.3 KiB
C
110 lines
4.3 KiB
C
|
|
/*
|
|||
|
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|||
|
|
*
|
|||
|
|
* SPDX-License-Identifier: CC0-1.0
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
#include <stdio.h>
|
|||
|
|
#include <stdlib.h>
|
|||
|
|
#include <math.h>
|
|||
|
|
#include <assert.h>
|
|||
|
|
#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));
|
|||
|
|
}
|