带你了解STM32:SPI通信(软件部分)

目录

0.SPI相交于I2C的优缺点

1.SPI通信

2.硬件电路

3.移位示意图(SPI硬件电路设计的核心)(下面的时序都是这个逻辑进行字节交换)

4.SPI时序基本单元

5.SPI时序(W25Q64)

6.W25Q64简介

7.硬件电路

8.W25Q64框图

9.Flash操作注意事项

10.参考资料(状态寄存器、框架图、指令集......)

11.软件SPI读写W25Q64代码

第一步:按图接线到面包板上

第二步:复制OLED显示屏代码

工程思路:

第三步:建立MySPI模块,完成通信引脚封装、初始化、时序:起始、终止、交换一个字节

模式0

模式1

模式2

模式3

第四步:MySPI头文件声明

第五步:新建立一个头文件,命名为W25Q64_Ins,封装指令码

第六步:建立W25Q64驱动模块,调用底层SPI,拼接各种指令和功能的完整时序,比如:写使能、擦除、页编程、读数据等等,模块函数功能实现参考手册,模块的建成也要看Flash操作注意事项

第七步:W25Q64头文件声明

第八步:主函数调用


0.SPI相交于I2C的优缺点

优点:1.SPI传输更快,SPI协议并没有严格规定最大传输速度,这个最大速度取决于芯片厂商的设计需求,比如:W25Q64存储器芯片,最大可达80MHz;2.设计比较简单粗暴,比I2C简单好学

缺点:1.因为设计比较简单粗暴,所以功能就没有I2C怎么多了;2.SPI的硬件资源开销多,通信线的个数比较多,并且通信过程中,经常会有资源浪费的现象


1.SPI通信

SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线
四根通信线:SCK(Serial Clock)(别名:SCLK、CLK、CK)、MOSI(Master Output Slave Input)(别名:DO)、MISO(Master Input Slave Output)(别名:DI)、SS(Slave Select)(别名:NSS、CS)

SCK:时钟信号,数据位的输出和输入,都是在SCK的上升沿和下降沿进行的,数据位的收发时刻就可以明确的确定;MOSI:主机输出从机输入,如果是主机接到这根线上,那就是MO,主机输出,如果是从机接到这条线上,就是SI,从机输入;MISO:主机从从机接收数据的线路;MOSI和MISO加在一起相当于I2C总线的SDA,但是SDA是半双工,这里是全双工;SS:从机选择线,直接连接到从机上,不用寻址,低电平呼叫从机,高电平释放从机
同步,全双工
支持总线挂载多设备(一主多从)

从左到右:W25Q64(Flash存储器芯片)、OLED、2.4G无线通信模块、Micro SD卡


2.硬件电路

所有SPI设备的SCK、MOSI、MISO分别连在一起

主机另外引出多条SS控制线,分别接到各从机的SS引脚

输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入


3.移位示意图(SPI硬件电路设计的核心)(下面的时序都是这个逻辑进行字节交换)

SPI一般是高位先行,每来一个时钟,移位寄存器会向左进行移位,移位寄存器时钟源主机提供(波特率发生器),主机移位寄存器左移数据,从左边出去通过MOSI引脚,移动到从机移位寄存器右边,从机移位寄存器左边移出去的数据,通过MISO引脚,输入到主机移位寄存器的右边

电路工程流程:波特率发生器时钟的上升沿,所以移位寄存器向左移动一位,移出去的位放在引脚上,波特率发生器时钟的下降沿,引脚上的位,采样输入到移位寄存器的最低位

假设,主机有个数据10101010要发送到从机,同时从机一个数据01010101要发送到主机,驱动时钟先产生一个上升沿,所有的位会往左移动一次(图1) ,移除去的数据会放在通信线上,实际是放在输出数据寄存器上,此时MOSI数据是1,所以MOSI的电平是高电平,MISO数据是0,所以MISO的电平是低电平,这就是第一个时钟上升沿执行的结果(图2) ;之后时钟置一个下降沿,在下降沿时,主机和从机内,都会进行数据采样输入,也就是MOSI的1,会采样输入到从机的最低位,MISO的0,会采样输入到主机的最低位。这就是一个时钟结束后的现象(上升沿和下降沿的组合)(图3);如此字节交换,最终8个时钟过后,主机的数据在从机里,从机的数据在主机里。

如果只发不收,仍然用交换字节的时序,接收的数据(一般给从机写入0x00或0xFF)不看即可;如果只收不发,同理,调用交换字节的时序,随便发一个数据,从机不会看这个随便发的数据(一般发0x00或0xFF)


4.SPI时序基本单元

起始条件:SS从高电平切换到低电平


终止条件:SS从低电平切换到高电平


交换一个字节(模式0)(最常用)

MISO因为有多个从机输出连在一起,如果同时开启输出,会造成冲突,所以解决方法是在SS未被选中的状态,从机的MISO引脚必须关断输出,即配置为高阻状态(就是图中的一根线),SS上升沿之后,从机的MISO必须置回高阻状态

CPOL(时钟极性)=0:空闲状态时,SCK为低电平

CPHA(时钟相位,决定第一个时钟采样移入还是第二个时钟采样移入)=0:SCK第一个边沿移入数据,第二个边沿移出数据,在SCK第一个边沿之前就把数据移出了(或者理解为在第0个边沿移出)。相较于模式1提前半个相位(时钟)将数据移出


交换一个字节(模式1)

MISO因为有多个从机输出连在一起,如果同时开启输出,会造成冲突,所以解决方法是在SS未被选中的状态,从机的MISO引脚必须关断输出,即配置为高阻状态(就是图中的一根线),SS上升沿之后,从机的MISO必须置回高阻状态

CPOL=0:空闲状态时,SCK为低电平

CPHA=1:SCK第一个边沿移出数据,第二个边沿移入数据。


交换一个字节(模式2)

将模式0的SCK极性取反,就是模式2

CPOL=1:空闲状态时,SCK为高电平

CPHA=0:SCK第一个边沿移入数据,第二个边沿移出数据


交换一个字节(模式3)

将模式1的SCK极性取反,就是模式3

CPOL=1:空闲状态时,SCK为高电平

CPHA=1:SCK第一个边沿移出数据,第二个边沿移入数据


5.SPI时序(W25Q64)

采用指令码加读写数据的模型。流程:SPI起始后,第一个交换发送给从机的数据,这个数据一般是指令码;在从机中对应的会定义一个指令集,不同指令,可以有不同的数据个数,有的指令,只需要一个字节的指令码就可以完成,如:W25Q64的写使能、写失能等指令,有的指令,后面就需要再跟要读写的数据,比如:W25Q64的写数据、读数据等
发送指令

向SS指定的设备,发送指令(0x06),0x06表示写使能,主机向从机发送写使能的指令,从机接收到指令后,控制硬件,进行写使能


指定地址写

向SS指定的设备,发送写指令(0x02),随后在指定地址(Address[23:0])(地址是24位的分为3个字节传输)下,写入指定数据(Data)

第一个字节,发送写数据的指令;第二个字节到第四个字节都是地址,0x12(23~16位)、0x34(15~8位)、0x56(7~0位);第五个字节:写入的数据,表示在0x123456地址下,写入0x55这个数据
指定地址读

向SS指定的设备,发送读指令(0x03), 随后在指定地址(Address[23:0])下,读取从机数据(Data)

第一个字节,发送读数据的指令;第二个字节到第四个字节都是地址,0x12(23~16位)、0x34(15~8位)、0x56(7~0位);第五个字节:读取的数据,表示在0x123456地址下的数据通过MISO发给主机


6.W25Q64简介

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


7.硬件电路


8.W25Q64框图

存储器的规划示意图

8MB的存储空间,先划分为若干的块(Block),其中每一块再划分为若干的扇区(Sector),对于每个扇区内部又可以分成很多页(Page)
SPI Command & Control Logic:SPI控制逻辑。芯片内部进行地址锁存、数据读写等操作,这个是芯片自行完成的
Status Register:状态寄存器。芯片是否处于忙状态、是否写使能、是否写保护等等都可以在这个寄存器里面体现
Write Conteol Logic:写控制逻辑。和外部的WP引脚相连,通过这个引脚实现硬件写保护
High Vollage Generators:高电压生成器。配合Flash进行编程
指定地址,通过SPI发过来3个字节的地址,所以一页内的字节地址,就取决于最低一个字节,而高位的2个字节,就对应的是页地址,所以发送的3个字节的地址,前两个字节会进入这个页地址锁存计数器里,最后一个字节会进入字节地址锁存计数器里。然后,页地址,通过写保护和行解码,选择要操作哪一页,字节地址,通过列解码和256字节页缓存区(RAM存储器),进行指定字节的读写操作

Page Address Latch/Counter:页地址锁存/计数器

Byte Address Latch/Counter:字节地址锁存/计数器

Column Decode And 256-Byte Page Buffer:256字节页缓冲区。一种RAM存储器,因为Flash的写入太慢,跟不上SPI的频率,所以写入的数据会先放在RAM里面暂存,等时序结束后,芯片在慢慢地把数据写入到Flash里


9.Flash操作注意事项

写入操作时:

写入操作前,必须先进行写使能

每个数据位只能由1改写为0,不能由0改写为1

写入数据前必须先擦除,擦除后,所有数据位变为1

擦除必须按最小擦除(一个扇区)(对于W25Q64是4096个字节)单元进行,如果不擦除,读出的数据=原始数据&写入的数据

连续写入多字节时,最多写入一页(对于W25Q64是256个字节)的数据,超过页尾位置的数据,会回到页首覆盖写入

写入操作结束后,芯片进入忙状态,不响应新的读写操作
读取操作时:

直接调用读取时序,无需使能,无需额外操作,没有页的限制,读取操作结束后不会进入忙状态,但不能在忙状态时读取


10.参考资料(状态寄存器、框架图、指令集......)


11.软件SPI读写W25Q64代码

第一步:按图接线到面包板上

第二步:复制OLED显示屏代码

工程思路:

首先建立一个MySPI模块,这个模块包含通信引脚封装、初始化、时序:起始、终止、交换一个字节

然后基于MySPI,建立一个W25Q64模块,这个模块调用底层SPI,拼接各种指令和功能的完整时序,比如:写使能、擦除、页编程、读数据等等,所以这个模块是W25Q64的硬件驱动层

最后,在主函数里,调用W25Q64的硬件驱动层的函数,完成想要实现的功能

第三步:建立MySPI模块,完成通信引脚封装、初始化、时序:起始、终止、交换一个字节

模式0

另外一种方法,但是最开始的ByteSend就没有了

模式1

模式2

在模式0的基础上,将所有的SCK,0改为1,1改为0

模式3

在模式1的基础上,将所有的SCK,0改为1,1改为0

第四步:MySPI头文件声明

第五步:新建立一个头文件,命名为W25Q64_Ins,封装指令码

第六步:建立W25Q64驱动模块,调用底层SPI,拼接各种指令和功能的完整时序,比如:写使能、擦除、页编程、读数据等等,模块函数功能实现参考手册,模块的建成也要看Flash操作注意事项

第七步:W25Q64头文件声明

第八步:主函数调用

相关推荐
蜀黍@猿4 小时前
【GD32】MCU选型参考标准
arm开发·单片机·mcu
CiLerLinux5 小时前
第五十五章 ESP32S3 基于MQTT协议连接OneNet物联网开放平台
单片机·嵌入式硬件·物联网
单片机系统设计6 小时前
基于STM32的智能物联网加湿器/智能家居
stm32·单片机·物联网·毕业设计·智能家居
一支闲人7 小时前
带你了解STM32:I2C通信(第二部分)
stm32·单片机·嵌入式硬件·基础知识·适用于新手小白
充哥单片机设计8 小时前
【STM32项目开源】基于STM32的自适应车流交通信号灯
stm32·单片机·嵌入式硬件
liujing102329299 小时前
stm32底层项目20251011
stm32·单片机·嵌入式硬件
小刘爱玩单片机13 小时前
【嵌入式简单外设篇】-光敏模块
stm32·单片机·嵌入式硬件
迎風吹頭髮17 小时前
UNIX下C语言编程与实践62-UNIX UDP 编程:socket、bind、sendto、recvfrom 函数的使用
c语言·单片机·unix
DIY全栈开发18 小时前
《MCU职位》面试问题
单片机·嵌入式硬件·面试