STM32 HAL+PWM+DMA方式驱动WS2812灯珠波形分析

8 篇文章 0 订阅
8 篇文章 39 订阅

通过示波器观察PWM+DMA的方式驱动WS2812灯珠的波形及分析对应的现象

1. 在DMA传送完PWM波形后不关闭PWM的DMA输出

灯珠显示效果:
灯珠会错乱显示(没有按正常设定的颜色显示)
示波器显示如下:
在这里插入图片描述

2. 在DMA传送完PWM波形后,在PWM传输完成后回调函数中关闭PWM的DMA输出

灯珠显示效果:
会按照设定的颜色正常显示,但灯带的起始位置会有绿色的余光(基于自己测试时使用的灯带)
示波器显示如下
在这里插入图片描述

3. 在DMA传送完PWM波形后,在DMA中断函数中关闭PWM的DMA输出

灯珠显示效果:
按照设定的颜色模式正常显示
示波器显示效果如下:
在这里插入图片描述

分析

方式1在pwm通过DMA的方式传输完成后会保持高电平,且会产生杂波,可能是导致灯珠显示错乱的主要原因.
方式2在DMA传输完成的回调函数关闭PWM输出,还会产生杂波,而将关闭PWM输出的函数放到DMA中断中便不会产生杂波,这个现象感觉很怪异,DMA中断函数HAL_DMA_IRQ()会调用传输完成的回调函数HAL_TIM_PWM_PulseFinishedCallback()但不知到为什么就不可以.

  • 会产生杂波的方式:
/* 中断回调函数,在设定的pwm通过DMA发送完成后会调用 */
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef* htim)
{
  /*
  TODO:无论在这里是否关闭DMA输出,在PWM传输完成后都会产生一段杂波(用示波器看到的)。但是在这里关闭DMA输出后
       灯珠的颜色可以正常显示,杂波不会影响当前及后续灯珠的显示。但是在这里不关闭DMA输出,便会影响灯珠的显示。
      (不清楚原因)
  TODO:在DMA中断函数中关闭DMA输出便不会产生杂波
  */
  /* 注意这里的通道号要用 HAL_TIM_ACTIVE_CHANNEL_x而不能用TIM_CHANNEL_x,看定时器句柄定义的Channel类型便可知晓*/
  if(htim->Instance == TIM3) {
    if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {
      HAL_TIM_PWM_Stop_DMA(&htim3, TIM_CHANNEL_1);
    } else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) {
      HAL_TIM_PWM_Stop_DMA(&htim3, TIM_CHANNEL_2);
    }   
  } 
}
  • 不会产生杂波的方式
/**
  * @brief This function handles DMA1 stream4 global interrupt.
  */
void DMA1_Stream4_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hdma_tim3_ch1);
  /* 传输完成后,关闭DMA传输 */
  HAL_TIM_PWM_Stop_DMA(&htim3, TIM_CHANNEL_1);
}
/**
  * @brief This function handles DMA1 stream5 global interrupt.
  */
void DMA1_Stream5_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hdma_tim3_ch2);
  /* 传输完成后,关闭DMA传输 */
  HAL_TIM_PWM_Stop_DMA(&htim3, TIM_CHANNEL_2);
  
}

感觉非常不能理解的一点是:HAL_DMA_IRQHandler()函数中会调用HAL_TIM_PWM_PulseFinishedCallback()函数,这就相当于产生杂波的方式比不产生杂波的方式提前调用了HAL_TIM_PWM_Stop_DMA()函数.

如有大佬知道,希望能够不吝赐教!

  • 9
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
实现这个功能需要使用STM32F103的PWM输出和ws2812带的控制协议。具体步骤如下: 1. 配置STM32F103的PWM输出,将其设置为TIM2通道1,频率为800KHz,占空比为50%。 2. 将ws2812带连接到STM32F103的PWM输出引脚上,并按照ws2812的控制协议发送颜色数据。 3. 在主循环中使用一个计数器变量,每隔一段时间就更新一次ws2812颜色数据。可以使用随机数生成器生成新的颜色值,或者使用预定义的颜色序列进行循环显示。 4. 在每次更新ws2812颜色数据时,按照ws2812的控制协议将数据发送到带上,使其显示出新的颜色。 下面是一个简单的示例代码,实现了每隔500ms更新一次ws2812颜色数据的功能: ``` #include "stm32f10x.h" #define LED_NUM 16 // ws2812带上LED的数量 uint8_t led_data[LED_NUM * 3]; // ws2812颜色数据缓存 void ws2812_send_data(uint8_t *data, uint16_t len) { // 发送ws2812控制信号和颜色数据 // 省略具体实现,可以参考ws2812库的实现 } int main(void) { // 初始化GPIO和TIM2 GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Period = 29; // 800KHz TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_Pulse = 14; // 50%占空比 TIM_OC1Init(TIM2, &TIM_OCInitStructure); TIM_Cmd(TIM2, ENABLE); // 初始化ws2812颜色数据 for (int i = 0; i < LED_NUM; i++) { led_data[i * 3] = 0; // 红色分量 led_data[i * 3 + 1] = 0; // 绿色分量 led_data[i * 3 + 2] = 0; // 蓝色分量 } // 循环更新ws2812颜色数据 while (1) { // 生成随机颜色 for (int i = 0; i < LED_NUM; i++) { led_data[i * 3] = rand() % 256; // 红色分量 led_data[i * 3 + 1] = rand() % 256; // 绿色分量 led_data[i * 3 + 2] = rand() % 256; // 蓝色分量 } // 发送ws2812颜色数据 ws2812_send_data(led_data, LED_NUM * 3); // 延时500ms for (int i = 0; i < 1000000; i++); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值