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

STM32CubeMX-HAL库的SPI接口使用

[复制链接]
STMCU-管管 发布时间:2020-10-19 13:37
STM32CubeMX-HAL库的SPI接口使用
; e9 p( S. K! u% ^4 m

' O# F  g9 E" j8 _( z+ o- i+ X本文主要介绍STM32的SPI接口、cubeMX软件配置SPI接口和分析SPI相关代码。8 @6 x/ ]& b. n6 p. y2 k
STM32之SPI简介:" |9 a" ?4 l1 e/ T: a0 t
SPI协议【Serial Peripheral Interface】
8 h1 W1 v9 d7 U$ l+ j8 B    串行外围设备接口,是一种高速全双工的通信总线。主要用在MCU与FLASH\ADC\LCD等模块之间的通信。

  [; X6 W0 r3 c0 A) hSPI信号线5 c3 m$ `. B9 v' C
    SPI 共包含 4 条总线。

6 @" h( K5 O% oSS(Slave Select):片选信号线,当有多个SPI 设备与 MCU 相连时,每个设备的这个片选信号线是与 MCU 单独的引脚相连的,而其他的 SCK、MOSI、MISO 线则为多个设备并联到相同的 SPI 总线上,低电平有效。# c: ]( S7 H- i
SCK (Serial Clock):时钟信号线,由主通信设备产生,不同的设备支持的时钟频率不一样,如 STM32 的 SPI 时钟频率最大为 f PCLK /2。
4 a0 n) V# r$ b$ X* FMOSI (Master Output Slave Input):主设备输出 / 从设备输入引脚。主机的数据从这条信号线输出,从机由这条信号线读入数据,即这条线上数据的方向为主机到从机。
1 D7 D& W, N9 G2 o9 O0 ]MISO(Master Input Slave Output):主设备输入 / 从设备输出引脚。主机从这条信号线读入数据,从机的数据则由这条信号线输出,即在这条线上数据的方向为从机到主机。
' S/ a1 x$ j/ r/ h# Q; J( f& ]    其中SCK,MOSI,MISO是接在一起的,NSS分别接到不同的IO管脚控制。主器件要和从器件通信就先拉低对应从器件的NSS管脚使能。默认状态IO1,IO2,IO3全为高电平,当主器件和从器件1通信时,拉低IO1管脚使能从器件1。而从器件2,3不使能,不作响应。下图是主器件与多个从器件通信图。. I8 ^. G% _8 @2 r- V! p% B
11.png
  L  j" ?4 h( Q4 A( w! @0 P
SPI特性& @( {: H: C# k$ o2 l' [
    单次传输可选择为 8 或 16 位。波特率预分频系数(最大为 fPCLK/2) 。时钟极性(CPOL)和相位(CPHA)可编程设置。数据顺序的传输顺序可进行编程选择,MSB 在前或 LSB 在前。
& y8 {1 Q; u0 d# u
    注:MSB(Most Significant Bit)是“最高有效位”,LSB(Least Significant Bit)是“最低有效位”。8 Y5 X6 U( c. O# I
    可触发中断的专用发送和接收标志。可以使用 DMA 进行数据传输操作。下图是STM32的SPI框架图。$ G, K, Z" i9 k$ ^% ?
12.png 0 e' B/ }* a: Q
    如上图,MISO数据线接收到的信号经移位寄存器处理后把数据转移到接收缓冲区,然后这个数据就可以由我们的软件从接收缓冲区读出了。当要发送数据时,我们把数据写入发送缓冲区,硬件将会把它用移位寄存器处理后输出到 MOSI数据线。SCK 的时钟信号则由波特率发生器产生,我们可以通过波特率控制位(BR)来控制它输出的波特率。: q, A% R0 O! h3 {8 A* j
    控制寄存器 CR1掌管着主控制电路,STM32的 SPI模块的协议设置(时钟极性、相位等)就是由它来制定的。而控制寄存器 CR2则用于设置各种中断使能。
6 X" Y0 @! _: J% v6 W0 o  L6 W    最后为 NSS引脚,这个引脚扮演着 SPI协议中的SS片选信号线的角色,如果我们把 NSS引脚配置为硬件自动控制,SPI模块能够自动判别它能否成为 SPI的主机,或自动进入 SPI从机模式。但实际上我们用得更多的是由软件控制某些 GPIO引脚单独作为SS信号,这个 GPIO引脚可以随便选择。
( P1 H. D5 {- U( v2 TSPI时钟时序6 |8 Q/ d; U! o% h9 c$ T. I7 T. S
    根据时钟极性(CPOL)及相位(CPHA)不同,SPI有四种工作模式。
" V* J: n' ~+ S0 C    时钟极性(CPOL)定义了时钟空闲状态电平:
  H! f4 A( k8 f$ E& CCPOL=0为时钟空闲时为低电平
' H" U+ b* B* k( ?CPOL=1为时钟空闲时为高电平0 c3 Q  S, D* r) `+ k
    时钟相位(CPHA)定义数据的采集时间。2 q6 M( s2 t- ]7 s5 E
CPHA=0:在时钟的第一个跳变沿(上升沿或下降沿)进行数据采样。8 _# _) J4 s# H2 r1 |
CPHA=1:在时钟的第二个跳变沿(上升沿或下降沿)进行数据采样。
3 f$ P" [# T! B" X1 \( L9 s
13.png # O1 p! k) ^7 x- A7 x4 z
CubeMX软件配置SPI:
( \2 P- b: X8 i) E- S& r7 Y" P" Y    下面继续介绍cubeMX软件配置STM32L152的SPI接口方法。

, m# C# @  Y* P(1)打开软件,选择对应芯片后,配置好时钟源;6 g5 u+ K# j. N: @+ ]
(2)勾选SPI1为全双工,硬件NSS关闭,如下图:' X/ p* i3 ^4 l6 O- c
14.png
# Y# M! u) e( w  R  o5 `3 ^1 @(3)勾选好后,PA5、PA6、PA7如下图,在配置PA4为普通io口,gpio_output
" P$ B7 Q  ^2 K: H+ J+ E 15.png
0 n9 z/ P# B1 l6 x8 I(4)SPI1的参数配置选择默认,如下图所示$ M  c# h* N4 }' [# R
16.png ! h& v( y; o9 S& q* I
(5)生成代码,保存即可。
4 e. l: E# i, \$ g    HAL库的SPI函数分析:6 i% T$ X( Y" W6 a: g; _' X% u
    下面具体分析下生成的SPI函数和函数调用。
  \2 V; ~9 N. \0 P
SPI_HandleTypeDef hspi1; //SPI结构体类定义,下面看其结构体内部的声明。
17.png 4 Y0 [1 ?) A( {# Q1 ?5 t% d0 w
18.png # k/ H- _% ^8 h, Y5 u7 ~
! o! l5 ~5 d9 c  h" T
下面分析SPI的初始化函数:/ t' n$ |1 {; q! Y

0 b, b5 G- {% h' o) k$ w

  1. # i! c4 T4 ?7 ?" g* I
  2. void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
    ) l& d. h" y$ ?7 K" }( J
  3. {! x! o2 D" P/ _' ]2 U  |
  4. GPIO_InitTypeDef GPIO_InitStruct;9 X  m" q' A# }5 _: f7 T
  5. if(hspi->Instance==SPI1)0 I2 e; n# c7 j( ~
  6. {
    % c7 ]1 k/ p$ M' U
  7. /* USER CODE BEGIN SPI1_MspInit 0 */: a( C2 v$ I) |
  8. /* USER CODE END SPI1_MspInit 0 */
    $ l+ R& w! \( t2 z* ]9 K! V
  9. /* Peripheral clock enable */) x+ q) M0 R$ D2 i
  10. __HAL_RCC_SPI1_CLK_ENABLE();//使能SPI1时钟
    . }) y* Z4 `! k+ o8 `5 _
  11. /**SPI1 GPIO Configuration
    8 a( i/ V% {) D1 D; Y3 V& _/ D
  12. PA5     ------> SPI1_SCK
    ( r: b" F  n( x; e, N0 |* v% A
  13. PA6     ------> SPI1_MISO4 n2 Z; j; Z+ p4 Q" [7 n
  14. PA7     ------> SPI1_MOSI  T) x6 h% }) j2 _$ K* w
  15. */
    ) F8 u3 _  h$ h
  16. GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
    / e3 h) W" E6 }! I; L9 ?
  17. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;% K" \( M. I! V! {7 t
  18. GPIO_InitStruct.Pull = GPIO_NOPULL;2 F( L7 J" @4 A6 C
  19. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;. R/ G/ q" v4 c9 p( y! Q: {
  20. GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    0 O; f$ f( m( d  |* ^8 r8 }
  21. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);//配置SPI的数据线和时钟线. D" V: N5 a% F6 _- l' _- L
  22. /* USER CODE BEGIN SPI1_MspInit 1 */+ R9 _' A( }3 x1 Z$ R8 Z& @/ G
  23. /* USER CODE END SPI1_MspInit 1 */- s" _) B0 e) Y
  24. }
    6 n: Q# P- o: N+ L1 ]: J% W
  25. 8 O4 p% t+ \6 @) a* Q2 c
  26. static void MX_SPI1_Init(void)) j/ ]7 W" F" g) O
  27. {" u9 @$ f; n, B+ Y% e6 c! r
  28. hspi1.Instance = SPI1;; E1 l/ q; d& ~
  29. hspi1.Init.Mode = SPI_MODE_MASTER;//主模式! z3 a; i* _+ h. l
  30. hspi1.Init.Direction = SPI_DIRECTION_2LINES;//全双工9 Y: S2 t" |7 n
  31. hspi1.Init.DataSize = SPI_DATASIZE_8BIT;//数据位为8位
    ' ^/ X- D  _+ h
  32. hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;//CPOL=0,low
    5 ^$ f( O' S9 z9 b
  33. hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;//CPHA为数据线的第一个变化沿
    8 z- i/ X- J( G& N
  34. hspi1.Init.NSS = SPI_NSS_SOFT;//软件控制NSS
    7 j3 g2 n% Z3 g4 z" y2 T1 Y! e
  35. hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;//2分频,32M/2=16MHz
    & K: S% g- L8 e; |. G! w" x
  36. hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;//最高位先发送
    % U+ u, m5 L, D8 p
  37. hspi1.Init.TIMode = SPI_TIMODE_DISABLE;//TIMODE模式关闭
    " p; I( K7 p% t
  38. hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;//CRC关闭9 K9 q5 B1 j- e9 {: ~# z% U
  39. hspi1.Init.CRCPolynomial = 10;//默认值,无效2 f! a0 _1 }. x0 o
  40. if (HAL_SPI_Init(&hspi1) != HAL_OK)//初始化
      f- Z& Y: E7 r& y) K2 u) J; a2 s
  41. {! E7 E; O. ]4 m+ M- M( Z% a
  42. _Error_Handler(__FILE__, __LINE__);
    & Y6 V5 d( i1 ^! {, g6 T
  43. }
    ; w; a- {( z# x- n4 Q; z
  44. }
复制代码
% \2 i) C: X& V* F  i$ I1 h, t  y
) f, t4 b/ Z; {1 x& p  o0 a# W5 E0 n
利用SPI接口发送和接收数据主要调用以下两个函数:, ?1 p% Q" l* B9 [/ U4 k* m
' O8 O! O# v, U: B9 |# |- a
  1. 5 O! e" O& E4 W2 p* O  W
  2. HAL_StatusTypeDef  HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);//发送数据1 w& A1 s5 q. k9 a# U
  3. HAL_StatusTypeDef  HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);//接收数据
复制代码

4 {! P& _7 j0 F, h8 r; }7 \! O1 _" n. C) I# @: ]
5 ?! I6 V) x+ D: \% A

, j6 J; h9 f. b: {8 |* c) d( v& Q; \7 O

/ H* Y( F- i. f" a6 e* h" J; u5 y. Z" X) N! ]5 x( W
赞 收藏 1 评论0 发布时间:2020-10-19 13:37

举报

0个回答

所属标签

相似技术帖

官网相关资源

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