2024-06-02 11:48 PM - edited 2024-06-03 12:24 AM
I want to drive a WS2812 LED strip using PWM and DMA. I've tried everything, but it's not working. I'm running at 72MHz, and I'm using htim2.Init.Prescaler = 0; and htim2.Init.Period = 90-1;. This is how my library works.
/*
* wsled.c
*
* Created on: May 31, 2024
* Author: arge
*/
#include "main.h"
#include "math.h"
#define MAX_LED 180
#define USE_BRIGHTNESS 0
extern TIM_HandleTypeDef htim2;
extern DMA_HandleTypeDef hdma_tim2_ch1;
uint8_t LED_Data[MAX_LED][4];
uint8_t LED_Mod[MAX_LED][4]; // for brightness
int datasentflag=0;
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
HAL_TIM_PWM_Stop_DMA(&htim2, TIM_CHANNEL_1);
datasentflag=1;
}
void Set_LED (int LEDnum, int Red, int Green, int Blue)
{
LED_Data[LEDnum][0] = LEDnum;
LED_Data[LEDnum][1] = Green;
LED_Data[LEDnum][2] = Red;
LED_Data[LEDnum][3] = Blue;
}
#define PI 3.14159265
void Set_Brightness (int brightness) // 0-45
{
#if USE_BRIGHTNESS
if (brightness > 45) brightness = 45;
for (int i=0; i<MAX_LED; i++)
{
LED_Mod[i][0] = LED_Data[i][0];
for (int j=1; j<4; j++)
{
float angle = 90-brightness; // in degrees
angle = angle*PI / 180; // in rad
LED_Mod[i][j] = (LED_Data[i][j])/(tan(angle));
}
}
#endif
}
uint32_t pwmData[(24*MAX_LED)+50];
void WS2812_Send (void)
{
uint32_t indx=0;
uint32_t color;
for (int i= 0; i<MAX_LED; i++)
{
#if USE_BRIGHTNESS
color = ((LED_Mod[i][1]<<16) | (LED_Mod[i][2]<<8) | (LED_Mod[i][3]));
#else
color = ((LED_Data[i][1]<<16) | (LED_Data[i][2]<<8) | (LED_Data[i][3]));
#endif
for (int i=23; i>=0; i--)
{
if (color&(1<<i))
{
pwmData[indx] = 60; // 2/3 of 90
}
else pwmData[indx] = 30; // 1/3 of 90
indx++;
}
}
for (int i=0; i<50; i++)
{
pwmData[indx] = 0;
indx++;
}
HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_1, pwmData,indx);
while (!datasentflag){};
datasentflag = 0;
}
void Reset_LED (void)
{
for (int i=0; i<MAX_LED; i++)
{
LED_Data[i][0] = i;
LED_Data[i][1] = 0;
LED_Data[i][2] = 0;
LED_Data[i][3] = 0;
}
}
When I look at the oscilloscope, the frequency is 800kHz, and each period is 1.25 microseconds, which seems correct according to the datasheet. However, the intervals are always constant. When I use SetLed(12.led,255,0,0);, the 12th LED should light up green, but there is no response. If I set all LEDs to 255, not only the 12th LED but all LEDs light up. I've been struggling with this for 3 days. Can you help me?