stm32 驱动ws2812

2020-01-07 19:22发布

最近正在用stm32做一个台灯,使用到了ws2812 LED,到网上找ws2812的stm32驱动,找半天找到一个,结果还是用不了。所以决定还是自己动手来吧。
下面的驱动代码贴出来,时候大家要使用也不错的
ws2812.h

  1. #ifndef __WS2812_H
  2. #define __WS2812_H

  3. #ifdef __cplusplus
  4. extern "C"
  5. {
  6. #endif

  7. #include "stm32f10x_conf.h"

  8. // The following macro must be ported to  your platform
  9. // 以下的宏定义请移植到你的IO Pin
  10. #define   ws2812DIN_HIGH()     (GPIOA->BSRR = 0x00001000)
  11. #define   ws2812DIN_LOW()      (GPIOA->BSRR = 0x10000000)
  12. #define   ws2812DIN_INIT()     {
  13.                                                                 RCC->APB2ENR |= 0x01<<2;
  14.                                                                 GPIOA->CRH &= ~(0x000f0000);
  15.                                                                 GPIOA->CRH |= (0x00030000);
  16.                                                                 GPIOA->BSRR |= (0x10000000);
  17.                                                                 }

  18. // RGB structure
  19. typedef struct
  20. {
  21.         // R,G,B color value
  22.     uint8_t ucRedVal;
  23.     uint8_t ucGreenVal;
  24.     uint8_t ucBlueVal;
  25. }RGB_t;
  26. // when you want to use ws2812 , you must call this function
  27. void ws2812_Init(void);
  28. void ws2812_SendRes(void);
  29. void ws2812_SendRGBData(RGB_t xRGB);


  30. /*** typical usage for above API, 典型的使用方法
  31.  ws2812_Init();
  32.     GRB_t xRGB;
  33.     xRGB.ucRedVal = 0xff;
  34.     xRGB.ucGreenVal = 0x00;
  35.     xRGB.ucBlueVal = 0x00;
  36.     while(1)
  37.     {
  38.             // The first ws2812
  39.             ws2812_SendRGBData(xRGB);
  40.             // The second ws2812
  41.             ws2812_SendRGBData(xRGB);
  42.             // The third ws2812
  43.             ws2812_SendRGBData(xRGB);
  44.             //  The fourth ws2812
  45.             ws2812_SendRGBData(xRGB);
  46.             // send frame seperator
  47.             ws2812_SendRes();


  48.     }

  49. */

  50. #ifdef __cplusplus
  51. }
  52. #endif
  53. #endif
复制代码

ws2812.c 文件


  1. #include "ws2812.h"

  2. /*
  3. * @Desc: delay a approximate us
  4. * @Args: ulUs, us about to delay
  5. * @Returns: None
  6. */
  7. static void
  8. DelayUs(uint32_t ulUs)
  9. {
  10.         uint32_t j;
  11.         while(ulUs--)
  12.         {
  13.                 j = 12;
  14.                 while(j)
  15.                 {
  16.                         j--;
  17.                 }
  18.         }
  19. }


  20. /*
  21. * @Desc: delay a number of nop for your platform(one nop equal to 13.9 ns)
  22. * @Args: ulNopNum, nop number
  23. * @Returns: None
  24. *
  25. */
  26. static void
  27. DelayNop(uint32_t ulNopNum)
  28. {
  29.         while(ulNopNum)
  30.         {
  31.                 __NOP();
  32.                 ulNopNum--;
  33.         }
  34. }


  35. /*
  36. * @Desc: init ws2812, just init io Pin,
  37. *   you must call this function firstly whenever
  38. *   you want to use ws28128
  39. * @Args: None
  40. * @Returns: None
  41. *
  42. */
  43. void
  44. ws2812_Init(void)
  45. {
  46.         ws2812DIN_INIT();
  47. }


  48. /*
  49. * @Desc: send rgb value to a ws2812,
  50. * @Args: xRGB, rgb value container variable
  51. * @Returns: NOne
  52. *
  53. */
  54. void
  55. ws2812_SendRGBData(RGB_t xRGB)
  56. {
  57.         uint32_t i = 0;
  58.         uint32_t ulColor = 0;
  59.         // put blue color  bit to ulColor
  60.         for(i = 0; i < 8; i++)
  61.         {
  62.                 ulColor = ((xRGB.ucBlueVal & 0x01) | (ulColor << 1));
  63.                 xRGB.ucBlueVal >>= 1;
  64.         }
  65.         // put red color  bit to ulColor
  66.         for(i = 8; i < 16; i++)
  67.         {
  68.                 ulColor = ((xRGB.ucRedVal & 0x01) | (ulColor << 1));
  69.                 xRGB.ucRedVal >>= 1;
  70.         }
  71.         // put green color bit to ulColor
  72.         for(i = 16; i < 24; i++)
  73.         {
  74.                 ulColor = ((xRGB.ucGreenVal & 0x01) | (ulColor << 1));
  75.                 xRGB.ucGreenVal >>= 1;
  76.         }
  77.         // send 24 bits color data
  78.         for(i = 0; i < 24; i++)
  79.         {
  80.                 if((ulColor & (uint32_t)0x01))
  81.                 {
  82.                         ws2812DIN_HIGH();
  83.                         DelayNop(20);
  84.                         ws2812DIN_LOW();
  85.                 }
  86.                 else
  87.                 {
  88.                         ws2812DIN_HIGH();
  89.                         ws2812DIN_LOW();
  90.                         DelayNop(20);
  91.                 }
  92.                 ulColor >>= 1;
  93.         }
  94. }

  95. /*
  96. * @Desc: send a frame seperator
  97. * @Args: None
  98. * @Returns: None
  99. */
  100. void
  101. ws2812_SendRes(void)
  102. {
  103.     ws2812DIN_LOW();
  104.     DelayUs(100);
  105. }

复制代码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
37条回答
isakura
2020-01-10 14:27
first_blood 发表于 2017-3-14 21:21
spi+dma,不占用CPU,就是用ram虚拟出一段显存出来,更新RGB灯,只需要更新一下ram就行。用spi的位模拟ws28 ...

看了下WS2812的驱动。。。0和1是占空比不一样,

        高      低
0 是  0.35  0.8  us
1 是  0.7    0.6  us

这种用SPI怎么实现?SPI的波特率是一定的啊,除非  SPI 设定的波特率位时间可以到0.1us才有可能实现

一周热门 更多>