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

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

[复制链接]
STMCU小助手 发布时间:2021-11-8 17:04
今天准备移植STM32F030R8T6的程序到STM32G030C8T6上,程序中用到了硬件SPI外设,因为STM32G0用的HAL+LL库而不是不是标准库,所以我用STM32Cube MX生成了SPI的LL库代码,但是使能SPI后发现硬件怎么都不能触发RXNE接收标志,生成代码如下:0 E4 h  P. r; ~" ^; y# ]% ^
# _- x# j& ?( m& D
  1. void MX_SPI1_Init(void)8 r: ]6 a, |4 ~2 A# _: ]7 T: ]4 G
  2. {
      O. F  O; T9 q1 N
  3. " v5 t5 Y* h$ h3 B$ f8 P
  4.   /* USER CODE BEGIN SPI1_Init 0 */
    ) E4 z+ c, B% B3 ]

  5. 9 H2 i, {/ g* U5 C) u
  6.   /* USER CODE END SPI1_Init 0 */
    , }, G6 D+ {% N  g
  7. - T5 D9 A, C$ K4 M0 B# B9 A
  8.   LL_SPI_InitTypeDef SPI_InitStruct = {0};
    3 O% h) O: _: ~+ w

  9. 6 X5 t) F7 W  r. d# i# v% |8 W
  10.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    # e8 j; [0 f: K& ?8 G$ P4 @
  11. 3 t3 X; J  q. z: p9 H
  12.   /* Peripheral clock enable */
    2 e! j" B9 P' w7 M* S& q' N3 U
  13.   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
    8 X$ g$ V( }$ q: C
  14. 2 b( |  S1 j/ z- m9 A
  15.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);3 V, U' r8 e% V8 L3 {- J$ @( M
  16.   /**SPI1 GPIO Configuration
    9 ]' [. _, Q" l* I! [
  17.   PA5   ------> SPI1_SCK# G! v- e* H. k" m7 R" u9 S
  18.   PA6   ------> SPI1_MISO
    6 T7 e) O/ |  z* M+ Y9 `7 p5 n
  19.   PA7   ------> SPI1_MOSI
    ; X3 b' S0 V* {4 X  Q; Z* y! `
  20.   */8 ~% U  H8 v/ Y
  21.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;& c( B/ H' v: O5 H4 l- z+ b7 b( n
  22.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;1 y# ~5 M" ~; ^$ k6 \( I* t. F
  23.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    . n/ T" Z9 k; g! X* E5 Q1 s
  24.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;) ?' R) F  F9 p6 t
  25.   GPIO_InitStruct.Alternate = LL_GPIO_AF_0;( J! K0 n& G9 K4 e, O0 |, v" ^1 v

  26. , X! Z4 S( \+ W/ e1 w
  27.   GPIO_InitStruct.Pin = SPI_SCK_PIN;/ |# f: h5 v9 T& z7 M/ `3 W
  28.   LL_GPIO_Init(SPI_SCK_PORT, &GPIO_InitStruct);/ L4 l) Z2 p8 v. z7 S3 M

  29. ) i2 X' e3 `- F$ a0 a5 E$ r
  30.   GPIO_InitStruct.Pin = SPI_MISO_PIN;7 d8 Y/ G. K5 P3 S' u
  31.   LL_GPIO_Init(SPI_MISO_PORT, &GPIO_InitStruct);# q2 p0 h  D- u8 z; Y

  32. . D& d# D+ A. @+ `8 ~5 k3 J. n
  33.   GPIO_InitStruct.Pin = SPI_MOSI_PIN;5 j3 w) t" B  j1 Q1 [$ l$ X
  34.   LL_GPIO_Init(SPI_MOSI_PORT, &GPIO_InitStruct);9 O, Z" v# M4 C# W6 ?0 p
  35. * M# ^3 m* i& m1 M; H! H* k" k
  36.   /* USER CODE BEGIN SPI1_Init 1 */
    : f# n& X9 A+ J

  37. $ y9 h9 G5 Y1 d3 {+ a  I2 G
  38.   /* USER CODE END SPI1_Init 1 */+ h& X; W4 X. \4 K* N6 P3 ~
  39.   SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
    8 J! H3 d- W2 r5 p" [& |
  40.   SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
    # ^' P8 E- b: M# A
  41.   SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;" l' m8 G3 }, U2 `5 j
  42.   SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;' R. }% G6 n7 ~# ~
  43.   SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;4 T! U% A- B# O% `( t! ^% b
  44.   SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
      a4 V  |" |3 H7 T; U: ]& n9 r
  45.   SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;
    + o/ l6 w' \5 V
  46.   SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;3 V; L( n7 r& y7 Z7 R
  47.   SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;+ D9 R* N0 f+ a# N0 r7 `8 }
  48.   SPI_InitStruct.CRCPoly = 7;
    & i& f: I; X0 g8 I1 ~! y1 K: q- Y+ Y
  49.   LL_SPI_Init(SPI1, &SPI_InitStruct);
    / v4 V2 U. L8 M; k0 q/ k+ I
  50.   LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);, J3 Z& P5 @, w
  51.   LL_SPI_DisableNSSPulseMgt(SPI1);
    ! W- y- ^$ \. m2 V  o, o
  52.   /* USER CODE BEGIN SPI1_Init 2 */
    6 u1 E( n, _0 z0 Z! k6 b4 r. r
  53.   LL_SPI_Enable(SPI1); //用户手动使能SPI6 c5 _! O) V: v0 `# ?- k& k9 ]
  54.   /* USER CODE END SPI1_Init 2 */
    * L- j4 p' P: o% a; ?
  55. ( M9 B0 z9 \7 D+ ~
  56. }- h  k/ D2 C+ j
复制代码
! o$ y! p6 s2 t% `. r4 F0 \: J7 h
程序正常运行后,通过在线DEBUG并调出SPI外设后,查看相关寄存器,可以看出SPI能正常发送,但是因为CR2寄存器的RXNE标志一直不能被触发,导致接收不到数据,如下图所示:
3 l7 n4 l* X* I
2021060720475766.png
  C' L; _9 I" ^
9 o9 B# s$ P4 P) V: ^. \; I) B
但是相同的设置在STM32F0的标准库上是可以正常运行了,模式配置都一样,但是用LL库的STM32G0上就不能运行,后来查看STM32G031K LL库的使用 - SPI这篇文章,发现代码中额外添加了以下语句:9 B8 T6 K% h) g. h7 n

: h: f) H) w8 d9 @& a5 k* ?
  1. /* Configure the SPI2 FIFO Threshold */
    6 d$ V, {# s" ^% `$ p0 V. q
  2.   LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);//设置RX非空事件产生的FIFO阈值,根据通信时最<span style="background-color: rgb(255, 255, 255);">小数据的大小设置,我这边最小为8位,所以设置为四分之一</span>
复制代码
3 A4 l" `  U4 V* k0 I
通过查看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标志就一直不能触发,也就接收不到任何数据。
! i8 ]& n* e& ^' b
3 q# ~& B8 I& l! V4 @8 [
2021060721150377.png

1 c* V% W% r, h7 X
) `$ B4 x; q  N% ^. u5 p4 [反观用了标准库函数的STM32F0,同样的设置为什么就可以正常运行呢???通过查看标准库函数SPI_Init(),可以发现函数中对CR2进行了赋值操作,而对应值正是SPI_DataSize_8b这个宏,该宏的值为0x0700,Bit12 FRXTH=1,该值对应FRXTH接收阈值为1/4,所以程序能正常运行,RXNE可以正常触发,这也就解释了为什么同样的配置在标准库上SPI能正常运行,但是在LL库上却不能正常运行的问题所在。# ]! G2 h- E* n& z0 [
7 c* z, V- {7 J4 F- ^
  1. void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)
    1 [9 Z2 ~* K. d" e, K- [* W
  2. {1 y& |; ~! K; K; L& g% m% O3 x
  3.         ........ A7 g7 X+ S2 C" h2 I  d
  4.          /* Configure SPIx: Data Size */; }9 l4 B2 s) f; D9 D- ^" T* e
  5.         tmpreg |= (uint16_t)(SPI_InitStruct->SPI_DataSize); //SPI发送接收的数据为8位
    ( b7 \3 `2 P8 K; m+ u, S
  6.         /* Write to SPIx CR2 */" Y. M5 G, k# @, M
  7.         SPIx->CR2 = tmpreg; * J$ Y% H+ u2 Y4 m$ B
  8.         ......
复制代码
, @* p) Z' {6 ^' `$ H- ^* B
6 s+ Q7 E) ^- F
/ u  k! m8 g! Q: d. j" q7 N5 f

% n) o- Z( E5 [, e" j
收藏 评论0 发布时间:2021-11-8 17:04

举报

0个回答

所属标签

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