当CPHA=1的时候,即表示会在时钟的奇数边沿开始对数据进行采样(第一个时钟边沿开始)。其中,当CPOL=0时,即表示SCK时钟空闲电平为低电平,由低电平变为高电平在变为低电平时,会在奇数边沿(上升沿)进行采样。反之,当CPOL=1时,即SCK时钟空闲时为高电平,由高电平变为低电平在变为高电平,会在偶数边沿(下降沿)进行采样。如下图:
1.3 数据交换
在SCK时钟周期下,MOSI和MISO同时处于工作状态。如下图:
如上,SPI通信中,主机和从机都有属于自己的移位寄存器,其用于数据的传输。主机移位寄存器数据经过MOSI将数据写入从机的移位寄存器,同时,从机移位寄存器的数据页通过MISO传给主机,实现数据的交换。
2. SPI 实现方式2.1 硬件SPI APM32F1xx系列开发板本身自带硬件电路设计而成的硬件SPI。在通信过程中,其依赖于内置的SPI外设,由硬件直接管理数据的传输过程,无需额外编程来控制SPI通信过程中的各个步骤。
2.1.1 硬件SPI使用的优缺点 优点:
1、 可以提供更高的通信速度和一致性
2、 可以实现更高的通信模式。如DMA传输、中断处理和主机模式。
3、 代码复杂度低,易于操作。
缺点:
1、 硬件SPI的配置和功能是固定的,不易修改。
2、 硬件SPI依赖于特定的硬件控制器,不同平台开发存在兼容性问题。
2.2 GPIO模拟SPI 在开发过程中,为了规避因硬件SPI不足而导致开发受阻的情况,可以通过GPIO口和软件控制来实现模拟SPI的通信过程。
2.2.1 GPIO模拟SPI使用的优缺点 优点:
1、 GPIO引脚配置灵活,可以任意选用开发板上的GPIO引脚来进行模拟操作。
2、 成本低,软件模拟SPI不需要额外的硬件设计,只需要有GPIO引脚即可。
缺点:
1、 通信速度低,受困于mcu的处理能力。
2、 代码复杂度高,需要更多的资源。
3. Flash 介绍
Flash,全称是 Flash Memory Controller,即闪存存储器控制器。FLASH通常用于存储程序代码、数据等信息。Flash包括内部Flash和外部Flash。在本文中采用到的W25Q64模块,便是一个SPI接口的外部Flash模块。在运行过程中,Flash存放的代码不会进行修改,且Flash按照扇区来进行操作。
Flash在写入之前数据前,通常需要进行擦除操作。因为Flash要写入数据时,其无法直接在已经被编程的扇区上进行修改,而是需要将整个扇区擦除成初始状态,然后在进行写入操作。
3.1 W25Q64 介绍 W25Q64是一款基于外设接口(SPI)的闪存芯片,它具有8Mbyte的存储空间,是一款大容量的SPI Flash产品。W25Q64将8M的字节容量分为128个块,每个块大小为64K,每个块又分为16个扇区,每个扇区有4K大小。W25Q64的最小擦除单位是扇区,这需要给其开辟一个至少大小为4K的缓冲区。
3.1.1 W25Q64常见命令指令
通过SPI向W25Q64发送指令,即可操作W25Q64。本文中操作所用到的一些指令表,如下图所示:
以页编程为例。在操作之前,需要拉低CS片选,在8个CLK时钟周期里,DI发出指令0x02,随后,在剩下的24个CLK时钟周期里,发送24Bit的地址,最后256*8个CLK,发送256字节数据。其时序图如下:
3.1.2 W25Q64使用的优缺点 优点:
1、 存储空间大
2、 支持高速的串行读写操作,具有较快的数据传输速率
3、 功耗低
4、 采用SPI接口进行通信,容易实现连接和控制。
缺点:
1、 价格高
2、 有限的使用寿命
3、 擦除操作慢
4 . APM32F1xx GPIO模拟SPI读写外部Flash例程讲解 本例程功能介绍:下载程序后,对灯、串口、GPIO模拟SPI的管脚进行初始化和使能操作。之后,对FlashID和DeviceID进行读取操作,读取结束之后会根据判断条件进入不同的状态。如果FlashID读取的数值跟定义好的ID一致,将会进行Flash的读写操作。如果不一致,LED3将会常亮。在Flash的读写操作中,进入写操作之前,先进行一次擦除操作,之后会分别进行写和读数据。操作结束之后,将读取和写入的数据进行对比并放到一个变量1中。之后,进行一次擦除操作,并在进行一次读取操作,与OXFF进行一次对比,并将对比放在变量2中,用于判断是否擦除成功。最后,将变量所得进行一一对比,并且串口和灯会分别做出不同的输出。下面将会对本例程的硬件设计、软件设计框架以及软件设计中的重要函数进行讲解。
4.1 硬件设计 本次实验所需要的硬件设计:
1.外部Flash模块
2.USB转TTL线
外部 Flash模块使用的是 W25Q64型号,W25Q64模块和 APM32F1xx 连接图如下:
USB转TTL线所使用到的GPIO管脚为PA9,PA10,利用USB转TTL线进行数据的接收和发送。其原理图如下:
4.2 软件设计
通过 APM32F1xx 实现GPIO模拟SPI读写外部Flash,需要根据模块的型号配置好外部Flash的ID信息,并且完成GPIO的管脚配置设计以及SPI通信时序,完成之后即可进行读写操作,并对读写操作完成结果输出。代码实现流程图如下:
4.2.1 GPIO引脚配置
对模拟SPI所使用到的GPIO管脚,将SCK、CS、MOSI管脚配置为推挽输出模式,MISO配置为下拉输入模式。参考代码如下:
4.2.2 模拟SPI时序读写操作 本文前面的章节中提出,SPI的传输可以看作一个虚拟的环形拓扑结构,表示输入和输出是在同一时间下进行。参考代码如下:
根据代码得知:
1.在每次读和写一个Byte时,都会循环8次,每次接收和发送一个Bit。在循环中,每次将byte的最高位存放到temp变量中;
2.byte左移一位,将次高位变为最高位,此操作用于下次取最高位。
3.将rx_data右移一位,挪动其最低位,8次循环后,rx_data将高位在前。
4.拉低时钟线,即将空闲电平设置为低电平。
5.根据temp值设置MOSI的引脚电平。
6.拉高时钟线,此时从设备读取MOSI的数据,并写数据到MISO。
7.读取完MISO上的数据,会将其保存到rx_data的最低位。
8.SPI读写结束后,拉低时钟线,进入空闲状态。
4.2.3 W25Q64设备信息读取操作
W25Q64主要有三个ID:制造商编号ID(Manufacturer)、设备ID(Device ID)、唯一表示ID(Unique ID)。其中,制造商编号ID是由Winbond生产的,它的值MF[7:0]为0xEF。设备ID包含两部分,ID[15:0]是芯片类型,为0x4017。ID[7:0]是存储容量。最后,唯一标识ID表示芯片的唯一性,常用于加密。如下图所示:
在代码实现过程中,使用0xAB指令获取设备ID[7:0],使用0x9F指令获取JEDEC ID(MF[7:0] +ID[15:0])。在实现过程中,均要先把/CS引脚拉低,然后分别把”ABh”、”9Fh”通过DI发送到芯片。在发送完”ABh”后,会经过一段tRES1时间间隔,芯片便恢复正常工作。在这当中,编程、擦除和写状态寄存器指令执行周期内,执行该指令无效。在发送完”9Fh”后,3个ID信息会分别从DO管脚在SCK的下降沿发送出去。参考代码如下图所示:
4.2.4 扇区擦除操作 根据芯片手册可知,发送0xD8指令,在发送24位的扇区地址,对整个块里面的扇区内容进行全擦除,在擦除完之后,所有字节均变为”FFh”,参考代码如下图所示:
4.2.5 页写入数据操作
W25Q64只能按页写数据,每页数据为256字节,因此一次最多写256字节。进行写入数据时,需要先发送0x02指令,在发送24位的扇区地址,即可对该扇区进行写入操作。参考代码如下图所示:
4.2.6 读取数据操作 进行读取数据时,需要先发送0x03指令,在发送24位的扇区地址,即可对该扇区进行读取操作。参考代码如下图所示:
4.2.7 等待Flash写完成操作
W25Q64有三个状态寄存器,bit[0]代表的是擦除/写入状态标志位。当写入或者读取操作结束时,需要对状态寄存器进行判断,发送”05h”数据获取状态寄存器的数据,当状态寄存器bit[0]的值为1时,还在进行擦除或者写入操作,当该位为0时,表示这时没有任何操作在进行,可以对W25Q64进行擦除或者写入操作。参考代码如下图所示:
5. APM32F1xx GPIO模拟SPI读写外部Flash Demo例程附件