You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32 Neopixel驱动异常:PWM回调触发异常及初始LED乱码问题

STM32 Neopixel驱动初始显示异常问题

问题概述

基于Digikey论坛示例开发STM32的Neopixel驱动,LED显示异常:首次尝试时前8个像素亮起绿色后停滞,最终总会出现固定的异常颜色图案。

排查发现HAL_TIM_PWM_PulseFinishedCallback仅在ascendingRed循环首次执行时触发,后续不再触发,推测与结构体/联合体指针使用有关。将PixelDRV_t的timer成员改为指针类型后,回调可正常触发,LED能正常更新,但初始阶段LED显示异常图案的问题仍存在。

原始驱动代码

#define NUM_PIXELS 40
#define RGBW_DMA_BUFF_SIZE (NUM_PIXELS * 32) + 1

typedef union
{
  struct
  {
    uint8_t w;
    uint8_t b;
    uint8_t r;
    uint8_t g;
  } color;
  uint32_t data;
} PixelRGBW_t;

/*
 * Note, must use a 32bit timer channel to work.
 */
typedef struct
{
    TIM_HandleTypeDef timer;
    uint32_t timer_channel;
    uint32_t pixel_length;
    uint32_t buf_length;
}PixelDRV_t;

uint8_t pixelRGBW_init(PixelDRV_t *strip, PixelRGBW_t *color, TIM_HandleTypeDef setTIMER, uint32_t setCHANNEL, uint32_t setLENGTH, uint32_t *Pbuff)
{

    strip->timer = setTIMER;
    strip->timer_channel = setCHANNEL;
    strip->pixel_length = setLENGTH;
    strip->buf_length = (setLENGTH * 32) + 1;
    for(int x = 0; x < setLENGTH; x++)
    {
        for (int b = 31; b >= 0; b--)
        {
            if ((color->data >> b) & 0x01)
            {
                *Pbuff = NEOPIXEL_RGBW_ONE;
            }
            else
            {
                *Pbuff = NEOPIXEL_RGBW_ZERO;
            }

            Pbuff++;
        }
        color++;
    }
    return HAL_OK;
}

uint8_t setPixelColorMonoRGBW(PixelDRV_t *strip, PixelRGBW_t *color, uint32_t pixel, uint8_t red, uint8_t green, uint8_t blue, uint8_t white)
{
    color[pixel].color.r = red;
    color[pixel].color.g = green;
    color[pixel].color.b = blue;
    color[pixel].color.w = white;
    return HAL_OK;
}
uint8_t setPixelLengthColorMonoRGBW(PixelDRV_t *strip, PixelRGBW_t *color, uint8_t red, uint8_t green, uint8_t blue, uint8_t white)
{
    for(int a = 0; a < strip->pixel_length; a++)
    {
        color[a].color.r = red;
        color[a].color.g = green;
        color[a].color.b = blue;
        color[a].color.w = white;
    }
    return HAL_OK;
}
/*
Sets the relevant "1" and "0" bits into the buffer to be written to the Neopixels via PWM. Must set whole strip's values, even if you are only updating one LED in one pixel, since all pixels need to know their RGB values, even if they are zero.
*/
uint8_t setPixelBufRGBW(PixelDRV_t *strip, PixelRGBW_t *color, uint32_t *Pbuff)
{
    for(int x = 0; x < strip->pixel_length; x++)
    {
        for (int b = 31; b >= 0; b--)
        {
            if ((color[x].data >> b) & 0x01)
            {
                *Pbuff = NEOPIXEL_RGBW_ONE;
            }
            else
            {
                *Pbuff = NEOPIXEL_RGBW_ZERO;
            }
            Pbuff++;
        }
    }
    return HAL_OK;
}

uint8_t transmitPixelBufRGBW(PixelDRV_t *strip, PixelRGBW_t *color, uint32_t *Pbuff)
{
    HAL_TIM_PWM_Start_DMA(&strip->timer, strip->timer_channel, Pbuff, strip->buf_length);
    return HAL_OK;
}

测试主文件代码

PixelRGBW_t STRIP1;
PixelRGBW_t* strip1 = &STRIP1;

PixelDRV_t PIXEL_DRV1;
PixelDRV_t* pixel_drv1 = &PIXEL_DRV1;

uint32_t dmaBuffer[RGBW_DMA_BUFF_SIZE] = {0};
uint32_t *pBuff = &dmaBuffer;

void Init_NeoPixels();
void ascendingRed();
void descendingRed();
void ascendingGreen();
void descendingGreen();
void ascendingBlue();
void descendingBlue();

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
  HAL_TIM_PWM_Stop_DMA(&htim2, TIM_CHANNEL_3);
}

int main(void)
{
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_I2C1_Init();
  MX_I2S3_Init();
  MX_DMA_Init();
  MX_TIM2_Init(); //timer being used for neopixels.
  MX_SPI2_Init();
  /* USER CODE BEGIN 2 */
  Init_NeoPixels();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
      ascendingRed();
      HAL_Delay(1000);
      descendingRed();
      HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

void Init_NeoPixels()
{
    pixelRGBW_init(pixel_drv1, strip1, htim2, TIM_CHANNEL_3, 40, pBuff);
}

void ascendingRed()
{
    for(int x = 0; x < pixel_drv1->pixel_length; x++)
    {
        setPixelColorMonoRGBW(pixel_drv1, strip1, x, 255, 0, 0, 0);
        setPixelBufRGBW(pixel_drv1, strip1, pBuff);
        transmitPixelBufRGBW(pixel_drv1, strip1, pBuff);
        HAL_Delay(125);
    }
}

void descendingRed()
{
    for(int x = pixel_drv1->pixel_length; x >= 0; x--)
    {
        setPixelColorMonoRGBW(pixel_drv1, strip1, x, 0, 0, 0, 0);
        setPixelBufRGBW(pixel_drv1, strip1, pBuff);
        transmitPixelBufRGBW(pixel_drv1, strip1, pBuff);
        HAL_Delay(125);
    }
}

修改后的关键代码

将PixelDRV_t的timer成员改为指针类型后,回调可正常触发:

typedef struct
{
    TIM_HandleTypeDef* timer;
    uint32_t timer_channel;
    uint32_t pixel_length;
    uint32_t buf_length;
}PixelDRV_t;

uint8_t pixelRGBW_init(PixelDRV_t *strip, PixelRGBW_t *color, TIM_HandleTypeDef* setTIMER, uint32_t setCHANNEL, uint32_t setLENGTH, uint32_t *Pbuff)
{
    /*
    if(strip->pixel_length != sizeof(color))
    {
        return HAL_ERROR;
    }
    */
    strip->timer = setTIMER;
    strip->timer_channel = setCHANNEL;
    strip->pixel_length = setLENGTH;
    strip->buf_length = (setLENGTH * 32) + 1;
    for(int x = 0; x < setLENGTH; x++)
    {
        for (int b = 31; b >= 0; b--)
        {
            if ((color->data >> b) & 0x01)
            {
                *Pbuff = NEOPIXEL_RGBW_ONE;
            }
            else
            {
                *Pbuff = NEOPIXEL_RGBW_ZERO;
            }

            Pbuff++;
        }
        color++;
    }
    return HAL_OK;
}

当前剩余问题

修改后LED可正常更新,但初始阶段仍会显示异常颜色图案,需要解决该问题。

内容的提问来源于stack exchange,提问作者Anonymaton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 06:55:08