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

STM32CubeMX-HAL库的SPI接口使用

[复制链接]
STMCU-管管 发布时间:2020-10-19 13:37
STM32CubeMX-HAL库的SPI接口使用
7 U5 V6 @9 A: V; ^, ]* p

8 M. f" |( g0 A8 w# _' _& P本文主要介绍STM32的SPI接口、cubeMX软件配置SPI接口和分析SPI相关代码。
  {" Y" d! x% B* f0 cSTM32之SPI简介:) U4 S1 w/ I" O" ~* ^# A
SPI协议【Serial Peripheral Interface】4 J2 p, p; U: [! z; m0 `6 f: K
    串行外围设备接口,是一种高速全双工的通信总线。主要用在MCU与FLASH\ADC\LCD等模块之间的通信。

1 x1 A2 A1 L4 h' U  w. {) {SPI信号线& v! W4 G0 K: n) [: I4 S
    SPI 共包含 4 条总线。

6 F5 K7 B3 a3 ~& @2 Q6 QSS(Slave Select):片选信号线,当有多个SPI 设备与 MCU 相连时,每个设备的这个片选信号线是与 MCU 单独的引脚相连的,而其他的 SCK、MOSI、MISO 线则为多个设备并联到相同的 SPI 总线上,低电平有效。
& ~$ S9 q$ Z: u; E" c% z  i! W2 bSCK (Serial Clock):时钟信号线,由主通信设备产生,不同的设备支持的时钟频率不一样,如 STM32 的 SPI 时钟频率最大为 f PCLK /2。
& x7 w2 ^) ~" y. BMOSI (Master Output Slave Input):主设备输出 / 从设备输入引脚。主机的数据从这条信号线输出,从机由这条信号线读入数据,即这条线上数据的方向为主机到从机。. ]* _& v, f* g) R% G
MISO(Master Input Slave Output):主设备输入 / 从设备输出引脚。主机从这条信号线读入数据,从机的数据则由这条信号线输出,即在这条线上数据的方向为从机到主机。# H7 M0 S" w& e5 w6 m" Z
    其中SCK,MOSI,MISO是接在一起的,NSS分别接到不同的IO管脚控制。主器件要和从器件通信就先拉低对应从器件的NSS管脚使能。默认状态IO1,IO2,IO3全为高电平,当主器件和从器件1通信时,拉低IO1管脚使能从器件1。而从器件2,3不使能,不作响应。下图是主器件与多个从器件通信图。% M5 [! |$ s% O# o
11.png * w: w2 l7 K( e3 E
SPI特性: B: e3 s! j; H$ Y7 s% u
    单次传输可选择为 8 或 16 位。波特率预分频系数(最大为 fPCLK/2) 。时钟极性(CPOL)和相位(CPHA)可编程设置。数据顺序的传输顺序可进行编程选择,MSB 在前或 LSB 在前。
! w/ k5 e. G9 b# P
    注:MSB(Most Significant Bit)是“最高有效位”,LSB(Least Significant Bit)是“最低有效位”。
: I. a: }, A1 b% T! s    可触发中断的专用发送和接收标志。可以使用 DMA 进行数据传输操作。下图是STM32的SPI框架图。
/ ]' C) A7 u5 o; [% A0 B% F) d
12.png
7 a- M# ^. e; y* I
    如上图,MISO数据线接收到的信号经移位寄存器处理后把数据转移到接收缓冲区,然后这个数据就可以由我们的软件从接收缓冲区读出了。当要发送数据时,我们把数据写入发送缓冲区,硬件将会把它用移位寄存器处理后输出到 MOSI数据线。SCK 的时钟信号则由波特率发生器产生,我们可以通过波特率控制位(BR)来控制它输出的波特率。
& h4 W3 i+ C: p7 R2 h9 A0 \/ o    控制寄存器 CR1掌管着主控制电路,STM32的 SPI模块的协议设置(时钟极性、相位等)就是由它来制定的。而控制寄存器 CR2则用于设置各种中断使能。5 Q7 w! x6 K; c# `5 W
    最后为 NSS引脚,这个引脚扮演着 SPI协议中的SS片选信号线的角色,如果我们把 NSS引脚配置为硬件自动控制,SPI模块能够自动判别它能否成为 SPI的主机,或自动进入 SPI从机模式。但实际上我们用得更多的是由软件控制某些 GPIO引脚单独作为SS信号,这个 GPIO引脚可以随便选择。
6 t9 S9 m2 n4 g4 U$ P$ s5 u5 VSPI时钟时序8 _8 Y; Y7 q# B4 o% y+ q7 N1 J
    根据时钟极性(CPOL)及相位(CPHA)不同,SPI有四种工作模式。
  j& Z, e+ d# n0 s. J    时钟极性(CPOL)定义了时钟空闲状态电平:# r4 F+ v: m! m% Y) w
CPOL=0为时钟空闲时为低电平, E% `8 v6 _3 z, b) @- ]
CPOL=1为时钟空闲时为高电平% u  v* {' Z4 S- f9 S' \
    时钟相位(CPHA)定义数据的采集时间。% D( {7 W% _- _) d3 Z" W
CPHA=0:在时钟的第一个跳变沿(上升沿或下降沿)进行数据采样。
% Q6 ~6 i, O+ z2 i5 @& qCPHA=1:在时钟的第二个跳变沿(上升沿或下降沿)进行数据采样。
7 v4 p; y& v- R% n2 I
13.png 8 P4 U8 E. l# }
CubeMX软件配置SPI:7 \! {% _( Z! D4 s: ~& K
    下面继续介绍cubeMX软件配置STM32L152的SPI接口方法。

; O& ~2 E- f8 K$ i(1)打开软件,选择对应芯片后,配置好时钟源;
, T9 k- S. k+ W* l(2)勾选SPI1为全双工,硬件NSS关闭,如下图:9 m2 y1 s* H5 ~
14.png : K8 @. G# C! }6 J  Y$ |
(3)勾选好后,PA5、PA6、PA7如下图,在配置PA4为普通io口,gpio_output
# i+ Q; \7 Y2 L 15.png
; m/ X# ~7 G1 P2 G: M. r* f: Q(4)SPI1的参数配置选择默认,如下图所示
, C/ V3 _6 w9 i; x3 M0 A* s 16.png
9 q1 T2 ?, w7 K; C  [  n: p  r(5)生成代码,保存即可。
0 s) W# q* ]/ m. `! z% m0 W    HAL库的SPI函数分析:3 ~2 W2 q; K, Q$ ?. k* ]4 U
    下面具体分析下生成的SPI函数和函数调用。
) V  \5 [- Z7 h/ U  L3 l
SPI_HandleTypeDef hspi1; //SPI结构体类定义,下面看其结构体内部的声明。
17.png * l) Q6 F% V: e! i" _5 E
18.png / e% q5 P) k6 i! C! `# w4 [

  Q' B3 R! e# o9 H- m
下面分析SPI的初始化函数:9 T  m2 C! V* V, J  o

5 b: r6 r- \& D2 ]

  1. 5 Z- _- d' j/ l( m
  2. void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi). H& }6 x3 y. I- i" @0 Q4 |: N
  3. {2 X" T! j& y$ v9 k
  4. GPIO_InitTypeDef GPIO_InitStruct;& T! a7 `  m( V; a/ P5 P$ F
  5. if(hspi->Instance==SPI1)
    % y+ \; \' J, U3 j$ Y# J8 K
  6. {) j8 Q% `3 w* s* A& ~' k% H9 D
  7. /* USER CODE BEGIN SPI1_MspInit 0 */* ]) d; `$ c4 s/ N- W7 I& _0 P! `
  8. /* USER CODE END SPI1_MspInit 0 */; k" y' c% \5 |0 X
  9. /* Peripheral clock enable */
    ) n  L5 r2 _. l
  10. __HAL_RCC_SPI1_CLK_ENABLE();//使能SPI1时钟
    # q# z7 O% a# d. G0 ?
  11. /**SPI1 GPIO Configuration" A- h/ w- d+ D, t7 K" D( s8 f' ]
  12. PA5     ------> SPI1_SCK
    / Z) I; \+ o( H8 y& B
  13. PA6     ------> SPI1_MISO) c  w- x  @0 r  h( G7 u
  14. PA7     ------> SPI1_MOSI$ X6 g' Y$ c. e) o4 U0 N
  15. */* K. j+ C9 K7 W/ K, k
  16. GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;" F) G5 h$ q. l7 e' @' b1 Y
  17. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;, l7 T2 U: i" C  N+ @
  18. GPIO_InitStruct.Pull = GPIO_NOPULL;
    & x% O  l' L" W7 }
  19. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;) @* L1 X8 C6 r2 w2 s* q
  20. GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
      h1 Y( f* |! b$ I! v3 {! G
  21. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);//配置SPI的数据线和时钟线  N8 }% G7 @; D0 I  T9 t
  22. /* USER CODE BEGIN SPI1_MspInit 1 */
    ' ?- W9 Q5 y4 e6 Z" B
  23. /* USER CODE END SPI1_MspInit 1 */
    6 m- }' M+ X+ Y. s* A1 l0 M
  24. }! {; L1 ?  v0 A; v. X8 U3 x
  25. 7 V$ u% y# E. D  E5 m
  26. static void MX_SPI1_Init(void)% ^' O- P0 O- q# l( u5 m4 S4 w
  27. {7 L8 B; X  X/ R6 l, k* }
  28. hspi1.Instance = SPI1;" D4 D$ R7 x, r" H! \
  29. hspi1.Init.Mode = SPI_MODE_MASTER;//主模式
    9 S; I( p$ h: P' I" D3 H
  30. hspi1.Init.Direction = SPI_DIRECTION_2LINES;//全双工
    0 \7 G+ @9 z0 I% r) C+ O
  31. hspi1.Init.DataSize = SPI_DATASIZE_8BIT;//数据位为8位1 ]- l1 S$ }& z5 \2 S  a! b
  32. hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;//CPOL=0,low1 }* o% {; M) @/ I" R
  33. hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;//CPHA为数据线的第一个变化沿# O  ]  h! e" g' _% g# q9 Q
  34. hspi1.Init.NSS = SPI_NSS_SOFT;//软件控制NSS
    0 A3 o; ]4 S5 @
  35. hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;//2分频,32M/2=16MHz3 L( h/ D" K) {5 S( Y: I+ f3 `" Z! y) I
  36. hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;//最高位先发送# D; Z! y2 n# }$ d6 v
  37. hspi1.Init.TIMode = SPI_TIMODE_DISABLE;//TIMODE模式关闭
    # ^! _" Q% S. ~0 `" l
  38. hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;//CRC关闭
    $ J: g# y& x! {' m  u( I) W
  39. hspi1.Init.CRCPolynomial = 10;//默认值,无效& \9 @( ]/ x1 J7 [
  40. if (HAL_SPI_Init(&hspi1) != HAL_OK)//初始化
      u7 |- T9 [3 f, q) ?! ]5 Q# v
  41. {
    ' \& ?) b8 w* J5 g5 C
  42. _Error_Handler(__FILE__, __LINE__);" T3 k/ s: }7 u  t' l# }7 j
  43. }
    9 ?8 i; C! s" G" e- ^
  44. }
复制代码
, x# ?! D0 w" ~9 Q, O0 ^
. H1 M% @, r, y
利用SPI接口发送和接收数据主要调用以下两个函数:9 d. B6 N9 R6 F$ I, t7 A

" L) `. X, T: D5 ?# R% j: p& w

  1. 0 W/ ]* o& g& m4 A9 K' M7 I) q
  2. HAL_StatusTypeDef  HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);//发送数据
    & z9 v7 A; x( o8 k2 j$ e" i+ v
  3. HAL_StatusTypeDef  HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);//接收数据
复制代码
: m3 h# v2 h) Q" m+ T; I, |# K; s

6 Y. A6 w; B$ u! Z- p6 X4 W- r  M; ^, Y
5 `- t( E# a& d! t$ m
& h4 d. k: x0 p5 Y; b4 M
; X) ~! S' L1 ^& X2 ^0 s1 g$ e8 y. [  t
6 G6 p% \' P" x' d
赞 收藏 1 评论0 发布时间:2020-10-19 13:37

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版