当前位置:   article > 正文

WS2812B彩灯 STM32HAL库开发:PWM+DMA(stm32f103c8t6)_ws2812编程实例

ws2812编程实例

目录

一、摘要

二、WS2812B介绍

三、CUBEMX配置

四、程序介绍(KEIL编译器)

五、数据手册


一、摘要

        1、本文使用示例单片机型号为stm32f103c8t6,RGB型号为WS2812B

        2、主要实现功能是实现用PWM+DMA使RGB_LED亮起不同颜色的灯光;

        3、目的:简单调通该型号RGB_LED,方便后续改编使用,希望各位读者可以依次做出更炫酷的效果。为了便于更好理解数据手册和单片机配置的关联,第二部分也放入了CUBEMX的部分配置图片

        4、优点:DMA转运,硬件自动数据搬运(由内存到外设),减少CPU资源占用,第一次使用DMA可以先大致看一下DMA相关知识,这会让你很容易理解下面的一些配置

二、WS2812B介绍

       ( 为了便于更好理解数据手册和单片机配置的关联,第二部分也放入了CUBEMX的部分)

 依据方向标识与单片机接好线路

注:VDD接5V

        DIN接单片机PWM输出引脚(本文中接PA8引脚,即TIM1_PWM输出通道1)

        DOUT接下一个LED的DIN引脚

此处重装值就是定时器一个周期从0计到89计90个数(后面介绍为什么是89)                                                          

通过控制PWM占空比发送0码和1码,额定周期为1.25us,则频率为800Khz

0码PWM占空比:

(0码高电平时间)/(周期)--->  0.4 / 1.25 = 0.32 

  用占空比乘以定时器重装值加一就是0码的CCR值(代表PWM高电平计数个数)--->

  0.32 * (89+1) = 28.8(取28,实测不可以高于28,但23到28都可以)

1码PWM占空比:

同理计算:(1码高电平时间)/ (周期)---> 0.8 / 1.25 = 0.64

(占空比)*(重置值+1)= CCR ---> 0.64 * 1.25 = 57.6(取58)

每一个LED的R、G、B分别由八位数据控制颜色浓度,(每种颜色浓度有0~255档,理论上RGB就可以组成256的3次方中颜色组合)即每个LED需要24BIT数据,那么需要发送数据的总长度则为(要控制LED数量 n)*(24),每个LED保存24BIT将剩余位传给后面LED。全部数据发送完成后要继续发送大于24us的低电平作为RESET_CODE等才可以点亮。

三、CUBEMX配置

 

时钟树配置

  

定时器配置

PWM频率:

Fpwm =Tclk / ((arr+1)*(psc+1))(单位:Hz)

上面提到数据传送频率为800Khz,Tclk为72Mhz,我们这里设置psc = 0,arr= 89,得到频率刚好为800Khz。

占空比:

duty circle = TIM3->CCR1 / arr(单位:%)

TIM3->CCR1  用户设定值(即上述0码和1码占空比计算所得CCR)

PWM-DMA配置

 1:DMA配置

 2:添加一个DMA

 3:选择定时器1的通道一外设

四、程序介绍(KEIL编译器)

RGB.H

  1. #ifndef __RGB_H__
  2. #define __RGB_H__
  3. #include "main.h"
  4. /*这里是上文计算所得CCR的宏定义*/
  5. #define CODE_1 (58) //1码定时器计数次数
  6. #define CODE_0 (25) //0码定时器计数次数
  7. /*建立一个定义单个LED三原色值大小的结构体*/
  8. typedef struct
  9. {
  10. uint8_t R;
  11. uint8_t G;
  12. uint8_t B;
  13. }RGB_Color_TypeDef;
  14. #define Pixel_NUM 1 //LED数量宏定义,这里我使用一个LED,(单词pixel为像素的意思)
  15. void RGB_SetColor(uint8_t LedId,RGB_Color_TypeDef Color);//给一个LED装载24个颜色数据码(0码和1码)
  16. void Reset_Load(void); //该函数用于将数组最后24个数据变为0,代表RESET_code
  17. void RGB_SendArray(void); //发送最终数组
  18. void RGB_RED(uint16_t Pixel_Len); //显示红灯
  19. void RGB_GREEN(uint16_t Pixel_Len);//显示绿灯
  20. void RGB_BLUE(uint16_t Pixel_Len); //显示蓝灯
  21. void RGB_WHITE(uint16_t Pixel_Len);//显示白灯
  22. #endif

 RGB.C

  1. #include "RGB.h"
  2. #include "tim.h"
  3. /*Some Static Colors------------------------------*/
  4. const RGB_Color_TypeDef RED = {255,0,0}; //显示红色RGB数据
  5. const RGB_Color_TypeDef GREEN = {0,255,0};
  6. const RGB_Color_TypeDef BLUE = {0,0,255};
  7. const RGB_Color_TypeDef SKY = {0,255,255};
  8. const RGB_Color_TypeDef MAGENTA = {255,0,220};
  9. const RGB_Color_TypeDef YELLOW = {127,216,0};
  10. const RGB_Color_TypeDef OEANGE = {127,106,0};
  11. const RGB_Color_TypeDef BLACK = {0,0,0};
  12. const RGB_Color_TypeDef WHITE = {255,255,255};
  13. /*二维数组存放最终PWM输出数组,每一行24个
  14. 数据代表一个LED,最后一行24个0代表RESET码*/
  15. uint32_t Pixel_Buf[Pixel_NUM+1][24];
  16. /*
  17. 功能:设定单个RGB LED的颜色,把结构体中RGB的24BIT转换为0码和1码
  18. 参数:LedId为LED序号,Color:定义的颜色结构体
  19. */
  20. void RGB_SetColor(uint8_t LedId,RGB_Color_TypeDef Color)
  21. {
  22. uint8_t i;
  23. if(LedId > Pixel_NUM)return; //avoid overflow 防止写入ID大于LED总数
  24. for(i=0;i<8;i++) Pixel_Buf[LedId][i] = ( (Color.G & (1 << (7 -i)))? (CODE_1):CODE_0 );//数组某一行0~7转化存放G
  25. for(i=8;i<16;i++) Pixel_Buf[LedId][i] = ( (Color.R & (1 << (15-i)))? (CODE_1):CODE_0 );//数组某一行8~15转化存放R
  26. for(i=16;i<24;i++) Pixel_Buf[LedId][i] = ( (Color.B & (1 << (23-i)))? (CODE_1):CODE_0 );//数组某一行16~23转化存放B
  27. }
  28. /*
  29. 功能:最后一行装在24个0,输出24个周期占空比为0的PWM波,作为最后reset延时,这里总时长为24*1.2=30us > 24us(要求大于24us)
  30. */
  31. void Reset_Load(void)
  32. {
  33. uint8_t i;
  34. for(i=0;i<24;i++)
  35. {
  36. Pixel_Buf[Pixel_NUM][i] = 0;
  37. }
  38. }
  39. /*
  40. 功能:发送数组
  41. 参数:(&htim1)定时器1,(TIM_CHANNEL_1)通道1,((uint32_t *)Pixel_Buf)待发送数组,
  42. (Pixel_NUM+1)*24)发送个数,数组行列相乘
  43. */
  44. void RGB_SendArray(void)
  45. {
  46. HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_1, (uint32_t *)Pixel_Buf,(Pixel_NUM+1)*24);
  47. }
  48. /*
  49. 功能:显示红色
  50. 参数:Pixel_Len为显示LED个数
  51. */
  52. void RGB_RED(uint16_t Pixel_Len)
  53. {
  54. uint16_t i;
  55. for(i=0;i<Pixel_Len;i++)//给对应个数LED写入红色
  56. {
  57. RGB_SetColor(i,RED);
  58. }
  59. Reset_Load();
  60. RGB_SendArray();
  61. }
  62. /*
  63. 功能:显示绿色
  64. 参数:Pixel_Len为显示LED个数
  65. */
  66. void RGB_GREEN(uint16_t Pixel_Len)
  67. {
  68. uint16_t i;
  69. for(i=0;i<Pixel_Len;i++)//给对应个数LED写入绿色
  70. {
  71. RGB_SetColor(i,GREEN);
  72. }
  73. Reset_Load();
  74. RGB_SendArray();
  75. }
  76. /*
  77. 功能:显示蓝色
  78. 参数:Pixel_Len为显示LED个数
  79. */
  80. void RGB_BLUE(uint16_t Pixel_Len)
  81. {
  82. uint16_t i;
  83. for(i=0;i<Pixel_Len;i++)//给对应个数LED写入蓝色
  84. {
  85. RGB_SetColor(i,BLUE);
  86. }
  87. Reset_Load();
  88. RGB_SendArray();
  89. }
  90. /*
  91. 功能:显示白色
  92. 参数:Pixel_Len为显示LED个数
  93. */
  94. void RGB_WHITE(uint16_t Pixel_Len)
  95. {
  96. uint16_t i;
  97. for(i=0;i<Pixel_Len;i++)//给对应个数LED写入白色
  98. {
  99. RGB_SetColor(i,WHITE);
  100. }
  101. Reset_Load();
  102. RGB_SendArray();
  103. }
  104. //也可以继续添加其他颜色,和颜色变化函数等

 main.c

( 在此处调用RGB头文件)

( 在while(1)里写入想要的颜色变化,这里现象为红绿蓝白四种颜色1秒变化一次)

五、数据手册

百度云盘 WS2812B

阿里云盘 WS2812B

ok,简单讲到这里,希望你可以以次添加更多功能复杂的函数,做出更炫酷更有趣的LED颜色变幻,如果有什么地方感觉说的不清晰可以留言评论


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/159706
推荐阅读
相关标签
  

闽ICP备14008679号