[DemoCode下载] 定时器触发PDMA传输到DAC转换方法

[复制链接]
1688|6
 楼主| gejigeji521 发表于 2024-7-13 16:54 | 显示全部楼层 |阅读模式
pd, DMA, DM, DAC, AC
  1. /*************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
  4. * [url=home.php?mod=space&uid=247401]@brief[/url]    Demonstrate how to PDMA and trigger DAC by Timer.
  5. *
  6. * [url=home.php?mod=space&uid=17282]@CopyRight[/url] (C) 2017 Nuvoton Technology Corp. All rights reserved.
  7. *
  8. ******************************************************************************/
  9. #include "stdio.h"
  10. #include "NuMicro.h"

  11. #if defined (__GNUC__) && !defined(__ARMCC_VERSION) && defined(OS_USE_SEMIHOSTING)
  12. extern void initialise_monitor_handles(void);
  13. #endif

  14. const uint16_t sine[] = {2047, 2251, 2453, 2651, 2844, 3028, 3202, 3365, 3515, 3650, 3769, 3871, 3954,
  15.                          4019, 4064, 4088, 4095, 4076, 4040, 3984, 3908, 3813, 3701, 3573, 3429, 3272,
  16.                          3102, 2921, 2732, 2536, 2335, 2132, 1927, 1724, 1523, 1328, 1141,  962,  794,
  17.                          639,  497,  371,  262,  171,   99,   45,   12,    0,    7,   35,   84,  151,
  18.                          238,  343,  465,  602,  754,  919, 1095, 1281, 1475, 1674, 1876
  19.                         };
  20. const uint32_t array_size = sizeof(sine) / sizeof(uint16_t);

  21. void SYS_Init(void)
  22. {
  23.     /* Unlock protected registers */
  24.     SYS_UnlockReg();

  25.     /* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
  26.     PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);

  27.     /* Enable HXT clock (external XTAL 12MHz) */
  28.     CLK_EnableXtalRC(CLK_PWRCTL_HXTEN_Msk);

  29.     /* Wait for HXT clock ready */
  30.     CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);

  31.     /* Set core clock as PLL_CLOCK from PLL */
  32.     CLK_SetCoreClock(FREQ_192MHZ);

  33.     /* Set both PCLK0 and PCLK1 as HCLK/2 */
  34.     CLK->PCLKDIV = CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2;

  35.     /* Enable DAC module clock */
  36.     CLK_EnableModuleClock(DAC_MODULE);

  37.     /* Enable Timer 0 module clock */
  38.     CLK_EnableModuleClock(TMR0_MODULE);

  39.     /* Enable PDMA module clock */
  40.     CLK_EnableModuleClock(PDMA_MODULE);

  41.     /* Set PB.12 and PB.13 to input mode */
  42.     PB->MODE &= ~(GPIO_MODE_MODE12_Msk | GPIO_MODE_MODE13_Msk);
  43.     /* Set PB multi-function pins for DAC voltage output */
  44.     SYS->GPB_MFPH |= SYS_GPB_MFPH_PB12MFP_DAC0_OUT | SYS_GPB_MFPH_PB13MFP_DAC1_OUT;

  45.     /* Disable digital input path of analog pin DAC0_OUT to prevent leakage */
  46.     GPIO_DISABLE_DIGITAL_PATH(PB, (1ul << 12));
  47.     /* Lock protected registers */
  48.     SYS_LockReg();
  49. }

  50. int32_t main(void)
  51. {
  52.     /* Init System, IP clock and multi-function I/O */
  53.     SYS_Init();

  54. #if defined (__GNUC__) && !defined(__ARMCC_VERSION) && defined(OS_USE_SEMIHOSTING)
  55.     initialise_monitor_handles();
  56. #endif

  57.     printf("This sample code use PDMA and trigger DAC0 output sine wave by Timer 0.\n");

  58.     /* Open Channel 0 */
  59.     PDMA_Open(PDMA,0x1);

  60.     /* Set transfer data width, and transfer count */
  61.     PDMA_SetTransferCnt(PDMA,0, PDMA_WIDTH_16, array_size);

  62.     /* transfer width is one word(32 bit) */
  63.     PDMA_SetTransferAddr(PDMA,0, (uint32_t)&sine[0], PDMA_SAR_INC, (uint32_t)&DAC0->DAT, PDMA_DAR_FIX);

  64.     /* Select channel 0 request source from DAC */
  65.     PDMA_SetTransferMode(PDMA,0, PDMA_DAC0_TX, FALSE, 0);

  66.     /* Set transfer type and burst size */
  67.     PDMA_SetBurstType(PDMA,0, PDMA_REQ_SINGLE, PDMA_BURST_128);

  68.     /* Set the timer 0 trigger DAC and enable D/A converter */
  69.     DAC_Open(DAC0, 0, DAC_TIMER0_TRIGGER);

  70.     /* The DAC conversion settling time is 1us */
  71.     DAC_SetDelayTime(DAC0, 1);

  72.     /* Clear the DAC conversion complete finish flag for safe */
  73.     DAC_CLR_INT_FLAG(DAC0, 0);

  74.     /* Enable the PDMA Mode */
  75.     DAC_ENABLE_PDMA(DAC0);

  76.     /* Enable Timer0 counting to start D/A conversion */
  77.     TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, 1000);
  78.     TIMER_SetTriggerTarget(TIMER0, TIMER_TRG_TO_DAC);
  79.     TIMER_Start(TIMER0);

  80.     while(1)
  81.     {
  82.         if (PDMA_GET_TD_STS(PDMA) == 0x1)
  83.         {
  84.             /* Re-Set transfer count and basic operation mode */
  85.             PDMA_SetTransferCnt(PDMA,0, PDMA_WIDTH_16, array_size);
  86.             PDMA_SetTransferMode(PDMA,0, PDMA_DAC0_TX, FALSE, 0);

  87.             /* Clear PDMA channel 0 transfer done flag */
  88.             PDMA_CLR_TD_FLAG(PDMA,0x1);
  89.         }
  90.     }
  91. }
概述:

程序通过 PDMA(外设直接存储器访问)和定时器触发 DAC 转换。
使用 PDMA 将数据传输到 DAC,从而减轻 CPU 负载。
关键部分:

使用定时器 0 触发 DAC 转换。
配置 PDMA 以传输数据到 DAC。
初始化系统时钟、定时器、DAC 和 PDMA 模块。
在主循环中监视 PDMA 传输完成标志,重新配置 PDMA 以进行下一次传输。

 楼主| gejigeji521 发表于 2024-7-13 16:55 | 显示全部楼层
关键的主要步骤如下:
  1. /* 主要步骤 */
  2. SYS_Init();
  3. PDMA_Open(PDMA, 0x1);
  4. PDMA_SetTransferCnt(PDMA, 0, PDMA_WIDTH_16, array_size);
  5. PDMA_SetTransferAddr(PDMA, 0, (uint32_t)&sine[0], PDMA_SAR_INC, (uint32_t)&DAC0->DAT, PDMA_DAR_FIX);
  6. PDMA_SetTransferMode(PDMA, 0, PDMA_DAC0_TX, FALSE, 0);
  7. PDMA_SetBurstType(PDMA, 0, PDMA_REQ_SINGLE, PDMA_BURST_128);
  8. DAC_Open(DAC0, 0, DAC_TIMER0_TRIGGER);
  9. DAC_SetDelayTime(DAC0, 1);
  10. DAC_CLR_INT_FLAG(DAC0, 0);
  11. DAC_ENABLE_PDMA(DAC0);
  12. TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, 1000);
  13. TIMER_SetTriggerTarget(TIMER0, TIMER_TRG_TO_DAC);
  14. TIMER_Start(TIMER0);

  15. while(1) {
  16.     if (PDMA_GET_TD_STS(PDMA) == 0x1) {
  17.         PDMA_SetTransferCnt(PDMA, 0, PDMA_WIDTH_16, array_size);
  18.         PDMA_SetTransferMode(PDMA, 0, PDMA_DAC0_TX, FALSE, 0);
  19.         PDMA_CLR_TD_FLAG(PDMA, 0x1);
  20.     }
  21. }
 楼主| gejigeji521 发表于 2024-7-13 17:05 | 显示全部楼层
关键函数说明:
  1. /**
  2. * @brief       设置 PDMA 传输地址
  3. *
  4. * @param[in]   pdma            指向指定 PDMA 模块的指针
  5. * @param[in]   u32Ch           选定的通道
  6. * @param[in]   u32SrcAddr      源地址
  7. * @param[in]   u32SrcCtrl      源控制属性。有效值为:
  8. *                - \ref PDMA_SAR_INC(源地址递增)
  9. *                - \ref PDMA_SAR_FIX(源地址固定)
  10. * @param[in]   u32DstAddr      目标地址
  11. * @param[in]   u32DstCtrl      目标控制属性。有效值为:
  12. *                - \ref PDMA_DAR_INC(目标地址递增)
  13. *                - \ref PDMA_DAR_FIX(目标地址固定)
  14. *
  15. * [url=home.php?mod=space&uid=266161]@return[/url]      无
  16. *
  17. * [url=home.php?mod=space&uid=1543424]@Details[/url]     此函数设置选定通道的源地址/目标地址和属性。
  18. */
  19. void PDMA_SetTransferAddr(PDMA_T * pdma, uint32_t u32Ch, uint32_t u32SrcAddr, uint32_t u32SrcCtrl, uint32_t u32DstAddr, uint32_t u32DstCtrl);


 楼主| gejigeji521 发表于 2024-7-13 17:06 | 显示全部楼层
对比上面的函数说明,再回头看示例中的操作思路就很明确了。
 楼主| gejigeji521 发表于 2024-7-13 17:06 | 显示全部楼层
函数参数说明
pdma:指向指定 PDMA 模块的指针。
u32Ch:选定的通道。
u32SrcAddr:源地址。
u32SrcCtrl:源控制属性,指示源地址是否递增或固定,有效值为 PDMA_SAR_INC(源地址递增)和 PDMA_SAR_FIX(源地址固定)。
u32DstAddr:目标地址。
u32DstCtrl:目标控制属性,指示目标地址是否递增或固定,有效值为 PDMA_DAR_INC(目标地址递增)和 PDMA_DAR_FIX(目标地址固定)。
函数作用
此函数用于设置选定 PDMA 通道的源地址和目标地址及其相应的控制属性。源地址和目标地址可以设定为递增或固定,根据传输的具体需求进行设置。
 楼主| gejigeji521 发表于 2024-7-13 17:21 | 显示全部楼层
PDMA_SetTransferMode 函数解释
  1. /**
  2. * @brief       设置 PDMA 传输模式
  3. *
  4. * @param[in]   pdma            指向指定 PDMA 模块的指针
  5. * @param[in]   u32Ch           选定的通道
  6. * @param[in]   u32Peripheral   选定的外设。有效值包括:
  7. *                - \ref PDMA_MEM
  8. *                - \ref PDMA_USB_TX
  9. *                - \ref PDMA_USB_RX
  10. *                - \ref PDMA_UART0_TX
  11. *                - \ref PDMA_UART0_RX
  12. *                - \ref PDMA_UART1_TX
  13. *                - \ref PDMA_UART1_RX
  14. *                - \ref PDMA_UART2_TX
  15. *                - \ref PDMA_UART2_RX
  16. *                - \ref PDMA_UART3_TX
  17. *                - \ref PDMA_UART3_RX
  18. *                - \ref PDMA_UART4_TX
  19. *                - \ref PDMA_UART4_RX
  20. *                - \ref PDMA_UART5_TX
  21. *                - \ref PDMA_UART5_RX
  22. *                - \ref PDMA_USCI0_TX
  23. *                - \ref PDMA_USCI0_RX
  24. *                - \ref PDMA_USCI1_TX
  25. *                - \ref PDMA_USCI1_RX
  26. *                - \ref PDMA_QSPI0_TX
  27. *                - \ref PDMA_QSPI0_RX
  28. *                - \ref PDMA_SPI0_TX
  29. *                - \ref PDMA_SPI0_RX
  30. *                - \ref PDMA_SPI1_TX
  31. *                - \ref PDMA_SPI1_RX
  32. *                - \ref PDMA_SPI2_TX
  33. *                - \ref PDMA_SPI2_RX
  34. *                - \ref PDMA_SPI3_TX
  35. *                - \ref PDMA_SPI3_RX
  36. *                - \ref PDMA_EPWM0_P1_RX
  37. *                - \ref PDMA_EPWM0_P2_RX
  38. *                - \ref PDMA_EPWM0_P3_RX
  39. *                - \ref PDMA_EPWM1_P1_RX
  40. *                - \ref PDMA_EPWM1_P2_RX
  41. *                - \ref PDMA_EPWM1_P3_RX
  42. *                - \ref PDMA_I2C0_TX
  43. *                - \ref PDMA_I2C0_RX
  44. *                - \ref PDMA_I2C1_TX
  45. *                - \ref PDMA_I2C1_RX
  46. *                - \ref PDMA_I2C2_TX
  47. *                - \ref PDMA_I2C2_RX
  48. *                - \ref PDMA_I2S0_TX
  49. *                - \ref PDMA_I2S0_RX
  50. *                - \ref PDMA_TMR0
  51. *                - \ref PDMA_TMR1
  52. *                - \ref PDMA_TMR2
  53. *                - \ref PDMA_TMR3
  54. *                - \ref PDMA_EADC0_RX
  55. *                - \ref PDMA_DAC0_TX
  56. *                - \ref PDMA_DAC1_TX
  57. *                - \ref PDMA_EPWM0_CH0_TX
  58. *                - \ref PDMA_EPWM0_CH1_TX
  59. *                - \ref PDMA_EPWM0_CH2_TX
  60. *                - \ref PDMA_EPWM0_CH3_TX
  61. *                - \ref PDMA_EPWM0_CH4_TX
  62. *                - \ref PDMA_EPWM0_CH5_TX
  63. *                - \ref PDMA_EPWM1_CH0_TX
  64. *                - \ref PDMA_EPWM1_CH1_TX
  65. *                - \ref PDMA_EPWM1_CH2_TX
  66. *                - \ref PDMA_EPWM1_CH3_TX
  67. *                - \ref PDMA_EPWM1_CH4_TX
  68. *                - \ref PDMA_EPWM1_CH5_TX
  69. *                - \ref PDMA_UART6_TX
  70. *                - \ref PDMA_UART6_RX
  71. *                - \ref PDMA_UART7_TX
  72. *                - \ref PDMA_UART7_RX
  73. *                - \ref PDMA_EADC1_RX
  74. * @param[in]   u32ScatterEn    是否启用散播聚集模式
  75. * @param[in]   u32DescAddr     散播聚集描述符地址
  76. *
  77. * @return      无
  78. *
  79. * @details     此函数设置选定通道的传输模式,包括外设设置。
  80. */
  81. void PDMA_SetTransferMode(PDMA_T * pdma, uint32_t u32Ch, uint32_t u32Peripheral, uint32_t u32ScatterEn, uint32_t u32DescAddr);
 楼主| gejigeji521 发表于 2024-7-13 17:21 | 显示全部楼层
函数参数说明
pdma:指向指定 PDMA 模块的指针。
u32Ch:选定的通道。
u32Peripheral:选定的外设。有效值为多个定义的常量,如 PDMA_MEM、PDMA_UART0_TX 等等,这些常量定义了特定的外设接口。
u32ScatterEn:是否启用散播聚集模式(Scatter-gather mode),用于复杂的传输需求。
u32DescAddr:散播聚集描述符地址,用于指向散播聚集模式下的描述符表。
函数作用
此函数用于设置选定 PDMA 通道的传输模式,包括与外设相关的设置。它可以配置传输的外设接口,并选择是否启用散播聚集模式,以满足不同的传输需求。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

196

主题

2465

帖子

8

粉丝
快速回复 在线客服 返回列表 返回顶部