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

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

[复制链接]
STMCU小助手 发布时间:2021-11-8 17:04
今天准备移植STM32F030R8T6的程序到STM32G030C8T6上,程序中用到了硬件SPI外设,因为STM32G0用的HAL+LL库而不是不是标准库,所以我用STM32Cube MX生成了SPI的LL库代码,但是使能SPI后发现硬件怎么都不能触发RXNE接收标志,生成代码如下:
2 Q& v2 Q; g; x, h$ i" g' _! I' D" M( e7 ?  A
  1. void MX_SPI1_Init(void)
    9 {) ~6 ~# z3 J6 N4 x8 ^5 l& {
  2. {
    ( y; w2 {+ \% K6 Q0 x" o* T" k

  3. 4 |8 G5 ]( F* z( M( g) F: x  P2 P
  4.   /* USER CODE BEGIN SPI1_Init 0 */
    : u( ?/ l9 \# A7 g3 A* T

  5. , o4 E% \" Q+ C) q! Y% {3 p
  6.   /* USER CODE END SPI1_Init 0 */
    ) P  Z) n' h3 ]3 `& F3 G2 Z" g+ t

  7. ; p+ {5 C. P$ c5 \3 F
  8.   LL_SPI_InitTypeDef SPI_InitStruct = {0};
    - L' }" s4 q$ O8 Q6 o

  9. # q9 Z& r! H% E# y* w( o+ a: }
  10.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    4 f' w% Q9 j4 }# A

  11. : G6 ]0 w1 {0 ?8 V6 m7 ?# t3 |
  12.   /* Peripheral clock enable *// ^" g. p8 S% a5 I) s
  13.   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
    ) k' c6 m0 M# _1 c6 [& g

  14. ! k: w$ S$ `, F9 N  p( O
  15.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);2 H( C, A0 x# @3 u9 ?
  16.   /**SPI1 GPIO Configuration2 l# O& E; e4 J4 n: B+ T: `
  17.   PA5   ------> SPI1_SCK
    : @. K9 k+ G( M/ i
  18.   PA6   ------> SPI1_MISO) K# z, p  f3 [$ I
  19.   PA7   ------> SPI1_MOSI
    * d* P" H; ]" ~
  20.   */
    ; t# _7 z, p2 F# j3 @; A
  21.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    . L: n8 m2 i, ^" k( W
  22.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
    " ~9 {+ L! ^1 o' C
  23.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    2 V* B8 K0 ~$ J* }  X1 J+ S
  24.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;$ S& H: [  V- |: u1 N) y" l
  25.   GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
    " P5 j3 r% ]* M4 Q

  26. # v4 v% N4 D5 ]/ n  ^
  27.   GPIO_InitStruct.Pin = SPI_SCK_PIN;% D7 W& [) |# p
  28.   LL_GPIO_Init(SPI_SCK_PORT, &GPIO_InitStruct);
    9 n, ]3 B7 H1 t& o2 m6 h4 B' r

  29. : r1 e  H3 ]5 ]# p3 ~9 c
  30.   GPIO_InitStruct.Pin = SPI_MISO_PIN;
    ; ^+ _+ w' A% o( e4 N9 S$ z
  31.   LL_GPIO_Init(SPI_MISO_PORT, &GPIO_InitStruct);
    ' |3 s5 N) F5 \! f" I# ]: ~. _
  32. ! b. s% z' k. [6 m
  33.   GPIO_InitStruct.Pin = SPI_MOSI_PIN;. |1 ]# s" e3 C5 p  w3 Y/ X0 C* _
  34.   LL_GPIO_Init(SPI_MOSI_PORT, &GPIO_InitStruct);
    ) T  f  S( X! @2 L# E! @/ x

  35. * |% q9 A/ v2 C8 F
  36.   /* USER CODE BEGIN SPI1_Init 1 */
    8 f: M- A  v5 `& D1 s

  37. ; M; E" u% Q# c, E5 o
  38.   /* USER CODE END SPI1_Init 1 */
    % m* a6 W7 {: D  J# w$ {) v
  39.   SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
    ( s! R' M! a. ?, T* J9 A- o8 K0 D8 d
  40.   SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
    6 J3 [/ |& I3 R5 ]* o
  41.   SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
    0 N5 W0 Z# U3 b+ `0 q
  42.   SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;
    . o, ?+ [$ I9 y$ N$ ?1 a/ @* Y
  43.   SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;& p9 S. F4 ?4 u" e0 D
  44.   SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
    4 I4 r1 Q1 X/ r9 D
  45.   SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;
    * v0 l: H' Q& Q
  46.   SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
    - M9 v+ H7 V! J# M  k
  47.   SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
    , z5 R$ S7 V0 K* [
  48.   SPI_InitStruct.CRCPoly = 7;) W3 D& l. h& A4 u9 M
  49.   LL_SPI_Init(SPI1, &SPI_InitStruct);
    2 q; [, r0 Y& u7 {" M+ l. j
  50.   LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);4 X! T: H* s' c5 f
  51.   LL_SPI_DisableNSSPulseMgt(SPI1);
    # R* v5 u2 m0 ?+ k0 [6 q
  52.   /* USER CODE BEGIN SPI1_Init 2 */( `, v# A, w% e6 v7 @) r0 k0 B
  53.   LL_SPI_Enable(SPI1); //用户手动使能SPI
    1 k+ s0 ]' P/ d) K+ U
  54.   /* USER CODE END SPI1_Init 2 */
    0 }: @& m! e' C
  55. ( M+ P0 G. X- X" y- w1 C# ~4 x
  56. }
    ! l. \- R+ N7 F8 v3 O* @
复制代码
8 @4 F( N0 z/ Q1 e( q
程序正常运行后,通过在线DEBUG并调出SPI外设后,查看相关寄存器,可以看出SPI能正常发送,但是因为CR2寄存器的RXNE标志一直不能被触发,导致接收不到数据,如下图所示:
* X9 d; z: A  S8 p
2021060720475766.png

& D1 V' w4 o$ B" r7 m7 w
0 C9 p; C4 ~/ d但是相同的设置在STM32F0的标准库上是可以正常运行了,模式配置都一样,但是用LL库的STM32G0上就不能运行,后来查看STM32G031K LL库的使用 - SPI这篇文章,发现代码中额外添加了以下语句:
  t5 ^# Z) M( X, t, |' `$ b( I1 r. Q, z) o  N' p
  1. /* Configure the SPI2 FIFO Threshold */" @  d  [. y) v% Y( E' B, ^# @
  2.   LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);//设置RX非空事件产生的FIFO阈值,根据通信时最<span style="background-color: rgb(255, 255, 255);">小数据的大小设置,我这边最小为8位,所以设置为四分之一</span>
复制代码
* ~' E' c( _- u  ~8 h6 {/ B) J
通过查看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标志就一直不能触发,也就接收不到任何数据。, A( N" {; z8 \  y: k( C/ {/ }( d

1 H7 n5 x* K! U9 g
2021060721150377.png

0 I; y# q( D' D4 ?5 F1 ^! W; r5 I& E. P1 H+ _+ V
反观用了标准库函数的STM32F0,同样的设置为什么就可以正常运行呢???通过查看标准库函数SPI_Init(),可以发现函数中对CR2进行了赋值操作,而对应值正是SPI_DataSize_8b这个宏,该宏的值为0x0700,Bit12 FRXTH=1,该值对应FRXTH接收阈值为1/4,所以程序能正常运行,RXNE可以正常触发,这也就解释了为什么同样的配置在标准库上SPI能正常运行,但是在LL库上却不能正常运行的问题所在。3 I; X: i4 B+ U1 P! j4 z
2 A* _9 W% k3 f
  1. void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)7 p& q5 P4 q6 P" a- L  |0 |  X
  2. {
    - d) M1 P. O; h3 x. s% F
  3.         .......; f# g3 z; q' b  w
  4.          /* Configure SPIx: Data Size */
      @0 m2 i# h( a; v" g
  5.         tmpreg |= (uint16_t)(SPI_InitStruct->SPI_DataSize); //SPI发送接收的数据为8位9 c2 \: R# G) h/ y- \
  6.         /* Write to SPIx CR2 */& D2 B8 E4 j+ |6 V
  7.         SPIx->CR2 = tmpreg; ) G. r' i8 ?1 L: b0 M
  8.         ......
复制代码

7 d- I6 `1 m, k* ^3 p" r  u0 K' F4 \3 O7 e. r* H/ U2 g; P- R
4 Y0 W4 ^' x* g$ O. G: W4 n" B3 R

, ]! _0 S" k4 S8 m% v+ x) \
收藏 评论0 发布时间:2021-11-8 17:04

举报

0个回答

所属标签

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