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

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

[复制链接]
STMCU小助手 发布时间:2022-4-15 10:00
本文开发环境:3 b( t, \* ^% {! D. K- `! i
4 y1 g% c4 ~/ X1 v0 _
MCU型号:STM32F103C8T6最小系统板5 s; w' U4 G  _8 d
IDE环境: MDK V5.36
) i  f$ J2 H# W0 @% D$ }" c代码生成工具:STM32CubeMx 6.3.0) V% z9 ^* G. s+ \- N. |

" T; D( q! ~2 z* [2 Y电路板实拍:

6 q* i0 W; |  U# k: J% `6 \
, I) ?2 ^4 a! @/ a0 p  J0 p+ b' y 3[)K)}}I4GK$JEUNN7}Q@0Q.png
6 Y! [$ q. K* j: h
4 b5 Q/ P, _" X; B/ f1 M 2861f2aa89e3425dab5fdc57ac47ed8d.gif
+ V2 C/ t& E+ G/ I+ C* @
" T8 X# I6 o5 P) [+ c2 r) X- m3 y6 e$ a) O
一、配置CubeMX
5 u& }; e* n* R# l4 l+ m+ F新建工程,选择芯片,配置SYS,RCC略! Y0 [. H- y/ a* u. V8 l  E
5 d5 p/ A" ^' A9 I* X# ~6 Y
1.1 时钟树配置$ ~' d5 Y* Q' {" y4 {5 r. I
这里直接把时钟开到最高72MHz
: h( ]9 m4 t3 ]! m
2 a& ~* K5 P8 B& v* y 7 C/ y# H, W2 i  o- y: N0 H3 q, p/ g

- [# |) Y' U9 ~; C% Q' d; \; e读数据手册,可以发现只有TIM1是挂载在APB2总线上的
1 s1 b# {/ d' b$ A7 N9 }
/ q' ^( S9 i' E$ U b3df693fa08945528c49c77e203e06ac.png 6 Y2 F. i9 o! b2 f

6 {8 M1 c4 k% R2 j' ]: z1.2 配置DMA

& w8 s5 L( F& O' }( a8 x0 t0 r9 J
+ k) h% U$ {5 p: W3 ?4 c JOVU68XH3ETFV8TIXZ}~MC2.png , C: W* R: B# T7 n
% Z. k4 |0 C( `  h. x  x1 |! u( I
周期计算:
& G7 S  j4 Z7 L& ^* ?
; t- W: u5 @: c( ?' _WS2812B需要800kb的周期,系统时钟是72MHz,TIM1是挂在APB2总线上的,它的时钟也是72MHz,6 D6 F0 }  h. n$ `
因此,有:72 * 1000 / 800 = 90 (89+1),因此自动装载值设为 89 ;$ O, @1 O* k8 t1 O
; J( k9 ]0 S% f- C
J7B}{IHZ[W@CE[6B$~0)V@K.png 6 |9 j  K& \6 `5 r2 _$ I3 k

' R/ `# T% G+ Q2 `2 _6 l% @这样cubeMX的配置就完毕了,打开生成的工程文件。
; F6 t2 A+ A/ F- g6 y& _9 r' z( k* E' q- @8 X% d
最终引脚配置图:7 k: \$ H' M+ W( B  I+ @

0 D9 I3 p' I0 f$ |+ ~4 ` 9]U$GZ`N0_KY_{TY0UMJT5P.png
" ^% c' Z) a- q/ E8 S* D: F* @' X+ r
可以发现,PWM输出引脚为PA8。  [( ~) X& Z* g0 I1 m
4 `* J4 Z# v3 R0 F) ?( y) H
二、代码部分& P& S) {& F3 o( t+ K# T- I
在main.c里添加:
" s: b& T4 X$ A1 `$ j. V% D4 J6 Q
! b. f/ C* {6 t0 c/ \' d2 G" o此函数实现了灯效的控制,可以通过用户传入的RGB参数,来自动填充数组:! O; j: _# `& k- v
4 |, l4 H% K/ G! L( b; [7 P+ B1 D
  1. int fputc(int ch,FILE *f)
    , O/ z5 ?" R) i( ^" r
  2. {& a. E+ w! e* r: u" n. ~  x
  3.         ITM_SendChar(ch);* ]; q6 h% z3 G/ g6 K, [: `7 N
  4.         return (ch);; M3 x3 R, Z- K+ m% D2 `
  5. }
    ! [% Z& P8 A6 @" g$ S4 U

  6. + G+ e2 ^1 i( B( O* g8 ~& n* p1 @
  7. #define ONE_PULSE        (60)                           //1 码计数个数& D; r! c+ M" \6 U7 y
  8. #define ZERO_PULSE       (30)                           //0 码计数个数$ c: @3 E. p6 Y$ ^& u% D
  9. #define RESET_PULSE      (48)                           //80 复位电平个数(不能低于40)' D; J3 z: W/ n; i9 e3 ~
  10. #define LED_NUMS         (25)                            //led 个数
    4 \( F" F" y, a" ^9 o$ A+ ?
  11. #define LED_DATA_LEN     (24)                           //led 长度,单个需要24个字节
    6 i7 q+ M+ o5 o% Y. d$ V0 ~
  12. #define WS2812_DATA_LEN  (LED_NUMS*LED_DATA_LEN)        //ws2812灯条需要的数组长度
    . Y, O+ C. p( |4 |
  13. #define DMA_LED_LEN (RESET_PULSE+WS2812_DATA_LEN)       //传输数据长度: z8 R" N: l( [2 S
  14. 6 }% i9 _+ G( |# x9 N0 ]1 o% H, ^; ?
  15. uint16_t static RGB_buffur[RESET_PULSE + WS2812_DATA_LEN] = { 0 };
    0 g. u+ `( q' L' ~& n$ |

  16. 4 c2 i% r1 o- M
  17. void ws2812_set_RGB(uint8_t R, uint8_t G, uint8_t B, uint16_t num)
    ; j2 Y7 E* S0 s( e8 z4 ~, Y3 |
  18. {
    0 X- A: E! M- t2 k, O9 f
  19.     //指针偏移:需要跳过复位信号的N个0
    + Q/ O8 K! l" {+ ~5 g
  20.     uint16_t* p = (RGB_buffur + RESET_PULSE) + (num * LED_DATA_LEN);
    / S& w4 ?1 P  }, Y
  21. 7 y/ W5 u8 Y9 O, P$ y! i
  22.     for (uint16_t i = 0;i < 8;i++)
    8 d7 T7 ^5 l# w8 m( L; y
  23.     {
    # c: u% a! ^2 }7 P& A& p% M6 Y
  24.         //填充数组
    5 f/ E% ^) g& a6 C2 [: o& D  g8 ~
  25.         p<i>      = (G << i) & (0x80)?ONE_PULSE:ZERO_PULSE;( Z( r' E4 g9 \! w* n1 h8 [
  26.         p[i + 8]  = (R << i) & (0x80)?ONE_PULSE:ZERO_PULSE;
    ' V0 J7 O- u8 v! W" L$ P) ~3 G
  27.         p[i + 16] = (B << i) & (0x80)?ONE_PULSE:ZERO_PULSE;- c. o1 H$ x5 _4 ]( V% I/ V
  28.     }4 h% s2 H8 B& E. X& \

  29. 6 {( J$ P6 z5 Q0 H( d  H9 T
  30. }</i>
复制代码

" N9 ?: Z2 E/ @0 Z+ H! I( [, o这里写2个小函数,方便对连续的一组灯进行控制
- t9 R: r& b7 Y3 D$ V% h) M/ V$ q1 g
  1. void LED_ON_Purple(int Num_Start,int Num_End)
    / f7 I$ u1 P9 o8 S* Z  _; x: E8 U
  2. {
    9 w$ |1 {4 m7 W9 z5 n6 X
  3.         int Num_flag;
    - K4 V0 a; _  b( _* G- e
  4.         for(Num_flag=Num_Start;Num_flag<=Num_End;Num_flag++) ws2812_set_RGB(0x94, 0x00, 0xD3, Num_flag);. d7 Z, ]* I5 K/ Y. ?
  5. }
      ]4 @$ x9 b1 Z3 p( |, |  V

  6. 1 U! K$ Q! }% Q  w% k' K! l
  7. void LED_OFF(int Num_Start,int Num_End)
    5 v# C4 o0 P) b1 Q+ O, i
  8. {
    8 M* S2 [+ q0 d  Z. h; G/ d  N
  9.         int Num_flag;- L. _( k, w% s
  10.         for(Num_flag=Num_Start;Num_flag<=Num_End;Num_flag++) ws2812_set_RGB(0x00, 0x00, 0x00, Num_flag);
    4 O7 ?5 c% J5 m
  11. }
复制代码
7 J/ E" @3 |, _' S" w& m/ ]
此函数设置了灯的颜色情况,并通过延时来控制灯的闪烁:4 P" V/ @5 H  X( J
$ E1 H8 |' t2 a! m9 T5 `+ n
  1. void ws2812_example(void)7 H. T9 C" V  o; `4 V7 m' U
  2. {  " R9 H4 m( l6 P1 V; G1 o7 q
  3.                 LED_ON_Purple(0,4);LED_OFF(5,24);5 F7 i, x" w- K
  4.             HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,DMA_LED_LEN); //#2.传输数据
    ; d- P& j) }' s% k/ M* @0 ]8 d
  5.                    HAL_Delay(500);//#3.延时:使效果可以被观察7 |, r# n, P3 I9 f; H, b( i% F
  6.         
    / h0 _' o. m. Z( _. N9 z& R) X/ O
  7.                 LED_OFF(0,4);LED_OFF(10,24);LED_ON_Purple(5,9);        , Z+ ^' R2 V8 h8 |" w+ q+ A
  8.                    HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,DMA_LED_LEN); # E" K6 ^6 Z5 n' Q  f- n* m
  9.                   HAL_Delay(500);; t7 Y0 q7 x  b0 a4 V
  10.          
    2 f) _' z, h5 l) d. ?( _2 ]; |
  11.                  LED_OFF(0,9);LED_ON_Purple(10,14);LED_OFF(15,24);
    # N" u, b! f7 M8 u9 @, N: H
  12.             HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,DMA_LED_LEN);
    $ ^' `) G( |( S1 a% M
  13.         HAL_Delay(500);
    $ Q* M& N8 ^6 i
  14.         
    - N$ q! N8 t! W" @% b8 [( D- K
  15.             LED_OFF(0,14);LED_ON_Purple(15,19);LED_OFF(20,24);
    ( h$ K- k4 C! y9 V. F) S' `
  16.                 HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,DMA_LED_LEN);
    9 a' w" U" t' c6 i
  17.         HAL_Delay(500);
      m( b- t/ u2 P# H8 y
  18.         
    6 r$ ]) d. c% h* [
  19.             LED_OFF(0,19);LED_ON_Purple(20,24);
    , w- N0 R" t! o4 ?1 G
  20.                 HAL_TIM_PWM_Start_DMA(&htim1,TIM_CHANNEL_1,(uint32_t *)RGB_buffur,DMA_LED_LEN); , M( g9 x& z3 u
  21.         HAL_Delay(500);
    4 C! Z$ L+ _: U
  22. }
复制代码
  1.   while (1)6 h3 A( x  B2 f: C. A
  2.   {% v# e+ a9 B/ N! f7 B
  3.                 ws2812_example();( G  A. P) Y* U- f% n' t
  4.     /* USER CODE END WHILE */
    ' b; p5 T* j% ?2 L+ i, r
  5. ! Z& m- n& I& o
  6.     /* USER CODE BEGIN 3 */4 a3 d3 {4 b! j
  7.   }
复制代码

0 t/ i1 F1 D+ C4 z, v5 q. {三、现象- x' D' j. o% X& z8 F3 y
(角落里有个灯没焊好,回头改一下)/ f& O" W# ^6 d* }6 S3 R
! o# a. Z8 N& x' p( Y6 j9 ]
af8ee788e2fa40c19b5174c5c0c6157c.gif
, ~4 _0 y4 r1 A
4 W% h/ e' C+ i+ E! E四、后记# g, M( V7 d4 Y: |8 u
我是在立创开源广场看到的5X5X5光立方工程,然后就想复现一下,理论上有五层(光立方),目前只做了一层(光平方)做测试,后续我会把五块都做出来然后连起来。4 ~. h" ?4 Q# |5 f9 m7 V* @, i
$ O' G! H5 x6 B$ \$ X2 ~0 \
然后WS2812的具体原理和代码逻辑,在前言里的那篇大佬写的博文里写的很清楚,在这里我也只是做一些小补充,然后移植到一个实例中来。
! E4 ?' R# h6 V  a# D1 a" b7 g8 C
另外,单片机给的3.3V供电不能保证电路能正常工作,灯少好像还行,但多了的话经过实测,至少要到3.5V的供电电压,这可能与具体元器件有关系,如果亮灭情况有问题的话,大家也可以从供电的角度查一查。8 Q8 h3 F( h% s; S: V! T
  o5 r2 B' d  B4 V
: @" r7 A, a( W1 j& y2 [
5 q* F4 S+ H- Z. j# a- N! H
5 j1 x* A$ Q. C6 I! R, v, V* z
赞 收藏 评论0 发布时间:2022-4-15 10:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版