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

【经验分享】STM32的SPI外设片选只有一个怎么破?

[复制链接]
STMCU小助手 发布时间:2022-6-23 21:00

之前用STM32的SPI需要控制很多外部芯片,可是一个SPI的外设只有一个片选,要实现独立片选一主多从,怎么实现呢?

+ j+ s# ^: F# d& b/ D: F

SPI总线拓扑

一般地,SPI总线按照下图方式进行连接,一主多从。


0 B# u% T1 G! P* ?3 r2 b  W& u& u/ l
D20@Z{HTNK{J0FJJ1[EQZ26.png

* a# ~* j3 {( J- ?* i

如上图:

  • 每个从设备都有独立的片选引脚,主机同一时间段内,与一个从设备进行通信,也即选中一个从设备。
  • MOSI/MISO/SCLK并联在一起
  • MISO须是三态门,当从设备未选中时,该脚须设置为高阻态,而不能是输出态,否则会影响总线!
  • 对于MOSI/SCLK,虽然并联在一起,但是由于仅一个输出,多输入。
    * F0 w3 m1 u, N6 J8 n+ J* |  M

    5 V! h# ~0 Z6 `! A9 x7 q

但是你看STM32的SPI外设,一个SPI仅有一个NSS信号,以STM32F407的SPI2为例:


/ U: Y) {% W! G" M, a2 k8 p% f

那么要实现前面说的一主多从,怎么办呢?有朋友说,直接用GPIO去模拟不就可以了。

不错,SPI总线要用GPIO模拟还是很容易的,但是这样做波特率做不高,需要占用CPU时间,效率比较低!而用SPI外设控制器,底层bit流的收发由外设控制器实现,用GPIO模拟则需要CPU参与。


, |) q& z; N$ _) @7 U

怎么破呢?菊花链拓扑) {* N* T  d, V' a) f
: ?) P# S$ |) g+ G4 Q, Q: n
# S; W9 N) L5 G+ ?1 |& L+ X, y
]$)3V2VSM`}FB4IQGA%D@UH.png
; L, Y' V+ t1 X' k" l5 i9 A
3 Z' s0 G. c& n

这种方案,省引脚。但是要移位控制,相对独立片选效率还是低不少。

1 P9 W. |* v% a4 F1 N2 r

独立片选拓扑

SPI外设的MOSI、MISO、SCK还是照用不误,但是片选我们不用,设置成通用输出模式,再用其他的GPIO片选从芯片即可。

上代码看看:

  1. <font face="Tahoma"><font size="3">void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
    % l! \0 T7 h$ J1 D
  2. {7 G+ y4 P5 g" N# I  Q4 f
  3.   GPIO_InitTypeDef GPIO_InitStruct = {<font color="rgb(184, 215, 163)">0</font>};. e! j, {2 @$ N3 k8 z
  4.   <font color="rgb(86, 156, 214)">if</font>(hspi->Instance==SPI1)! ^) P- d0 s6 a. n" x
  5.   {
    0 U6 G5 _+ h( W8 b4 ?2 v$ w
  6.     __HAL_RCC_SPI1_CLK_ENABLE();
      x* y1 n5 V# ^- U% g' b/ ^
  7.     __HAL_RCC_GPIOA_CLK_ENABLE();
    ; k/ C+ h! ^! t% W: I
  8.     <font color="rgb(87, 166, 74)"><i>/**SPI1 GPIO Configuration
    . q' x  ~9 Y8 M$ J4 J* |
  9.     PA5     ------> SPI1_SCK
    2 j1 j) x) E+ c5 ]/ I
  10.     PA6     ------> SPI1_MISO' D; F( n4 a/ r. ]/ s1 J) Y& V
  11.     PA7     ------> SPI1_MOSI
    - G+ C9 @; t, ]1 ^
  12.     PA15     ------> SPI1_NSS 但是这里不用% f# H$ @1 c6 y$ i
  13.     */</i></font>. m* m3 T$ t1 M
  14.     GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
    6 w6 J3 J% ]( a2 {
  15.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;6 E7 j$ ?- l$ m2 |% d  c5 m* z5 Q
  16.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    2 `4 t' b. B) S# r
  17.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    % L/ v0 }  e8 k" h& D$ R/ y& I
  18.     GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;2 d. ]7 F* q* S5 Q( S
  19.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    ' O: O, _) O! y! K, J9 i' U5 y

  20. 9 U0 \9 F  R4 X! w  O+ L2 q
  21.    /*__HAL_RCC_GPIOC_CLK_ENABLE();
    . D3 Q/ L! f7 @( x" G
  22.     GPIO_InitStruct.Pin = GPIO_PIN_1;
    5 B0 _, d! w/ g) i( C* h
  23.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
      p/ [3 y, s- l; l8 S
  24.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    / m0 |) b% T4 S: u# j
  25.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;3 b+ L) c! s6 n% q
  26.     GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;# }& ?3 [% m2 _) [
  27.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);*/ 8 r3 D/ p7 @. c& z
  28.   }* S, l8 Y; L; T' A, {, {% Z8 O
  29. }
    % y5 n7 ]7 ?- o) i/ s, n0 W" `
  30. </font></font><p style="line-height: 26px;"><font color="black"><font face="Tahoma"><font size="3">初始化SPI外设</font></font></font></p><font face="Tahoma"><font size="3"><font color="rgb(155, 155, 155)">#define SPI_CS1                        GPIO_PIN_1</font>
    , K; U& R2 _; a; Y
  31. <font color="rgb(155, 155, 155)">#define SPI_CS1_PORT                   GPIOC</font>
    ' d0 @" D, S9 h: w
  32. <font color="rgb(155, 155, 155)">#define SPI_CS2                        GPIO_PIN_2</font>; ~9 _4 U1 o) @& p. P( k$ `
  33. <font color="rgb(155, 155, 155)">#define SPI_CS2_PORT                   GPIOC</font>
      e" D# P: s4 b+ b& M% T3 v- t4 T
  34. <font color="rgb(155, 155, 155)">#define SPI_CS3                        GPIO_PIN_3</font>( g" _; X+ P8 W% B5 J4 @
  35. <font color="rgb(155, 155, 155)">#define SPI_CS3_PORT                   GPIOC</font>* f( c3 Z! G- y' t+ v0 [7 }; u( n
  36. static void init_spi(SPI_HandleTypeDef * spi_handle)0 R2 ]; n1 b$ U( l4 S
  37. {2 L, r1 D! {9 l; L7 A
  38.   <font color="rgb(87, 166, 74)"><i>/* SPI1 parameter configuration*/</i></font>
    # y% Z% o6 u8 w+ |- Q2 R- M
  39.   spi_handle->Instance = SPI1;: E' i1 c! }2 _
  40.   spi_handle->Init.Mode = SPI_MODE_MASTER;
    & P2 D- x2 v5 F- h: q' I
  41.   spi_handle->Init.Direction = SPI_DIRECTION_2LINES;
    / j8 N% @* S. h2 w3 y8 P! p
  42.   spi_handle->Init.DataSize = SPI_DATASIZE_8BIT;
    2 s; }. f5 J- D8 _  ?
  43.   spi_handle->Init.CLKPolarity = SPI_POLARITY_LOW;
    & }% B: @3 _) k' U
  44.   spi_handle->Init.CLKPhase = SPI_PHASE_1EDGE;) M6 n3 [; j! V: [6 B/ a$ A1 k
  45.   spi_handle->Init.NSS = SPI_NSS_HARD_OUTPUT;( N7 A- G* Q4 \9 j4 L: }) w* t; g
  46.   spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
    8 k. t8 v, P" J
  47.   spi_handle->Init.FirstBit = SPI_FIRSTBIT_MSB;
    ; g* B, v0 Q4 b/ \( s
  48.   spi_handle->Init.TIMode = SPI_TIMODE_DISABLE;+ h! B& f' X- |2 q* b
  49.   spi_handle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    % U5 T+ s* Z% M5 m) x) x
  50.   spi_handle->Init.CRCPolynomial = <font color="rgb(184, 215, 163)">10</font>;
    : u5 Q: i# V0 v  V7 H# Z, s; ~) m
  51.   ASSERT (HAL_SPI_Init(spi_handle) != HAL_OK);. M) c* s: A$ N# c. i; R

  52. ) [! e: r. Y1 [
  53. GPIO_InitTypeDef  GPIO_InitStructure;
    # E! a$ h% h+ H* x9 {6 S

  54.   `% q3 |; z: p
  55. __HAL_RCC_GPIOC_CLK_ENABLE();- O8 I& J' _1 g) m

  56. 7 N8 ~/ k1 I. z* C3 t6 _. c
  57. GPIO_InitStructure.Pin = SPI_CS1;# P  U1 p' P4 c% u$ v' L
  58. GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    ! e9 g* P6 g" I2 o
  59. GPIO_InitStructure.Pull = GPIO_NOPULL;" B; V+ q* Z  X3 e" [5 y( ~
  60. GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_MEDIUM;: i; C) n- y! ^
  61. HAL_GPIO_Init(SPI_CS1_PORT, &GPIO_InitStructure); . ?# e- S9 M6 W' \) Z: V
  62.   ; T" _3 N$ j7 k0 Y
  63. GPIO_InitStructure.Pin = SPI_CS2;# T6 N1 W& Q" m6 P: y
  64. HAL_GPIO_Init(SPI_CS2_PORT, &GPIO_InitStructure);  
    ! I! q, s/ l0 t8 F) X( ]$ m5 T2 D

  65. ! ]# O8 h1 i( K5 W( Q% I& ]
  66. GPIO_InitStructure.Pin = SPI_CS3;
    # f! i0 ]5 O) D- j. a
  67. HAL_GPIO_Init(SPI_CS3_PORT, &GPIO_InitStructure);   ' a1 d% E- `( `: a( }( K) q1 G
  68. }4 ~% v' i$ w) {2 G& w
  69. </font></font><p style="line-height: 26px;"><font color="black"><font face="Tahoma"><font size="3">从而原来SPI的收发函数前后加上片选信号即可:</font></font></font></p><font face="Tahoma"><font size="3"><font color="rgb(86, 156, 214)">typedef</font> <font color="rgb(86, 156, 214)">enum</font> - C# n* S& U! E/ p& x7 K5 b3 {* z3 H
  70. {  
    & R' D9 z6 d( F4 s) e
  71. SPI_CH_1=<font color="rgb(184, 215, 163)">0</font>,
    & s2 G( n" z/ q& j2 {8 C
  72. SPI_CH_2,+ k% }2 F7 A' d! m
  73. SPI_CH_3,
    : t( y( S2 y% M! o
  74. SPI_CH_LAST,$ O; p9 j% {% s$ d$ Z% G# W; b0 E  s
  75. } SPI_CH;
    ! F/ s: K) @0 z( |. p
  76. static HAL_StatusTypeDef SPI_Select(SPI_CH ch)$ t3 u2 e$ Z; X; r1 Y$ x$ H
  77. {# g: V$ V5 m9 n9 W  J6 R
  78.    <font color="rgb(86, 156, 214)">switch</font> (ch)
    : j0 n6 i/ O0 J* v* \5 `; I
  79.    {
    % d9 Q4 s# a4 A
  80.      <font color="rgb(86, 156, 214)">case</font> SPI_CH_1:; A' j% f; V7 h. R
  81.        HAL_GPIO_WritePin(SPI_CS1_PORT,SPI_CS1,GPIO_PIN_RESET);! F& _7 N& U5 P7 j. J
  82.        <font color="rgb(86, 156, 214)">break</font>;
    ! o! a9 k: o+ Q  u  g8 Q
  83.        1 m) L5 n+ c' i
  84.      <font color="rgb(86, 156, 214)">case</font> SPI_CH_2:
    + l/ k/ a: r' |+ p/ Z- p; c- E
  85.        HAL_GPIO_WritePin(SPI_CS2_PORT,SPI_CS2,GPIO_PIN_RESET);; z, `8 ?6 ^! v
  86.        <font color="rgb(86, 156, 214)">break</font>;
    - D) V2 e' B. U2 y) @4 l
  87.       
    - [- Z. c& c1 W. ^# g. {; N" s! r
  88.      <font color="rgb(86, 156, 214)">case</font> SPI_CH_3:
    & a. W6 ?8 J7 v# Y
  89.        HAL_GPIO_WritePin(SPI_CS3_PORT,SPI_CS3,GPIO_PIN_RESET);
    - U8 z# ^! x2 {+ e1 @( ~6 ?
  90.        <font color="rgb(86, 156, 214)">break</font>;       5 J0 p. n) m9 g0 O5 p  u! {3 C5 g
  91.      + g2 B/ n: e, b
  92.      <font color="rgb(86, 156, 214)">default</font>:0 N- E. b  _6 a5 [3 d' e
  93.        <font color="rgb(86, 156, 214)">return</font> HAL_ERROR;! X6 ^+ ?( d; F9 E% |
  94.    }  6 `. g3 }/ W# `8 R% I* w
  95.    <font color="rgb(86, 156, 214)">return</font> HAL_OK;
    , p7 S" Q# V4 y0 F- K7 C3 {' R
  96. }
    6 w9 O* J7 H7 O- f
  97. static HAL_StatusTypeDef SPI_DeSelect(SPI_CH ch)* @- H, x/ X+ z. f2 H
  98. {
    - i0 ?3 v* V. C$ s
  99.    <font color="rgb(86, 156, 214)">switch</font> (ch)
    6 _6 u4 B! ]5 W' T9 P
  100.    {6 H& }+ Y' ~( f
  101.      <font color="rgb(86, 156, 214)">case</font> SPI_CH_1:
    1 w/ w- `! s& H2 R
  102.        HAL_GPIO_WritePin(SPI_CS1_PORT,SPI_CS1,GPIO_PIN_SET);7 V1 \8 U( N$ E( F, M( s
  103.        <font color="rgb(86, 156, 214)">break</font>;# z7 F" t" ~5 \. A- C; |# }
  104.          d7 ?. t+ ~5 k; ]6 d( v
  105.      <font color="rgb(86, 156, 214)">case</font> SPI_CH_2:
    2 W9 K; _" R1 U# @% Q+ I! o" \! O
  106.        HAL_GPIO_WritePin(SPI_CS2_PORT,SPI_CS2,GPIO_PIN_SET);
    1 _$ ?+ W1 \& v7 b' M
  107.        <font color="rgb(86, 156, 214)">break</font>;
    3 i% b* [; ^7 U1 l& u
  108.        ! h& c/ b  @+ ~% J, [& o
  109.      <font color="rgb(86, 156, 214)">case</font> SPI_CH_3:
    8 ~. c2 h$ i+ H8 s' {
  110.        HAL_GPIO_WritePin(SPI_CS3_PORT,SPI_CS3,GPIO_PIN_SET);
    & L* L% n* g- g$ ~( g3 N
  111.        <font color="rgb(86, 156, 214)">break</font>;      
    4 i* X. E0 ^; p0 H! e) `4 w
  112.      9 L8 y% d& Q4 q' [+ `$ L& i( x6 \
  113.      <font color="rgb(86, 156, 214)">default</font>:
      b' c, ]! _- q  x- p; M( ^) D
  114.        <font color="rgb(86, 156, 214)">return</font> HAL_ERROR;) e; D6 Y8 }4 `  m. b" [
  115.    }
    0 X: o; J3 e' W: w# Q9 g
  116.    <font color="rgb(86, 156, 214)">return</font> HAL_OK;
    - d" w! {& L6 L( M( L$ V' ~
  117. }. ^" S9 y0 u, U6 |. S
  118. 6 k7 q1 U# s. g- T5 J% o7 C
  119. HAL_StatusTypeDef SPI_TransmitReceive(SPI_CH ch,; i$ U" g  n, e; R# W
  120.                     SPI_HandleTypeDef *hspi,
    & S( r+ `; }; n" ]# G' a
  121.                     uint8_t *pTxData, 9 Q8 {5 C8 G1 k" [" s" ~; g$ G
  122.                     uint8_t *pRxData, 7 a4 _  @7 C* D/ n3 s# G- m
  123.                     uint16_t Size,
    ; r' Y$ ^/ j  {4 }
  124.                     uint32_t Timeout)
    , F+ i- V. G% j. ?2 o
  125. {# d( X+ B# q2 e3 h; Q6 Y' f
  126.    HAL_StatusTypeDef ret;
    . V  {- e3 K  ^. [4 ?+ L. Q* R
  127.    <font color="rgb(86, 156, 214)">if</font>(ch>=SPI_CH_LAST)
    * j6 s; f, x( c( _+ T$ m& b0 O
  128.      <font color="rgb(86, 156, 214)">return</font> HAL_ERROR;  
    , H' }9 h9 P* U. E" }# w1 W) w1 Z6 k- C8 g
  129.    
    $ W: ?. i& s( d" m, z6 x( w  A2 y3 Z
  130.    SPI_Select(ch);+ N, d3 v" F0 B+ N9 `6 f
  131.    ret = HAL_SPI_TransmitReceive(hspi,pTxData,pRxData,Size,Timeout);
    7 h  \5 I4 t4 t, ~8 \
  132.    SPI_DeSelect(ch);
    # A0 Z9 y- n: U' ?
  133.    
    5 r9 L8 n! w+ U2 v# K2 q
  134.    <font color="rgb(86, 156, 214)">return</font> ret;0 }4 s; ?1 w5 w* L# G" e
  135. }8 {' g8 t/ K# l! H

  136. 1 w) Y" H  S; \3 U' N" Q, P
  137. HAL_StatusTypeDef SPI_Transmit(SPI_CH ch,
    / b% R4 X% N$ J/ J" Q  M/ S* o
  138.                  SPI_HandleTypeDef *hspi, ) _! ~( h* u) |
  139.                  uint8_t *pData, , U. r3 a  z; O7 ^( D$ M! p# D
  140.                  uint16_t Size, 6 i) {& }# {4 S- P& o. F- m; O
  141.                  uint32_t Timeout)" d0 t8 U) s. U8 H+ Z0 l! Q3 ]
  142. {
    * o$ L9 U% ~5 Q# [
  143.    HAL_StatusTypeDef ret; / {  b( C7 I7 ~, n2 o
  144.    <font color="rgb(86, 156, 214)">if</font>(ch>=SPI_CH_LAST)
    , x7 M5 T# X+ d; ^6 T
  145.      <font color="rgb(86, 156, 214)">return</font> HAL_ERROR;  
    # f8 M$ q  f& a# z6 Z! `! g
  146.     8 e/ n5 p: n) w8 r  f" ]' W5 r
  147.    SPI_Select(ch);
    7 E1 X' M$ t6 X6 K* U) s8 O# z5 e
  148.    ret = HAL_SPI_Transmit(hspi,pData,Size,Timeout);5 }( M0 l. x, M
  149.    SPI_DeSelect(ch);
    ( x, s: b9 N5 }! q" k1 ]" c& c
  150.    $ B3 G5 b0 B( ~; F
  151.    <font color="rgb(86, 156, 214)">return</font> ret;  
    ! l- m, I) E- Y- ]5 K
  152. }</font></font>
复制代码

& x7 d5 m4 ^+ H6 B( `

如此一来,一个SPI外设就可以控制多个从芯片了。你如果有兴趣,不妨照这个思路试试看

  f9 k& t6 y1 }  f. Q7 Y. h
8 j) H* B$ S* F( D' f; [6 b
赞 收藏 评论0 发布时间:2022-6-23 21:00

举报

0个回答

所属标签

相似技术帖

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