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

【经验分享】STM32CUBEMX--SPI,TLC5947外部PWM移植

[复制链接]
STMCU小助手 发布时间:2022-4-29 23:30
概述
9 J! S' }9 R& oSPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议,比如 EEPROM,FLASH,实时时钟,AD转换器。
" f* Z1 _6 ~3 G0 L. |2 k2 [TLC5947是一款SPI接口的PWM脉宽调制24路LED驱动模块/RGB LED驱动器芯片,它能驱动24路的PWM。
9 l: X8 r% N- D
) v# m( e6 D) K2 [1 U0 A硬件准备( C) T. x3 K$ L2 N
首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:# o& V& x$ ]2 C  e  g# P

# c; \# C9 Z5 S: M9 u H0)1(DOD46`N0X`9J48V~LL.png ) A: u- Q, X9 }& R4 |3 D

4 i2 e+ k1 X8 S* e3 Q* K' W+ f
. N5 u9 c7 O8 b! k& u" \选择芯片型号
) M7 M: E: D+ ]8 a9 }& n8 \' r使用STM32CUBEMX选择芯片stm32f030r8,如下所示:5 v. ~! I! l/ D+ p  l7 i$ R  i
& D( ^* R# W. \

1 U, U! f/ E& x6 j' V
2 J' ~. B% @% C; i配置时钟源
* u$ B, a" Q  b! kHSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:  j) ]4 ~% w+ R, e; j, [# A1 F4 D! P
  e0 I& r( m' P3 c( @/ [& J
3I~E5[66G3QWMV3W``VG_LQ.png
' _* R3 G# I" A2 _2 l4 b, P1 r, X- S& k% p
配置时钟树: ~8 y* m( g+ z9 H' T4 _; Z3 e4 b
STM32F0的最高主频到48M,所以配置48即可:6 Q; {: q8 q' N# D6 b
5 h; o! U/ L  d0 {( [. @
20200604204550406.png
! U0 s1 Z: n9 r/ @3 X2 \
& g  q) O( @$ G/ sSPI配置
) Q' g# `5 e- v+ f. b本次实验使用的SPI与Flash通信,配置如下。: \* {2 S8 I8 G' {8 H
SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是MISO(主设备数据输入)、MOSI(主设备数据输出)、SCLK(时钟)、CS(片选)。, }2 Z6 y( M" s2 Z6 a) Z: y7 m2 l
(1)MISO– Master Input Slave Output,主设备数据输入,从设备数据输出;
" X' Y1 S& [3 X+ q6 `! x3 Z3 R(2)MOSI– Master Output Slave Input,主设备数据输出,从设备数据输入;
! [$ E" r: f: b7 z8 ^(3)SCLK – Serial Clock,时钟信号,由主设备产生;! M$ C# p7 f( j* r
(4)CS – Chip Select,从设备使能信号,由主设备控制。
! G$ B( s* Y7 i/ z7 h7 G" f; L1 W0 f! S! \) s
接线方式
* @& J3 G5 e, f5 j5 I
$ u  s5 c4 m5 o4 u  g 2@E`[W1X]_0VQR`N}%OL%{1.png 3 r. k, a$ v/ w9 _" p" g
' S# g# l" ]9 ]3 r
负责通讯的3根线了。通讯是通过数据交换完成的,这里先要知道SPI是串行通讯协议,也就是说数据是一位一位的传输的。这就是SCLK时钟线存在的原因,由SCLK提供时钟脉冲,SDI,SDO则基于此脉冲完成数据传输。数据输出通过 SDO线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。完成一位数据传输,输入也使用同样原理。因此,至少需要8次时钟信号的改变(上沿和下沿为一次),才能完成8位数据的传输。
4 j$ d7 K; M5 G- Y0 {1 i; e1 I7 m时钟信号线SCLK只能由主设备控制,从设备不能控制。同样,在一个基于SPI的设备中,至少有一个主设备。这样的传输方式有一个优点,在数据位的传输过程中可以暂停,也就是时钟的周期可以为不等宽,因为时钟线由主设备控制,当没有时钟跳变时,从设备不采集或传送数据。SPI还是一个数据交换协议:因为SPI的数据输入和输出线独立,所以允许同时完成数据的输入和输出。芯片集成的SPI串行同步时钟极性和相位可以通过寄存器配置,IO模拟的SPI串行同步时钟需要根据从设备支持的时钟极性和相位来通讯。! L9 O0 k* C: y$ M% w/ @/ i1 S
最后,SPI接口的一个缺点:没有指定的流控制,没有应答机制确认是否接收到数据。
1 c8 }2 W8 n3 f: D6 e( w2 x& T  ~7 E0 u' ^/ D5 [7 o% i
20210627194827850.png
1 }  }; f  f1 W! l, v' ]+ k' l* O# T- Z
其中,CS是从芯片是否被主芯片选中的控制信号,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),主芯片对此从芯片的操作才有效。这就使在同一条总线上连接多个SPI设备成为可能。6 s7 P! a5 n* i3 x$ d; \9 |
TLC5947需要配置2个CS线,分别是BLANK和LAT。$ R# j: t& r3 d1 Q9 v6 B6 {+ f
: m- D6 X& |5 V7 `3 A3 h7 o% J
20210627195354888.png
! J: D& k/ h- {* f& e4 u
; Y6 l, @2 E& ]3 z6 m生成工程设置& ^# Y( b, B' i' \2 G; ?
注意在生产工程设置中不能出现中文,不然会报错。
% `0 z6 Q! N) E# R
4 Y6 ]' D. W8 J2 q# M! V) K 20210627195732778.png " O7 N3 f8 W2 W  D! i& w8 @: v
) Z( P7 L- b# ^- _7 U) Z$ u: K1 |, j7 k
生成代码; j* u% N6 E( p$ l

! [2 n' q3 e! i& b' O" D
20200604205807980.png
( ^4 \0 d/ T: N+ g: o$ m
4 I1 j" F9 y) i' @% t" ~& p配置keil
$ t  ~5 }/ q$ x
* E4 d9 ^/ W/ ~: }5 S( |
20200604210002645.png
) F( e' ]- j  e$ q: F  ?
; Z8 c. [, X" n! z' c0 jTLC5947的原理及应用
' X$ t, `- F7 x, R! iBLANK:所有恒流输出关闭。当blank 接高时,所有恒流输出(输出0通过out23)强制关闭,脉宽调制PWM定时控制器初始化,灰度计数器重置为0。当blank接低时,所有恒流输出由灰度脉宽调制定时控制器控制。. X- R6 g# u6 @, z. Y2 |
GND:负极5 }6 A8 B/ C& ]1 @: {
IREF:设置恒定电流值,设置T0到T23引脚输出的电流值。通过在IREF和GND之间连接一个外部电阻所需要的值。
, T; m" [( \2 F4 `' _SCLK:串行数据移位时钟。- F3 c( Q, Y5 P* B' s
SIN:灰度数据的串行输入。
; e% X0 f3 M+ \. n$ O. l1 ZSOUT:串行数据输出。: M, v; l' w4 g
VCC:供电6 P" X: x# f& T3 V! J# Q# b
XLAT:灰度数据转换。灰度移位寄存器中的数据以从低到高的方式移动到灰度数据锁存器,在XLAT引脚上转换。当XLAT.上升沿被输入时,所有恒流输出被强制关闭,直到下一个灰度显示周期。灰度计数器不会随着XLAT边沿的上升而重置为0。% \. q5 E7 X0 e: h. r) w

, K7 F- l# T/ u& i" K8 O3 ^( s( f: m4 C PM0GL23A`ZBPAB37N2)Z7QH.png + W; e2 x: \$ Y. ?! S2 ?

0 J$ Q# b7 i: j$ G- v由于芯片为开漏输出,故接线如下所示。
. q0 ]0 O# C: o  S  E4 D! s" w( D0 n2 ]! U- D
20210627201319812.png - K) k( E, T* Y* W

3 Q, s9 X5 [4 V. \时序图如下所示。
0 K& \. Z1 `7 t5 S: \& G3 L
! S  P' w# ]7 c 20210627201552404.png & k) Y% {% {/ U! b. j

6 R. f8 W1 o4 i7 x! [代码. Q. ?* y% e4 \1 W
本例程向通道0中写入呼吸灯程序通道1输出12.5%,通道2输出25%,通道3-通道22输出50%,通道23输出75%,例程代码如下。  y/ [; n& E) z
变量定义。
  1. /* USER CODE BEGIN PV */
    : O0 }1 f; @% v1 k
  2. uint16_t leds[24]=
    0 ]5 _; P% g; v
  3. {$ Z; K, f; K; H% U% D
  4. 512,512,1024,2048,2048,2048,
    5 [1 k/ i. P+ F4 Z& y( b
  5. 2048,2048,2048,2048,2048,2048,1 j3 t4 v4 {1 q6 \. N6 F( d8 Q
  6. 2048,2048,2048,2048,2048,2048,
    5 d: R5 X8 x  {$ c; e
  7. 2048,2048,3000,2048,2048,3072& B; A2 G  `# ^$ w' @
  8. };
    " p4 [! A) W, Z6 O2 T6 c2 G
  9. void TLC_Update(void);9 F  N2 ?+ `8 r. G7 X0 l% `0 ]- F) l
  10. void TLC_Write(uint8_t data);
    3 w8 q& y' W9 x. u& [
  11. int i=0;; G; `  b) z- @, y
  12. int flag=0;
      |  T3 ^/ R3 t9 g0 A9 W0 |- t
  13. /* USER CODE END PV */
复制代码
7 i% }" {2 E0 Q4 p0 h/ f
SPI发送函数定义。8 J8 B1 V& \: ^7 k+ [- J
7 D+ o" R1 N/ Y  _5 k- [
  1. /* USER CODE BEGIN 4 */, J  A( u$ e/ I, D
  2. void TLC_Update(void)
    ! r6 Z( g* {8 Y- R
  3. {      
    - s9 z; S. z: m8 v; e3 x# \
  4.     HAL_GPIO_WritePin(BLANK_GPIO_Port, BLANK_Pin, GPIO_PIN_SET);6 }+ W: F+ v6 N: h
  5. //                HAL_Delay(1);        
    0 u/ ~* K: `: r
  6.     for (int8_t i = 23; i >= 0; i -= 2)" F0 \5 ^( t4 P. u* W: C5 w1 w. r
  7.     {( j1 X' m7 O% O/ e
  8.         uint8_t send1 = 0;
    * j) S$ _* Y: X. j; u
  9.         uint8_t send = leds<i> >> 4;
    , u: w4 H# |1 N2 f+ x# q
  10.         TLC_Write(send);
    ( O4 g( }2 t3 z; ^* k. K& r0 X. s; X
  11.         send = (leds<i> & 0x000F);( L3 X+ E3 Y* z- l2 u& ?
  12.         send <<= 4;: A( d8 s6 U$ y: Q/ |7 m
  13.         send1 = (leds[i-1]) >> 8;   
    ! r" T9 n) e- `
  14.         send |= send1;7 W) j& G8 m. r" G$ D( e
  15.         TLC_Write(send);; z2 e# a* o* p2 X- Y
  16.         send = leds[i-1];
    ! Z6 |/ N) ^$ V8 i
  17.         TLC_Write(send);
    2 i& y7 _9 L1 Y& o+ \6 ~5 K
  18.     }    # K) ^* e" f6 R/ W3 L3 ]+ U8 \2 x* Z
  19. 7 q$ r+ g2 k5 f3 o( C$ n
  20.     HAL_GPIO_WritePin(XLAT_GPIO_Port, XLAT_Pin, GPIO_PIN_SET);$ c2 D3 N3 m1 R6 X
  21. //                HAL_Delay(1);        
    9 L9 G2 j# P4 Q+ f
  22.     HAL_GPIO_WritePin(XLAT_GPIO_Port, XLAT_Pin, GPIO_PIN_RESET);) f3 k- a2 T" |6 h2 u% o7 L
  23. //                HAL_Delay(1);        
    % H% s3 p- }6 U
  24.     HAL_GPIO_WritePin(BLANK_GPIO_Port, BLANK_Pin, GPIO_PIN_RESET);5 D  `: i4 b% I0 _# o. U

  25. & D8 S4 A0 y. ^0 X: i9 o' E: D
  26.     return ;
    $ a" c  u; W. j6 Q4 H
  27. }6 v7 p. \+ v4 _" O# o; B# v! |- ^

  28. ( f3 U- \& N$ u* k2 F( N# P

  29. , o: ~0 U. E+ s" B; u" J/ q3 \  Q
  30. void TLC_Write(uint8_t data), F8 |$ u  m# M  E/ B: w
  31. {
    1 `) ^8 U4 ^) c# K$ o. O, Z
  32.     HAL_SPI_Transmit(&hspi1, &data, sizeof(data), 0);1 R! Z$ K- J% @
  33.     while(HAL_SPI_GetState(&hspi1) == HAL_SPI_STATE_RESET);% m* I; \2 B/ c% F. ?6 `8 q& [
  34. . T( ~4 w, p: I- ~5 }+ O9 ~. `. x9 H
  35.     return ;
    " N% m3 h5 C$ n! J9 D2 z4 G7 L+ i
  36. }5 Q) h% v  u% K+ @- a, m1 e
  37. /* USER CODE END 4 */</i></i>
复制代码
1 X  \/ x* ~# Z. _! l# J: Y1 n$ O
主程序。
  1.   /* USER CODE BEGIN WHILE */
    / j  p  [9 v: u
  2.   while (1)5 f7 _1 p! N- y- U: K  k
  3.   {8 f* `1 M6 D3 Q
  4.     /* USER CODE END WHILE */
    " |; F  s' O  A$ k

  5. 7 [( N0 G, E: Y: j  e
  6.     /* USER CODE BEGIN 3 */0 O% e$ ^. S' s4 k- Z
  7.                 if(flag==0)//灯渐亮
    . d" U5 j1 A& B; T- D" Y7 g
  8.                                 i+=5;
    8 q- W# s  |! ?+ N& }
  9.                 else//灯渐灭
      k1 A$ F" h: L
  10.                                 i-=5;: R% u; f; V9 e, ~1 E  l
  11.                 0 w& N, n0 a. z6 e8 Y# C; I
  12.                 if(flag==0&&i==4095)//灯最亮
    : `% m' Z, ^3 g# @, m! ~! v
  13.                 {5 d5 n% X4 l& N. o2 v9 i% X# A
  14.                         HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
    ! ^' Q# O+ X. X: ?9 c( C" Z2 j: g+ K
  15.                         flag=1;
    ' R8 p9 x1 K+ e6 o: x- }
  16.                 }
    5 c. ]+ [' c4 ?/ F7 r
  17.                 if(flag==1&&i==0)//灯最暗4 z2 K. O8 I' n9 a/ z3 n
  18.                 {  g! D) k. j8 N  {+ R2 v
  19.                         HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
    ( X- \8 j/ e: Z8 A+ K
  20.                         flag=0;' Q5 e: |' B  x
  21.                 }                        8 D. Q$ H0 @/ n. W
  22.                 leds[0]=i;//更新通道0的PWM
    9 v+ ?6 l6 H  R$ [; i" m" o
  23.                 TLC_Update();//更新PWM9 l0 b( o5 Y6 Z, t3 [& K' x7 ?( i  i* r/ I
  24.                 HAL_Delay(1);                ; L$ h: f9 w# a
  25.   }$ X* y: \4 p; ?- j+ n
  26.   /* USER CODE END 3 */
    ! f+ ?  r7 u: j' k
  27.         " G, W, y, k) _+ ^' [
  28.         
    . d# Z. A4 p% a9 Q& P
  29. }7 u! E) }- g( L! a9 R  I
复制代码
% T; }, M5 F/ P! z+ j- |! I
: W( r# U, A# w  v8 q2 K
赞 收藏 评论0 发布时间:2022-4-29 23:30

举报

0个回答

所属标签

相似技术帖

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