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

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

[复制链接]
STMCU小助手 发布时间:2021-11-8 17:04
今天准备移植STM32F030R8T6的程序到STM32G030C8T6上,程序中用到了硬件SPI外设,因为STM32G0用的HAL+LL库而不是不是标准库,所以我用STM32Cube MX生成了SPI的LL库代码,但是使能SPI后发现硬件怎么都不能触发RXNE接收标志,生成代码如下:9 N$ W! V( j& v5 H

! ~( I/ S* f8 N1 p+ \) y+ i0 {
  1. void MX_SPI1_Init(void)$ e/ T" |) ^+ G3 N, p9 m: j
  2. {
    4 J/ X+ j9 J+ u& f

  3. % K. e6 N7 X- P% b( ?
  4.   /* USER CODE BEGIN SPI1_Init 0 */
      f* r! T' g. T6 G# t* q

  5. ( x/ [/ s  C& X/ @9 }
  6.   /* USER CODE END SPI1_Init 0 */  @* r% v) G$ j2 X, L
  7. ( \: F0 n7 O% E
  8.   LL_SPI_InitTypeDef SPI_InitStruct = {0};: S! {& E0 R7 w! V' [( b# S

  9. " {6 M3 }/ T: w) o$ l$ s
  10.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};1 N$ c' _/ a! c' h3 m
  11. : L6 s& r- f% u$ E9 N. m& p
  12.   /* Peripheral clock enable */
    / }/ `7 m5 ^) `7 w
  13.   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);  P% I2 w$ t" q3 l/ M: ~

  14. 9 }' X' W; j1 M1 f8 H
  15.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
    & B) q! r( R& t$ W6 O  D
  16.   /**SPI1 GPIO Configuration. D" x! u0 |  b
  17.   PA5   ------> SPI1_SCK/ e' G  L' i) `
  18.   PA6   ------> SPI1_MISO
    2 s! [: H! \; Q$ G5 @
  19.   PA7   ------> SPI1_MOSI2 G/ r+ L3 ]' U" P6 M4 L
  20.   */
    3 N* s& E  x; k* i' d! n
  21.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    + {8 E' T2 T9 }8 V! W
  22.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
    # |4 ~! Y! I7 f
  23.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    8 Q: v# u7 q4 a. O& v
  24.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;- Q& N/ I0 C0 }* g3 T  f& S, _
  25.   GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
    1 l; E( X7 B; W
  26. ( ]# ^& k( V6 t
  27.   GPIO_InitStruct.Pin = SPI_SCK_PIN;; n. \2 K& A+ K9 _" e+ d
  28.   LL_GPIO_Init(SPI_SCK_PORT, &GPIO_InitStruct);
    0 t  L) e$ b! W% C& O8 J# K
  29. ( o) i- c5 t; V- x4 x! p5 i. K4 I
  30.   GPIO_InitStruct.Pin = SPI_MISO_PIN;
    ( x7 z# l8 k- F+ m; t' k/ L
  31.   LL_GPIO_Init(SPI_MISO_PORT, &GPIO_InitStruct);
    % o; ]! Z# h; E
  32. / j1 ?/ }# O$ C2 x$ q
  33.   GPIO_InitStruct.Pin = SPI_MOSI_PIN;! x6 {9 n  r6 ^4 {1 I3 w) K# _
  34.   LL_GPIO_Init(SPI_MOSI_PORT, &GPIO_InitStruct);; h- c; k& \+ d8 C

  35. : }) O& P) h/ P! P6 G7 w  R
  36.   /* USER CODE BEGIN SPI1_Init 1 */& b7 c  e7 `& G# v/ S. L
  37. 6 ^, M7 h& P  f: {9 r7 e4 J5 U$ @
  38.   /* USER CODE END SPI1_Init 1 */
    2 {% A. v7 x0 X3 `  ]3 T# K- s% R
  39.   SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
    . I$ j* M2 v, t
  40.   SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;0 `. ]! \( o( U8 d% E
  41.   SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;& l7 v- |& b+ k% }; p8 L0 `- R% \: M
  42.   SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;2 L0 ^( l; J# B( V$ N
  43.   SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;8 X# s8 f1 J7 a8 h# c' N
  44.   SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
    9 s, _0 n7 `4 g/ S/ Z
  45.   SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;
    9 j' Z, H' D3 }% @5 n
  46.   SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
    # A+ [# `4 b6 N- A: q0 a2 J- B
  47.   SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;( {- Y% ]/ b% v0 m- R) Q
  48.   SPI_InitStruct.CRCPoly = 7;! v  z% x+ d8 L3 h7 y- E- j' C$ d
  49.   LL_SPI_Init(SPI1, &SPI_InitStruct);) L: r3 b( ], d2 b; F
  50.   LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);8 M' ]2 E) ~3 \6 B1 t4 k
  51.   LL_SPI_DisableNSSPulseMgt(SPI1);( R  H% \! i. v& l# h# a  }
  52.   /* USER CODE BEGIN SPI1_Init 2 */3 }, ^8 E# Y" J5 t4 j
  53.   LL_SPI_Enable(SPI1); //用户手动使能SPI
    ) M( q2 S. R1 Q9 X
  54.   /* USER CODE END SPI1_Init 2 */
    3 c6 s- v8 v, k2 n1 N
  55. 0 P  d# Q. R& M8 h, o
  56. }
    7 w; D% G- |1 Y7 b# j$ @
复制代码

9 K# }6 [( i9 p; {程序正常运行后,通过在线DEBUG并调出SPI外设后,查看相关寄存器,可以看出SPI能正常发送,但是因为CR2寄存器的RXNE标志一直不能被触发,导致接收不到数据,如下图所示:- p4 D1 a/ }1 r+ ~+ i
2021060720475766.png

# n+ q& O7 G! \1 b% ]
3 ^. q& r6 @. f% x+ A% c4 B) J但是相同的设置在STM32F0的标准库上是可以正常运行了,模式配置都一样,但是用LL库的STM32G0上就不能运行,后来查看STM32G031K LL库的使用 - SPI这篇文章,发现代码中额外添加了以下语句:" ~- u7 s0 t( w1 y+ Y* ^  w1 t
" I* o' W, i3 l/ Q1 |
  1. /* Configure the SPI2 FIFO Threshold */
    1 ~+ E  o& Z$ z+ d* T& s# ~) A
  2.   LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);//设置RX非空事件产生的FIFO阈值,根据通信时最<span style="background-color: rgb(255, 255, 255);">小数据的大小设置,我这边最小为8位,所以设置为四分之一</span>
复制代码

4 n6 g' V( {# ~; o+ B  Q8 @' |通过查看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标志就一直不能触发,也就接收不到任何数据。, S3 o5 Y3 x4 d. B9 y
/ e6 `1 T3 ~; C) }9 Y4 {
2021060721150377.png
  P( x( [" z. [

& H1 o8 e4 J  v2 o) B7 |% {0 N3 z反观用了标准库函数的STM32F0,同样的设置为什么就可以正常运行呢???通过查看标准库函数SPI_Init(),可以发现函数中对CR2进行了赋值操作,而对应值正是SPI_DataSize_8b这个宏,该宏的值为0x0700,Bit12 FRXTH=1,该值对应FRXTH接收阈值为1/4,所以程序能正常运行,RXNE可以正常触发,这也就解释了为什么同样的配置在标准库上SPI能正常运行,但是在LL库上却不能正常运行的问题所在。
) h4 ^  c; N" M( g) \, D. x3 Y) q5 e2 C/ r4 j) I
  1. void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)
    . u0 c1 j: I% Q, E! ]3 D2 f
  2. {
    " [' \2 u3 h: G* W% G" ]
  3.         .......! i5 Y# E7 h2 J6 l$ U. t% K
  4.          /* Configure SPIx: Data Size */1 r$ O- N: j: H; D+ F: R9 b( @. z
  5.         tmpreg |= (uint16_t)(SPI_InitStruct->SPI_DataSize); //SPI发送接收的数据为8位4 A2 b4 s: S7 B; _3 }
  6.         /* Write to SPIx CR2 */
    * X, i1 b  `8 n7 ?  F! d* j
  7.         SPIx->CR2 = tmpreg;
    % `) M, ?0 m0 u
  8.         ......
复制代码
9 ?& g9 w* l# W2 c; f" f
$ J) k" L, f. F; }

! g0 B  H( b. _3 U4 S% S% H* A: o3 a+ J6 B
赞 收藏 评论0 发布时间:2021-11-8 17:04

举报

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