STM32学习和实践笔记(45):SPI-FLASH实验

1.SPI介绍

1.1 SPI****简介

SPI的全称是"Serial Peripheral Interface",意为串行外围接口,是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在EEPROM、FLASH、实时时钟、AD转换器,还有数字信号处理器和数字信号解码器之间。SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线。

SPI内部结构简易图:

MISO:master input slave output

MOSI:master output slave input

由主机产生sclck时钟

SPI 主要特点有: 可以同时发出和接收串行数据; 可以当作主机或从机工作; 提供频率可编程时钟; 发送结束中断标志; 写冲突保护; 总线竞争保护等。

SPI 总线有四种工作方式,通过时钟极性( CPOL)和时钟相位( CPHA)区分,这两者的组合,主要决定了在在时间的哪个位置采样数据。

STM32采用采用SPI的哪种工作方式,主要取决于外部的SPI设备,与外部设备保持一致就可以了。本试验中使用的flash, 使用CPHA =1且CPOL=1。

STM32F1的SPI 接口提供两个主要功能,支持 SPI 协议或 I2S 音频协议。(就是说,SPI的四个IO口,也可以配置成I2S的四个IO口!)

STM32F1的SPI时钟最高可以到 36MHz,支持 DMA功能。STM32F1的SPI内部结构图:

(1)标号1:SPI接口引脚

STM32F1芯片有多个 SPI 外设,它们的 SPI 通讯信号引出到不同的 GPIO 引脚上,使用时必须配置到这些指定的引脚。SPI1 是挂接在APB2总线上,而SPI2和SPI3挂接在APB1总线上。NSS是作片选功能,也可以用其余IO口代替。

(2)标号2:时钟控制逻辑

SCK 线的时钟信号,由波特率发生器根据" 控制寄存器 CR1"中的 BR[0:2]位控制,该位是对 fpclk 时钟的分频因子,对 fpclk 的分频结果就是 SCK 引脚的输出时钟频率,计算方法如下:

(3)标号3:数据控制逻辑

(4)标号4:整体逻辑控制

2.SPI****配置步骤

具体步骤如下:(SPI相关库函数在stm32f10x_spi.c和

stm32f10x_spi.h文件中)

(1)使能SPI及对应GPIO端口时钟并配置引脚的复用功能

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );

RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);

(2)初始化SPI,包括数据帧长度、传输模式、MSB和LSB顺序等

void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);

typedef struct

{

uint16_t SPI_Direction; //设置SPI的单双向模式

uint16_t SPI_Mode; //设置 SPI 的主/从机端模式

uint16_t SPI_DataSize; //设置 SPI 的数据帧长度,可选 8/16 位

uint16_t SPI_CPOL; //设置时钟极性 CPOL,可选高/低电平

uint16_t SPI_CPHA; //设置时钟相位,可选奇/偶数边沿采样

uint16_t SPI_NSS; //设置 NSS 引脚由 SPI 硬件控制还是软件控制

uint16_t SPI_BaudRatePrescaler;//设置时钟分频因子

uint16_t SPI_FirstBit; //设置 MSB/LSB 顺序

uint16_t SPI_CRCPolynomial; //设置 CRC 校验的表达式

}SPI_InitTypeDef;

SPI_Direction:用于设置 SPI 的通信方向,可设置为双线全双工(SPI_Direction_2Lines_FullDuplex),双线只接收(SPI_Direction_2Lines_RxOnly),单线只接收(SPI_Direction_1Line_Rx)、单线只发送模式(SPI_Direction_1Line_Tx)。

SPI_Mode:用于设置 SPI 工作在主机模式(SPI_Mode_Master)或从机模式(SPI_Mode_Slave ),这两个模式的最大区别为 SPI 的 SCK 信号线的时序, SCK 的时序是由通讯中的主机产生的。若被配置为从机模式, STM32 的 SPI 外设将接受外来的 SCK 信号。

SPI_DataSize:用于设置SPI通信的数据帧长度,可以选择8位(SPI_DataSize_8b)或者 16 位(SPI_DataSize_16b)。

SPI_CPOL:用于设置时钟极性,可设置为高电平(SPI_CPOL_High)或低电平(SPI_CPOL_Low )。

SPI_CPHA:用于设置时钟相位,也就是选择在串行同步时钟的第几个跳变沿(上升或下降)数据被采样,可以为 SPI_CPHA_1Edge(在 SCK 的奇数边沿采集数据) 或SPI_CPHA_2Edge (在 SCK 的偶数边沿采集数据) 。

SPI_NSS:用于设置NSS引脚的使用模式,可以选择为硬件模式(SPI_NSS_Hard )与软件模式(SPI_NSS_Soft ),在硬件模式中的 NSS信号由 SPI 硬件自动产生,而软件模式则需要我们使用相应的 GPIO 端口来控制。

SPI_BaudRatePrescaler:用于设置波特率分频因子,分频后的时钟即为 SPI 的 SCK 信号线的时钟频率。可设置为 fpclk 的 2、 4、 6、 8、 16、 32、 64、 128、 256 分频。

SPI_FirstBit:用于设置数据传输顺序是 MSB 位在前还是 LSB 位在前。

SPI_CRCPolynomial:用于设置 CRC 校验多项式,提高通信可靠性。

本实验配置代码如下:

SPI_InitTypeDef SPI_InitStructure;

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工

SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI

SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构

SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平

SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始

SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式

SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

(3)使能(开启)SPI

void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);

(4)SPI数据传输

void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);

uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);

(5)查看SPI传输状态

FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);

使用较多的是发送完成标志(SPI_I2S_FLAG_TXE)和接收完成标志(SPI_I2S_FLAG_RXNE)

SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE);

相关推荐
2301_781143562 小时前
python学习(一)
python·学习
zore_c2 小时前
【C语言】排序算法——快速排序详解(含多种变式)!!!
c语言·数据结构·笔记·算法·排序算法·深度优先·推荐算法
客梦2 小时前
数据结构--哈希表
数据结构·笔记
先知后行。2 小时前
电子元器件2
单片机·学习
lkbhua莱克瓦242 小时前
基础-SQL的通用语法、分类以及DDL
开发语言·数据库·笔记·sql·mysql·ddl
代码游侠2 小时前
应用——HTTP天气查询
网络·笔记·网络协议·算法·http
HERR_QQ2 小时前
【cpp tool】GDB coredump vscode GUI 和多线程常用笔记
ide·笔记·vscode
夏幻灵2 小时前
如何理解编译?
经验分享·笔记
星海辉映2 小时前
arduino 蓝牙控制LED灯实验
stm32