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

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

[复制链接]
STMCU小助手 发布时间:2021-11-8 17:04
今天准备移植STM32F030R8T6的程序到STM32G030C8T6上,程序中用到了硬件SPI外设,因为STM32G0用的HAL+LL库而不是不是标准库,所以我用STM32Cube MX生成了SPI的LL库代码,但是使能SPI后发现硬件怎么都不能触发RXNE接收标志,生成代码如下:, I* [! q2 y# ?' U6 i. n+ e

/ z4 i8 o  _/ K; p" w/ O
  1. void MX_SPI1_Init(void)
    2 j; }9 m2 i5 E  R7 m/ l
  2. {) c1 K" }3 d% f& x- y0 s; G, f

  3. , A7 H9 X8 o# t# {0 ?9 D7 R, `
  4.   /* USER CODE BEGIN SPI1_Init 0 */
    : X* t* v  w4 J1 q
  5. . T2 b& S4 N+ m
  6.   /* USER CODE END SPI1_Init 0 */
    7 w! w* ?1 U  p- I2 _* R
  7. / H1 k3 n" t! \* v6 t
  8.   LL_SPI_InitTypeDef SPI_InitStruct = {0};) g% I- w0 J+ v6 O* l
  9. 0 j2 L# F$ o1 Z1 n( _& Y
  10.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    2 g$ t0 t9 P% [- n; ^4 }' i- E

  11. # k; i5 R; N2 ~  x3 I( S
  12.   /* Peripheral clock enable */3 M- M: I- A7 F4 R
  13.   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
    * x0 X; s- x( w0 w, i
  14. , g& U, n  u+ e* s# z* ^$ f
  15.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
    # y1 y" R& T* U1 L/ a6 A
  16.   /**SPI1 GPIO Configuration
    ( K" F4 Q& ], E9 f8 o" z' P
  17.   PA5   ------> SPI1_SCK3 J% E! a' A8 H3 j  u
  18.   PA6   ------> SPI1_MISO
    + }1 Z8 a+ O, Y# a- o% h3 ]( f% E
  19.   PA7   ------> SPI1_MOSI6 S: H5 A! z* x
  20.   */
    ! E) C# {2 U9 u
  21.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;3 `) T+ e, |+ r; u3 \2 y
  22.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;, M# U8 _# |8 f5 N; P
  23.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;) D" }/ H$ q0 S4 k0 R: Y1 \
  24.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;  x& [: J% o# C
  25.   GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
    - ]- ]' L* b8 M, V! R5 r) u/ ^5 N

  26. / y2 v# \: B5 r( Y' x; s# e
  27.   GPIO_InitStruct.Pin = SPI_SCK_PIN;
    ; s% Q' A9 w3 e2 B) r9 }" D2 E
  28.   LL_GPIO_Init(SPI_SCK_PORT, &GPIO_InitStruct);
    % \8 r/ u% K' u# n$ {, n4 n
  29. $ v0 w9 ]4 ^% n7 w, O5 Y
  30.   GPIO_InitStruct.Pin = SPI_MISO_PIN;
    % P8 d* u" S- B6 \' _( @& Y
  31.   LL_GPIO_Init(SPI_MISO_PORT, &GPIO_InitStruct);+ `9 T! N6 g! X3 V9 v
  32. 5 J- q" P/ Q/ {
  33.   GPIO_InitStruct.Pin = SPI_MOSI_PIN;
    - s( X0 h* k7 X+ M
  34.   LL_GPIO_Init(SPI_MOSI_PORT, &GPIO_InitStruct);* G0 u. S3 p5 ~
  35. 0 b# j6 u4 N/ |1 ^. a! Z
  36.   /* USER CODE BEGIN SPI1_Init 1 */
    # p) L4 Z& n7 v! W" c4 z9 }8 u

  37. : @* }6 Z2 B$ e3 x& T# \- \
  38.   /* USER CODE END SPI1_Init 1 */1 N/ ^- [# f+ F8 D4 ^7 ^" t6 q: h
  39.   SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
    * h( b+ b9 K# L1 {% r. J/ F' j  |
  40.   SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
    * L% X7 }" I9 q# Z  J3 t
  41.   SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
    ) t6 f# `; H' D, x
  42.   SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;
    - T" k: V( b( c' b
  43.   SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;) x1 G: f, [: ~  k) C/ z" r2 Z
  44.   SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
    2 `3 H% X( o4 c" y- @8 f
  45.   SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;
    3 m8 B. l9 v3 N& p  f
  46.   SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;/ ^' ?0 ?$ k2 t7 t2 H
  47.   SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
    ' J4 O; a( \! g9 K0 D1 k
  48.   SPI_InitStruct.CRCPoly = 7;
    7 }0 u, N# Q; J. e# M5 ]9 S5 I
  49.   LL_SPI_Init(SPI1, &SPI_InitStruct);
    % z; P( J- b7 F2 O! h4 H% V* b3 e
  50.   LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);6 @7 w+ H) z1 a
  51.   LL_SPI_DisableNSSPulseMgt(SPI1);  O* G  p9 k2 `$ M4 j5 a
  52.   /* USER CODE BEGIN SPI1_Init 2 */" c7 e# f; I+ M  [
  53.   LL_SPI_Enable(SPI1); //用户手动使能SPI
    , V' s5 A3 ^# Z; P1 G( D2 O8 v
  54.   /* USER CODE END SPI1_Init 2 */# v7 t& i0 x( P" Q5 Y. i  D; C- @. |; E
  55. ) I! W& l) H& `! @4 G
  56. }% G' l1 n  F5 @. h1 P0 J8 R# H
复制代码
' n6 E, g' r1 Z* S& R& n( [
程序正常运行后,通过在线DEBUG并调出SPI外设后,查看相关寄存器,可以看出SPI能正常发送,但是因为CR2寄存器的RXNE标志一直不能被触发,导致接收不到数据,如下图所示:
8 b2 |( X( r/ A( o/ s
2021060720475766.png

+ @4 E: d% l9 T5 N& a* k
8 h4 o( r" h3 V# ]8 ^但是相同的设置在STM32F0的标准库上是可以正常运行了,模式配置都一样,但是用LL库的STM32G0上就不能运行,后来查看STM32G031K LL库的使用 - SPI这篇文章,发现代码中额外添加了以下语句:
; `# ]7 U3 S8 q# [8 U" k  H2 u, ]& o* s! \2 \# Z0 [
  1. /* Configure the SPI2 FIFO Threshold */) u" g  ]5 \* l
  2.   LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);//设置RX非空事件产生的FIFO阈值,根据通信时最<span style="background-color: rgb(255, 255, 255);">小数据的大小设置,我这边最小为8位,所以设置为四分之一</span>
复制代码
* F& X2 a( J! G! I6 k# f  w
通过查看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标志就一直不能触发,也就接收不到任何数据。
( E$ x5 x1 k3 h' [% y9 c" d; F. s1 k
2021060721150377.png

: a3 f/ V  T" {& U& {
3 O# _/ {  ~! y, B. X反观用了标准库函数的STM32F0,同样的设置为什么就可以正常运行呢???通过查看标准库函数SPI_Init(),可以发现函数中对CR2进行了赋值操作,而对应值正是SPI_DataSize_8b这个宏,该宏的值为0x0700,Bit12 FRXTH=1,该值对应FRXTH接收阈值为1/4,所以程序能正常运行,RXNE可以正常触发,这也就解释了为什么同样的配置在标准库上SPI能正常运行,但是在LL库上却不能正常运行的问题所在。) n+ {; C  I* N. s" D1 K+ c

6 p8 m1 a) {- i2 W( C/ x+ t
  1. void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct). h# J# D, O/ {
  2. {
    ! ^* _, M+ I2 o9 z9 }) t
  3.         .......* S2 n8 C; Y6 `5 g2 S( B
  4.          /* Configure SPIx: Data Size */0 D1 a% K) t! }' L
  5.         tmpreg |= (uint16_t)(SPI_InitStruct->SPI_DataSize); //SPI发送接收的数据为8位/ b7 v: v# e- d0 X* i7 N
  6.         /* Write to SPIx CR2 */+ C% Z8 J* A# r6 N. n
  7.         SPIx->CR2 = tmpreg;
    * }% l0 c, o( X* J' {
  8.         ......
复制代码

5 a2 l% {- O  u0 Z$ K' F3 U$ N+ R. |
. n, E1 k4 r. @4 s; ?4 _% ^2 |0 Z2 R7 h1 v. `
. b7 a% c8 H0 L1 K% ~, K
收藏 评论0 发布时间:2021-11-8 17:04

举报

0个回答

所属标签

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