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

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

[复制链接]
STMCU小助手 发布时间:2021-11-8 17:04
今天准备移植STM32F030R8T6的程序到STM32G030C8T6上,程序中用到了硬件SPI外设,因为STM32G0用的HAL+LL库而不是不是标准库,所以我用STM32Cube MX生成了SPI的LL库代码,但是使能SPI后发现硬件怎么都不能触发RXNE接收标志,生成代码如下:
5 u* B0 `; _) l, M
' m) o" H' K( ?' O& s
  1. void MX_SPI1_Init(void)
    / }5 d- {$ t8 b& c% k5 P+ Q
  2. {
    9 @3 H) ]1 r7 p% I3 c- u* b& o

  3. / z6 H7 v( q8 s, b8 @% X
  4.   /* USER CODE BEGIN SPI1_Init 0 */7 x3 S, R& k) K

  5. 4 G5 G/ N: m. L
  6.   /* USER CODE END SPI1_Init 0 */
    ! q% _9 B' S3 U6 k1 I

  7. ! Y, y) |  C9 F; U( k/ ~' O
  8.   LL_SPI_InitTypeDef SPI_InitStruct = {0};% L- w9 D: q2 t; |9 T+ G0 q$ Y9 ~
  9. ( v- d! }8 D4 c. z% v- Q
  10.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    / J4 o9 e7 U3 d) K4 [* r$ F

  11. . `6 A6 k4 T5 v( [
  12.   /* Peripheral clock enable */! c0 X: a- P! T- a# s: N7 W
  13.   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);! D2 E5 M1 e, \+ a! [: g

  14. + [, i! Z- T/ f. {1 Z! Z4 w! J$ i
  15.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
    : O- B& _0 f1 t' z
  16.   /**SPI1 GPIO Configuration. I; H: y& c0 W4 I9 z8 _
  17.   PA5   ------> SPI1_SCK
    0 r) \+ B7 S% F" W4 i
  18.   PA6   ------> SPI1_MISO) {! _% W$ _  u/ q! f0 U. r+ m/ B4 d
  19.   PA7   ------> SPI1_MOSI
    # g  |0 L. A& P: |3 e
  20.   */
    ( u2 Y- ], J" t/ H
  21.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    ( _' H" x. ?8 M4 k( t+ W. P4 T- C0 W
  22.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
    8 H4 l+ ~$ v( e" q) A" e9 S
  23.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;* y* l0 t# W! f, g/ J
  24.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;6 H. e- U  L" t: Q9 |
  25.   GPIO_InitStruct.Alternate = LL_GPIO_AF_0;& [6 w# N& Z  \6 d/ D

  26. ' j+ c( T/ ^) y0 a  W! F8 j. n* Y0 q0 A
  27.   GPIO_InitStruct.Pin = SPI_SCK_PIN;$ t. A( x7 K3 v+ f& Y9 J! \/ P! }5 R
  28.   LL_GPIO_Init(SPI_SCK_PORT, &GPIO_InitStruct);$ X  k+ ]: b' Z5 Q9 M; h

  29. " u- u+ F4 V; U( A) C
  30.   GPIO_InitStruct.Pin = SPI_MISO_PIN;$ I/ V/ _* `  w
  31.   LL_GPIO_Init(SPI_MISO_PORT, &GPIO_InitStruct);
    . {5 X6 ~+ X  N& V
  32. : {1 G' B7 |0 V/ f& x8 Q( e- r
  33.   GPIO_InitStruct.Pin = SPI_MOSI_PIN;- M, [7 K1 ?6 T; p( U) d
  34.   LL_GPIO_Init(SPI_MOSI_PORT, &GPIO_InitStruct);
    - D7 H! k; r& R8 L
  35. ' U' k. z, o% z7 T$ n* L8 U. Z
  36.   /* USER CODE BEGIN SPI1_Init 1 */9 I/ T( [* s) s: }; [: R5 g" C: m* t

  37. * B! U; F6 @9 h
  38.   /* USER CODE END SPI1_Init 1 */+ W! d/ Q& f$ x& M% Z
  39.   SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;3 J. [6 L/ Y4 n8 Y- |& D8 M
  40.   SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
    3 ?5 e7 z* b! u9 ~: e5 Q7 H
  41.   SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
    4 x, s5 e% V6 y% S& B& s, _
  42.   SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;
      o3 W, g- b0 ^! m
  43.   SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
    % O3 v+ W/ G' \. ^( }
  44.   SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
    * X6 I% i  l5 P* m" e
  45.   SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;! @- P) g( R, s. G6 ~% [5 I  ^: t
  46.   SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;. ~3 x3 T' f& O+ |' `
  47.   SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;8 q) @* z4 g' \8 J5 N5 U; C
  48.   SPI_InitStruct.CRCPoly = 7;
    $ d2 u) G: Q/ A( h" v) i
  49.   LL_SPI_Init(SPI1, &SPI_InitStruct);
    0 O3 J# c/ K5 n" {0 K' q; a
  50.   LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
    & b7 H- Z# G2 q7 E8 f
  51.   LL_SPI_DisableNSSPulseMgt(SPI1);* g2 `; [4 U4 c! ]
  52.   /* USER CODE BEGIN SPI1_Init 2 */
    2 e1 ?; N0 Q7 S- w( Y; j. M" U
  53.   LL_SPI_Enable(SPI1); //用户手动使能SPI1 O1 n" B0 {$ K$ T9 ?
  54.   /* USER CODE END SPI1_Init 2 */& E& a' h5 ?  M  }2 r2 [

  55. 0 x- }1 v/ S! J$ F( V) |; p
  56. }
    - P! _7 ?4 B& L6 V3 K+ H  u& y  L
复制代码

* g, o/ ^8 Z. m8 `, d/ e3 E程序正常运行后,通过在线DEBUG并调出SPI外设后,查看相关寄存器,可以看出SPI能正常发送,但是因为CR2寄存器的RXNE标志一直不能被触发,导致接收不到数据,如下图所示:
) ^, D! p9 V9 x/ H* ]2 I
2021060720475766.png
5 s9 |" [7 A: I0 Y

) L0 j. M, s' t/ k" ^3 H但是相同的设置在STM32F0的标准库上是可以正常运行了,模式配置都一样,但是用LL库的STM32G0上就不能运行,后来查看STM32G031K LL库的使用 - SPI这篇文章,发现代码中额外添加了以下语句:4 W4 d3 J8 h% n2 G8 `( a
" m; H( T+ |5 B# E: F
  1. /* Configure the SPI2 FIFO Threshold */4 v- h: `+ t# O4 `$ P" J
  2.   LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);//设置RX非空事件产生的FIFO阈值,根据通信时最<span style="background-color: rgb(255, 255, 255);">小数据的大小设置,我这边最小为8位,所以设置为四分之一</span>
复制代码

! h2 t# k7 t& d0 @通过查看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标志就一直不能触发,也就接收不到任何数据。# C( o8 n) @) b$ H

7 N% `& ~9 j6 Z4 |4 K+ u
2021060721150377.png
7 Z+ B9 U$ F0 G! E, y

# s% B8 P2 V3 Y# M9 H1 W, E反观用了标准库函数的STM32F0,同样的设置为什么就可以正常运行呢???通过查看标准库函数SPI_Init(),可以发现函数中对CR2进行了赋值操作,而对应值正是SPI_DataSize_8b这个宏,该宏的值为0x0700,Bit12 FRXTH=1,该值对应FRXTH接收阈值为1/4,所以程序能正常运行,RXNE可以正常触发,这也就解释了为什么同样的配置在标准库上SPI能正常运行,但是在LL库上却不能正常运行的问题所在。" U" g* y4 f! S

$ _( v/ |; [4 G' w3 ~
  1. void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)  {7 C7 z7 h' l9 y9 y
  2. {
    9 V  r- y" u1 r5 k* V0 y. W
  3.         .......
    ( j* j/ E( k. W$ x) q$ |
  4.          /* Configure SPIx: Data Size */* \8 n2 L3 g) ^$ ]7 [
  5.         tmpreg |= (uint16_t)(SPI_InitStruct->SPI_DataSize); //SPI发送接收的数据为8位' G( @+ |. d5 r$ g% H: u" t$ u
  6.         /* Write to SPIx CR2 */
    , E0 M! r6 G5 k( [, v& D) `
  7.         SPIx->CR2 = tmpreg; : ]- {' }; a. W9 m5 w2 k
  8.         ......
复制代码

% O/ i! A. m- M, N# U" ~( L/ j
6 a9 G- s7 `% d( k
- g3 j6 o/ [( r) `5 I: h% E! y3 M& V2 `6 `' K0 T! f8 V5 ~6 T; @
收藏 评论0 发布时间:2021-11-8 17:04

举报

0个回答

所属标签

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