STM32 SPI功能详解
目录
1.SPI通信协议
1.1 简介
相比较于I2C:
1.2 硬件电路
所有SPI设备的SCK、MOSI、MISO分别连在一起
主机另外引出多条SS控制线,分别接到各从机的SS引脚
输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入
1.3 移位示意图
- SPI的移位操作:
MOSI
发送给从机。MISO
发送给主机。- 单向数据传输的资源浪费:
0x00
或0xFF
(即发送无效数据)。- 数据置换的本质:
- 优化方式:
1.4 SPI时序基本单元
起始条件:SS从高电平切换到低电平
终止条件:SS从低电平切换到高电平
在SPI协议中,有两个值来确定SPI的模式, 定义了时钟信号如何与数据同步 。
CPOLL (时钟极性) :决定时钟信号在空闲状态下的电平。0表示时钟空闲时为低电平,1表示时钟空闲时为高电平。
CPHA (时钟相位) :表示相位, 决定数据采样的时刻。0表示数据在第一个时钟沿采样,1表示在第二个时钟沿采样。
CPOL | CPHA | 模式 | 描述 |
---|---|---|---|
0 | 0 | 0 | SPICLK初始电平为低电平,数据在第一个时钟沿(上升沿)采样(数据移入移位寄存器) |
0 | 1 | 1 | SPICLK初始电平为低电平,数据在第二个时钟沿(下降沿)采样 |
1 | 0 | 2 | SPICLK初始电平为高电平,数据在第一个时钟沿(下降沿)采样 |
1 | 1 | 3 | SPICLK初始电平为高电平,数据在第二个时钟沿(上升沿)采样 |
交换一个字节(模式0)
CPOL=0:空闲状态时,SCK为低电平
CPHA=0:SCK第一个边沿移入数据,第二个边沿移出数据
注意:这里所谓的移入和移出是相对于从设备来说的!!!!!
交换一个字节(模式1)
交换一个字节(模式2)
交换一个字节(模式3)
上面说过,在从机未没选中的时候,其MISO必须置为高阻态模式:
红色标中的就是被置为了高阻态,不过一般不需要去关心,这个从机一般都会自己去做的。
MOSI,来自从设备,可以理解为是从设备引申到主设备的,主设备输出给从设备数据,从设备在该MOSI上采样来自主设备的数据。
1.5 SPI时序
发送指令:
指定地址写:
指定地址读:
2.W25Q64
参考资料
原理图:

2.1 简介
W25Qxx系列是一种低成本、小型化、使用简单的非易失性存储器,常应用于数据存储、字库存储、固件程序存储等场景
存储介质:Nor Flash(闪存)
时钟频率:80MHz / 160MHz (Dual SPI) / 320MHz (Quad SPI)存储容量(24位地址):
型号 | 容量 |
---|---|
W25Q40 | 4Mbit / 512KByte |
W25Q80 | 8Mbit / 1MByte |
W25Q16 | 16Mbit / 2MByte |
W25Q32 | 32Mbit / 4MByte |
W25Q64 | 64Mbit / 8MByte |
W25Q128 | 128Mbit / 16MByte |
W25Q256 | 256Mbit / 32MByte |
2.2 硬件电路
引脚 | 功能 |
---|---|
VCC、GND | 电源(2.7~3.6V) |
CS(SS) | SPI片选 |
CLK(SCK) | SPI时钟 |
DI(MOSI) | SPI主机输出从机输入 |
DO(MISO) | SPI主机输入从机输出 |
WP | 写保护 |
HOLD | 数据保持 |
2.3 框图
2.3.1 结构介绍
24位的地址,最大的寻址范围是16MB(224➗1024➗1024),一个24位的地址就对应1个字节(Byte)的存储数据(这个具体后面讲)
但是对于这个芯片只有8MB,也就是地址空间只用了一半。
\1. Block Segmentation(分块结构)
\2. Write Protect Logic and Row Decode(写保护逻辑和行解码)
\3. SPI Command & Control Logic(SPI命令和控制逻辑)
\4. Write Control Logic(写入控制逻辑)
\5. Status Register(状态寄存器)
\6. High Voltage Generators(高压发生器)
7. Page Address Latch/Counter 和 Byte Address Latch/Counter(页地址锁存器/计数器 和 字节地址锁存器/计数器)
8. Column Decode and 256-Byte Page Buffer(列解码和256字节页缓冲区)
\9. Block Diagram总体工作流程
存储分层:
SPI通信:
地址管理:
数据传输:
状态反馈:
2.3.2 混淆
注意这个模块的地址空间范围只有一半。
因此当需要写入数据的时候,就需要发送3字节的地址,高两位字节用于找到对应块的对应扇区的对应页,最后一位字节确定页内的地址
往哪里存储,这肯定是要有地址去指向的。地址通过层级结构(块 > 扇区 > 页 > 字节)来定位存储空间。而一个地址指向的存储空间,其容量是1字节。
8MB的容量又是怎么算出来的?
24位的地址,不就有224个地址么,而1个地址又对应指向1个字节(Byte)的存储空间,那也就是说存储容量有224Byte,而224➗1024=16348KB、16348➗1024=16MB,即24位的地址其存储容量为16MB
而这里介绍的W25Q64,它只用了一半的地址空间,从块号的地址范围为:00~7F就可以知道,所以这个模块的存储容量就是8MB
将数据 0xAB
写入地址 0x123456
,流程如下:
- 主机发送写命令。
- 主机发送 3 字节地址
0x123456
:
12h
:块选择。34h
:页选择。56h
:页内的具体字节位置。- 主机发送数据
0xAB
。 - 存储器将
0xAB
写入到地址0x123456
对应的存储单元。
2.4 Flash操作注意事项
2.4.1 写操作
- 写入前需要“写使能”
- 只能从1改写为0,不能从0改写为1
- 写入数据前必须先擦除
- 擦除的最小单元
- 最多写入一页数据(256字节)
- 写入后芯片进入忙状态
2.4.2 读取操作
- 直接调用读取时序
- 没有页限制
- 读取操作结束后不会进入忙状态
- 忙状态时不能读取
操作 | 特点 | 注意事项 |
---|---|---|
写入 | 需先写使能 数据位只能从1改为0 写入前需擦除 最多写入1页 | 写入后芯片进入忙状态,不可立即响应其他命令。 |
擦除 | 必须按最小擦除单元进行 所有位恢复为1 | 擦除速度较慢,应用时需考虑优化操作顺序。 |
读取 | 无需写使能 无页限制,连续读取任意长度 读取结束后不会忙状态 | 忙状态下不能读取,主机需先检查芯片是否空闲。 |
2.5 芯片手册补充
W25Q64BV.PDF
2.5.1 状态寄存器
BUSY是状态寄存器(S0)中的只读位,当设备执行页面程序、扇区擦除、块擦除、芯片擦除或写入状态寄存器指令时,该位被设置为1状态。在此期间,设备将忽略除读取状态寄存器和擦除挂起指令之外的其他指令(请参阅AC特性中的tW、tPP、tSE、tBE和tCE)。当程序、擦除或写入状态寄存器指令完成时,BUSY位将被清除为0状态,表示设备已准备好执行进一步的指令。
写启用锁存器(WEL)是状态寄存器(S1)中的只读位,在执行写启用指令后设置为1。当设备被写禁用时,WEL状态位被清除为0。通电或执行以下任何指令后,会出现写禁用状态:写禁用、页面程序、扇区擦除、块擦除、芯片擦除和写状态寄存器。
暂时最低两位就行了
2.5.2 指令集
可以通过输入表中的相关Instruction给设备来确认设备。
1. Write Enable (06h)
\2. Write Disable (04h)
3. Read Status Register-1 (05h)
\4. Read Status Register-2 (35h)
\5. Write Status Register (01h)
6. Page Program (02h)
\7. Quad Page Program (32h)
\8. Block Erase (64KB, D8h
\9. Block Erase (32KB, 52h)
10. Sector Erase (4KB, 20h)
\11. Chip Erase (C7h/60h)
\12. Erase Suspend (75h) / Erase Resume (7Ah)
\13. Power-down (B9h)
\14. High Performance Mode (A3h)
\15. Continuous Read Mode Reset (FFh)
\16. Release Power-down or HPM / Device ID (ABh):
\17. Manufacturer / Device ID (90h)
\18. Read Unique ID (4Bh)
19. JEDEC ID (9Fh)
20. Read Data (03h)
\21. Fast Read (0Bh)
\22. Fast Read Dual Output (3Bh)
IO0
和 IO1
两根数据线同时输出数据,提高速度。\23. Fast Read Dual I/O (BBh)
\24. Fast Read Quad Output (6Bh)
IO0
、IO1
、IO2
和 IO3
同时输出。\25. Fast Read Quad I/O (EBh)
\26. Octal Word Read Quad I/O (E3h)
剩下的一些时序图去看手册就行了。
3.软件操作W25Q64
📎11-1 软件SPI读写W25Q64.zip
User:
Hardware:
/**
* 函 数:SPI交换传输一个字节,使用SPI模式0
* 参 数:ByteSend 要发送的一个字节
* 返 回 值:接收的一个字节
*/
uint8_t MySPI_SwapByte(uint8_t ByteSend)
{
uint8_t i, ByteReceive = 0x00; //定义接收的数据,并赋初值0x00,此处必须赋初值0x00,后面会用到
for (i = 0; i < 8; i ++) //循环8次,依次交换每一位数据
{
/*两个!可以对数据进行两次逻辑取反,作用是把非0值统一转换为1,即:!!(0) = 0,!!(非0) = 1*/
MySPI_W_MOSI(!!(ByteSend & (0x80 >> i))); //使用掩码的方式取出ByteSend的指定一位数据并写入到MOSI线
MySPI_W_SCK(1); //拉高SCK,主设备上升沿移出数据(上面已经调用了),从设备从MOSI移入设备
if (MySPI_R_MISO()){ByteReceive |= (0x80 >> i);} //读取MISO数据,并存储到Byte变量
//当MISO为1时,置变量指定位为1,当MISO为0时,不做处理,指定位为默认的初值0
MySPI_W_SCK(0); //拉低SCK,下降沿移入数据
}
return ByteReceive; //返回接收到的一个字节数据
}
需要注意的是不要混淆
移入:
MOSI:调用MySPI_W_MOSI
就相当于将高位移出移位寄存器放入MOSI管,之后MySPI_W_SCK(1);
就是将SCK电平拉高,表明我主设备已经将数据移出放入到MOSI了(同时从设备也已经将数据移出到MISO),这时候从设备就可以移入数据,所以上图时序图中讲到的第一个SCK边沿移入数据是针对于MOSI上的从设备来说的。
MISO:而此时对于主设备,讲道理第一个SCK上升沿,从设备移入数据了,主设备应该同步也从MISO将数据移入寄存器,但由于是模拟实现的SPI,程序无法同步实现。MySPI_W_SCK(1);
所以只能后续紧跟着调用MySPI_R_MISO
将MISO的数据移入进主设备的寄存器,所以上图时序图的第一个SCK边沿移入数据也是中是MISO上的主设备来说。
MySPI_W_MOSI
将数据移出到MOSI移出:
MySPI_W_SCK(0);
拉低SCK,其实就是告诉从设备可以将数据移出到MISOMySPI_W_MOSI
将数据移出到MOSI。也就是说对于SCK的上升沿和下降沿其实主要是告诉从设备可以进行移入(MOSI)和移出(MISO)了,至于主设备是需要自己紧跟着在上升沿代码调用后进行移入(MISO),调用前将数据移出(MOSI);在下降沿代码前将数据进行移出(MOSI)
由于是软件实现,主设备无法说做到上升沿时刻同步移出数据,所以只能先移出数据,再将SCK电平置高。
下面来看看模式1的:
/**
* 函 数:SPI交换传输一个字节,使用SPI模式1
* 参 数:ByteSend 要发送的一个字节
* 返 回 值:接收的一个字节
*/
uint8_t MySPI_SwapByte(uint8_t ByteSend)
{
uint8_t i, ByteReceive = 0x00; //定义接收的数据,并赋初值0x00,此处必须赋初值0x00,后面会用到
for (i = 0; i < 8; i ++) //循环8次,依次交换每一位数据
{
MySPI_W_SCK(1); //拉高SCK,主设备将数据移出到MOSI(下面调用MySPI_W_MOSI),从设备也会将数据移出到MIS
/*两个!可以对数据进行两次逻辑取反,作用是把非0值统一转换为1,即:!!(0) = 0,!!(非0) = 1*/
MySPI_W_MOSI(!!(ByteSend & (0x80 >> i))); //使用掩码的方式取出ByteSend的指定一位数据并写入到MOSI线
MySPI_W_SCK(0); //拉低SCK,主设备下降沿从MISO移入数据(下面调用MySPI_R_MISO),从设备从MOSI移出数据
if (MySPI_R_MISO()){ByteReceive |= (0x80 >> i);} //读取MISO数据,并存储到Byte变量
//当MISO为1时,置变量指定位为1,当MISO为0时,不做处理,指定位为默认的初值0
}
return ByteReceive; //返回接收到的一个字节数据
}
也就是说在上升沿和下降沿代码调用后主设备紧跟着调用相应的函数完成相应的移出移入操作
MySPI_W_SCK(1);
—> MySPI_W_MOSI
移出MySPI_W_SCK(0);
—> MySPI_R_MISO
移入这个就比较好理解一点。
4.SPI外设
4.1 简介
STM32内部集成了硬件SPI收发电路,可以由硬件自动执行时钟生成、数据收发等功能,减轻CPU的负担
可配置8位/16位数据帧、高位先行/低位先行。一般都是用8位数据帧,也就是一个字节,以及高位先行
时钟频率: fPCLK / (2, 4, 8, 16, 32, 64, 128, 256)。SPI外设的时钟,其实就是由外设时钟分频而来的,PCLK就是Peripheral Clock外设时钟,APB2的是72MHz,APB1的是36MHz。所以SPI的时钟频率需要看挂载哪个总线上
支持多主机模型、主或从操作
可精简为半双工/单工通信
支持DMA
兼容I2S协议
STM32F103C8T6 硬件SPI资源:SPI1(APB1)、SPI2(APB2)
4.2 框图
主机SPI外设框图
1. MOSI、MISO、SCK、NSS 引脚
这些是 SPI 外设的主要硬件引脚:
其中实现了交叉,也就是如果主机为从设备,数据变成从MISO口输出,从MOSI输入
2. 移位寄存器
移位寄存器是 SPI 的核心,用于实现数据的串行传输:
数据在 MOSI 和 MISO 之间传输,通过 SCK 时钟信号逐位移入或移出。
控制位 LSBFIRST: 控制数据的传输顺序,决定是先传输低位(LSB)还是高位(MSB)。

3. 接收缓冲区
用于暂存接收到的数据:
4. 发送缓冲区
用于暂存需要发送的数据:
5. 主控制电路
主控制电路是 SPI 的控制逻辑核心,管理通信模式和数据传输:
6. 波特率发生器
控制 SPI 的时钟分频,产生通信所需的时钟信号:

7. 通信电路
通信电路负责协调数据的发送和接收,包括:
8. SPI 控制寄存器(SPI_CR1 和 SPI_CR2)
这些寄存器用于配置 SPI 外设的工作模式:
9. 状态寄存器(SPI_SR)
状态寄存器反映 SPI 当前的运行状态:
10. 地址和数据总线
连接 SPI 和系统总线,用于数据的读写和地址的映射:
4.3 基本结构
4.4 传输时序图
4.4.1 主模式全双工连续传输
4.4.2 非连续传输
4.5 软件/硬件波形对比
5.结构体和相关API
5.1 结构体
/**
* @brief SPI Init structure definition
*/
typedef struct
{
uint16_t SPI_Direction; /*!< Specifies the SPI unidirectional or bidirectional data mode.
This parameter can be a value of @ref SPI_data_direction */
uint16_t SPI_Mode; /*!< Specifies the SPI operating mode.
This parameter can be a value of @ref SPI_mode */
uint16_t SPI_DataSize; /*!< Specifies the SPI data size.
This parameter can be a value of @ref SPI_data_size */
uint16_t SPI_CPOL; /*!< Specifies the serial clock steady state.
This parameter can be a value of @ref SPI_Clock_Polarity */
uint16_t SPI_CPHA; /*!< Specifies the clock active edge for the bit capture.
This parameter can be a value of @ref SPI_Clock_Phase */
uint16_t SPI_NSS; /*!< Specifies whether the NSS signal is managed by
hardware (NSS pin) or by software using the SSI bit.
This parameter can be a value of @ref SPI_Slave_Select_management */
uint16_t SPI_BaudRatePrescaler; /*!< Specifies the Baud Rate prescaler value which will be
used to configure the transmit and receive SCK clock.
This parameter can be a value of @ref SPI_BaudRate_Prescaler.
@note The communication clock is derived from the master
clock. The slave clock does not need to be set. */
uint16_t SPI_FirstBit; /*!< Specifies whether data transfers start from MSB or LSB bit.
This parameter can be a value of @ref SPI_MSB_LSB_transmission */
uint16_t SPI_CRCPolynomial; /*!< Specifies the polynomial used for the CRC calculation. */
}SPI_InitTypeDef;
SPI_Direction
描述:
指定SPI的数据传输模式,是单向或双向通信。
取值范围:
可取以下值(具体定义在@ref SPI_data_direction
中):
SPI_Direction_2Lines_FullDuplex
:全双工模式(两条线用于发送和接收)。SPI_Direction_2Lines_RxOnly
:仅接收模式(两条线,只有接收)。SPI_Direction_1Line_Rx
:单线接收模式(单独一条线)。SPI_Direction_1Line_Tx
:单线发送模式(单独一条线)。SPI_Mode
描述:
指定SPI的工作模式,是主机模式(Master)还是从机模式(Slave)。
取值范围:
可取以下值(具体定义在@ref SPI_mode
中):
SPI_Mode_Master
:主机模式。SPI_Mode_Slave
:从机模式。SPI_DataSize
描述:
指定SPI传输的数据帧大小。
取值范围:
可取以下值(具体定义在@ref SPI_data_size
中):
SPI_DataSize_8b
:8位数据帧。SPI_DataSize_16b
:16位数据帧。SPI_CPOL
描述:
指定串行时钟的空闲状态(极性),即SCK引脚的电平状态。
取值范围:
可取以下值(具体定义在@ref SPI_Clock_Polarity
中):
SPI_CPOL_Low
:空闲时SCK保持低电平。SPI_CPOL_High
:空闲时SCK保持高电平。SPI_CPHA
描述:
指定串行时钟的采样边沿,即数据采集发生在哪一个时钟边沿。
取值范围:
可取以下值(具体定义在@ref SPI_Clock_Phase
中):
SPI_CPHA_1Edge
:第一个时钟跳变沿采样数据。SPI_CPHA_2Edge
:第二个时钟跳变沿采样数据。SPI_NSS
描述:
指定从属选择(NSS)信号的管理方式,是否由硬件(NSS引脚)管理或通过软件(SSI位)模拟管理。
取值范围:
可取以下值(具体定义在@ref SPI_Slave_Select_management
中):
SPI_NSS_Soft
:NSS由软件管理(使用SSI位)。SPI_NSS_Hard
:NSS由硬件管理(NSS引脚)。SPI_BaudRatePrescaler
描述:
指定波特率分频系数,用于配置发送和接收的SCK时钟。
取值范围:
可取以下值(具体定义在@ref SPI_BaudRate_Prescaler
中):
SPI_BaudRatePrescaler_2
:SCK = fPCLK/2。SPI_BaudRatePrescaler_4
:SCK = fPCLK/4。SPI_BaudRatePrescaler_8
:SCK = fPCLK/8。SPI_BaudRatePrescaler_16
:SCK = fPCLK/16。SPI_BaudRatePrescaler_32
:SCK = fPCLK/32。SPI_BaudRatePrescaler_64
:SCK = fPCLK/64。SPI_BaudRatePrescaler_128
:SCK = fPCLK/128。SPI_BaudRatePrescaler_256
:SCK = fPCLK/256。SPI_FirstBit
描述:
指定数据传输的起始位方向,是从最高有效位(MSB)还是最低有效位(LSB)开始。
取值范围:
可取以下值(具体定义在@ref SPI_MSB_LSB_transmission
中):
SPI_FirstBit_MSB
:从MSB(最高有效位)开始传输。SPI_FirstBit_LSB
:从LSB(最低有效位)开始传输。SPI_CRCPolynomial
描述:
指定用于循环冗余校验(CRC)计算的多项式值。
取值范围:
0x07
、0x1021
等。5.2 API
1. void SPI_I2S_DeInit(SPI_TypeDef* SPIx)
作用:
将指定的SPI/I2S外设复位,清除所有配置,恢复到默认状态。
参数:
SPIx
:需要复位的SPI外设(如SPI1
或SPI2
)。使用实例:
SPI_I2S_DeInit(SPI1); // 复位SPI1外设
2. void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)
作用:
初始化SPI外设,并配置其通信参数。
参数:
SPIx
:需要初始化的SPI外设(如SPI1
)。SPI_InitStruct
:包含SPI初始化参数的结构体。使用实例:
SPI_InitTypeDef SPI_InitStruct;
SPI_StructInit(&SPI_InitStruct); // 初始化结构体为默认值
SPI_InitStruct.SPI_Mode = SPI_Mode_Master; // 设置为主机模式
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; // 波特率分频
SPI_Init(SPI1, &SPI_InitStruct); // 初始化SPI1
3. void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct)
作用:
将SPI_InitTypeDef
结构体填充为默认值。
参数:
SPI_InitStruct
:指向需要初始化的SPI_InitTypeDef
结构体。使用实例:
SPI_InitTypeDef SPI_InitStruct;
SPI_StructInit(&SPI_InitStruct); // 填充为默认值
4. void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState)
作用:
启用或禁用SPI外设。
参数:
SPIx
:需要控制的SPI外设(如SPI1
)。NewState
:设置状态,ENABLE
表示启用,DISABLE
表示禁用。使用实例:
SPI_Cmd(SPI1, ENABLE); // 启用SPI1
5. void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState)
作用:
启用或禁用SPI/I2S的中断。
参数:
SPIx
:需要控制的SPI/I2S外设(如SPI1
)。SPI_I2S_IT
:指定中断类型,例如SPI_I2S_IT_TXE
(发送缓冲区空中断)。NewState
:设置状态,ENABLE
表示启用,DISABLE
表示禁用。使用实例:
SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, ENABLE); // 启用发送缓冲区空中断
6. void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState)
作用:
启用或禁用SPI/I2S的DMA功能。
参数:
SPIx
:需要控制的SPI/I2S外设(如SPI1
)。SPI_I2S_DMAReq
:指定DMA请求类型,例如SPI_I2S_DMAReq_Tx
(DMA发送请求)。NewState
:设置状态,ENABLE
表示启用,DISABLE
表示禁用。使用实例:
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE); // 启用SPI1的DMA发送请求
7. void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data)
作用:
通过SPI/I2S外设发送数据。
参数:
SPIx
:需要操作的SPI/I2S外设(如SPI1
)。Data
:要发送的数据。使用实例:
SPI_I2S_SendData(SPI1, 0x55AA); // 发送数据0x55AA
8. uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx)
作用:
从SPI/I2S外设读取接收到的数据。
参数:
SPIx
:需要操作的SPI/I2S外设(如SPI1
)。使用实例:
uint16_t receivedData = SPI_I2S_ReceiveData(SPI1); // 读取接收到的数据
9. void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft)
作用:
在软件管理模式下配置NSS信号。
参数:
SPIx
:需要操作的SPI外设(如SPI1
)。SPI_NSSInternalSoft
:设置NSS信号为高电平或低电平。SPI_NSSInternalSoft_Set
:设置NSS为高。SPI_NSSInternalSoft_Reset
:设置NSS为低。使用实例:
SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set); // 设置NSS信号为高电平
10. FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG)
作用:
检查指定的SPI/I2S标志位状态。
参数:
SPIx
:需要操作的SPI/I2S外设(如SPI1
)。SPI_I2S_FLAG
:指定要检查的标志位,例如SPI_I2S_FLAG_TXE
(发送缓冲区空标志)。使用实例:
if (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == SET) {
// 发送缓冲区为空
}
11. void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG)
作用:
清除指定的SPI/I2S标志位。
参数:
SPIx
:需要操作的SPI/I2S外设(如SPI1
)。SPI_I2S_FLAG
:指定要清除的标志位。使用实例:
SPI_I2S_ClearFlag(SPI1, SPI_I2S_FLAG_OVR); // 清除溢出错误标志
12. ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT)
作用:
检查指定的SPI/I2S中断状态。
参数:
SPIx
:需要操作的SPI/I2S外设(如SPI1
)。SPI_I2S_IT
:指定要检查的中断类型,例如SPI_I2S_IT_RXNE
(接收缓冲区非空中断)。使用实例:
if (SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_RXNE) == SET) {
// 接收缓冲区非空
}
6.硬件操作W25Q64
📎11-2 硬件SPI读写W25Q64.zip
User:
Hardware:
作者:憧憬一下