wave_gen_example_main.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /* Wave Generator Example
  2. This example code is in the Public Domain (or CC0 licensed, at your option.)
  3. DAC output channel, waveform, wave frequency can be customized in menuconfig.
  4. If any questions about this example or more information is needed, please read README.md before your start.
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <math.h>
  9. #include <assert.h>
  10. #include "freertos/FreeRTOS.h"
  11. #include "freertos/task.h"
  12. #include "freertos/queue.h"
  13. #include "driver/gpio.h"
  14. #include "driver/dac.h"
  15. #include "driver/timer.h"
  16. #include "esp_log.h"
  17. /* The timer ISR has an execution time of 5.5 micro-seconds(us).
  18. Therefore, a timer period less than 5.5 us will cause trigger the interrupt watchdog.
  19. 7 us is a safe interval that will not trigger the watchdog. No need to customize it.
  20. */
  21. #define WITH_RELOAD 1
  22. #define TIMER_INTR_US 7 // Execution time of each ISR interval in micro-seconds
  23. #define TIMER_DIVIDER 16
  24. #define POINT_ARR_LEN 200 // Length of points array
  25. #define AMP_DAC 255 // Amplitude of DAC voltage. If it's more than 256 will causes dac_output_voltage() output 0.
  26. #define VDD 3300 // VDD is 3.3V, 3300mV
  27. #define CONST_PERIOD_2_PI 6.2832
  28. #define SEC_TO_MICRO_SEC(x) ((x) / 1000 / 1000) // Convert second to micro-second
  29. #define UNUSED_PARAM __attribute__((unused)) // A const period parameter which equals 2 * pai, used to calculate raw dac output value.
  30. #define TIMER_TICKS (TIMER_BASE_CLK / TIMER_DIVIDER) // TIMER_BASE_CLK = APB_CLK = 80MHz
  31. #define ALARM_VAL_US SEC_TO_MICRO_SEC(TIMER_INTR_US * TIMER_TICKS) // Alarm value in micro-seconds
  32. #define OUTPUT_POINT_NUM (int)(1000000 / (TIMER_INTR_US * FREQ) + 0.5) // The number of output wave points.
  33. #define DAC_CHAN CONFIG_EXAMPLE_DAC_CHANNEL // DAC_CHANNEL_1 (GPIO25) by default
  34. #define FREQ CONFIG_EXAMPLE_WAVE_FREQUENCY // 3kHz by default
  35. _Static_assert(OUTPUT_POINT_NUM <= POINT_ARR_LEN, "The CONFIG_EXAMPLE_WAVE_FREQUENCY is too low and using too long buffer.");
  36. static int raw_val[POINT_ARR_LEN]; // Used to store raw values
  37. static int volt_val[POINT_ARR_LEN]; // Used to store voltage values(in mV)
  38. static const char *TAG = "wave_gen";
  39. static int g_index = 0;
  40. /* Timer interrupt service routine */
  41. static void IRAM_ATTR timer0_ISR(void *ptr)
  42. {
  43. timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
  44. timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0);
  45. int *head = (int*)ptr;
  46. /* DAC output ISR has an execution time of 4.4 us*/
  47. if (g_index >= OUTPUT_POINT_NUM) g_index = 0;
  48. dac_output_voltage(DAC_CHAN, *(head + g_index));
  49. g_index++;
  50. }
  51. /* Timer group0 TIMER_0 initialization */
  52. static void example_timer_init(int timer_idx, bool auto_reload)
  53. {
  54. esp_err_t ret;
  55. timer_config_t config = {
  56. .divider = TIMER_DIVIDER,
  57. .counter_dir = TIMER_COUNT_UP,
  58. .counter_en = TIMER_PAUSE,
  59. .alarm_en = TIMER_ALARM_EN,
  60. .intr_type = TIMER_INTR_LEVEL,
  61. .auto_reload = auto_reload,
  62. };
  63. ret = timer_init(TIMER_GROUP_0, timer_idx, &config);
  64. ESP_ERROR_CHECK(ret);
  65. ret = timer_set_counter_value(TIMER_GROUP_0, timer_idx, 0x00000000ULL);
  66. ESP_ERROR_CHECK(ret);
  67. ret = timer_set_alarm_value(TIMER_GROUP_0, timer_idx, ALARM_VAL_US);
  68. ESP_ERROR_CHECK(ret);
  69. ret = timer_enable_intr(TIMER_GROUP_0, TIMER_0);
  70. ESP_ERROR_CHECK(ret);
  71. /* Register an ISR handler */
  72. timer_isr_register(TIMER_GROUP_0, timer_idx, timer0_ISR, (void *)raw_val, 0, NULL);
  73. }
  74. static void prepare_data(int pnt_num)
  75. {
  76. timer_pause(TIMER_GROUP_0, TIMER_0);
  77. for (int i = 0; i < pnt_num; i ++) {
  78. #ifdef CONFIG_EXAMPLE_WAVEFORM_SINE
  79. raw_val[i] = (int)((sin( i * CONST_PERIOD_2_PI / pnt_num) + 1) * (double)(AMP_DAC)/2 + 0.5);
  80. #elif CONFIG_EXAMPLE_WAVEFORM_TRIANGLE
  81. raw_val[i] = (i > (pnt_num/2)) ? (2 * AMP_DAC * (pnt_num - i) / pnt_num) : (2 * AMP_DAC * i / pnt_num);
  82. #elif CONFIG_EXAMPLE_WAVEFORM_SAWTOOTH
  83. raw_val[i] = (i == pnt_num) ? 0 : (i * AMP_DAC / pnt_num);
  84. #elif CONFIG_EXAMPLE_WAVEFORM_SQUARE
  85. raw_val[i] = (i < (pnt_num/2)) ? AMP_DAC : 0;
  86. #endif
  87. volt_val[i] = (int)(VDD * raw_val[i] / (float)AMP_DAC);
  88. }
  89. timer_start(TIMER_GROUP_0, TIMER_0);
  90. }
  91. static void log_info(void)
  92. {
  93. ESP_LOGI(TAG, "DAC output channel: %d", DAC_CHAN);
  94. if (DAC_CHAN == DAC_CHANNEL_1) {
  95. ESP_LOGI(TAG, "GPIO:%d", GPIO_NUM_25);
  96. } else {
  97. ESP_LOGI(TAG, "GPIO:%d", GPIO_NUM_26);
  98. }
  99. #ifdef CONFIG_EXAMPLE_WAVEFORM_SINE
  100. ESP_LOGI(TAG, "Waveform: SINE");
  101. #elif CONFIG_EXAMPLE_WAVEFORM_TRIANGLE
  102. ESP_LOGI(TAG, "Waveform: TRIANGLE");
  103. #elif CONFIG_EXAMPLE_WAVEFORM_SAWTOOTH
  104. ESP_LOGI(TAG, "Waveform: SAWTOOTH");
  105. #elif CONFIG_EXAMPLE_WAVEFORM_SQUARE
  106. ESP_LOGI(TAG, "Waveform: SQUARE");
  107. #endif
  108. ESP_LOGI(TAG, "Frequency(Hz): %d", FREQ);
  109. ESP_LOGI(TAG, "Output points num: %d\n", OUTPUT_POINT_NUM);
  110. }
  111. void app_main(void)
  112. {
  113. esp_err_t ret;
  114. example_timer_init(TIMER_0, WITH_RELOAD);
  115. ret = dac_output_enable(DAC_CHAN);
  116. ESP_ERROR_CHECK(ret);
  117. log_info();
  118. g_index = 0;
  119. prepare_data(OUTPUT_POINT_NUM);
  120. while(1) {
  121. vTaskDelay(10);
  122. #if CONFIG_EXAMPLE_LOG_VOLTAGE
  123. if (g_index < OUTPUT_POINT_NUM) {
  124. ESP_LOGI(TAG, "Output voltage(mV): %d", volt_val[g_index]);
  125. ESP_LOGD(TAG, "g_index: %d\n", g_index);
  126. }
  127. #endif
  128. }
  129. }