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

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

[复制链接]
STMCU小助手 发布时间:2021-11-8 17:04
今天准备移植STM32F030R8T6的程序到STM32G030C8T6上,程序中用到了硬件SPI外设,因为STM32G0用的HAL+LL库而不是不是标准库,所以我用STM32Cube MX生成了SPI的LL库代码,但是使能SPI后发现硬件怎么都不能触发RXNE接收标志,生成代码如下:7 _: k# z7 {' k% W' w4 b. e" L; u
! [" F8 X, d' |' o9 i
  1. void MX_SPI1_Init(void)
    1 I: z- g/ B4 q
  2. {
    7 S) H: O& p" R) _$ k
  3. 2 v- w& a: q8 c0 n
  4.   /* USER CODE BEGIN SPI1_Init 0 */
    " ?3 z; @5 T/ a  e' [+ p
  5. . |. \9 Q3 D9 ^+ e$ R
  6.   /* USER CODE END SPI1_Init 0 */0 q0 e" {6 H+ {# z; t/ K- ]

  7. * x( q: J8 h4 ~9 A- k0 J
  8.   LL_SPI_InitTypeDef SPI_InitStruct = {0};3 O: X! D5 Z. D. u

  9. % R8 M* |, y/ j! H3 k" b
  10.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    & X: O- I1 n+ F
  11. 9 m. G7 E" u" `$ F7 e
  12.   /* Peripheral clock enable */
    / k4 V$ Q& e; N4 D- e, D
  13.   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);$ q- l0 u- _9 c# M3 Q$ W

  14. 9 V8 x' Q0 h' a
  15.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);) d& l2 }4 m. ?0 I0 E- A" B) A
  16.   /**SPI1 GPIO Configuration' u( j* d3 a8 v2 @( I1 N# H" g; a
  17.   PA5   ------> SPI1_SCK
    % @0 {: Y- Q& t, O5 g! K
  18.   PA6   ------> SPI1_MISO
    % z5 {+ @7 E0 q/ B
  19.   PA7   ------> SPI1_MOSI2 s# ?& Y. D2 ^+ l8 n
  20.   */& S/ i, N2 V, v
  21.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;; x3 R) h+ s; X& v& ]
  22.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
    " r5 o3 q, o/ c/ E: q
  23.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;$ q8 ~5 M, j% V. E) ^1 z; L
  24.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
      u; a3 \4 z7 X! X$ k/ O9 Q4 f
  25.   GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
    2 F2 I. E, m. V. o( Z& m7 z

  26. " q5 A# H/ p, K: |% o
  27.   GPIO_InitStruct.Pin = SPI_SCK_PIN;7 l6 w% m3 ]0 n4 B
  28.   LL_GPIO_Init(SPI_SCK_PORT, &GPIO_InitStruct);
    2 t- G& f% u, y

  29.   T6 B; X, W+ {
  30.   GPIO_InitStruct.Pin = SPI_MISO_PIN;
    / _7 ^6 i) V0 k- F& [/ n( {
  31.   LL_GPIO_Init(SPI_MISO_PORT, &GPIO_InitStruct);% ~! I9 q" ^! d5 c8 C0 L
  32. , f$ f# H. k8 G
  33.   GPIO_InitStruct.Pin = SPI_MOSI_PIN;
    . A; z7 R3 f' _7 _5 @" P
  34.   LL_GPIO_Init(SPI_MOSI_PORT, &GPIO_InitStruct);" s: C' e8 M& s6 r" ~2 H5 U

  35. 1 g  d# \% g$ Z5 J- N) D* y
  36.   /* USER CODE BEGIN SPI1_Init 1 */
    : G& N& o7 f+ a) s
  37. 7 A# G  ?7 g, L' g
  38.   /* USER CODE END SPI1_Init 1 */( w' p, P) u+ j& E
  39.   SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
    9 v" ~2 @4 i$ e7 h/ ?, o- n
  40.   SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;( _4 H. j/ C  B: O+ [# y7 e
  41.   SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
    , a9 ^; [9 X3 {2 a( w' L/ U
  42.   SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;5 b. ^4 p2 x3 O% V8 }7 ?+ j
  43.   SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
    $ y! m4 a+ r$ G$ g4 z* b
  44.   SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;" l: L, {, I  u+ M3 P  {
  45.   SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;
    0 c4 O; S1 ]( K/ z7 t' {
  46.   SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
    / O9 c2 @& h: A! f% x! e7 a* M7 D
  47.   SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;- @7 J9 C. `$ D0 g( ^+ r' F
  48.   SPI_InitStruct.CRCPoly = 7;; r$ s2 a" z3 D1 M3 x
  49.   LL_SPI_Init(SPI1, &SPI_InitStruct);% D8 x8 Z- ~; `, t
  50.   LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
    : \& U$ M7 y: H: E5 B
  51.   LL_SPI_DisableNSSPulseMgt(SPI1);
    " @/ J( Z, c! D' s  h8 f
  52.   /* USER CODE BEGIN SPI1_Init 2 */
    . |+ K: q  m9 w7 W3 a
  53.   LL_SPI_Enable(SPI1); //用户手动使能SPI
    ! L5 T, p' S3 S' |1 A  a: e5 B
  54.   /* USER CODE END SPI1_Init 2 */& c  i2 p9 c5 b; Y

  55. ; ~& ~0 l0 M  x7 z  y! H5 J
  56. }% k, N9 g- D  E( p& b% H6 p$ T  d. }* p
复制代码
  i- X/ H$ @( R
程序正常运行后,通过在线DEBUG并调出SPI外设后,查看相关寄存器,可以看出SPI能正常发送,但是因为CR2寄存器的RXNE标志一直不能被触发,导致接收不到数据,如下图所示:+ l' Z* |, i9 t& v% k
2021060720475766.png
0 ~. M3 I5 i' V, s
4 y8 j* r! W, T
但是相同的设置在STM32F0的标准库上是可以正常运行了,模式配置都一样,但是用LL库的STM32G0上就不能运行,后来查看STM32G031K LL库的使用 - SPI这篇文章,发现代码中额外添加了以下语句:
+ p) U. r! [9 X6 L
* Z! x8 u1 R# J. r! |, d; V
  1. /* Configure the SPI2 FIFO Threshold */4 K9 I1 b+ s" G2 P
  2.   LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);//设置RX非空事件产生的FIFO阈值,根据通信时最<span style="background-color: rgb(255, 255, 255);">小数据的大小设置,我这边最小为8位,所以设置为四分之一</span>
复制代码
5 ?: _- W! N) e: w( w# J2 e
通过查看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标志就一直不能触发,也就接收不到任何数据。
7 D) [- f6 q7 K( U+ ~4 V8 j) t3 b  Z8 L
2021060721150377.png
- w6 |2 x: K# M; ]$ [1 y

8 x/ Q6 ^& T0 R% W% A反观用了标准库函数的STM32F0,同样的设置为什么就可以正常运行呢???通过查看标准库函数SPI_Init(),可以发现函数中对CR2进行了赋值操作,而对应值正是SPI_DataSize_8b这个宏,该宏的值为0x0700,Bit12 FRXTH=1,该值对应FRXTH接收阈值为1/4,所以程序能正常运行,RXNE可以正常触发,这也就解释了为什么同样的配置在标准库上SPI能正常运行,但是在LL库上却不能正常运行的问题所在。$ m5 o! \0 P7 ?7 H

( t9 ]; h0 O9 {
  1. void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)+ V1 [3 r  R( A
  2. {
    $ N6 W) \# K7 ^$ v  z
  3.         .......
    & x' N) d$ s3 ?2 G
  4.          /* Configure SPIx: Data Size */$ m, A! Q; E4 u, F0 I
  5.         tmpreg |= (uint16_t)(SPI_InitStruct->SPI_DataSize); //SPI发送接收的数据为8位
    - l/ ]& q2 U9 `  A  R1 b; k4 `
  6.         /* Write to SPIx CR2 */
    6 A( K) _  i( i5 i  F6 V
  7.         SPIx->CR2 = tmpreg;
    , [) G& i: m& y4 C- l5 r* L: {5 `
  8.         ......
复制代码

0 p# f. e0 F; X0 o' \
' \6 |" I; {  r& e/ x' {  s5 j( q& n" w" `. T7 B
# R& s+ q2 h7 a  t0 Z# h# o
收藏 评论0 发布时间:2021-11-8 17:04

举报

0个回答

所属标签

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