0

A try to controlling WS2812 LEDs using timer PWM and DMA. I almost succeeded but now I have a problem that I can't solve. As You can see on the image the first two LEDs glow green but another LEDs glow reed. But all of them should glow green.

![Link for image:] https://ibb.co/c2XEqS

I use Nucleo Board with STM32F1 microcontroller (64MHZ).

Timer initialization:

void Init_TIM4()
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

    GPIO_InitTypeDef gpio;
    GPIO_StructInit(&gpio);

    gpio.GPIO_Mode = GPIO_Mode_AF_PP;
    gpio.GPIO_Pin = GPIO_Pin_8;
    gpio.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio);

    TIM_TimeBaseInitTypeDef tim;
    TIM_TimeBaseStructInit(&tim);
    tim.TIM_CounterMode = TIM_CounterMode_Up;
    tim.TIM_Period = 80;
    tim.TIM_ClockDivision = 0;
    TIM_TimeBaseInit(TIM4, &tim);

    TIM_OCInitTypeDef channel;
    TIM_OCStructInit(&channel);
    channel.TIM_OCMode = TIM_OCMode_PWM1;
    channel.TIM_OutputState = TIM_OutputState_Enable;
    channel.TIM_Pulse = 0;
    channel.TIM_OCIdleState = TIM_OCIdleState_Set;
    TIM_OC3Init(TIM4, &channel);
    }

DMA and rest of code:

#define BUFFER_SIZE 25

volatile uint16_t src_buffer[BUFFER_SIZE] = {32, 32, 32, 32, 32, 32, 32, 32, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,0};

void send_data()
{
    DMA_SetCurrDataCounter(DMA1_Channel1, BUFFER_SIZE);
    DMA_Cmd(DMA1_Channel1, ENABLE);
    TIM_Cmd(TIM4, ENABLE);

    while(!DMA_GetFlagStatus(DMA1_FLAG_TC1));
    TIM_Cmd(TIM4, DISABLE);
    DMA_Cmd(DMA1_Channel1, DISABLE);
    DMA_ClearFlag(DMA1_FLAG_TC1);
}

int main(void)
{
   Init_TIM4();

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    DMA_InitTypeDef dma;

    DMA_StructInit(&dma);
    dma.DMA_PeripheralBaseAddr = (uint32_t)&TIM4->CCR3;
    dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    dma.DMA_MemoryBaseAddr = (uint32_t)src_buffer;
    dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
    dma.DMA_BufferSize = BUFFER_SIZE;
    dma.DMA_M2M = DMA_M2M_Disable;
    dma.DMA_DIR = DMA_DIR_PeripheralDST;
    dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    dma.DMA_Mode = DMA_Mode_Normal;
    dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

    DMA_Init(DMA1_Channel1, &dma);
    TIM_DMACmd(TIM4, TIM_DMA_CC1, ENABLE);

    for (int i = 0; i < 8; i++) {
        send_data();
    }
    while(1)
    {

    }
}
Biddut
  • 418
  • 1
  • 6
  • 17
Damian U
  • 371
  • 2
  • 19
  • 2
    For something like this, it'd be good to show what debugging you've done beyond write code and observe it doesn't work. What, specifically, does not behave as you expect? There are a lot of calls to functions that look a little bit like STM HAL and/or LL calls, but not quite - e.g. is DMA_Init your own creation, or STM's HAL_DMA_Init or LL_DMA_Init? There are also calls that doesn't look like anything from STM, e.g. DMA_Cmd, TIM_Cmd. – Sigve Kolbeinson Mar 28 '18 at 20:12
  • 1
    For your code, at a hunch, I'd look at the memory base address, is that being reset anywhere between transmissions? Or is it incrementing beyond src_buffer? I'd also look at your PWM values. If TIM4 is ticking at 64 MHz (you don't say explicitly, and it's not shown in code) and resetting at 80 ticks, we get a period of 1.25 us, which match the WS2818. However, the duty cycles given by PWM values of 32 and 16 doesn't give valid timings according to https://cdn.sparkfun.com/datasheets/Components/LED/WS2812.pdf – Sigve Kolbeinson Mar 28 '18 at 20:19

0 Answers0