打印
[牛人杂谈]

采用EPWM触发PDMA发送执行DAC功能

[复制链接]
655|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gejigeji521|  楼主 | 2024-7-13 18:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PWM, DMA, DM, DAC, AC
/*************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
* [url=home.php?mod=space&uid=247401]@brief[/url]    Demonstrate how to use PDMA and trigger DAC0 by EPWM.
*
* [url=home.php?mod=space&uid=17282]@CopyRight[/url] (C) 2017 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#include "stdio.h"
#include "NuMicro.h"

#if defined (__GNUC__) && !defined(__ARMCC_VERSION) && defined(OS_USE_SEMIHOSTING)
extern void initialise_monitor_handles(void);
#endif

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


const uint32_t array_size = sizeof(sine) / sizeof(uint16_t);

void SYS_Init(void)
{
    /* Unlock protected registers */
    SYS_UnlockReg();

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

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

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

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

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

    /* Enable DAC module clock */
    CLK_EnableModuleClock(DAC_MODULE);

    /* Enable EPWM0 module clock */
    CLK_EnableModuleClock(EPWM0_MODULE);

    /* Enable PDMA clock source */
    CLK_EnableModuleClock(PDMA_MODULE);

    /* Select EPWM0 module clock source as PCLK0 */
    CLK_SetModuleClock(EPWM0_MODULE, CLK_CLKSEL2_EPWM0SEL_PCLK0, 0);

    /* Set PB.12 to input mode */
    PB->MODE &= ~GPIO_MODE_MODE12_Msk;
    /* Set PB multi-function pin for DAC voltage output */
    SYS->GPB_MFPH |= SYS_GPB_MFPH_PB12MFP_DAC0_OUT;
    /* Disable digital input path of analog pin DAC0_OUT to prevent leakage */
    GPIO_DISABLE_DIGITAL_PATH(PB, (1ul << 12));
    /* Set PG multi-function pins for EPWMA Channel 0 */
    SYS->GPG_MFPH |= SYS_GPG_MFPH_PG8MFP_EPWM0_CH0;
    /* Lock protected registers */
    SYS_LockReg();
}

void EPWM0_Init()
{

    /* Set EPWM0 Timer clock prescaler */
    EPWM_SET_PRESCALER(EPWM0, 0, 100);

    /* Set up counter type */
    EPWM0->CTL1 &= ~EPWM_CTL1_CNTTYPE0_Msk;

    /* Set EPWM0 timer duty */
    EPWM_SET_CMR(EPWM0, 0, 360);

    /* Set EPWM0 timer period */
    EPWM_SET_CNR(EPWM0, 0, 1720);

    /* EPWM period point trigger DAC enable */
    EPWM_EnableDACTrigger(EPWM0, 0, EPWM_TRIGGER_DAC_PERIOD);

    /* Set output level at zero, compare up, period(center) and compare down of channel 0 */
    EPWM_SET_OUTPUT_LEVEL(EPWM0, 0x1, EPWM_OUTPUT_HIGH, EPWM_OUTPUT_LOW, EPWM_OUTPUT_NOTHING, EPWM_OUTPUT_NOTHING);

    /* Enable output of EPWM0 channel 0 */
    EPWM_EnableOutput(EPWM0, 0x1);
}



int32_t main(void)
{

    /* Init System, IP clock and multi-function I/O */
    SYS_Init();

#if defined (__GNUC__) && !defined(__ARMCC_VERSION) && defined(OS_USE_SEMIHOSTING)
    initialise_monitor_handles();
#endif

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


    /* Init EPWM0 trigger for DAC */
    EPWM0_Init();

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

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

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

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

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

    /* Set the EPWM0 trigger DAC and enable D/A converter */
    DAC_Open(DAC0, 0, DAC_EPWM0_TRIGGER);

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

    /* Enable the PDMA Mode */
    DAC_ENABLE_PDMA(DAC0);

    /* Enable EPWM0 channel 0 to start D/A conversion */
    EPWM_Start(EPWM0, 0x1);

    while(1)
    {
        if (PDMA_GET_TD_STS(PDMA) == 0x1)
        {
            /* Re-Set transfer count and basic operation mode */
            PDMA_SetTransferCnt(PDMA,0, PDMA_WIDTH_16, array_size);
            PDMA_SetTransferMode(PDMA,0, PDMA_DAC0_TX, FALSE, 0);

            /* Clear PDMA channel 0 transfer done flag */
            PDMA_CLR_TD_FLAG(PDMA,0x1);
        }

    }


}

除了定时器可以定时触发PDMA执行DAC输出任务,EPWM也可以实现定时触发。
在这个初始化函数中:
  • 定时器设置:

    • 设置 EPWM 的预分频器,使得计时更精确。
    • 设置 EPWM 的计数器和周期。
    • 配置 EPWM 在每个周期触发 DAC 更新。
  • PWM 波形输出:

    • 设置 EPWM 输出的高低电平,使得在特定比较值时输出高电平或低电平。
    • 启用 EPWM 输出,使得信号在硬件引脚上输出。

使用特权

评论回复
沙发
gejigeji521|  楼主 | 2024-7-13 18:25 | 只看该作者
在这个程序中,EPWM 的作用不仅限于提供定时控制,还包括输出 PWM 波形。EPWM 的定时功能用于触发 DAC 更新,使得 DAC 可以输出稳定的正弦波信号;同时,EPWM 还可以在特定引脚上输出 PWM 波形,满足系统的其他需求。这样一来,EPWM 就在一个程序中实现了多重功能,提高了系统的灵活性和效率。

使用特权

评论回复
板凳
gejigeji521|  楼主 | 2024-7-13 18:25 | 只看该作者
在该示例中,EPWM触发PDMA的具体位置是在EPWM波形的周期点(period point)。这意味着在每个PWM周期结束时,触发一次PDMA传输。这样,EPWM可以在每个周期的结尾触发一次DAC更新,从而输出新的DAC值。

使用特权

评论回复
地板
gejigeji521|  楼主 | 2024-7-13 18:25 | 只看该作者
请注意以下代码
void EPWM0_Init()
{
    /* Set EPWM0 Timer clock prescaler */
    EPWM_SET_PRESCALER(EPWM0, 0, 100);

    /* Set up counter type */
    EPWM0->CTL1 &= ~EPWM_CTL1_CNTTYPE0_Msk;

    /* Set EPWM0 timer duty */
    EPWM_SET_CMR(EPWM0, 0, 360);

    /* Set EPWM0 timer period */
    EPWM_SET_CNR(EPWM0, 0, 1720);

    /* EPWM period point trigger DAC enable */
    EPWM_EnableDACTrigger(EPWM0, 0, EPWM_TRIGGER_DAC_PERIOD);

    /* Set output level at zero, compare up, period(center) and compare down of channel 0 */
    EPWM_SET_OUTPUT_LEVEL(EPWM0, 0x1, EPWM_OUTPUT_HIGH, EPWM_OUTPUT_LOW, EPWM_OUTPUT_NOTHING, EPWM_OUTPUT_NOTHING);

    /* Enable output of EPWM0 channel 0 */
    EPWM_EnableOutput(EPWM0, 0x1);
}

使用特权

评论回复
5
gejigeji521|  楼主 | 2024-7-13 18:25 | 只看该作者
触发的方式设置
/* EPWM period point trigger DAC enable */
EPWM_EnableDACTrigger(EPWM0, 0, EPWM_TRIGGER_DAC_PERIOD);

使用特权

评论回复
6
gejigeji521|  楼主 | 2024-7-13 18:26 | 只看该作者
EPWM_EnableDACTrigger 函数
EPWM_EnableDACTrigger 函数的第三个参数 EPWM_TRIGGER_DAC_PERIOD 表示在每个PWM周期结束时触发DAC。这是一个宏定义,指定了触发事件发生的位置:

EPWM_TRIGGER_DAC_PERIOD:在PWM周期点(period point)触发。
因此,每当EPWM的计数器达到其周期计数值(即一个PWM周期的结束点)时,EPWM将生成一个触发信号,触发PDMA传输。这使得PDMA能够在每个周期结束时,将新的正弦波数据传输到DAC,从而更新DAC的输出。

使用特权

评论回复
7
gejigeji521|  楼主 | 2024-7-13 18:26 | 只看该作者
EPWM在PWM波形的周期点(period point)触发PDMA。这意味着在每个PWM周期结束时,触发一次PDMA传输,从而确保DAC能够在每个周期更新其输出值,实现稳定的正弦波输出。

使用特权

评论回复
8
gejigeji521|  楼主 | 2024-7-13 18:27 | 只看该作者
EPWM触发和定时器触发在微控制器中的应用有着不同的特点和优缺点,主要区别如下:

EPWM触发
工作原理:

EPWM(Enhanced Pulse Width Modulation)模块可以生成可调节的PWM波形,用于控制电机驱动、LED亮度调节等应用。EPWM可以通过设置比较匹配和定时器计数器来生成不同的PWM波形。
EPWM可以配置为在特定的事件(如周期点、上升/下降沿等)时触发其他外设,如DAC、ADC、PDMA等。这种触发方式可以实现精确的时间控制和同步操作。
优点:

提供精确的时间控制,可以在PWM波形的特定点上触发外设操作,例如在周期结束时更新DAC值。
可以实现复杂的PWM波形生成和精确的同步控制。
缺点:

需要专门的硬件支持,相对于简单的定时器,配置和使用上可能稍显复杂。
占用一定的硬件资源。
定时器触发
工作原理:

定时器用于生成精确的时间基准,例如周期性地产生中断或触发事件。定时器可以配置为在达到特定的计数值时触发其他操作。
可以用于定时任务、延时计时、时间测量等。
优点:

简单易用,通常只需配置计数器和预分频器即可实现基本功能。
适用于需要周期性执行的简单任务,如定时中断、延时操作等。
缺点:

通常只能提供固定的时间间隔或触发点,灵活性不如EPWM触发。
不能直接生成PWM波形,而是用于生成时间基准。
总结
EPWM触发适合需要精确同步和控制的应用,例如在特定时刻更新外设数据(如DAC输出)。
定时器触发适用于周期性任务和基本的时间测量,配置简单,但灵活性不如EPWM触发。
选择使用哪种触发方式取决于具体的应用需求:如果需要PWM波形控制和精确的同步操作,EPWM触发是更好的选择;如果只需要基本的定时或延时功能,定时器触发则更为合适。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

177

主题

2224

帖子

8

粉丝