adc_dma_sample.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #include <stdio.h>
  2. #include "pico/stdlib.h"
  3. #include "hardware/dma.h"
  4. #include "hardware/adc.h"
  5. #include "hardware/clocks.h"
  6. #include "hardware/pwm.h"
  7. #define LED_PIN PICO_DEFAULT_LED_PIN // LED
  8. uint slice_num;
  9. #define ADC0_PIN ADC_BASE_PIN
  10. #define ADC1_PIN (ADC_BASE_PIN+1)
  11. #define ADC2_PIN (ADC_BASE_PIN+2)
  12. #define ADC_VREF 3.3f
  13. #define ADC_SAMPLE_CLKS 96
  14. #define SAMPLE_RATE 1000
  15. typedef enum {
  16. adc_input0,
  17. adc_input1,
  18. adc_input2,
  19. adc_input3,
  20. adc_input4,
  21. } _adc_input_t;
  22. #define RW_BUFFER_SIZE 256
  23. int adc_dma_ch;
  24. volatile static uint8_t rw_buffer[2][RW_BUFFER_SIZE];
  25. volatile static int write_buf_selector = 0;
  26. volatile static int read_buf_selector = 1;
  27. void adc_dma_irq_handler(void)
  28. {
  29. // 割り込みフラグクリア
  30. dma_channel_acknowledge_irq0(adc_dma_ch);
  31. write_buf_selector = read_buf_selector ^ 1;
  32. // DMA転送を再トリガー
  33. dma_channel_set_write_addr(adc_dma_ch, rw_buffer[write_buf_selector], false);
  34. dma_channel_set_trans_count(adc_dma_ch, RW_BUFFER_SIZE, true);
  35. }
  36. void pwm_irq_handler(void)
  37. {
  38. static int counter = 0;
  39. pwm_clear_irq(slice_num);
  40. pwm_set_gpio_level(LED_PIN, (uint16_t)rw_buffer[read_buf_selector][counter++]);
  41. if(counter > RW_BUFFER_SIZE) {
  42. read_buf_selector = write_buf_selector ^ 1;
  43. counter = 0;
  44. }
  45. }
  46. int main()
  47. {
  48. stdio_init_all();
  49. float adc_div, pwm_div;
  50. gpio_set_function(LED_PIN, GPIO_FUNC_PWM);
  51. pwm_config c = pwm_get_default_config();
  52. pwm_div = clock_get_hz(clk_sys) / SAMPLE_RATE / RW_BUFFER_SIZE;
  53. pwm_config_set_clkdiv(&c, pwm_div);
  54. pwm_config_set_wrap(&c, RW_BUFFER_SIZE);
  55. slice_num = pwm_gpio_to_slice_num(LED_PIN);
  56. pwm_init(slice_num, &c, false);
  57. pwm_set_gpio_level(LED_PIN, 0xFF );
  58. // PWM IRQ
  59. pwm_clear_irq(slice_num);
  60. pwm_set_irq_enabled(slice_num, true);
  61. irq_set_exclusive_handler(PWM_DEFAULT_IRQ_NUM(), pwm_irq_handler);
  62. irq_set_enabled(PWM_DEFAULT_IRQ_NUM(), true);
  63. // ADCの設定
  64. adc_init();
  65. adc_gpio_init(ADC0_PIN);
  66. // ADC FIFOの設定
  67. adc_fifo_setup(
  68. true, // FIFOを有効化するならtrue
  69. true, // DREQを有効化するならtrue
  70. 1, // DREQ、IRQを発生させるFIFOエントリ数
  71. false, // 最上位ビットをエラーフラグにするならtrue
  72. true // バイトシフトするならtrue
  73. );
  74. // ADCクロック分周比
  75. adc_div = (float)clock_get_hz(clk_adc) / (float)ADC_SAMPLE_CLKS / SAMPLE_RATE;
  76. adc_set_clkdiv(adc_div);
  77. printf("adc_div = %f\n", adc_div);
  78. adc_dma_ch = dma_claim_unused_channel(true);
  79. dma_channel_config dma_conf = dma_channel_get_default_config(adc_dma_ch);
  80. channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_8);
  81. channel_config_set_read_increment(&dma_conf, false);
  82. channel_config_set_write_increment(&dma_conf, true);
  83. channel_config_set_dreq(&dma_conf, DREQ_ADC);
  84. // DMAチャネル設定
  85. dma_channel_configure(
  86. adc_dma_ch,
  87. &dma_conf,
  88. (rw_buffer[0]), // 書き込み先はRW_BUFFER
  89. &adc_hw->fifo, // 読み出し元はRW_BUFFER
  90. RW_BUFFER_SIZE, // 転送回数
  91. false // 開始しない
  92. );
  93. dma_channel_set_irq0_enabled(adc_dma_ch, true);
  94. irq_set_exclusive_handler(DMA_IRQ_0, adc_dma_irq_handler);
  95. irq_set_enabled(DMA_IRQ_0, true);
  96. dma_channel_start(adc_dma_ch);
  97. adc_run(true);
  98. pwm_set_enabled(slice_num, true);
  99. while (true) {
  100. tight_loop_contents();
  101. }
  102. }