找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 20230|回复: 39
打印 上一主题 下一主题
收起左侧

WS2812B渐变色流水算法+PWM DMA驱动STM32源程序

  [复制链接]
跳转到指定楼层
楼主
最近在学习STM32,到定时器与DMA章节,正巧手头有先前买的WS2812B模块,查找相关资料,于是成功点亮了,
又按照自己想法和思路写了一个渐变色算法,和渐变色流水功能,

可自定义灯的数量和渐变色的深度

渐变色原理:
假如红蓝两色变换
红(亮度):10   8   6   4   2   0
蓝(亮度):0     2   4   6   8   10


这样就形成两种颜色的过度
加大其分辨率,两颜色之间颜色差越小,生成颜色数据越多


在流水过程中,颜色取到数组末尾时,要将数组首端的数据加在末尾,使其颜色无差别连接

控制代码:

生成三种颜色数据数组
  1. /**
  2. * color_length 每种颜色渐变最大长度,总颜色长度:color_length * 3
  3. * return 颜色数据总长度
  4. */
  5. uint32_t set_Color_Loop(uint8_t color_length)
  6. {
  7.     RGB = (uint32_t*)malloc(color_length*3*sizeof(uint32_t));//分配数组大小,(所有渐变色颜色长度)
  8.     color_length -= 1;
  9.     for(uint8_t i=0;i<=color_length;i++)
  10.     {
  11.         RGB[i] = (((0xff/color_length)*i)<<8)|((0xff/color_length)*(color_length-i));                                       //蓝到绿
  12.         RGB[color_length + 1 +i] = (((0xff/color_length)*i)<<16)|((0xff/color_length)*(color_length-i))<<8; //绿到红
  13.         RGB[((color_length+1)*2) +i] = ((0xff/color_length)*i)|((0xff/color_length)*(color_length-i))<<16;   //红到蓝
  14.     }
  15.     return color_length*3;
  16. }


  17. 无间断位移获取8位颜色数据
  18. /**
  19. * colorwidth 每次获取多少位
  20. */

  21. void out_RGB(uint16_t data_Max_Length,uint16_t colorwidth)
  22. {
  23.     static uint32_t rgb_position = 0;
  24.     for(uint32_t i = 0;i < colorwidth; i++){
  25.         uint16_t c = (rgb_position + i) % data_Max_Length;//末尾颜色数据结束时将首位的收据填充到数组
  26.         send_Data(RGB[c]);
  27.     }
  28.     rgb_position ++;
  29.     rgb_position %= data_Max_Length;
  30. }
复制代码


两种图片效果



手机拍不出灯光效果,实际肉眼看还是非常漂亮的
视频效果:
游客,本帖隐藏的内容需要积分高于 1 才可浏览,您当前积分为 0


  1. #include "sys.h"
  2. #include "delay.h"
  3. #include "usart.h"
  4. #include "WS2812B.h"
  5. #include <stdlib.h>

  6. uint32_t *RGB;//颜色列表数组

  7. void LED_Init(void);
  8. void PWM_Init(void);
  9. uint32_t set_Color_Loop(uint8_t color_length);
  10. void out_RGB(uint16_t data_Max_Length,uint16_t colorwidth);

  11. int main(void)
  12. {
  13.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  14.     uart_init(115200);
  15.     delay_init();
  16.     LED_Init();
  17.        
  18.         WS2812B_TIM_init();
  19.         uint32_t len = set_Color_Loop(32);//每两种颜色之间的位数
  20.        
  21.     while(1)
  22.     {
  23.                 out_RGB(len,8);//8个灯,每次输出8个数据
  24.                 delay_ms(80);
  25.     }
  26. }

  27. /**
  28. * colorwidth 每次获取多少位
  29. */

  30. void out_RGB(uint16_t data_Max_Length,uint16_t colorwidth)
  31. {
  32.         static uint32_t rgb_position = 0;
  33.         for(uint32_t i = 0;i < colorwidth; i++){
  34.                 uint16_t c = (rgb_position + i) % data_Max_Length;//末尾颜色数据结束时将首位的收据填充到数组
  35.                 send_Data(RGB[c]);
  36.         }
  37.         rgb_position ++;
  38.         rgb_position %= data_Max_Length;
  39. }

  40. /**
  41. * color_length 每种颜色渐变最大长度,总颜色长度:color_length * 3
  42. * return 颜色数据总长度
  43. */
  44. uint32_t set_Color_Loop(uint8_t color_length)
  45. {
  46.         RGB = (uint32_t*)malloc(color_length*3*sizeof(uint32_t));//分配数组大小,(所有渐变色颜色长度)
  47.         color_length -= 1;
  48.         for(uint8_t i=0;i<=color_length;i++)
  49.         {
  50.                 RGB[i] = (((0xff/color_length)*i)<<8)|((0xff/color_length)*(color_length-i));                                                //蓝到绿
  51.                 RGB[color_length + 1 +i] = (((0xff/color_length)*i)<<16)|((0xff/color_length)*(color_length-i))<<8; //绿到红
  52.                 RGB[((color_length+1)*2) +i] = ((0xff/color_length)*i)|((0xff/color_length)*(color_length-i))<<16;  //红到蓝
  53.         }
  54.         return color_length*3;
  55. }

  56. void LED_Init()
  57. {
  58.     GPIO_InitTypeDef GPIO_InitTypeStruct;
  59.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOB,ENABLE);
  60.     GPIO_InitTypeStruct.GPIO_Mode = GPIO_Mode_Out_PP;
  61.     GPIO_InitTypeStruct.GPIO_Pin = GPIO_Pin_5;
  62.     GPIO_InitTypeStruct.GPIO_Speed = GPIO_Speed_50MHz;
  63.     GPIO_Init(GPIOE,&GPIO_InitTypeStruct);
  64.     GPIO_InitTypeStruct.GPIO_Pin = GPIO_Pin_5;
  65.     GPIO_Init(GPIOB,&GPIO_InitTypeStruct);
  66.     GPIOB->ODR ^= GPIO_Pin_5;
  67.     GPIOE->ODR ^= GPIO_Pin_5;
  68. }
复制代码

PWM+DMA驱动WS2812的代码请查看附件
WS2812B.rar (295.82 KB, 下载次数: 1087)

评分

参与人数 3黑币 +89 收起 理由
wpppmlah + 30 共享资料的黑币奖励!
hzd530 + 9
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏29 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:603929 发表于 2019-10-16 08:40 | 只看该作者
正好在做这个,学习一下
回复

使用道具 举报

板凳
ID:394041 发表于 2020-4-10 15:47 | 只看该作者
谢谢分享,学习一下
回复

使用道具 举报

地板
ID:168165 发表于 2020-4-14 20:39 | 只看该作者
不闪动呀
回复

使用道具 举报

5#
ID:383785 发表于 2020-5-29 19:24 | 只看该作者
不错 学习一下
回复

使用道具 举报

6#
ID:731155 发表于 2020-5-30 13:17 | 只看该作者
非常不错,感谢分享!!!!
回复

使用道具 举报

7#
ID:471251 发表于 2020-6-9 20:00 | 只看该作者

谢谢分享,学习一下
回复

使用道具 举报

8#
ID:219315 发表于 2020-6-12 15:04 | 只看该作者
实际烧到单片机里运行,灯光效果很漂亮。
回复

使用道具 举报

9#
ID:394041 发表于 2020-7-1 22:26 来自手机 | 只看该作者
谢谢,有空试一下。
回复

使用道具 举报

10#
ID:610978 发表于 2020-9-11 11:02 | 只看该作者
感谢楼主分享,下载到板子里可以正常工作,我尝试吧TIM2换成TIM1就不能亮了,这是为什么呢?
是我哪里漏修改了么?

void WS2812B_TIM_init(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    DMA_InitTypeDef DMA_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    /* GPIOA Configuration: TIM2 Channel 1 as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
    /* Compute the prescaler value */
    //PrescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1;
    /* Time base configuration */
    TIM_TimeBaseStructure.TIM_Period = 89; // 800kHz
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
          TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    /* PWM1 Mode configuration: Channel1 */
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 0;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);

    /* configure DMA */
    /* DMA clock enable */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    /* DMA1 Channel6 Config */
    DMA_DeInit(DMA1_Channel2);

    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM1->CCR1;        // physical address of Timer 3 CCR1
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)LED_BYTE_Buffer;                // this is the buffer memory
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                                                // data shifted from memory to peripheral
    DMA_InitStructure.DMA_BufferSize = 24;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                        // automatically increase buffer index
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                        // stop DMA feed after buffer size is reached
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

    DMA_Init(DMA1_Channel2, &DMA_InitStructure);

    /* TIM3 CC1 DMA Request enable */
        /* 只能使用通道1 TIMx_UP */
    TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);
}
回复

使用道具 举报

11#
ID:791100 发表于 2020-11-10 16:39 | 只看该作者
非常感谢,值得学习一下,非常好
回复

使用道具 举报

12#
ID:384489 发表于 2020-11-20 15:06 | 只看该作者
感谢分享,学习一下,非SPI方式。
回复

使用道具 举报

13#
ID:235359 发表于 2020-12-28 16:40 | 只看该作者
正好在做这个,学习一下
回复

使用道具 举报

14#
ID:585349 发表于 2020-12-30 11:28 | 只看该作者
我有一条晚上2812灯带是三根线的,引脚怎么去接
回复

使用道具 举报

15#
ID:831068 发表于 2021-1-7 15:41 | 只看该作者
孙少 发表于 2020-12-30 11:28
我有一条晚上2812灯带是三根线的,引脚怎么去接

vcc+gnd+signal=三根线
回复

使用道具 举报

16#
ID:210471 发表于 2021-3-5 17:04 | 只看该作者
点亮了很好看
回复

使用道具 举报

17#
ID:48216 发表于 2021-3-9 00:27 | 只看该作者

点亮了很好看
回复

使用道具 举报

18#
ID:753687 发表于 2021-3-13 15:16 | 只看该作者
正好手里有一个ws2812,也想做这个,学习一下
回复

使用道具 举报

19#
ID:890487 发表于 2021-3-13 16:33 | 只看该作者
看看能不能移植到esp8266 谢谢楼主
回复

使用道具 举报

20#
ID:202803 发表于 2021-5-20 14:01 | 只看该作者
请问使用PWM方式的话不使用DMA怎么实现呢,因为有的单片机是没有DMA控制器的
回复

使用道具 举报

21#
ID:423238 发表于 2021-5-21 15:46 来自手机 | 只看该作者
有8266的驱动程序没
回复

使用道具 举报

22#
ID:963713 发表于 2021-9-2 15:43 | 只看该作者
点亮了很好看
回复

使用道具 举报

23#
ID:226821 发表于 2021-9-6 08:56 | 只看该作者
Thankjs share nice colorful effect
回复

使用道具 举报

24#
ID:89237 发表于 2021-9-6 09:03 | 只看该作者

点亮了很好看
回复

使用道具 举报

25#
ID:436885 发表于 2021-9-14 18:19 | 只看该作者
大家用的是什么型号芯片?
回复

使用道具 举报

26#
ID:88256 发表于 2021-9-17 01:49 | 只看该作者
改到ESP-12F上试了一下,发现只有8个灯数量太少变化就不明显,等有空改长了试试
回复

使用道具 举报

27#
ID:973189 发表于 2021-10-19 07:39 | 只看该作者
先记录下来,后面学习一下
回复

使用道具 举报

28#
ID:986209 发表于 2021-11-30 22:48 | 只看该作者
牛呀,才学习就可以写出这样的程序不简单
回复

使用道具 举报

29#
ID:384489 发表于 2022-1-10 16:47 | 只看该作者
用过SPI,试试PWM的。
回复

使用道具 举报

30#
ID:837560 发表于 2022-1-25 17:14 | 只看该作者
不错,不错有空研究一下
回复

使用道具 举报

31#
ID:947605 发表于 2022-4-25 19:30 | 只看该作者
很漂亮,帅啊
回复

使用道具 举报

32#
ID:375944 发表于 2022-8-12 08:52 | 只看该作者
正用到这款做机器人控制灯用,学习下!
回复

使用道具 举报

33#
ID:1040201 发表于 2022-9-2 16:29 | 只看该作者
感谢楼主,我去抽点时间学习一下 。
回复

使用道具 举报

34#
ID:651494 发表于 2022-9-3 15:30 | 只看该作者
主循环用个大DELAY,还让不让其他进程活?改天给你们写个,估计都还是大学生。
回复

使用道具 举报

35#
ID:46750 发表于 2023-5-11 10:43 | 只看该作者
漂亮,这种算法有乘除法运算,运行效率和储存空间都是挑战,对于成本较低的MCU,就...
有没有高手来完善一下
回复

使用道具 举报

36#
ID:339520 发表于 2023-6-19 13:46 | 只看该作者
1毛钱的应广单片机PMS150G驱动WS2812代码写完了。
回复

使用道具 举报

37#
ID:356964 发表于 2023-8-18 08:01 | 只看该作者
谢谢分享,学习一下!学习这个有瘾!
回复

使用道具 举报

38#
ID:356964 发表于 2023-8-18 08:02 | 只看该作者
乐此不疲!乐此不疲!感谢分享!
回复

使用道具 举报

39#
ID:31514 发表于 2024-1-5 22:45 | 只看该作者
请教一下楼主,我移植到51单片机上,只有白色,不知道是什么原因
回复

使用道具 举报

40#
ID:349598 发表于 2024-1-12 21:49 | 只看该作者
不错!谢谢楼主分享。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表