目录
SPI FLASH
1. 概述
单片机开发过程中,我们经常会需要将一些数据记录下来,所以会使用到非易失性存储器。非易失性存储器有EEPROM,FLASH等。这里我所使用的是FLASH用来存储数据。FLASH的存储空间大,并且交互速度快。
2. SPI
SPI是MCU与FLASH的一种通讯方式。SPI不同于UART,SPI是同步通讯,通过控制CLK时钟线,根据所设置的SPI模式来进行数据采集,在下面会有简单的介绍。
2.1. 引脚介绍
- SCK:时钟总线
- CS:片选信号
- MOSI:数据总线(输出)
- MISO:数据总线(输入)
2.1.1. SCK - 时钟总线
SPI不像UART一样,可以进行异步通讯。UART是通过协商波特率,规定了双方通讯时的采样周期,从而达到异步通讯。而SPI是通过SCK来主动控制数据的采样点(控制SCK高低电平)。在SCK在空闲状态
与有效状态
之间跳变的时候,单片机会在上升沿
或下降沿
期间,去采集数据总线上的数据。在芯片手册上,会有CPOL
和CPHA
两个标志位,用来设置SPI数据采样方式
。
0 | 1 | |
---|---|---|
CPOL | 空闲电平为 0 | 空闲电平为1 |
CPHA | 第一个跳变沿采集 | 第二个跳变沿采集 |
模式设置
模式 | CPOL | CPHA |
---|---|---|
MODE 0 | 0 | 0 |
MODE 1 | 0 | 1 |
MODE 2 | 1 | 0 |
MODE 3 | 1 | 1 |
2.1.2. MOSI/MISO
这两根是数据总线,一根是输出总线,一根是输入总线。数据采集的时候会从这两根数据上采集Bit,进而获取Byte。
2.1.3. CS
CS是片选信号,当CS有效时,才可以通讯。当"主机"(例如MCU)拥有多个CS的时候,可以用一路SPI去控制多个从设备,通过将CS设置为有效状态即可,但同时只能有一个从设备进行通讯
。
2.2. 数据收发
硬件SPI
2.2.1. 发送数据
将数据写入发送寄存器,等待数据发送完成即可。
2.2.2. 接收数据
先发送一个数据,等大概数据发送完成后,再去数据接受缓存器中获取数据。这里就是SPI比较特殊的一点,为什么接受数据时得先发送一个数据?
其实根本上还是跟SCK有关,SPI进行数据交互是个根据SCK状态来决定的,一般来说SCK都是由主机控制,当主机需要从从机获取数据的时候,就需要控制SCK,从机会根据SCK的状态来将数据一位一位发出。
在接收一个数据之前,发送一个数据,是因为当使用硬件SPI时,为了方便,直接使用发送一个字节,来产生响应的SCK时序,以此来触发从机发送数据,当然,也可以直接通过控制SCK引脚直接控制来达到同样的效果
。
2.2.3. 时序图
//TODO:
3. FLASH 基本操作
FLASH型号:W25Q64
此处仅仅为了记录在实际项目中的应用。
3.1. 读数据
FLASH支持随机地址的读写,再读数据之前,需要先将读命令和读地址写入到FLASH,然后做一个延时,为了等待FLASH准备好数据,之后再去读取数据。读出来数据后,最好再做一次相同的操作,将两次的数据进行比对,确保数据准确性
。
3.2. 擦数据
FLASH不像EEPROM一样,可以随意的写入、更改数据,FLASH有一个特性是内存中的数据只能从1->0,不可逆,当目标地址存的数据不能满足新写入的数据的需求的时候,就需要擦除掉,擦除后该地址的数据为FF,,然后再写入新的数据。每次只能擦除一个扇区、一个块、一片(全擦)。
3.3. 写数据
- 可写性判断:先将目标地址的数据读出,进行比对(
当目标地址数据 & 新数据 == 新数据
)时,可以直接写入数据,否则需要做擦除操作后再写入。 - 数据写入:写入数据。
- 数据比对:写入完成后,将目标地址的数据读出,与写入的数据作比较,确保数据一致性。
4. 数据库
在实际的应用中,上述写入操作是基操,对于单纯的存储log数据适用,数据永远是追加在后面的。但是有特殊的时候,会要求将参数也存入FLASH中(一般来存在EEPROM中比较方便),这时候需要将FLASH当做数据库一样去使用。
4.1 数据搬移
通过使用缓存区的方式,将不变的数据搬移到缓存区中,再擦除原扇区的数据,再将缓存区的数据搬移回来,再写入数据。
操作步骤:
- 擦除缓存区(空闲扇区)。
- 将目标扇区的数据(除需要写入的那一部分)读出,写入到缓存区。
- 擦除原扇区地址。
- 将缓存区的数据全部搬移回目标扇区。
- 插入数据(此时目标地址为FF,可以任意写入数据)。
4.2 数据搬移管理
在数据搬移过程中,我们做了多次的扇区擦除、读数据、写数据等操作,当处理的数据量较大时,耗时会长一点,那么很有可能在此过程中发生了断电之类的情况,那么就会造成数据的丢失,因此我们这里可以增加一个管理数据,来记录一些搬移的过程,来保证我们数据的安全。
管理区就是在一块空闲的扇区中,用一些内容来记录当前数据搬移进度。
管理区中填充的内容
- magic_word:魔术字,一般用来标识搬移至缓存器完成、回搬至目标扇区完成。比如初始值为0x00000000,当搬移至缓存区完成后,将更新为0xAAAAAAAA,当回搬至目标区后,更新为0xBBBBBBBB。在程序运行过程中,判断该值若是0xAAAAAAAA,则需要进行数据回搬处理。
- target_address:目标区地址
- cache_address:缓存区地址
在程序初始化的时候会将FLASH中的数据读取到RAM中,RAM和FLASH中的数据保持同步。