STM32F103使用TIM+DMA驱动WS2812灯带


ws2812做为RGB灯,在很多场合都是非常有用的,我准备使用STM32H755的M4内核驱动时,遇到了一些问题,因此先用STM32F103来验证一下,找到库存的STM32103的开发板,来实现驱动,特记录如下:

1.使用STM32CubeMX 新建基于STM32F103C8Tx的工程:

2.打开外部时钟,因为内部时钟最高只能跑到64MHz。

3.在时钟配置界面,配置72MHz的总线时钟。

从上面我们得到Timer的时钟总线为72MHz。

4.打开TIM1的配置界面配置如下:

这里我们需要将GPIO 的输出速度选择为高速模式。

5.配置pwm

在定时器配置中,我们根据WS2812 的最大传输速率800kbps,设置定时器不分频和计数周期为89+1,这样下来波形的频率为72 M /(89+1) = 800 K,并且一个波形的周期为1 / 800 = 1.25 us

6.配置DMA

我们打开DMA的界面,添加一个DMA,选择方向为从内存到外设,内存为递增,数据宽度为半字节,即16 bit。

到此界面配置结束,生成工程后,使用mdk 打开工程。

【代码添加】

1.新建RGB.c 添加代码如下:

view plaincopy to clipboardprint?

1.#include “RGB.h”

2.#include “main.h”

3.#include “tim.h”

4.

5.uint16_t RGB_buffur[Reste_Data + WS2812_Data_Len] = { 0 }; //数据缓存数组

6.

7.void WS2812_Display_1(uint32_t Color, uint16_t num)

8.{

9.

10.//指针偏移:需要跳过复位信号的N 个0

11.uint16_t* p = (RGB_buffur + Reste_Data) +(num * Led_Data_Len);

12.

13.for (uint8_t i = 0; i < 8; ++i)

14.p[i+8]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);

15.for (uint8_t i = 8; i < 16; ++i)

16.p[i-8]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);

17.for (uint8_t i = 16; i < 24; ++i)

18.p[i]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);

19.

20.}

21.

22.

23.void WS2812_Display_2( uint8_t red, uint8_t green, uint8_t blue,uint16_t num)

24.{

25.

26.uint8_t i;

27.uint32_t Color=(green << 16 | red << 8 | blue);// 将2 个8 位数据合并转化为32 位数据类型

28.

29.//指针偏移:需要跳过复位信号的N 个0

30.uint16_t* p = (RGB_buffur + Reste_Data) + (num * Led_Data_Len);

31.

32.for (i = 0; i < 24; ++i) // 对数组进行编辑

33.p[i]= (((Color << i) & 0X800000) ? Hight_Data : Low_Data);

34.

35.}

36.

37.

38.void WS2812_Number_4(uint32_t Color1,uint32_t Color2,uint32_t Color3,uint32_t Color4)

39.{

40.

41.uint16_t RGB_Buff_4[Reste_Data + 4 *WS2812_Data_Len] = { 0 };

42.uint16_t* p;

43.uint32_t Color;

44.

45.for( uint8_t k=0;k<4;k++)

46.{

47.switch (k) // 进行指针偏移

48.{

49.case 0: p= (RGB_Buff_4 + Reste_Data) +(0 * Led_Data_Len),Color=Color1;break;

50.case 1: p= (RGB_Buff_4 + Reste_Data) +(1 * Led_Data_Len),Color=Color2;break;

51.case 2: p= (RGB_Buff_4 + Reste_Data) +(2 * Led_Data_Len),Color=Color3;break;

52.case 3: p= (RGB_Buff_4 + Reste_Data) +(3 * Led_Data_Len),Color=Color4;break;

53.default : ;break;

54.}

55.

56.for (uint8_t i = 0; i < 8; ++i) // 对数组进行编辑

57.{

58. for (uint8_t i = 0; i < 8; ++i)

59.p[i+8]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);

60.for (uint8_t i = 8; i < 16; ++i)

61.p[i-8]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);

62.for (uint8_t i = 16; i < 24; ++i)

63.p[i]= (((Color << i) & 0X800000) ? Hight_Data :Low_Data);

64.}

65.

66.}

67.

68.HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_Buff_4,(176));//启动DMA传输

69.

70.}

71.

72.//DMA传输完成回调函数

73.void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)

74.{

75.HAL_TIM_PWM_Stop_DMA(&htim1,TIM_CHANNEL_1);

76.}

2.添加RGB.h 代码如下:

view plaincopy to clipboardprint?

1.#ifndef __RGB_H

2.#define __RGB_H

3.#include “main.h”

4.#define Hight_Data ( 64 ) //1码相对计数值

5. #define Low_Data ( 36 ) //0码相对计数值

6. #define Reste_Data ( 80 ) //80复位电平相对计数值

7.#define Led_Num ( 4 ) //WS2812灯个数

8.#define Led_Data_Len ( 24 )//WS2812数据长度,单个需要24个字节

9.#define WS2812_Data_Len (Led_Num * Led_Data_Len) //ws2812级联后需要的数组长度

10.

11.//uint16_t RGB_buffur[Reste_Data + WS2812_Data_Len] = { 0 }; //数据缓存数组

12.

13.

14.void WS2812_Display_1(uint32_t Color,uint16_t num);

15.void WS2812_Display_2( uint8_t red, uint8_t green, uint8_t blue,uint16_t num);

16.

17.void WS2812_Number_4(uint32_t Color1,uint32_t Color2,uint32_t Color3,uint32_t Color4);//封装好的四个灯函数,只需要分别输入四个灯的颜色即可

18.

19.

20.#endif

3.Main

首先引RGB.h头文件

再使用extern一下数组

view plaincopy to clipboardprint?

1.extern uint16_t RGB_buffur[Reste_Data +WS2812_Data_Len];

在while中添加周期的亮灯:

view plaincopy to clipboardprint?

1.WS2812_Number_4(0x180000,0x001800,0x000018,0);

2.HAL_Delay(500);

3.WS2812_Number_4(0,0×180000,0x001800,0x000018);

4.HAL_Delay(500);

5.WS2812_Number_4(0x000018,0,0×180000,0x001800);

6.HAL_Delay(500);

7.WS2812_Number_4(0x001800,0x000018,0,0×180000);

8.HAL_Delay(500);

【验证】

将ws2812 的DI 引脚接到PA8,VCC 与GND 接到开发板的电源上,将程序下载到开发板后,可以看到如期点亮了WB2812。

            <!-- 非定向300*250按钮    17/09  wenjing  begin -->
            <!-- 非定向300*250按钮  end -->
        </div>



Source link

未经允许不得转载:紫竹林-程序员中文网 » STM32F103使用TIM+DMA驱动WS2812灯带

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
关于我们 免责申明 意见反馈 隐私政策
程序员中文网:公益在线网站,帮助学习者快速成长!
关注微信 技术交流
推荐文章
每天精选资源文章推送
推荐文章
随时随地碎片化学习
推荐文章
发现有趣的