pwm_dma_sample.c 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #include <stdio.h>
  2. #include "pico/stdlib.h"
  3. #include "hardware/dma.h"
  4. #include "hardware/pwm.h"
  5. #include "hardware/clocks.h"
  6. #define AUDIO_OUT_PIN 2
  7. __asm(\
  8. ".section \".rodata\" \n"
  9. ".balign 4\n"
  10. ".global _audio_data\n"
  11. ".global _audio_data_len\n"
  12. "_audio_data:\n"
  13. ".incbin \"test12.raw\"\n"
  14. ".set _audio_data_len, . - _audio_data\n"
  15. ".section \".text\"\n"
  16. );
  17. extern const uint8_t _audio_data[];
  18. extern uint32_t _audio_data_len[];
  19. uint slice_num = 0;
  20. int dma_ch = 0;
  21. int main()
  22. {
  23. stdio_init_all();
  24. printf("audio_data_len = %d\n", _audio_data_len);
  25. // サンプリング周波数の都合でシステムクロックを
  26. // 125MHzに切り替える
  27. set_sys_clock_khz(125000, true);
  28. // PWM出力ピン
  29. gpio_set_function(AUDIO_OUT_PIN, GPIO_FUNC_PWM);
  30. // スライス番号
  31. slice_num = pwm_gpio_to_slice_num(AUDIO_OUT_PIN);
  32. // PWMの設定
  33. pwm_config pwm_conf = pwm_get_default_config();
  34. pwm_config_set_wrap(&pwm_conf, 4095); // PWM周波数15.259kHz
  35. pwm_config_set_clkdiv(&pwm_conf, 2.0f); // 62.5MHz
  36. pwm_init(slice_num, &pwm_conf, false);
  37. // DMAの設定
  38. dma_ch = dma_claim_unused_channel(true);
  39. dma_channel_config dma_conf = dma_channel_get_default_config(dma_ch);
  40. // 粒度は16bit中の下位12bit
  41. channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_16);
  42. // 送り出しはメモリ
  43. channel_config_set_read_increment(&dma_conf, true);
  44. // 受け側はDMAのCCレジスタ
  45. channel_config_set_write_increment(&dma_conf, false);
  46. // DREQを設定
  47. channel_config_set_dreq(&dma_conf, pwm_get_dreq(slice_num));
  48. // DMAチャネル設定
  49. dma_channel_configure(
  50. dma_ch,
  51. &dma_conf,
  52. (uint16_t *)&pwm_hw->slice[slice_num].cc+2, // 書き込み先はCCレジスタ
  53. (uint8_t *)_audio_data, // 読み出し元は12bitオーディオデータ
  54. (uint)_audio_data_len, // 転送回数
  55. false // 開始しない
  56. );
  57. // PWMを開始
  58. pwm_set_enabled(slice_num, true);
  59. // DMA転送を開始
  60. dma_channel_start(dma_ch);
  61. // DMAが完了するのを待つ
  62. dma_channel_wait_for_finish_blocking(dma_ch);
  63. // 再生終了
  64. pwm_set_enabled(slice_num, false);
  65. while (true) {
  66. tight_loop_contents();
  67. }
  68. }