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

【经验分享】分析STM32G0 SPI外设不能触发RXNE接收标志的原因

[复制链接]
STMCU小助手 发布时间:2021-11-8 17:04
今天准备移植STM32F030R8T6的程序到STM32G030C8T6上,程序中用到了硬件SPI外设,因为STM32G0用的HAL+LL库而不是不是标准库,所以我用STM32Cube MX生成了SPI的LL库代码,但是使能SPI后发现硬件怎么都不能触发RXNE接收标志,生成代码如下:5 }; \: S: i2 ^6 F
! Q5 W5 B2 A) F* [$ o6 D
  1. void MX_SPI1_Init(void)
    * n& K. r, n6 X
  2. {( u  X  G. ?! }# S* _' O
  3. 7 p; w/ A+ \/ M: K6 L& n
  4.   /* USER CODE BEGIN SPI1_Init 0 */- `$ F, W4 {9 R% J+ B) _7 j
  5. " Z. [# S+ O+ I5 }0 h
  6.   /* USER CODE END SPI1_Init 0 */
    ) w* T/ ]  C3 |. e. K0 m9 ~
  7. - p% L9 ?: {6 j7 G8 P$ l6 _$ }
  8.   LL_SPI_InitTypeDef SPI_InitStruct = {0};
    / A# \6 Q$ _5 ]
  9. 6 G3 d, Q; ]. Q. b+ V7 R
  10.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    5 @' D5 R8 u  f/ E: q" V2 U7 m

  11. 2 |/ `4 g# Y# N9 a& n  m
  12.   /* Peripheral clock enable */
    8 z% X4 [# C! ~2 B" h: A
  13.   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);2 n8 J0 }, s4 v# W' Z

  14. + Z1 u1 m) D' H: ~8 B7 K  a
  15.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);8 V' H( I7 }0 ]. s. @: T. o2 G
  16.   /**SPI1 GPIO Configuration
    ' S' u' w0 j5 ]& v# B4 R
  17.   PA5   ------> SPI1_SCK
    9 u' t$ _  V& o$ v8 H9 E/ k: u+ O
  18.   PA6   ------> SPI1_MISO2 Q$ V0 I3 f$ s, |
  19.   PA7   ------> SPI1_MOSI: p& Y, A+ ~/ c. N+ {2 X7 J' T8 @4 q% [
  20.   */' \' d3 S' Y- u' G* Q* u' L
  21.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;/ _, @, a- F2 _9 ~( [' m0 Q
  22.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;+ h9 y6 n" e7 B9 m7 X7 q7 `/ u
  23.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;8 O5 B, o, t% c
  24.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
    2 |3 R5 h' }/ K3 j
  25.   GPIO_InitStruct.Alternate = LL_GPIO_AF_0;6 J" V. j! k3 M0 D) n7 Z/ N1 {; h
  26. 8 ?+ G1 e' a8 ~; R
  27.   GPIO_InitStruct.Pin = SPI_SCK_PIN;# j8 I' J0 Z9 D5 D0 f
  28.   LL_GPIO_Init(SPI_SCK_PORT, &GPIO_InitStruct);* L0 t  v  j  _

  29. : R' D3 ?+ x7 K; }
  30.   GPIO_InitStruct.Pin = SPI_MISO_PIN;. G) l" [( u) u* \
  31.   LL_GPIO_Init(SPI_MISO_PORT, &GPIO_InitStruct);/ @' ^/ W  |% }8 y6 g5 Y6 {! T: I1 @
  32. 3 Y9 K: |0 Y' u8 n) k" ~
  33.   GPIO_InitStruct.Pin = SPI_MOSI_PIN;1 f* r. z) |/ `+ r" K
  34.   LL_GPIO_Init(SPI_MOSI_PORT, &GPIO_InitStruct);
    3 T, Q4 G- v/ v, A5 L/ _2 I
  35. + Y: B" }% \3 j8 G, [5 n# e% ~" a5 N
  36.   /* USER CODE BEGIN SPI1_Init 1 */
    ! ?- g1 X4 C9 k8 @

  37. # `! A* Q& p; n; S( Y4 C3 ~6 H
  38.   /* USER CODE END SPI1_Init 1 */
    6 r0 R8 S! B& u) I* q: q
  39.   SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
    - N: S4 ?0 R, G
  40.   SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
    ) N1 q" v6 f. d: y6 ^+ S
  41.   SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
    : ]/ R8 l6 N5 N) J+ V2 J1 z
  42.   SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;
    ( Z/ m. x( Y' q+ h2 p' ]6 d
  43.   SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
    ' o4 `1 r3 Z$ F% }3 r3 W* ?
  44.   SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
    . H9 E8 v( I0 C# V
  45.   SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;
    1 V) p) S5 m% @
  46.   SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
    + |6 d2 e2 M/ r$ L6 X; }) l+ t. N, l: T9 a
  47.   SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
    + l- Z$ v5 W( S3 f
  48.   SPI_InitStruct.CRCPoly = 7;# K1 z' i2 M+ W2 t' p
  49.   LL_SPI_Init(SPI1, &SPI_InitStruct);  f) y$ M7 P8 U$ N
  50.   LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
      y, p) v* X/ [8 L0 s
  51.   LL_SPI_DisableNSSPulseMgt(SPI1);
    % S) _- R2 D+ {9 o
  52.   /* USER CODE BEGIN SPI1_Init 2 */
    7 e. c" m" x8 A. u7 U% Y" H/ P
  53.   LL_SPI_Enable(SPI1); //用户手动使能SPI% f% a" t, y: `( c/ ~' K$ T4 k
  54.   /* USER CODE END SPI1_Init 2 */$ q7 N" r1 |7 E
  55. ' M7 o  m  H$ A: d( O
  56. }
    2 G) c' k6 e& P: ^! D
复制代码

  G' R3 i. a- S' w% U程序正常运行后,通过在线DEBUG并调出SPI外设后,查看相关寄存器,可以看出SPI能正常发送,但是因为CR2寄存器的RXNE标志一直不能被触发,导致接收不到数据,如下图所示:7 u( l6 u; l. r
2021060720475766.png

) D/ Y% r) f, o' _. P( m+ `9 O0 r
% u7 k  d9 G+ z2 }! D1 }  ~6 ~但是相同的设置在STM32F0的标准库上是可以正常运行了,模式配置都一样,但是用LL库的STM32G0上就不能运行,后来查看STM32G031K LL库的使用 - SPI这篇文章,发现代码中额外添加了以下语句:3 M9 v7 W* u! U& T! N; V- @0 ?- H

4 B$ C4 m+ A, p# k& ?$ j
  1. /* Configure the SPI2 FIFO Threshold */) c9 W4 |! @; m8 J# {2 h
  2.   LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);//设置RX非空事件产生的FIFO阈值,根据通信时最<span style="background-color: rgb(255, 255, 255);">小数据的大小设置,我这边最小为8位,所以设置为四分之一</span>
复制代码
0 z5 V. c; t8 _4 C0 K: H
通过查看STM32G0x0官方数据手册的24.6.2 SPI control register 2 (SPIx_CR2)小节,可以看到设置外设接收8位数据,RX FIFO阈值要设置为1/4,但因为Cube MX生成的代码没有设置FIFO阈值,并且LL_SPI_Init()函数也并没有直接对CR2寄存器的FRXTH位进行设置,导致了代码中虽然设置的是接收8位数据,但寄存器为默认16位的阈值,所以RXNE标志就一直不能触发,也就接收不到任何数据。0 @. s* u" o4 i4 y! z) P
# A" o" N5 U! a4 ?% N( y! |1 X
2021060721150377.png

# o) t8 s& d6 p* _
7 S3 g) d- X5 |$ o7 }- Z0 h反观用了标准库函数的STM32F0,同样的设置为什么就可以正常运行呢???通过查看标准库函数SPI_Init(),可以发现函数中对CR2进行了赋值操作,而对应值正是SPI_DataSize_8b这个宏,该宏的值为0x0700,Bit12 FRXTH=1,该值对应FRXTH接收阈值为1/4,所以程序能正常运行,RXNE可以正常触发,这也就解释了为什么同样的配置在标准库上SPI能正常运行,但是在LL库上却不能正常运行的问题所在。: L4 }! A( N7 c

7 [8 U# f3 x5 B1 I% y  a$ p" d
  1. void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)
    1 d3 R7 |# o0 [. B$ o& O
  2. {
    ) _+ ?' t; h" q$ J4 h5 Q
  3.         .......1 E* @1 I$ t$ W7 i% T0 U& b
  4.          /* Configure SPIx: Data Size */
    6 p/ i6 w6 M, @
  5.         tmpreg |= (uint16_t)(SPI_InitStruct->SPI_DataSize); //SPI发送接收的数据为8位. V$ d1 J9 H0 `( h
  6.         /* Write to SPIx CR2 */3 i' I6 B% e% B% a: `  i' g- F9 _, R
  7.         SPIx->CR2 = tmpreg;
    9 p# ^1 ^% j9 F" N- u+ Z
  8.         ......
复制代码

2 Q' _( u% l5 X' @. f: z6 a
9 g. j' Q% r. w+ T* R  d% o3 @% c* M8 ?2 Z! u4 d# D8 G: {
9 {( H% v2 C# j& c+ g' @
收藏 评论0 发布时间:2021-11-8 17:04

举报

0个回答

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版