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

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

[复制链接]
STMCU小助手 发布时间:2021-11-8 17:04
今天准备移植STM32F030R8T6的程序到STM32G030C8T6上,程序中用到了硬件SPI外设,因为STM32G0用的HAL+LL库而不是不是标准库,所以我用STM32Cube MX生成了SPI的LL库代码,但是使能SPI后发现硬件怎么都不能触发RXNE接收标志,生成代码如下:
7 l, J' j/ d* F) R3 N% a& `9 x& s+ Y
  1. void MX_SPI1_Init(void)
    6 j9 W5 h3 _/ {" h
  2. {5 }+ ^" A, z0 B! p; I

  3. 6 m! J5 G( Z, O( i, P
  4.   /* USER CODE BEGIN SPI1_Init 0 */5 D  O, K! A; A% O9 Q4 g

  5. " A$ ^8 J: m7 u7 p
  6.   /* USER CODE END SPI1_Init 0 */
    2 e4 F( C9 P5 _3 O' Z" U& z3 ^
  7. : q( F0 D7 L8 }. W& s7 {
  8.   LL_SPI_InitTypeDef SPI_InitStruct = {0};2 J0 Q* a$ s7 ^' c7 R

  9. 6 e! d2 w- x  T  r
  10.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
      O" ^$ V( B8 h% f4 |* \  Q

  11. 6 ^% D) B+ Z$ Y- X& k3 r/ J9 m
  12.   /* Peripheral clock enable */3 S) X0 u/ T* t
  13.   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
    - i7 ~5 e6 a: P9 b+ V# H" l( K* {$ C

  14. & R/ k: R$ }5 y& c
  15.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
    9 M& L) p6 }( [4 a& `# l% \- G
  16.   /**SPI1 GPIO Configuration
    $ i3 ?* Y0 L! P& q% ~' T, X
  17.   PA5   ------> SPI1_SCK, I& Z& [" G8 I
  18.   PA6   ------> SPI1_MISO) K3 b- ]& m4 k1 z' G2 W
  19.   PA7   ------> SPI1_MOSI, X$ D5 R+ q4 Y
  20.   */  d* y2 G8 I# {3 s5 j
  21.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    + `: b& q9 e0 S# Q& Z
  22.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
      q- v% k; ~" x
  23.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;1 U" z- G0 Q8 B. u$ p& v5 v
  24.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;9 ~/ v  Z: M2 ^
  25.   GPIO_InitStruct.Alternate = LL_GPIO_AF_0;4 B' L9 ?2 y% ]2 B( _/ e) i) ?

  26. & q0 M& C+ g5 d. h7 _; R& ]) v# `
  27.   GPIO_InitStruct.Pin = SPI_SCK_PIN;
    & u% \8 |# F* B& U$ Z) A
  28.   LL_GPIO_Init(SPI_SCK_PORT, &GPIO_InitStruct);$ D4 W: \. P5 j6 e+ z$ Y) [
  29. , Y* B, a* [, @) g1 o% U8 V( T
  30.   GPIO_InitStruct.Pin = SPI_MISO_PIN;
    ; P5 S" }3 a, {: S+ E5 n1 Y
  31.   LL_GPIO_Init(SPI_MISO_PORT, &GPIO_InitStruct);4 Q$ l' e. l2 P" P

  32. 0 t# T0 t1 B) U) t# _5 \+ T: [' M
  33.   GPIO_InitStruct.Pin = SPI_MOSI_PIN;1 D+ y, ?2 s( I
  34.   LL_GPIO_Init(SPI_MOSI_PORT, &GPIO_InitStruct);
    ; n1 N0 r$ w+ `' J+ Y
  35.   A( c% n' d/ Z" ?. L
  36.   /* USER CODE BEGIN SPI1_Init 1 *// A' f3 n& y/ {* J( q+ O
  37. : a4 |2 b9 O. H* w8 y& i
  38.   /* USER CODE END SPI1_Init 1 */
    : O! D: L% l: f1 U% B1 v$ s; J" a9 v
  39.   SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
    3 M3 v/ c" r$ c- y5 ~
  40.   SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
    5 c5 @) A' ~2 Y/ a5 `! o; T  F7 o
  41.   SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;9 S: Z: X; X* _# e2 z8 |
  42.   SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;
    / g1 [& A1 M6 ^6 H# K9 z0 S8 Y
  43.   SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;2 `# [- [8 S6 i
  44.   SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
    , S, r& x2 {5 b3 }  W
  45.   SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;: _/ R" c( L. G
  46.   SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;& g0 I( R" C; B/ {* \$ H, _! _( I
  47.   SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
    ( ]# K$ C" o) j) p' r# K& B, f
  48.   SPI_InitStruct.CRCPoly = 7;
    0 L2 b6 y2 t( ~% R/ T. B! D6 C
  49.   LL_SPI_Init(SPI1, &SPI_InitStruct);  P$ S5 O8 q% U( v
  50.   LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);/ H, ^" E; [2 L  @
  51.   LL_SPI_DisableNSSPulseMgt(SPI1);
    3 Z5 D9 R$ U- H0 q
  52.   /* USER CODE BEGIN SPI1_Init 2 */# ?+ w3 R9 f0 I/ n+ h
  53.   LL_SPI_Enable(SPI1); //用户手动使能SPI. O" V5 F" C3 c8 Q$ g- i% p) Q
  54.   /* USER CODE END SPI1_Init 2 */* z& L7 D; Q0 F  ~* X' k
  55. + M' e) _+ i( T; }. H9 l8 x
  56. }6 y* Y& i6 S2 n  w. J8 R
复制代码
/ M5 d$ a4 N  l9 C# Z
程序正常运行后,通过在线DEBUG并调出SPI外设后,查看相关寄存器,可以看出SPI能正常发送,但是因为CR2寄存器的RXNE标志一直不能被触发,导致接收不到数据,如下图所示:( e4 P6 W0 |1 v4 H& S% O
2021060720475766.png

2 l/ \. F1 s, |" w$ _, j8 |' L+ i# O- v
但是相同的设置在STM32F0的标准库上是可以正常运行了,模式配置都一样,但是用LL库的STM32G0上就不能运行,后来查看STM32G031K LL库的使用 - SPI这篇文章,发现代码中额外添加了以下语句:3 `+ A# p9 V9 u* ^: }4 a

% ~& z( e9 ^4 @" ^6 p0 K9 W! b8 V/ O
  1. /* Configure the SPI2 FIFO Threshold */
    . M- y4 t9 e: f4 ^. K; S6 K. J4 _
  2.   LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);//设置RX非空事件产生的FIFO阈值,根据通信时最<span style="background-color: rgb(255, 255, 255);">小数据的大小设置,我这边最小为8位,所以设置为四分之一</span>
复制代码
/ x' c9 h0 C1 o& g
通过查看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标志就一直不能触发,也就接收不到任何数据。
" j) i/ B/ a2 G6 q5 x# j% P+ W6 i* T0 c
2021060721150377.png
9 U' E7 r( C. t5 u
. ^  s3 X  D2 S5 d+ I9 `* N' G2 G
反观用了标准库函数的STM32F0,同样的设置为什么就可以正常运行呢???通过查看标准库函数SPI_Init(),可以发现函数中对CR2进行了赋值操作,而对应值正是SPI_DataSize_8b这个宏,该宏的值为0x0700,Bit12 FRXTH=1,该值对应FRXTH接收阈值为1/4,所以程序能正常运行,RXNE可以正常触发,这也就解释了为什么同样的配置在标准库上SPI能正常运行,但是在LL库上却不能正常运行的问题所在。, A( R; m# }7 J
/ I- Z  N  M! \, C' K
  1. void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)
    * k0 o2 g- }, j: u
  2. {6 E4 Q, L. @2 [- K& Q9 q
  3.         .......
    $ E# f& }! n* E# y. c: {
  4.          /* Configure SPIx: Data Size */
    0 F" f" g. M0 f5 T3 Z8 E; v
  5.         tmpreg |= (uint16_t)(SPI_InitStruct->SPI_DataSize); //SPI发送接收的数据为8位  e6 i" v; @, m4 X* }! `
  6.         /* Write to SPIx CR2 */& q, [$ E+ @& I
  7.         SPIx->CR2 = tmpreg; & \* s0 s' m' A; I, q- r+ x, v
  8.         ......
复制代码
* o3 O9 [% ^: h! ]+ V. f

9 u5 B  r, M: N/ R" O: c3 D+ Y, Z

* D( a# ~  J8 \' E! r) R* x3 \
收藏 评论0 发布时间:2021-11-8 17:04

举报

0个回答

所属标签

相似分享

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