在线时间3 小时
UID3912890
注册时间2023-4-11
NXP金币0
该用户从未签到
新手上路

- 积分
- 27
- 最后登录
- 2025-10-26
|
#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));
}
}
|
|