本帖最后由 90houyidai 于 2025-3-12 16:57 编辑
接上回,定时器呼吸灯,在中断中调整PWM的占空比来改变LED灯的亮度
这次采用DMA的方式来点亮RGB灯,灯珠采用WS2812
WS2812是单总线RGB灯,采用串联的方式可以方便的点亮多颗灯
24bit采用GRB888的方式通过IO将0码、1码组合后发送给灯珠
一般的有三种方式来实现时序波形的发送:
1、IO延时
2、SPI
3、定时器PWM
本次使用定时器PWM+DMA,参考GPTIMER例程
#define TIMEBASE 249
#define CODE1 170
#define CODE0 80
uint32_t gpt_pwmbuffer2[48*8*3+50]={};
void TestGpTimerPwmDma()
{
//初始化灯组缓存
memset(gpt_pwmbuffer2, 0, 48*24+50);
for (size_t i = 0; i < 8; i++)
{
gpt_pwmbuffer[i] = CODE1;
gpt_pwmbuffer2[i] = CODE1;
gpt_pwmbuffer3[i][2] = CODE1;
}
for (size_t i = 8; i < 8*2; i++)
{
gpt_pwmbuffer[i] = CODE0;
gpt_pwmbuffer2[i] = CODE0;
gpt_pwmbuffer3[i][2] = CODE0;
}
for (size_t i = 16; i < 8*3; i++)
{
gpt_pwmbuffer[i] = CODE0;
gpt_pwmbuffer2[i] = CODE0;
gpt_pwmbuffer3[i][2] = CODE0;
}
// Use GPTIMER and DMA to generate arbitrary waveform
SYS_EnableAHBClock(AHB_MASK_DMAC0);
DMAC_Init();
pwmdma_lli[0].Control = DMAC_MakeControl(DMAC_ADDR_INCR_ON, DMAC_ADDR_INCR_OFF, DMAC_WIDTH_32_BIT,
DMAC_WIDTH_32_BIT, DMAC_BURST_1, DMAC_BURST_1, 0, DISABLE);
for (uint32_t i = 0; i < (48*24+50); i++)
{
pwmdma_lli[i].SrcAddr = (uint32_t)&gpt_pwmbuffer2[i];
pwmdma_lli[i].DstAddr = (uint32_t)&GPTIMER1->CCR0;
pwmdma_lli[i].LLI = (i<(48*24+50-1))?(uint32_t)&pwmdma_lli[i+1]:(uint32_t)&pwmdma_lli[0];
pwmdma_lli[i].Control = pwmdma_lli[0].Control;
}
DMAC_ConfigLLI(DMAC_CHANNEL5, DMAC_MEM_TO_PERIPHERAL_PERIPHERAL_CTRL, 0, GPTIMER1_CC_DMA0_REQ, (uint32_t)pwmdma_lli);
GPIO_AF_ENABLE(GPTIMER1_CH0);
SYS_EnableAPBClock(APB_MASK_GPTIMER1);
GPTIMER_InitTypeDef tm_init;
GPTIMER_StructInit(&tm_init);
tm_init.Autoreload = TIMEBASE;
GPTIMER_Init(GPTIMER1, &tm_init);
GPTIMER_OC_InitTypeDef oc_init;
GPTIMER_OC_StructInit(&oc_init);
oc_init.OCState = GPTIMER_OCSTATE_ENABLE;
oc_init.OCMode = GPTIMER_OCMODE_PWM1;
GPTIMER_OC_Init(GPTIMER1, GPTIMER_CHANNEL_CH0, &oc_init);
GPTIMER_OC_EnableFast(GPTIMER1, GPTIMER_CHANNEL_CH0);
GPTIMER_OC_EnablePreload(GPTIMER1, GPTIMER_CHANNEL_CH0);
GPTIMER_EnableARRPreload(GPTIMER1);
GPTIMER_EnableDmaUpdate(GPTIMER1);
GPTIMER_EnableDmaCC0(GPTIMER1);
GPTIMER_EnableAllOutputs(GPTIMER1);
GPTIMER_EnableCounter(GPTIMER1);
GPTIMER_GenerateEventUpdate(GPTIMER1); /* Enable UEV by setting UG bit to Load buffer data into preload registers */
GPTIMER_GenerateEventUpdate(GPTIMER1); /* Enable UEV by setting UG bit to load data from preload to active registers */
}
更新LED数据缓存即可进行调光调色,尝试过使用单个dma.lli,但是地址貌似没有自增操作
IMG_3626
|