STM32 SPI理解

1、SPI协议简介

SPI 协议是由摩托罗拉公司提出的通讯协议(Serial Peripheral Interface),即串行外围设备接口,是一种高速全双工的通信总线。它被广泛地使用在 ADC、 LCD 等设备与 MCU 间,要求通讯速率较高的场合.

SPI 通讯使用 3 条总线及片选线, 3 条总线分别为 SCK、 MOSI、 MISO,片选线为CS.

  1. SCK (Serial Clock): 时钟信号线,用于通讯数据同步。它由通讯主机产生,决定了通讯的速率,不同的设备支持的最高时钟频率不一样,如 STM32 的 SPI 时钟频率最大为fpclk/2,两个设备之间通讯时,通讯速率受限于低速设备。
  2. MOSI (Master Output, Slave Input): 主设备输出/从设备输入引脚。主机的数据从这条信号线输出,从机由这条信号线读入主机发送的数据,即这条线上数据的方向为主机到从机。
  3. MISO(Master Input,, Slave Output): 主设备输入/从设备输出引脚。主机从这条信号线读入数据,从机的数据由这条信号线输出到主机,即在这条线上数据的方向为从机到主机。
  4. I2C 协议中通过设备地址来寻址、选中总线上的某个设备并与其进行通讯;而 SPI 协议中没有设备地址,它使用 NSS 信号线来寻址,当主机要选择从设备时,把该从设备的 NSS 信号线设置为低电平,该从设备即被选中,即片选有效,接着主机开始与被选中的从设备进行 SPI 通讯。所以SPI 通讯以 NSS 线置低电平为开始信号,以 NSS 线被拉高作为结束信号。

2、SPI时隙图

在这里插入图片描述

2.1、起始信号

NSS 信号线由高变低,是 SPI 通讯的起始信号。 NSS 是每个从机各自独占的信号线,当从机在自己的 NSS 线检测到起始信号后,就知道自己被主机选中了,开始准备与主机通讯。在图中的标号6处,
NSS 信号由低变高,是 SPI 通讯的停止信号,表示本次通讯结束,从机的选中状态被取消.

2.2、数据的有效性

SPI 使用 MOSI 及 MISO 信号线来传输数据,使用 SCK 信号线进行数据同步。 MOSI
及 MISO 数据线在 SCK 的每个时钟周期传输一位数据,且数据输入输出是同时进行的。

在 SCK 的下降沿时被采样。即在 SCK 的下降沿时刻, MOSI 及 MISO 的数据有效
SPI 每次数据传输可以 8 位或 16 位为单位,每次传输的单位数不受限制。

2.3、CPOL/CPHA 及通讯模式

时钟极性 CPOL 是指 SPI 通讯设备处于空闲状态时, SCK 信号线的电平信号(即 SPI 通
讯开始前、 NSS 线为高电平时 SCK 的状态)。 CPOL=0 时, SCK 在空闲状态时为低电平,
CPOL=1 时,则相反。

时钟相位 CPHA 是指数据的采样的时刻,当 CPHA=0 时, MOSI 或 MISO 数据线上的
信号将会在 SCK 时钟线的“奇数边沿” 被采样。当 CPHA=1 时,数据线在 SCK 的“偶数
边沿” 采样。

在这里插入图片描述

3、通讯过程

STM32 作为 SPI 通讯的主机端时的数据收发过程
在这里插入图片描述

主模式收发流程及事件说明如下:

  1. 控制 NSS 信号线,产生起始信号(图中没有画出);
  2. 把要发送的数据写入到“数据寄存器 DR”中,该数据会被存储到发送缓冲区;
  3. 通讯开始, SCK 时钟开始运行。 MOSI 把发送缓冲区中的数据一位一位地传输出
    去; MISO 则把数据一位一位地存储进接收缓冲区中
  4. 当发送完一帧数据的时候,“状态寄存器 SR”中的“TXE 标志位”会被置 1,表
    示传输完一帧,发送缓冲区已空;类似地,当接收完一帧数据的时候,“ RXNE
    标志位”会被置 1,表示传输完一帧,接收缓冲区非空;
  5. 等待到“TXE 标志位”为 1 时,若还要继续发送数据,则再次往“数据寄存器
    DR”写入数据即可;等待到“RXNE 标志位”为 1 时,通过读取“数据寄存器
    DR”可以获取接收缓冲区中的内容

4 、编程实战

4.1、原理图

在这里插入图片描述

4.2编程要点

(1) 初始化通讯使用的目标引脚及端口时钟;
(2) 使能 SPI 外设的时钟;
(3) 配置 SPI 外设的模式、地址、速率等参数并使能 SPI 外设;
(4) 编写基本 SPI 按字节收发的函数;
(5) 编写对 FLASH 擦除及读写操作的的函数;
(6) 编写测试程序,对读写数据进行校验。

4.3、SPI(主模式)配置步骤

  1. 通过SPI_CR1寄存器的BR[2:0]位定义串行时钟波特率。
  2. 选择CPOL和CPHA位,定义数据传输和串行时钟间的相位关系(见图212)。
  3. 设置DFF位来定义8位或16位数据帧格式。
  4. 配置SPI_CR1寄存器的LSBFIRST位定义帧格式。
  5. 如果需要NSS引脚工作在输入模式,硬件模式下,在整个数据帧传输期间应把NSS脚连接
    到高电平;在软件模式下,需设置SPI_CR1寄存器的SSM位和SSI位。如果NSS引脚工作
    在输出模式,则只需设置SSOE位。
  6. 必须设置MSTR位和SPE位(只当NSS脚被连到高电平,这些位才能保持置位)。
    在这个配置中, MOSI引脚是数据输出,而MISO引脚是数据输入。

4.4、程序源码

void SPI_FLASH_Init(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
	
	/* 开启SPI时钟*/
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE );
	
	/* SPI相关引脚使能 */
 	FLASH_SPI_CS_APBxClock_FUN( RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOA|
								GPIO_Pin_6|GPIO_Pin_7, ENABLE);
	
  /* CS引脚  PC0*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
	
  /* CLK*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* MISO*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* MOSI*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_SetBits( GPIOC, GPIO_Pin_0);

  // FLASH特性支持 0 3 CPOL CPHA
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//收发
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//主模式
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//8位
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;// 1 1
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(FLASH_SPIx , &SPI_InitStructure);
  SPI_Cmd(FLASH_SPIx , ENABLE);
}

把 STM32 的 SPI 外设配置为主机端,使用 SPI 模式 3(CPOL=1, CPHA=1), NSS 引脚由软件控制以及 MSB 先行模式。 代码中把 SPI 的时钟频率配置成了 4 分频

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为了维护世界和平_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值