查看: 130|回复: 5

[求助] 各位大佬 ,想使用rt1052的flexio模拟ws2812的驱动,有人实现吗

[复制链接]

该用户从未签到

1

主题

3

帖子

0

新手上路

Rank: 1

积分
27
最后登录
2025-10-26
发表于 7 天前 | 显示全部楼层 |阅读模式
#include "fsl_flexio.h"
#include "fsl_edma.h"
#include "fsl_dmamux.h"
#include "fsl_iomuxc.h"
#include "fsl_clock.h"
#include "fsl_gpio.h"
#include "fsl_common.h"

#define FLEXIO_BASE        FLEXIO2
#define FLEXIO_CLOCK_NAME  kCLOCK_Flexio2
#define LED_PIN            7
#define DMA_CHANNEL        0
#define FLEXIO_SHIFTER     0
#define FLEXIO_DMA_REQUEST kDmaRequestMuxFlexIO2Request0Request1

#define NUM_LEDS           1
#define DATA_SIZE          (NUM_LEDS * 24)

AT_NONCACHEABLE_SECTION(volatile uint32_t ws2812_buffer[DATA_SIZE]);

static edma_handle_t dmaHandle;
static volatile bool dmaTransferDone = false;

static uint16_t TIMCMP_0 = 0;
static uint16_t TIMCMP_1 = 0;

void EDMA_Callback(edma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds)
{
    if (transferDone)
    {
        dmaTransferDone = true;
    }
}

uint32_t WS2812_GetFlexIO2Clock(void) {
    uint32_t clockFreq = 0;
    uint32_t mux = (CCM->CSCMR2 & CCM_CSCMR2_FLEXIO2_CLK_SEL_MASK) >> CCM_CSCMR2_FLEXIO2_CLK_SEL_SHIFT;
    uint32_t div = ((CCM->CS1CDR & CCM_CS1CDR_FLEXIO2_CLK_PODF_MASK) >> CCM_CS1CDR_FLEXIO2_CLK_PODF_SHIFT) + 1;

    switch (mux) {
        case 3:
            clockFreq = CLOCK_GetFreq(kCLOCK_Usb1PllClk);
            break;
        case 2:
            clockFreq = CLOCK_GetFreq(kCLOCK_SysPllClk);
            break;
        case 1:
            clockFreq = 24000000;
            break;
        default:
            clockFreq = 0;
            break;
    }
    return clockFreq / div;
}

void WS2812_FlexIO_Init(void)
{
    CLOCK_EnableClock(kCLOCK_Iomuxc);
    CLOCK_EnableClock(kCLOCK_Flexio2);

    IOMUXC_SetPinMux(IOMUXC_GPIO_B0_07_FLEXIO2_FLEXIO07, 1);
    IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_07_FLEXIO2_FLEXIO07, 0x10B0U);

    flexio_config_t flexioConfig;
    FLEXIO_GetDefaultConfig(&flexioConfig);
    FLEXIO_Init(FLEXIO_BASE, &flexioConfig);

    flexio_timer_config_t timerConfig;
    timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(0);
    timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
    timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
    timerConfig.pinConfig       = kFLEXIO_PinConfigOutput;
    timerConfig.pinSelect       = LED_PIN;
    timerConfig.timerMode       = kFLEXIO_TimerModeDual8BitPWM;
    timerConfig.timerOutput     = kFLEXIO_TimerOutputOneNotAffectedByReset;
    timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
    timerConfig.timerDisable    = kFLEXIO_TimerDisableOnTimerCompare;
    timerConfig.timerEnable     = kFLEXIO_TimerEnableOnTriggerRisingEdge;

    uint32_t flexioClock = WS2812_GetFlexIO2Clock();
    uint32_t timerDiv = (flexioClock / 800000) - 1;

    uint32_t T0H = (flexioClock / 1000000 * 270) / 1000;
    uint32_t T0L = timerDiv - T0H;
    uint32_t T1H = (flexioClock / 1000000 * 930) / 1000;
    uint32_t T1L = timerDiv - T1H;
    TIMCMP_0 = ((T0H << 8) | T0L);
    TIMCMP_1 = ((T1H << 8) | T1L);

    timerConfig.timerCompare = TIMCMP_1;
    FLEXIO_SetTimerConfig(FLEXIO_BASE, 0, &timerConfig);

    flexio_shifter_config_t shifterConfig;
    shifterConfig.timerSelect   = 0;
    shifterConfig.pinConfig     = kFLEXIO_PinConfigOutput;
    shifterConfig.pinSelect     = LED_PIN;
    shifterConfig.shifterMode   = kFLEXIO_ShifterModeTransmit;
    shifterConfig.pinPolarity   = kFLEXIO_PinActiveLow;
    shifterConfig.inputSource   = kFLEXIO_ShifterInputFromPin;
    shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
    shifterConfig.shifterStart  = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift;
    shifterConfig.shifterStop   = kFLEXIO_ShifterStopBitDisable;
    FLEXIO_SetShifterConfig(FLEXIO_BASE, FLEXIO_SHIFTER, &shifterConfig);

    FLEXIO_EnableShifterStatusDMA(FLEXIO_BASE, (1U << FLEXIO_SHIFTER), true);
    FLEXIO_BASE->SHIFTSTAT = 0xFF;

    for (int i = 0; i < 4; i++)
    {
        FLEXIO_BASE->SHIFTBUF[FLEXIO_SHIFTER] = TIMCMP_0;
    }
}

void WS2812_DMA_Init(void)
{
    edma_config_t edmaConfig;

    DMAMUX_Init(DMAMUX);
    DMAMUX_SetSource(DMAMUX, DMA_CHANNEL, FLEXIO_DMA_REQUEST);
    DMAMUX_EnableChannel(DMAMUX, DMA_CHANNEL);

    NVIC_SetPriority(DMA0_DMA16_IRQn, 2);
    NVIC_EnableIRQ(DMA0_DMA16_IRQn);

    EDMA_GetDefaultConfig(&edmaConfig);
    EDMA_Init(DMA0, &edmaConfig);

    EDMA_CreateHandle(&dmaHandle, DMA0, DMA_CHANNEL);
    EDMA_SetCallback(&dmaHandle, EDMA_Callback, NULL);

    dmaTransferDone = false;
}

void WS2812_PrepareData(uint8_t *led_data) {
    uint32_t index = 0;
    for (int i = 0; i < NUM_LEDS; i++) {
        for (int j = 0; j < 3; j++) {
            uint8_t byte = led_data[i * 3 + j];
            for (int bit = 7; bit >= 0; bit--) {
                ws2812_buffer[index++] = (byte & (1 << bit)) ? TIMCMP_1 : TIMCMP_0;
            }
        }
    }
}

void WS2812_SendData(uint8_t *led_data) {
    WS2812_PrepareData(led_data);

    edma_transfer_config_t transferConfig;
    EDMA_PrepareTransfer(&transferConfig,
                         (void *)ws2812_buffer,
                         sizeof(uint32_t),
                         (void *)&FLEXIO_BASE->SHIFTBUF[FLEXIO_SHIFTER],
                         sizeof(uint32_t),
                         sizeof(uint32_t),
                         sizeof(ws2812_buffer),
                         kEDMA_MemoryToPeripheral);

    dmaTransferDone = false;
    FLEXIO_BASE->SHIFTSTAT = 0xFF;
    DMA0->TCD[DMA_CHANNEL].SADDR = (uint32_t)&ws2812_buffer[0];

    if (!(DMA0->ERQ & (1 << DMA_CHANNEL))) {
        EDMA_EnableChannelRequest(DMA0, DMA_CHANNEL);
    }
    EDMA_SubmitTransfer(&dmaHandle, &transferConfig);
    EDMA_StartTransfer(&dmaHandle);

    while (!dmaTransferDone) {
        __NOP();
    }

    SDK_DelayAtLeastUs(300, CLOCK_GetFreq(kCLOCK_CpuClk));
}

int main(void)
{
    BOARD_BootClockRUN();
    init_after_reset();
    SCB_DisableDCache();

    if (!(CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_ENABLE_MASK)) {
        CCM_ANALOG->PLL_USB1_SET = CCM_ANALOG_PLL_USB1_ENABLE_MASK;
        CCM_ANALOG->PLL_USB1_CLR = CCM_ANALOG_PLL_USB1_POWER_MASK;
        CCM_ANALOG->PLL_USB1_SET = CCM_ANALOG_PLL_USB1_POWER_MASK;
        CCM_ANALOG->PLL_USB1_SET = CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK;
    }

    CLOCK_SetDiv(kCLOCK_Flexio2PreDiv, 0);
    CLOCK_SetDiv(kCLOCK_Flexio2Div, 0);

    CLOCK_EnableClock(kCLOCK_Iomuxc);

    WS2812_FlexIO_Init();
    WS2812_DMA_Init();

    uint8_t led_data[NUM_LEDS * 3];

    while (1)
    {
        for (int i = 0; i < NUM_LEDS; i++) {
            led_data[i * 3 + 0] = 0;
            led_data[i * 3 + 1] = 255;
            led_data[i * 3 + 2] = 0;
        }
        WS2812_SendData(led_data);
        SDK_DelayAtLeastUs(500000, CLOCK_GetFreq(kCLOCK_CpuClk));

        for (int i = 0; i < NUM_LEDS; i++) {
            led_data[i * 3 + 0] = 0;
            led_data[i * 3 + 1] = 0;
            led_data[i * 3 + 2] = 255;
        }
        WS2812_SendData(led_data);
        SDK_DelayAtLeastUs(500000, CLOCK_GetFreq(kCLOCK_CpuClk));
    }
}


回复

使用道具 举报

  • TA的每日心情
    奋斗
    昨天 17:24
  • 签到天数: 2465 天

    连续签到: 19 天

    [LV.Master]伴坛终老

    85

    主题

    2万

    帖子

    3

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    22895
    最后登录
    2025-10-28
    发表于 7 天前 | 显示全部楼层
    你这是实现了啊
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    1

    主题

    3

    帖子

    0

    新手上路

    Rank: 1

    积分
    27
    最后登录
    2025-10-26
     楼主| 发表于 7 天前 | 显示全部楼层

    没有效果啊,所以贴上来让大佬帮我看看
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    昨天 17:24
  • 签到天数: 2465 天

    连续签到: 19 天

    [LV.Master]伴坛终老

    85

    主题

    2万

    帖子

    3

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    22895
    最后登录
    2025-10-28
    发表于 7 天前 | 显示全部楼层
    调这个东西需要逻辑分析仪才行。要保证时序正确
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    1

    主题

    3

    帖子

    0

    新手上路

    Rank: 1

    积分
    27
    最后登录
    2025-10-26
     楼主| 发表于 7 天前 | 显示全部楼层
    流水源 发表于 2025-10-22 16:48
    调这个东西需要逻辑分析仪才行。要保证时序正确

    有的,现在是时序都抓不到,有时序其实就没什么问题了,调占空比就好,现在是定时器那块搞不定
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    昨天 17:24
  • 签到天数: 2465 天

    连续签到: 19 天

    [LV.Master]伴坛终老

    85

    主题

    2万

    帖子

    3

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    22895
    最后登录
    2025-10-28
    发表于 6 天前 | 显示全部楼层
    可以把工程整个发上来,看看
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-10-29 06:43 , Processed in 0.091319 second(s), 23 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表