关于CH573中TIMER2的PWMDMA有些问题

void TMR2_IRQHandler(void)

{

    if(TMR2_GetITFlag(TMR1_2_IT_DMA_END))

    {

        TMR2_ClearITFlag(TMR1_2_IT_DMA_END);

        PFIC_DisableIRQ(TMR2_IRQn);

    }

}

我发现在DMA中断函数里加上PFIC_DisableIRQ(TMR2_IRQn);后,仿真和下载都出了些问题,把这句话注销掉就没有问题。可是注销这句话后,程序就会不停的进DMA中断,执行不了其他事件,请问该如何解决。


屏幕截图 2023-11-15 102227.png

#include "WS2811.h"

__attribute__((aligned(4))) uint32_t PwmBuf[130];
__attribute__((aligned(4))) uint32_t GRB[3] = {18, 18, 42};
uint8_t color_count = 0;

void WS2811_Init(void)
{
    uint8_t i;
    GPIOA_ModeCfg(GPIO_Pin_11, GPIO_ModeOut_PP_20mA);
    TMR2_PWMCycleCfg(60);
    LED_Init();
    TMR2_DMACfg(ENABLE, (uint16_t)(uint32_t)&PwmBuf[0], (uint16_t)(uint32_t)&PwmBuf[129], Mode_Single);
    TMR2_PWMInit(High_Level, PWM_Times_1);
    TMR2_ClearITFlag(TMR1_2_IT_DMA_END);
    PFIC_EnableIRQ(TMR2_IRQn);
    TMR2_ITCfg(ENABLE, TMR1_2_IT_DMA_END);
}

void WS2811_Pattern(uint32_t *GRB)
{
    GPIOA_ModeCfg(GPIO_Pin_11, GPIO_ModeOut_PP_20mA);
    TMR2_PWMCycleCfg(60);
    LED_Color(GRB);
    TMR2_DMACfg(ENABLE, (uint16_t)(uint32_t)&PwmBuf[0], (uint16_t)(uint32_t)&PwmBuf[129], Mode_Single);
    TMR2_PWMInit(High_Level, PWM_Times_1);
    TMR2_ClearITFlag(TMR1_2_IT_DMA_END);
    PFIC_EnableIRQ(TMR2_IRQn);
    TMR2_ITCfg(ENABLE, TMR1_2_IT_DMA_END);
}

void LED_Color(uint32_t *GRB)
{
    uint8_t i;
    for(i = 0+color_count*24; i < 8+color_count*24; i++)
    {
        PwmBuf[i] = GRB[0];
    }
    for(i = 8+color_count*24; i < 16+color_count*24; i++)
    {
        PwmBuf[i] = GRB[1];
    }
    for(i = 16+color_count*24; i < 24+color_count*24; i++)
    {
        PwmBuf[i] = GRB[2];
    }
    for(i = 24+color_count*24; i < 130; i++)
    {
        PwmBuf[i] = 0;
    }

}

void LED_Init(void)
{
    uint8_t i, j;

    for(i = 0; i < 7; i++)
    {
        PwmBuf[i] = 18;
    }
    for(i = 7; i < 15; i++)
    {
        PwmBuf[i] = 42;
    }
    for(i = 15; i < 23; i++)
    {
        PwmBuf[i] = 18;
    }

    for(i = 23; i < 130; i++)
    {
        PwmBuf[i] = 0;
    }

    for(j = 0; j < 4; j++)
    {
        for(i = 23+j*24; i < 31+j*24; i++)
        {
            PwmBuf[i] = 18;
        }
        for(i = 31+j*24; i < 39+j*24; i++)
        {
            PwmBuf[i] = 42;
        }
        for(i = 39+j*24; i < 47+j*24; i++)
        {
            PwmBuf[i] = 18;
        }
    }
}

tmosTaskID WS2811_TaskID;
tmosEvents LED_ProcessEvent(tmosTaskID task_id, tmosEvents events)
{
    uint8_t *msgPtr;
    if(events & SYS_EVENT_MSG)
    {
        msgPtr = tmos_msg_receive(task_id);
        if(msgPtr)
            tmos_msg_deallocate(msgPtr);
        return events ^ SYS_EVENT_MSG;
    }

    if(events & WS2811_EVENT)
    {
        WS2811_Pattern(GRB);
        color_count++;
        if(color_count >= 5)
        {
            color_count = 0;
            if(GRB[0] == 42)
            {
                GRB[0] = 18;
                GRB[1] = 42;
            }
            else if(GRB[1] == 42)
            {
                GRB[1] = 18;
                GRB[2] = 42;
            }
            else if(GRB[2] == 42)
            {
                GRB[2] = 18;
                GRB[0] = 42;
            }
        }
        tmos_start_task(WS2811_TaskID, WS2811_EVENT, MS1_TO_SYSTEM_TIME(500));
        return events ^ WS2811_EVENT;
    }
    return 0;
}

void WS2811_Start(void)
{
    tmos_start_task(WS2811_TaskID, WS2811_EVENT, MS1_TO_SYSTEM_TIME(500));
}

__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode")))
void TMR2_IRQHandler(void)
{
    if(TMR2_GetITFlag(TMR1_2_IT_DMA_END))
    {
        TMR2_ClearITFlag(TMR1_2_IT_DMA_END);
        PFIC_DisableIRQ(TMR2_IRQn);
    }
}


你好,如果是使用PWM驱动2812,是可以不使用中断的,通过DMA发送数据。比如需要20个波形,则发送21个数据,最后一个数据作为PWM的停止(全高或者全低)。

或者可以使用SPI的方式进行驱动,我们有一个SPI驱动代码可以提供参考。


@TECH_Lpc

不使用中断,是注销掉这三句吗?

????TMR2_ClearITFlag(TMR1_2_IT_DMA_END);
????PFIC_EnableIRQ(TMR2_IRQn);
????TMR2_ITCfg(ENABLE,?TMR1_2_IT_DMA_END);

可是注销掉后,这PWM不会再工作了。用逻辑分析仪的话,发现并没有波形。

至于SPI的话,因为已经用掉SPI去驱动ST7789了,所以才会使用PWM来驱动WS2811。


你好,可参考:

image.png


只有登录才能回复,可以选择微信账号登录