今天准备移植STM32F030R8T6的程序到STM32G030C8T6上,程序中用到了硬件SPI外设,因为STM32G0用的HAL+LL库而不是不是标准库,所以我用STM32Cube MX生成了SPI的LL库代码,但是使能SPI后发现硬件怎么都不能触发RXNE接收标志,生成代码如下:5 }; \: S: i2 ^6 F
! Q5 W5 B2 A) F* [$ o6 D
- void MX_SPI1_Init(void)
* n& K. r, n6 X - {( u X G. ?! }# S* _' O
- 7 p; w/ A+ \/ M: K6 L& n
- /* USER CODE BEGIN SPI1_Init 0 */- `$ F, W4 {9 R% J+ B) _7 j
- " Z. [# S+ O+ I5 }0 h
- /* USER CODE END SPI1_Init 0 */
) w* T/ ] C3 |. e. K0 m9 ~ - - p% L9 ?: {6 j7 G8 P$ l6 _$ }
- LL_SPI_InitTypeDef SPI_InitStruct = {0};
/ A# \6 Q$ _5 ] - 6 G3 d, Q; ]. Q. b+ V7 R
- LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
5 @' D5 R8 u f/ E: q" V2 U7 m
2 |/ `4 g# Y# N9 a& n m- /* Peripheral clock enable */
8 z% X4 [# C! ~2 B" h: A - LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);2 n8 J0 }, s4 v# W' Z
+ Z1 u1 m) D' H: ~8 B7 K a- LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);8 V' H( I7 }0 ]. s. @: T. o2 G
- /**SPI1 GPIO Configuration
' S' u' w0 j5 ]& v# B4 R - PA5 ------> SPI1_SCK
9 u' t$ _ V& o$ v8 H9 E/ k: u+ O - PA6 ------> SPI1_MISO2 Q$ V0 I3 f$ s, |
- PA7 ------> SPI1_MOSI: p& Y, A+ ~/ c. N+ {2 X7 J' T8 @4 q% [
- */' \' d3 S' Y- u' G* Q* u' L
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;/ _, @, a- F2 _9 ~( [' m0 Q
- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;+ h9 y6 n" e7 B9 m7 X7 q7 `/ u
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;8 O5 B, o, t% c
- GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
2 |3 R5 h' }/ K3 j - GPIO_InitStruct.Alternate = LL_GPIO_AF_0;6 J" V. j! k3 M0 D) n7 Z/ N1 {; h
- 8 ?+ G1 e' a8 ~; R
- GPIO_InitStruct.Pin = SPI_SCK_PIN;# j8 I' J0 Z9 D5 D0 f
- LL_GPIO_Init(SPI_SCK_PORT, &GPIO_InitStruct);* L0 t v j _
: R' D3 ?+ x7 K; }- GPIO_InitStruct.Pin = SPI_MISO_PIN;. G) l" [( u) u* \
- LL_GPIO_Init(SPI_MISO_PORT, &GPIO_InitStruct);/ @' ^/ W |% }8 y6 g5 Y6 {! T: I1 @
- 3 Y9 K: |0 Y' u8 n) k" ~
- GPIO_InitStruct.Pin = SPI_MOSI_PIN;1 f* r. z) |/ `+ r" K
- LL_GPIO_Init(SPI_MOSI_PORT, &GPIO_InitStruct);
3 T, Q4 G- v/ v, A5 L/ _2 I - + Y: B" }% \3 j8 G, [5 n# e% ~" a5 N
- /* USER CODE BEGIN SPI1_Init 1 */
! ?- g1 X4 C9 k8 @
# `! A* Q& p; n; S( Y4 C3 ~6 H- /* USER CODE END SPI1_Init 1 */
6 r0 R8 S! B& u) I* q: q - SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
- N: S4 ?0 R, G - SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
) N1 q" v6 f. d: y6 ^+ S - SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
: ]/ R8 l6 N5 N) J+ V2 J1 z - SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;
( Z/ m. x( Y' q+ h2 p' ]6 d - SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
' o4 `1 r3 Z$ F% }3 r3 W* ? - SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
. H9 E8 v( I0 C# V - SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;
1 V) p) S5 m% @ - SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
+ |6 d2 e2 M/ r$ L6 X; }) l+ t. N, l: T9 a - SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
+ l- Z$ v5 W( S3 f - SPI_InitStruct.CRCPoly = 7;# K1 z' i2 M+ W2 t' p
- LL_SPI_Init(SPI1, &SPI_InitStruct); f) y$ M7 P8 U$ N
- LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
y, p) v* X/ [8 L0 s - LL_SPI_DisableNSSPulseMgt(SPI1);
% S) _- R2 D+ {9 o - /* USER CODE BEGIN SPI1_Init 2 */
7 e. c" m" x8 A. u7 U% Y" H/ P - LL_SPI_Enable(SPI1); //用户手动使能SPI% f% a" t, y: `( c/ ~' K$ T4 k
- /* USER CODE END SPI1_Init 2 */$ q7 N" r1 |7 E
- ' M7 o m H$ A: d( O
- }
2 G) c' k6 e& P: ^! D
复制代码
G' R3 i. a- S' w% U程序正常运行后,通过在线DEBUG并调出SPI外设后,查看相关寄存器,可以看出SPI能正常发送,但是因为CR2寄存器的RXNE标志一直不能被触发,导致接收不到数据,如下图所示:7 u( l6 u; l. r
) D/ Y% r) f, o' _. P( m+ `9 O0 r
% u7 k d9 G+ z2 }! D1 } ~6 ~但是相同的设置在STM32F0的标准库上是可以正常运行了,模式配置都一样,但是用LL库的STM32G0上就不能运行,后来查看STM32G031K LL库的使用 - SPI这篇文章,发现代码中额外添加了以下语句:3 M9 v7 W* u! U& T! N; V- @0 ?- H
4 B$ C4 m+ A, p# k& ?$ j- /* Configure the SPI2 FIFO Threshold */) c9 W4 |! @; m8 J# {2 h
- LL_SPI_SetRxFIFOThreshold(SPI2, LL_SPI_RX_FIFO_TH_QUARTER);//设置RX非空事件产生的FIFO阈值,根据通信时最<span style="background-color: rgb(255, 255, 255);">小数据的大小设置,我这边最小为8位,所以设置为四分之一</span>
复制代码 0 z5 V. c; t8 _4 C0 K: H
通过查看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 @. s* u" o4 i4 y! z) P
# A" o" N5 U! a4 ?% N( y! |1 X
# o) t8 s& d6 p* _
7 S3 g) d- X5 |$ o7 }- Z0 h反观用了标准库函数的STM32F0,同样的设置为什么就可以正常运行呢???通过查看标准库函数SPI_Init(),可以发现函数中对CR2进行了赋值操作,而对应值正是SPI_DataSize_8b这个宏,该宏的值为0x0700,Bit12 FRXTH=1,该值对应FRXTH接收阈值为1/4,所以程序能正常运行,RXNE可以正常触发,这也就解释了为什么同样的配置在标准库上SPI能正常运行,但是在LL库上却不能正常运行的问题所在。: L4 }! A( N7 c
7 [8 U# f3 x5 B1 I% y a$ p" d- void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)
1 d3 R7 |# o0 [. B$ o& O - {
) _+ ?' t; h" q$ J4 h5 Q - .......1 E* @1 I$ t$ W7 i% T0 U& b
- /* Configure SPIx: Data Size */
6 p/ i6 w6 M, @ - tmpreg |= (uint16_t)(SPI_InitStruct->SPI_DataSize); //SPI发送接收的数据为8位. V$ d1 J9 H0 `( h
- /* Write to SPIx CR2 */3 i' I6 B% e% B% a: ` i' g- F9 _, R
- SPIx->CR2 = tmpreg;
9 p# ^1 ^% j9 F" N- u+ Z - ......
复制代码
2 Q' _( u% l5 X' @. f: z6 a
9 g. j' Q% r. w+ T* R d% o3 @% c* M8 ?2 Z! u4 d# D8 G: {
9 {( H% v2 C# j& c+ g' @
|