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

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

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

1 p! |2 e) m) \: t( ~
  1. void MX_SPI1_Init(void)8 }3 e1 q/ s8 ^6 t
  2. {
    1 b% i) C7 O" u; F) a
  3. 1 K5 ?8 c% z* E% `  c( Z' \9 q
  4.   /* USER CODE BEGIN SPI1_Init 0 */
    2 ^3 ]& R6 T0 N3 ]  w) u7 t  f
  5. * s. r2 ]; f2 O# }
  6.   /* USER CODE END SPI1_Init 0 */' |. r! M# ~5 F3 G$ R3 N; r: h

  7. : I/ Z( g) f2 p- t4 G
  8.   LL_SPI_InitTypeDef SPI_InitStruct = {0};- e3 R( b8 r0 n. X0 s
  9. 2 k+ W' O) h/ s7 l% o
  10.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    5 }, h8 ?6 e0 |* _9 m! G
  11.   Q4 M8 |4 q; Y' h
  12.   /* Peripheral clock enable */
    + J! V0 z: v1 j2 G+ l' V8 R$ z
  13.   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);# p4 Q( z" Y) J& P  N$ j

  14. " m# u9 Z) k) [9 N6 G! A9 H. a
  15.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
    / T/ s" y( c% d. N% @3 p- R
  16.   /**SPI1 GPIO Configuration
    4 J& e& j! c/ C/ |" L
  17.   PA5   ------> SPI1_SCK
    3 V% J3 g1 A% b; M+ Y
  18.   PA6   ------> SPI1_MISO0 u! {! N5 ]% q: C) Y5 y  C
  19.   PA7   ------> SPI1_MOSI3 O$ w6 V: m# K, X1 R6 u6 e
  20.   */- Y3 P3 n/ S/ D3 h/ S
  21.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    5 C0 J) l/ ?% E9 E! Y
  22.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
    5 l3 u" `5 ]# ]) @0 l9 _
  23.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    : \. @, _2 E/ R
  24.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
    0 @$ _: k( O8 B3 l6 B, P
  25.   GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
    * K# f6 r, L; a8 B1 n' {! i7 P' Y
  26. 6 @" S) [2 l  i2 {4 u; V
  27.   GPIO_InitStruct.Pin = SPI_SCK_PIN;
    $ F1 k8 v6 }/ g/ q& `
  28.   LL_GPIO_Init(SPI_SCK_PORT, &GPIO_InitStruct);; J. U! a: U( v3 f
  29. + X, b. v. t) S) Z2 M4 x
  30.   GPIO_InitStruct.Pin = SPI_MISO_PIN;
    ' M! e/ k/ s+ F
  31.   LL_GPIO_Init(SPI_MISO_PORT, &GPIO_InitStruct);
    $ W7 o4 D/ h& H) G8 w2 l" V  e
  32.   H8 e! ^7 H" b* Z: Q2 |2 `
  33.   GPIO_InitStruct.Pin = SPI_MOSI_PIN;& F4 m+ U$ m* u, ]
  34.   LL_GPIO_Init(SPI_MOSI_PORT, &GPIO_InitStruct);
    % r, z% W/ Z% J$ h. x3 c6 ~
  35. 1 h- k7 G7 M4 F/ z, T' B& j
  36.   /* USER CODE BEGIN SPI1_Init 1 */8 `0 F" l1 j$ i, |6 C
  37. 2 ~; l, |  J+ J& j
  38.   /* USER CODE END SPI1_Init 1 */
    7 [' }& e, D) A! w: U! a4 r7 |( t! v
  39.   SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;7 H8 M9 M3 v2 q4 j; i4 L: z6 x
  40.   SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;1 v3 z; _0 o6 r: d$ {
  41.   SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;$ V2 W) k7 l7 ~" m+ C) s+ _
  42.   SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;
    # S& g1 {5 M- E- y- F5 C: }, D
  43.   SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
    8 T9 P, D" U- N* e: E$ O9 z
  44.   SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
    ) s5 e' G% n/ f
  45.   SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;: Y2 _# t  @: X, x# y$ a- V' d6 Y" S0 N
  46.   SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;! J6 s8 O1 t1 ^5 G5 l4 V- q
  47.   SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
    6 J0 D4 t; c4 ?0 K' I. c2 O, f
  48.   SPI_InitStruct.CRCPoly = 7;
    * P4 }+ U: A) P0 i1 j
  49.   LL_SPI_Init(SPI1, &SPI_InitStruct);6 A% {: {. R$ u) U; p$ `2 T8 f
  50.   LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);6 ~9 B5 n& ^( M; P, g8 {3 ]
  51.   LL_SPI_DisableNSSPulseMgt(SPI1);/ L4 w5 N. k" B  s
  52.   /* USER CODE BEGIN SPI1_Init 2 */
    - [- r3 ~. o7 ~
  53.   LL_SPI_Enable(SPI1); //用户手动使能SPI7 g. k- f) S: v
  54.   /* USER CODE END SPI1_Init 2 */& D: ]0 T1 |5 |

  55. . |+ {0 W, V8 s
  56. }
    ) K0 @7 j' i7 D- }
复制代码
& m. C* G" R/ ]4 G" h1 g  y- K
程序正常运行后,通过在线DEBUG并调出SPI外设后,查看相关寄存器,可以看出SPI能正常发送,但是因为CR2寄存器的RXNE标志一直不能被触发,导致接收不到数据,如下图所示:
% |7 n. Y* _# J3 v
2021060720475766.png

+ v5 t/ H2 `: I9 B- @4 m) C
/ o1 {1 F# w9 X8 b1 p7 s但是相同的设置在STM32F0的标准库上是可以正常运行了,模式配置都一样,但是用LL库的STM32G0上就不能运行,后来查看STM32G031K LL库的使用 - SPI这篇文章,发现代码中额外添加了以下语句:% y$ M. C9 S& z; T7 g* l

# d! p# |/ |( L/ u, g8 J. T
  1. /* Configure the SPI2 FIFO Threshold */
    3 _  L* m6 T9 M" r, w
  2.   LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);//设置RX非空事件产生的FIFO阈值,根据通信时最<span style="background-color: rgb(255, 255, 255);">小数据的大小设置,我这边最小为8位,所以设置为四分之一</span>
复制代码
& I3 s2 _# x8 m
通过查看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标志就一直不能触发,也就接收不到任何数据。0 n4 D  I# |% E* `$ o6 p1 w5 z

* ^) y- ?1 B' ^# r1 b
2021060721150377.png
6 S+ n% ^3 ]6 E7 {* P

8 B9 G3 C( B7 p0 G  n' x% y反观用了标准库函数的STM32F0,同样的设置为什么就可以正常运行呢???通过查看标准库函数SPI_Init(),可以发现函数中对CR2进行了赋值操作,而对应值正是SPI_DataSize_8b这个宏,该宏的值为0x0700,Bit12 FRXTH=1,该值对应FRXTH接收阈值为1/4,所以程序能正常运行,RXNE可以正常触发,这也就解释了为什么同样的配置在标准库上SPI能正常运行,但是在LL库上却不能正常运行的问题所在。- r+ ~6 i; r: R- o6 P1 }0 t

8 s6 N7 U: G7 A* X3 H$ v$ d
  1. void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)' _2 I5 C9 B8 U0 F# B2 s% ]" q! X
  2. {  }. E! n" i, ?# H- W) Z7 j2 @8 Q
  3.         .......
    , }& N( ]9 b0 f! u
  4.          /* Configure SPIx: Data Size */2 z! H' {7 q. _  M2 N! ?1 ^+ i% y4 h
  5.         tmpreg |= (uint16_t)(SPI_InitStruct->SPI_DataSize); //SPI发送接收的数据为8位
    3 Y1 ?  P  s; g
  6.         /* Write to SPIx CR2 */5 O* h) f' D  H& ?% n) A
  7.         SPIx->CR2 = tmpreg; / n6 q1 I: ~0 f# e- j1 H
  8.         ......
复制代码
* O4 p  N7 ~% t9 ~$ G, K

5 {3 l2 @$ D2 U- m
- B. F2 y. g4 q  j- x8 t2 X  W# c) w; ^$ \" f) ?
收藏 评论0 发布时间:2021-11-8 17:04

举报

0个回答

所属标签

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