qq_52602434 2024-05-30 09:35 采纳率: 40%
浏览 129

关于stm32驱动ws2812灯板出现频闪问题!

我的单片机项目是,通过esp wifi模块去接收云平台的信息,然后设置灯光模式,比如普通照亮和呼吸灯。
但是我发现,在频繁设置颜色的时候会出现错色,即连续设置多次绿色,其中有一次会变成别的颜色。
ws2812使用PWM加DMA方式控制的。
wifi模块是使用的USART中断。
至今找不到问题所在,求解答。

  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-05-30 09:35
    关注

    引自免费微信小程序:皆我百晓生

    在处理STM32与WS2812B LED灯条交互时遇到的频闪和错色问题,这里有几个可能的原因和相应的解决建议:

    1. PWM配置: 确保你的PWM配置正确无误,包括频率、占空比以及输出通道(GPIO)。确保每个LED都有足够的上升时间和下降时间以防止闪烁。
    // 配置定时器
    TIM_TimeBaseInitTypeDef TIM_InitStruct;
    TIM_InitStruct.Prescaler = 4199; // 计算出合适的预分频值,以得到约800kHz的PWM频率
    TIM_InitStruct.CounterMode = TIM_COUNTERMODE_UP;
    TIM_InitStruct.Period = 1000; // 这里为周期的计数值,根据实际需求调整
    HAL_TIM_Base_Init(&htim); // htim是你的定时器句柄
    
    // 配置PWM输出
    TIM_OCInitTypeDef TIM_OCInitStruct;
    TIM_OCInitStruct.OCMode = TIM_OCMODE_PWM1;
    TIM_OCInitStruct.Pulse = 500; // 对于呼吸灯,可以动态改变这个脉冲宽度,对于常亮,保持一致
    TIM_OCInitStruct.OCPolarity = TIM_OCPOLARITY_HIGH;
    TIM_OCInitStruct.OCFastMode = TIM_OCFASTMODE_DISABLE;
    HAL_TIM_PWM_ConfigChannel(&htim, &TIM_OCInitStruct, TIM_CHANNEL_1);
    
    1. DMA配置: 使用DMA时要特别注意数据传输的同步问题,确保数据被正确地写入到SPI接口。检查DMA的传输大小是否正确,例如,每个WS2812B LED需要3个字节(RGB)的数据。
    // DMA配置
    DMA_HandleTypeDef hdma_tim1_ch1;
    
    hdma_tim1_ch1.Init.Channel = DMA_CHANNEL_1;
    hdma_tim1_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_tim1_ch1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_tim1_ch1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_tim1_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_tim1_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_tim1_ch1.Init.Mode = DMA_CIRCULAR;
    hdma_tim1_ch1.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_tim1_ch1) != HAL_OK)
    {
        Error_Handler();
    }
    
    __HAL_LINKDMA(&htim, hdma[TIM deltaTime CHANNEl_1], hdma_tim1_ch1);
    
    // 启动DMA
    HAL_TIM_PWM_Start_DMA(&htim, TIM_CHANNEL_1, ws2812_buffer, sizeof(ws2812_buffer));
    
    1. 中断管理: 当ESP WiFi模块接收数据时,可能会打断正在执行的PWM更新操作。为了减少干扰,你可以考虑在中断上下文中只记录新的颜色,并在中断返回后启动一个延时任务来更新LED颜色。
    void USART_IRQHandler()
    {
        // ...
        if (USART->ISR & USART_ISR_RXNE)
        {
            uint8_t new_color = USART->RDR;
            led_color_queue[led_color_queue_tail] = new_color;
            led_color_queue_tail = (led_color_queue_tail + 1) % LED_COLOR_QUEUE_SIZE;
            
            // 如果队列满,丢弃新颜色
            if (led_color_queue_head == led_color_queue_tail)
                led_color_queue_head = (led_color_queue_head + 1) % LED_COLOR_QUEUE_SIZE;
            
            // 启动延时任务更新颜色
            HAL_Delay_StartTask(UPDATE_LED_COLOR_DELAY);
        }
        // ...
    }
    
    1. 延时任务: 创建一个延时任务,用于定期检查颜色队列并更新LED颜色。
    static void UpdateLedColor(void *pData)
    {
        while (1)
        {
            HAL_Delay(UPDATE_LED_COLOR_PERIOD); // 更新间隔时间
    
            if (led_color_queue_head != led_color_queue_tail)
            {
                uint8_t current_color = led_color_queue[led_color_queue_head];
                led_color_queue_head = (led_color_queue_head + 1) % LED_COLOR_QUEUE_SIZE;
    
                // 更新LED颜色
                UpdateWs2812B(current_color);
            }
        }
    }
    
    // 在main函数或其他合适的地方启动延时任务
    HAL_Delay_StartTask(UpdateLedColor, NULL);
    
    1. 检查硬件连接: 确认WS2812B的连接线没有接触不良或短路问题。有时,这些问题也会导致颜色错误。

    2. 调试技巧: 使用示波器检查PWM信号的波形,观察是否有异常。同时,检查串口通信是否正常,是否有数据丢失的情况。

    如果你按照以上步骤检查并调整了相关配置,但问题仍然存在,那么可能是硬件问题或者是软件中的其他潜在bug。在这种情况下,你需要更深入地分析代码逻辑,寻找可能的并发问题或资源冲突。

    评论 编辑记录

报告相同问题?

问题事件

  • 修改了问题 5月30日
  • 修改了问题 5月30日
  • 创建了问题 5月30日

悬赏问题

  • ¥15 35114 SVAC视频验签的问题
  • ¥15 impedancepy
  • ¥15 在虚拟机环境下完成以下,要求截图!
  • ¥15 求往届大挑得奖作品(ppt…)
  • ¥15 如何在vue.config.js中读取到public文件夹下window.APP_CONFIG.API_BASE_URL的值
  • ¥50 浦育平台scratch图形化编程
  • ¥20 求这个的原理图 只要原理图
  • ¥15 vue2项目中,如何配置环境,可以在打完包之后修改请求的服务器地址
  • ¥20 微信的店铺小程序如何修改背景图
  • ¥15 UE5.1局部变量对蓝图不可见