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

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

[复制链接]
STMCU小助手 发布时间:2021-11-8 17:04
今天准备移植STM32F030R8T6的程序到STM32G030C8T6上,程序中用到了硬件SPI外设,因为STM32G0用的HAL+LL库而不是不是标准库,所以我用STM32Cube MX生成了SPI的LL库代码,但是使能SPI后发现硬件怎么都不能触发RXNE接收标志,生成代码如下:  X( q8 B& l4 V: |+ o0 w
  q4 i$ K, H9 f; P- l" o' ?% d9 ~
  1. void MX_SPI1_Init(void)6 R8 A0 x( w( }4 ^/ j+ l
  2. {
    # O  a# `: q. H2 l1 a  F' B0 B

  3. ) c  g: a) Z7 {5 f- b6 P$ r, z- }
  4.   /* USER CODE BEGIN SPI1_Init 0 */
    & D" v+ k, Z% C
  5. # c% s# P/ ]! l( \
  6.   /* USER CODE END SPI1_Init 0 */
    5 \- g% O( [0 k2 v0 `+ F& M

  7. ; K* T! }: c1 U+ B2 q( Z5 z
  8.   LL_SPI_InitTypeDef SPI_InitStruct = {0};( ^  x! ~# o- M1 k0 u! T+ ^
  9. : z5 y/ q4 Y+ s4 Q, q, [/ U! T7 n
  10.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};. t2 [; k! K! P  Q; \6 q

  11. ' l2 H* q2 Z# Y8 h0 B# w1 r
  12.   /* Peripheral clock enable */, I3 x/ ^$ d* W3 u8 X9 m; h
  13.   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);+ u+ h2 g7 V: ^: |

  14. " ~9 T* [: V, v1 v$ e  H6 l( o
  15.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);$ f' J! ~. ?7 `! D
  16.   /**SPI1 GPIO Configuration5 X2 \& q! F' n  n# J, F
  17.   PA5   ------> SPI1_SCK% r# f( D2 E5 k2 b' X; W
  18.   PA6   ------> SPI1_MISO
    & M) D# D" |0 t5 `8 c  `2 B$ r
  19.   PA7   ------> SPI1_MOSI! l( \" B0 C4 v* K6 |/ e5 a
  20.   */% q! V# J7 i- }& R. ^$ n
  21.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;# g& [6 m/ y+ d% g
  22.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;$ |$ }# ~0 X" h# L% T- `% Q; S
  23.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    , |5 m3 }; }# J- v. o4 [3 B
  24.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
    ( `, |' U5 V8 Z
  25.   GPIO_InitStruct.Alternate = LL_GPIO_AF_0;+ z4 N* P9 }/ i  c* I

  26. ( H. A3 C8 {, Z- T" \0 ?1 I
  27.   GPIO_InitStruct.Pin = SPI_SCK_PIN;& p3 u' V( x/ t4 g* m$ D
  28.   LL_GPIO_Init(SPI_SCK_PORT, &GPIO_InitStruct);  o' t' _3 A2 K1 s! `
  29. 4 {. h, v' A4 ]7 D
  30.   GPIO_InitStruct.Pin = SPI_MISO_PIN;
    " @* L- l  I5 Y7 T$ D, m
  31.   LL_GPIO_Init(SPI_MISO_PORT, &GPIO_InitStruct);: r1 C/ f$ V- G9 d8 t
  32. 8 J7 B+ u4 x6 Q! L! y' D
  33.   GPIO_InitStruct.Pin = SPI_MOSI_PIN;
    " H: H* |" }' a2 D& j- {% t7 A0 ^
  34.   LL_GPIO_Init(SPI_MOSI_PORT, &GPIO_InitStruct);
    ! p, n. K; }8 ?! h

  35. 6 `' M; m/ i  h$ i- P
  36.   /* USER CODE BEGIN SPI1_Init 1 */( @- x& i9 m5 W7 j" R4 r
  37. + L* M. x1 S* J4 g) c5 G) a
  38.   /* USER CODE END SPI1_Init 1 */
    8 E' f2 s0 {2 j0 n7 C
  39.   SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
    / w- h) c6 H4 l% u. f
  40.   SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;0 ?4 {2 M8 x/ b/ m& q  l0 x
  41.   SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;3 V( ]8 {1 q& y) |5 h
  42.   SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;1 ], H6 s* w3 S( g# B; |
  43.   SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;9 J. k, `$ j1 U; d2 ?9 e* Z
  44.   SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
    % }3 h0 ~- @, A$ R8 m9 b& N- X
  45.   SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;- d4 ?9 L# {$ V
  46.   SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
    2 H1 v9 e6 R5 Y$ V4 e
  47.   SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;, U4 {8 @# a4 ^
  48.   SPI_InitStruct.CRCPoly = 7;: R  z& J  Q7 n' l3 t3 u: ^6 @
  49.   LL_SPI_Init(SPI1, &SPI_InitStruct);
    ; l9 \7 @8 @% z: w- {" |
  50.   LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
    " P/ V/ f$ d/ _0 a4 G2 S
  51.   LL_SPI_DisableNSSPulseMgt(SPI1);
    % ^+ ~8 O( n: a1 a0 d( o
  52.   /* USER CODE BEGIN SPI1_Init 2 */& d9 M+ {7 [9 ]
  53.   LL_SPI_Enable(SPI1); //用户手动使能SPI2 H+ n+ T5 A# E" R
  54.   /* USER CODE END SPI1_Init 2 */
    . Z8 b2 B( g! I2 M3 W$ R1 z
  55. " v9 O" _1 e- j/ `, d6 |1 k
  56. }
    + w/ R" ~% D, B# ^1 A
复制代码

( A0 R6 d/ o) V: h程序正常运行后,通过在线DEBUG并调出SPI外设后,查看相关寄存器,可以看出SPI能正常发送,但是因为CR2寄存器的RXNE标志一直不能被触发,导致接收不到数据,如下图所示:! A. Z5 J. e' r# R9 _2 b, Z
2021060720475766.png

' j: d7 S' ~: V- D0 j; }, _+ u0 k) Z! g, @! V
但是相同的设置在STM32F0的标准库上是可以正常运行了,模式配置都一样,但是用LL库的STM32G0上就不能运行,后来查看STM32G031K LL库的使用 - SPI这篇文章,发现代码中额外添加了以下语句:7 G" j! N- N) X% F6 ]( ?3 J
/ L( l! U5 ^& [+ K2 u
  1. /* Configure the SPI2 FIFO Threshold */
    + F4 `. t1 V/ x, M
  2.   LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);//设置RX非空事件产生的FIFO阈值,根据通信时最<span style="background-color: rgb(255, 255, 255);">小数据的大小设置,我这边最小为8位,所以设置为四分之一</span>
复制代码

! a0 [' j3 g! S2 Q+ a1 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标志就一直不能触发,也就接收不到任何数据。
2 l7 W; T5 D' ]# |4 `( K
$ U& }: T$ A: G( h. t" u: J. c
2021060721150377.png
" L, d$ @2 r: |* S( K+ W, c
+ l! G( l- B- C6 j7 _1 l" f. x/ a
反观用了标准库函数的STM32F0,同样的设置为什么就可以正常运行呢???通过查看标准库函数SPI_Init(),可以发现函数中对CR2进行了赋值操作,而对应值正是SPI_DataSize_8b这个宏,该宏的值为0x0700,Bit12 FRXTH=1,该值对应FRXTH接收阈值为1/4,所以程序能正常运行,RXNE可以正常触发,这也就解释了为什么同样的配置在标准库上SPI能正常运行,但是在LL库上却不能正常运行的问题所在。
3 |2 Z# m2 n  b' X, k1 N3 d3 w) }; A* V+ d; `; K
  1. void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)
    3 }5 H! ~+ O& M; S" Q- h6 W+ Y& I* D
  2. {
    / B, c( v3 V1 D* E
  3.         .......
    1 ]& a8 Q' P+ z; e7 ?3 P
  4.          /* Configure SPIx: Data Size */
    9 r6 s) \8 F- e
  5.         tmpreg |= (uint16_t)(SPI_InitStruct->SPI_DataSize); //SPI发送接收的数据为8位
    & g# `6 B, ^% D9 c& @' W
  6.         /* Write to SPIx CR2 */' W$ H  p  ]# o7 X8 G' s
  7.         SPIx->CR2 = tmpreg; 3 ^$ x; I5 m; E' s
  8.         ......
复制代码

# x8 f' o+ ?& L) X! ?: r! D
/ q- I* y( Q& g: E. ?' d: n& {% U5 t  ]2 j; L
/ }7 R) g% A- D5 d
赞 收藏 评论0 发布时间:2021-11-8 17:04

举报

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