你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】实战小例程 基于STM32F103C8T6最小系统板和STM32CubeMX驱动WS2812B光立方

[复制链接]
STMCU小助手 发布时间:2022-4-15 10:00
本文开发环境:7 \* c; X6 T; @. P. r' }/ U
/ i. S' f7 u: i0 D
MCU型号:STM32F103C8T6最小系统板
1 H3 z" G) W# GIDE环境: MDK V5.36
+ K$ `: ?! w+ l  e/ k  {* W  t! O代码生成工具:STM32CubeMx 6.3.0
$ n( ~% `9 ], a9 N/ d) l! G7 B8 n4 X% z3 n& H+ T
电路板实拍:

% g% t3 {" n! ]1 f2 |  k) w7 D0 U2 x# A1 o( Z8 c. A
3[)K)}}I4GK$JEUNN7}Q@0Q.png
) D7 o' i2 C0 N% S) U8 o, M( w8 y, P3 |3 g8 h) ?; ~& i0 v
2861f2aa89e3425dab5fdc57ac47ed8d.gif
6 C3 \: e/ M3 Y1 \4 {" s( r0 l: [1 A6 f9 \8 D3 m
) ?& V# r! h* m% M8 Y
一、配置CubeMX" [& W% W( U. Z; a9 q& M
新建工程,选择芯片,配置SYS,RCC略% i3 G2 G# E0 w+ Q( Q: K

) e" s7 Z6 d0 }0 O8 i1.1 时钟树配置! L$ X7 Z  K! O" T! H3 S/ `% A
这里直接把时钟开到最高72MHz
7 H+ L' I& o8 J# V3 Y
& _. O" I) a* p& D1 @  E3 Q9 @ 0 u1 z4 ?- F  Z$ `9 t. m' c* D

# T/ u8 j- G7 C5 o% S. S6 j读数据手册,可以发现只有TIM1是挂载在APB2总线上的& J  O5 Q: z$ w
- y! g6 D. K7 V0 S! r! B* y2 E) c; R
b3df693fa08945528c49c77e203e06ac.png
6 P( `: f1 ]7 U7 a* J+ T) e
2 ^- w3 Z" _' b) I7 B' ~$ S1.2 配置DMA
- c% v4 F6 Z, R6 e8 O

1 d0 B  i& W' P7 ^7 o JOVU68XH3ETFV8TIXZ}~MC2.png
% o: x* i4 ^* e. t  V1 _9 `+ C: s8 l
周期计算:: P( P( y8 o/ @% b* z
( P) O  b7 \9 i( K& g) Z; D
WS2812B需要800kb的周期,系统时钟是72MHz,TIM1是挂在APB2总线上的,它的时钟也是72MHz,' a. b% s. `2 y
因此,有:72 * 1000 / 800 = 90 (89+1),因此自动装载值设为 89 ;
6 P5 R! V8 i  z, V1 P8 ?$ K' R6 i, o5 k! j2 p6 F
J7B}{IHZ[W@CE[6B$~0)V@K.png
  E1 M+ T: r% |& [8 v. L$ ^
- S% r6 p  M6 l! p- I" Z4 M5 {这样cubeMX的配置就完毕了,打开生成的工程文件。1 e! |- C: S4 L9 V+ s! l9 g4 P' I
, V) c- r+ k- v3 L0 W- j
最终引脚配置图:
5 i: q" H9 S# a$ U$ ^  g9 m' k$ `" U& L1 A9 ?# o& z- m2 C
9]U$GZ`N0_KY_{TY0UMJT5P.png
" l" A/ m) v3 p* L0 O
8 q& z+ l- ^4 v+ i8 m可以发现,PWM输出引脚为PA8。
% j, ?8 l( \+ A% ^) T* g$ i8 l4 a9 B& _# r! a
二、代码部分' u/ l- O) h% ]9 F+ z
在main.c里添加:
8 g; P8 g. O, x2 E& W3 E5 |  t: N. y; h' ~. {: X
此函数实现了灯效的控制,可以通过用户传入的RGB参数,来自动填充数组:
5 t5 O: X/ c2 o4 f+ g  a' N
3 j" x; Q5 ^. ^( u+ D+ h  S
  1. int fputc(int ch,FILE *f)
    $ O9 p9 j; y# O1 @% v0 x% t
  2. {% B: l3 L9 S+ C5 t; B. @+ b9 p6 Y2 F
  3.         ITM_SendChar(ch);' f$ M# c4 O5 h3 X/ `2 D" `, {
  4.         return (ch);
    2 D& V+ D! G( o8 D4 Q8 u: C
  5. }
    ! W9 l: b% \  }1 u0 }

  6. ' W3 t+ _. E% ?6 P  t9 T: i
  7. #define ONE_PULSE        (60)                           //1 码计数个数
    9 G- J3 `4 Y' G' j% G1 D; r% l
  8. #define ZERO_PULSE       (30)                           //0 码计数个数
    + ^3 t$ ~2 G2 T( P/ M* g
  9. #define RESET_PULSE      (48)                           //80 复位电平个数(不能低于40)( k3 Y1 g# N) J% s0 D) {6 M, g
  10. #define LED_NUMS         (25)                            //led 个数  M" w, Y- z2 Z4 ]- C
  11. #define LED_DATA_LEN     (24)                           //led 长度,单个需要24个字节
      ?4 Y% i( G8 `' t
  12. #define WS2812_DATA_LEN  (LED_NUMS*LED_DATA_LEN)        //ws2812灯条需要的数组长度* A, U: s) h' W/ o7 p
  13. #define DMA_LED_LEN (RESET_PULSE+WS2812_DATA_LEN)       //传输数据长度
    7 p2 d3 m3 R" v8 R* {6 U3 j

  14.   q6 D  g7 ~2 v5 f2 s/ g6 K
  15. uint16_t static RGB_buffur[RESET_PULSE + WS2812_DATA_LEN] = { 0 };, `8 y& S  ^5 \# U  H1 f' p0 u+ u

  16. 6 s6 |$ \  y9 Y+ Y- [% \# f- k
  17. void ws2812_set_RGB(uint8_t R, uint8_t G, uint8_t B, uint16_t num), E$ r! U+ k9 B0 W# `" c0 i9 a  K. d" X
  18. {7 y0 }0 w. C& D/ L+ @
  19.     //指针偏移:需要跳过复位信号的N个01 F% ^' C2 n- v, F7 _6 h0 F$ U. G
  20.     uint16_t* p = (RGB_buffur + RESET_PULSE) + (num * LED_DATA_LEN);
    # O0 u5 p% d. ?
  21. 7 e9 I9 Y4 k( n2 O# L+ ?. {
  22.     for (uint16_t i = 0;i < 8;i++)
    5 H4 A( A) n2 o* Z( h2 x
  23.     {
    2 l9 s9 s5 H; @* p6 d. [9 I
  24.         //填充数组
    & J/ N- q1 ]. _' W& |
  25.         p<i>      = (G << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
    % Q1 K3 k2 W5 E
  26.         p[i + 8]  = (R << i) & (0x80)?ONE_PULSE:ZERO_PULSE;! j4 }* q; j& v+ C
  27.         p[i + 16] = (B << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
    8 |% h2 D3 p; {, W# s$ o
  28.     }3 A" ^3 Z0 Q* K7 ^, |! M

  29. , C! Q3 U2 `: M: O0 x4 F- g% H! t
  30. }</i>
复制代码

; A! [5 j% `* Z6 w1 x( w; c- l. B这里写2个小函数,方便对连续的一组灯进行控制
; ^2 v* K  m1 q: j) E5 L" p- S0 ?; Z, j& i- r$ y/ \/ e
  1. void LED_ON_Purple(int Num_Start,int Num_End)
    8 n. K& r- J; q" u
  2. {
    / V( d: M2 [1 x/ N( A
  3.         int Num_flag;
    , H$ |8 F3 f, K! r
  4.         for(Num_flag=Num_Start;Num_flag<=Num_End;Num_flag++) ws2812_set_RGB(0x94, 0x00, 0xD3, Num_flag);; X* a+ Z- ]1 f+ n. ?4 b
  5. }) v' A8 B/ R8 p! K* k

  6. $ y; x; M9 v4 ~: U
  7. void LED_OFF(int Num_Start,int Num_End)8 i0 c& r0 _0 W0 C
  8. {1 n3 H! W$ E1 W! o7 C$ C1 ~
  9.         int Num_flag;) X2 c1 _+ e! F$ P/ Y4 `
  10.         for(Num_flag=Num_Start;Num_flag<=Num_End;Num_flag++) ws2812_set_RGB(0x00, 0x00, 0x00, Num_flag);
      ?) v$ Y0 F( o6 j( a1 A7 X% R. A
  11. }
复制代码

4 {( Y- i* w3 D* Q! \此函数设置了灯的颜色情况,并通过延时来控制灯的闪烁:
- ~( v8 v! I0 e' ]6 x! K5 `9 b7 L
3 Y" E7 Y5 _0 P; U6 P5 L
  1. void ws2812_example(void)
    3 _  k# m9 T# b& ^$ H+ u3 m" i
  2. {  : M4 L$ C% m8 u( }0 f* E9 X; o
  3.                 LED_ON_Purple(0,4);LED_OFF(5,24);
    . M' J+ J1 O/ W( R7 [0 h
  4.             HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,DMA_LED_LEN); //#2.传输数据9 M9 w+ Z" P1 u" b) h3 d
  5.                    HAL_Delay(500);//#3.延时:使效果可以被观察
    & i5 g' Y4 c# ]3 _+ Z& U9 }
  6.         
    . u0 f3 u  D# r! V- u9 E
  7.                 LED_OFF(0,4);LED_OFF(10,24);LED_ON_Purple(5,9);        " w2 ^3 C: O9 b' e6 ^9 T0 k: B
  8.                    HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,DMA_LED_LEN);
      T2 ^0 R5 S/ q" _& [
  9.                   HAL_Delay(500);$ u8 |, Z3 V% Z6 x6 Z# x5 v$ J
  10.          / t1 x) E" L5 y- t+ q. m
  11.                  LED_OFF(0,9);LED_ON_Purple(10,14);LED_OFF(15,24);
    , P$ m) X2 m8 J9 Q4 d" _% X6 l/ _
  12.             HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,DMA_LED_LEN);
    1 [; J( l7 ~! S! F
  13.         HAL_Delay(500);
    , W# j( W) Z+ _# y8 l6 l4 \
  14.         8 ^4 K4 r2 }* X. D' @  L
  15.             LED_OFF(0,14);LED_ON_Purple(15,19);LED_OFF(20,24);* ]8 q# W# }3 b; `5 t# P8 _& q9 f
  16.                 HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,DMA_LED_LEN);
    ) {* ?- d9 X6 S, p' y1 w
  17.         HAL_Delay(500);
    1 u+ D" b7 J7 [$ s) \7 k
  18.         4 [1 q% Y2 @$ A) L0 s  y
  19.             LED_OFF(0,19);LED_ON_Purple(20,24);- H) D9 L/ T$ n
  20.                 HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,DMA_LED_LEN); 0 g6 C& G8 L7 y  j7 g
  21.         HAL_Delay(500);# V# x' ~: S* P2 v/ w/ S5 w
  22. }
复制代码
  1.   while (1)
    + P4 Q9 g5 D) p/ i  r8 _
  2.   {' a" R# {4 Z1 ], d# x
  3.                 ws2812_example();
    0 i& R' i* U# c8 ^2 k/ j: w
  4.     /* USER CODE END WHILE *// W% O9 F" l" Y
  5. / t& q& S) q' F& p! r) z5 D# I  z
  6.     /* USER CODE BEGIN 3 */
    / R! L/ [, p. |
  7.   }
复制代码

- u3 `) v& y* C5 N& A5 e3 Z1 z' K三、现象5 X8 N, a2 w+ k1 b
(角落里有个灯没焊好,回头改一下): Y) A- _5 x& \+ N& m; I' |, v

7 V# c+ f2 [( k! m7 H/ C5 c af8ee788e2fa40c19b5174c5c0c6157c.gif / [  R0 N  m0 ]( g, `! m3 l

% q3 i3 X3 m$ U7 r9 E四、后记3 M7 k, B5 G$ d( e/ B1 c
我是在立创开源广场看到的5X5X5光立方工程,然后就想复现一下,理论上有五层(光立方),目前只做了一层(光平方)做测试,后续我会把五块都做出来然后连起来。
* j0 t0 t' U% U9 D0 D" q
7 M+ W. b3 K, ]) M$ n然后WS2812的具体原理和代码逻辑,在前言里的那篇大佬写的博文里写的很清楚,在这里我也只是做一些小补充,然后移植到一个实例中来。3 r' N! j6 A7 c% q, S1 K
) m1 O# ?7 S7 A! D
另外,单片机给的3.3V供电不能保证电路能正常工作,灯少好像还行,但多了的话经过实测,至少要到3.5V的供电电压,这可能与具体元器件有关系,如果亮灭情况有问题的话,大家也可以从供电的角度查一查。
$ m2 H& e/ l8 S2 d( I
0 U! b+ d( i2 c* Q, v! \- E( [$ ~
! C  v! b* ?& @* b. A, p  Y
" i) ^2 \4 L/ z! j
收藏 评论0 发布时间:2022-4-15 10:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版