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

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

[复制链接]
STMCU小助手 发布时间:2021-11-8 17:04
今天准备移植STM32F030R8T6的程序到STM32G030C8T6上,程序中用到了硬件SPI外设,因为STM32G0用的HAL+LL库而不是不是标准库,所以我用STM32Cube MX生成了SPI的LL库代码,但是使能SPI后发现硬件怎么都不能触发RXNE接收标志,生成代码如下:5 o; U* d6 p" }; a" q( E

- P2 |& I- d  \( U( z5 f
  1. void MX_SPI1_Init(void), {) C& s9 \  ]' x
  2. {
    6 r. _2 k0 h, J4 n4 Y

  3. * ~  O3 Y  W4 o7 ~7 E; ^. K9 f  z
  4.   /* USER CODE BEGIN SPI1_Init 0 */, Y: ]6 K9 Z: v" J: P, T

  5. ( Z1 s7 Z: n6 @0 T
  6.   /* USER CODE END SPI1_Init 0 */
    1 @/ H3 ^# c% x% J# ^- e

  7. 7 S9 H- N( D% a5 l1 y
  8.   LL_SPI_InitTypeDef SPI_InitStruct = {0};" R: R: B* H' }# d
  9. * Y( _; A. p1 |" U  C  P
  10.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};0 Z0 ?. a* }7 n; I8 M

  11. * R/ o& [* E5 @( E
  12.   /* Peripheral clock enable */+ z4 l5 t6 W% o0 V
  13.   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);" V! C, r7 Z) {- v1 l/ R+ z8 T! @
  14. 5 t. p' A' ]7 y! d* H9 A% f
  15.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);1 u1 U! k: D$ ]
  16.   /**SPI1 GPIO Configuration0 ^2 A# h' R9 |. B1 y) K# c1 O6 ?  C
  17.   PA5   ------> SPI1_SCK
    " Q5 Y+ M* J1 ?! V, b
  18.   PA6   ------> SPI1_MISO% p& f# Y) v7 Q, `! Z8 H  X: f6 |
  19.   PA7   ------> SPI1_MOSI# G# L  E/ [3 j; }$ w# ^+ I# ?
  20.   */  y, v7 y- w, F
  21.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;1 _$ q/ `2 Q0 X7 e7 n
  22.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
    1 j! _3 e6 J, V2 N: p
  23.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;2 r$ h7 @6 x) x4 Q' p6 I- b( d) k
  24.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
    4 A  J3 ?# m3 b4 ~$ [
  25.   GPIO_InitStruct.Alternate = LL_GPIO_AF_0;8 M1 I. r% }6 \1 S4 A8 o
  26. & r+ V, M  h( x! ~* H" y
  27.   GPIO_InitStruct.Pin = SPI_SCK_PIN;
    ) w6 X- [, X7 Z3 m  g& Z+ |
  28.   LL_GPIO_Init(SPI_SCK_PORT, &GPIO_InitStruct);
    ) E/ T1 ~3 @. ^. X" t- I
  29. 0 W5 B4 a: Q0 l' |1 b- R; k
  30.   GPIO_InitStruct.Pin = SPI_MISO_PIN;
    % W% E$ |& N2 v8 c$ u- D
  31.   LL_GPIO_Init(SPI_MISO_PORT, &GPIO_InitStruct);- T, b: i7 ?# C: V5 B7 U( J
  32. 4 }$ _6 T: S& s4 a# \9 K
  33.   GPIO_InitStruct.Pin = SPI_MOSI_PIN;
    ) R! j9 g/ m8 p1 q# Y
  34.   LL_GPIO_Init(SPI_MOSI_PORT, &GPIO_InitStruct);. S7 Z+ O/ l. W. }" }5 x) R5 `
  35. ( u8 l! C& P3 Z) h) \. u
  36.   /* USER CODE BEGIN SPI1_Init 1 */$ s; s0 F. w2 b  |# _! Q1 D
  37. : S! D6 I2 D' b! t/ ?
  38.   /* USER CODE END SPI1_Init 1 */+ `& S0 z. f9 m! n9 V5 w7 T$ j& G
  39.   SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
    3 b) N4 |/ T" F8 N# d
  40.   SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;) V/ ]6 j# @; J7 E
  41.   SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
    5 w) D% x) i7 Q% \- R- y  H7 S: i- ~
  42.   SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;
    ' o( Z. V/ Q# M; l2 m
  43.   SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;. u" {( ^! Z- t9 k. f4 W$ h* K
  44.   SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;7 E+ R8 s4 U3 ^5 f
  45.   SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;
    % n/ b0 Y) g* d& `$ ]3 Z
  46.   SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
    * B' a0 a5 b% @- B% v$ `
  47.   SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;3 |6 x# N8 G! B* @
  48.   SPI_InitStruct.CRCPoly = 7;
    * ~) _) ^, A, x0 I0 E1 r& I0 {( |  |
  49.   LL_SPI_Init(SPI1, &SPI_InitStruct);
    ( b( {9 F1 s6 A" U
  50.   LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
    7 K! r4 C" W1 T1 C7 d% h7 q
  51.   LL_SPI_DisableNSSPulseMgt(SPI1);
    ! R* x# D9 H9 }1 N$ C
  52.   /* USER CODE BEGIN SPI1_Init 2 */* A( S4 q  m$ }" @( v' P6 {( c8 g
  53.   LL_SPI_Enable(SPI1); //用户手动使能SPI$ W: a( w1 p0 Q1 D& Q
  54.   /* USER CODE END SPI1_Init 2 */: p2 j! L- p+ V
  55. 0 c8 \) F  w1 _: Z0 n
  56. }3 N" |% R2 R& `) n$ m+ X% `
复制代码
' F" M1 F9 D9 {5 J' R! \2 Z
程序正常运行后,通过在线DEBUG并调出SPI外设后,查看相关寄存器,可以看出SPI能正常发送,但是因为CR2寄存器的RXNE标志一直不能被触发,导致接收不到数据,如下图所示:: V4 _( i2 }0 x: G. o1 Q& w; {
2021060720475766.png

2 ?2 O, k( p8 c5 v  z. N  C9 Z) D* i" S! _" z. O; K2 [
但是相同的设置在STM32F0的标准库上是可以正常运行了,模式配置都一样,但是用LL库的STM32G0上就不能运行,后来查看STM32G031K LL库的使用 - SPI这篇文章,发现代码中额外添加了以下语句:
% b9 `  E7 r/ w. L1 ^0 w% I6 N; }8 \! J- b
  1. /* Configure the SPI2 FIFO Threshold */
    ! _# c, r: X- H! Y' c, j
  2.   LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);//设置RX非空事件产生的FIFO阈值,根据通信时最<span style="background-color: rgb(255, 255, 255);">小数据的大小设置,我这边最小为8位,所以设置为四分之一</span>
复制代码

5 H+ S6 [9 a5 y通过查看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标志就一直不能触发,也就接收不到任何数据。
, y) ~2 q" S! W' c
3 B% Q' T+ x2 l: W) P# i
2021060721150377.png

# o" J, b) {+ u6 e2 {' H" K. k
0 I2 ^( \& _$ b" `反观用了标准库函数的STM32F0,同样的设置为什么就可以正常运行呢???通过查看标准库函数SPI_Init(),可以发现函数中对CR2进行了赋值操作,而对应值正是SPI_DataSize_8b这个宏,该宏的值为0x0700,Bit12 FRXTH=1,该值对应FRXTH接收阈值为1/4,所以程序能正常运行,RXNE可以正常触发,这也就解释了为什么同样的配置在标准库上SPI能正常运行,但是在LL库上却不能正常运行的问题所在。+ O& \, C& {+ d' v% c
. }. _* T& ]" J' V) Y
  1. void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)
    8 O8 C$ T+ \0 N1 v: I# _
  2. {" a* b6 [, t- h) z/ K
  3.         .......
    , r8 x0 L# |9 E
  4.          /* Configure SPIx: Data Size */
    7 r: j- p0 h* H6 W* `2 O& y- Q
  5.         tmpreg |= (uint16_t)(SPI_InitStruct->SPI_DataSize); //SPI发送接收的数据为8位
    ' G! ?) @' l2 L
  6.         /* Write to SPIx CR2 */
      ?) w. ~8 A6 e  l6 k. p
  7.         SPIx->CR2 = tmpreg;
    + p# I& u9 H; R& J$ A
  8.         ......
复制代码
# m0 ]/ L& E5 |9 Z5 J

& F9 a' v; A& Y7 Y- K) {
( O6 o# Z: c9 k) O& E- a7 ]* z; V! h  }3 v) S; z
收藏 评论0 发布时间:2021-11-8 17:04

举报

0个回答

所属标签

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