SPI _FLASH芯片W25Q16配置FATFS

一、SPI FLASH芯片能干啥有哪些种类

存放数据。SPI FLASH普遍比EEPROM大得多。所以容量SPI FLASH占优势。但是价格,EEPROM占优势.

1、IIC EEPROM------容量小,采用的是IIC通信协议;用于在掉电时,存系统配置参数,比如屏幕亮度等。常用芯片型号有 AT24C02、FM24C02、CAT24C02等,其常见的封装多为DIP8,SOP8,TSSOP8等;

2、SPI NorFlash------容量略大,采用的是SPI 通信协议;用于存放程序和数据。程序和数据可存放在同一芯片上,拥有独立的数据总线和地址总线,能快速随机读取,允许系统直接从Flash中读取代码执行;可以单字节或单字编程,但不能单字节擦除,必须以Sector为单位或对整片执行擦除操作。常见到的S25FL128、MX25L1605、W25Q64等型号都是SPI NorFlash。

3、SPI NandFlash------采用了SPI NorFlash一样的SPI的通信协议,用于存储数据;在读写的速度上没什么区别,但在存储结构上却采用了与Parallel NandFlash相同的结构,所以SPI nand相对于SPI norFlash具有擦写的次数多,擦写速度快的优势。

4、eMMC Flash------eMMC采用统一的MMC标准接口,eMMC相当于NandFlash+主控IC;自身集成MMC Controller,存储单元与NandFlash相同。常见到的KLMAG8DEDD、THGBMAG8B4JBAIM、EMMC04G-S100等型号都是eMMC Flash。

5、SD卡------它在MMC的基础上发展而来,有两个可选的通信协议:SD模式和SPI模式。

二、W25Q16原理图及管脚

在这里插入图片描述

CS:CS为片选管脚,低电平有效。上电之后,在执行一条新的指令之前,必须让/CS管脚先有一个下降沿。 

DO(MISO):DO为串行数据输出引脚,在CLK(串行时钟)管脚的下降沿输出数据。

WP:WP为写保护管脚,有效电平为低电平。高电平可读可写,低电平仅仅可读。

DI(MOSI):DI为串行数据输入引脚,数据、地址和命令从DI引脚输入到芯片内部,在CLK(串行时钟)管脚的上升沿捕获捕获数据。

CLK(SLCK):CLK为串行时钟引脚。SPI时钟引脚,为输入输出提供时钟脉冲。

HOLD:HOLD为保持管脚,低电平有效。当CS为低电平,并且把HOLD拉低时,数据输出管脚将保持高阻态,并且会忽略数据输入管脚和时钟管脚上的信号。把HOLD管脚拉高,器件恢复正常工作。

VCC:电源2.7V~3.6V。

GND:接地。

三、SPI FLASH的四种模式

  1. 标准SPI

    标准SPI通常就称SPI,它是一种串行外设接口规范,有4根引脚信号:clk , cs, mosi, miso

  2. Dual SPI

    这种模式只是针对SPI Flash而言,不是针对所有SPI外设。对于SPI
    Flash,全双工并不常用,因此扩展了mosi和miso的用法,让它们工作在半双工,用以加倍数据传输。也就是对于Dual SPI
    Flash,可以发送一个命令字节进入dual mode,这样mosi(Data Input)变成SIO0(serial io
    0),mosi(DataOutput)变成SIO1(serial io 1),这样一个时钟周期内就能传输2个bit数据,加倍了数据传输。

  3. Qual SPI

    与Dual SPI类似,也是针对SPI Flash,Qual SPI,Flash增加了两根I/O线(SIO2,SIO3),目的是一个时钟内传输4个bit。

所以对于SPI Flash,有标准spi flash,dual spi , qual spi 三种类型,分别对应3-wire, 4-wire, 6-wire,在相同clock下,线数越多,传输速率越高。

四、W25Qxx Flash芯片存储

1、存储大小
W25Q16的存储单位为Page页、Sector扇区、 Block块,其中

1Page页 == 256 Bytes
1Sector扇区 == 16 Pages页=4096B=4KB
1Block 块 == 16 Sector扇区=95536B=64KB

在这里插入图片描述

以W25Q16JV为例,16表示存储器容量为16M_bit。上图为W25Q16JV的框图,其他各型号容量参考见下表:

  W25Q80DV 容量为 8M-bit,16 Block,256 Sector,4096 Page
  W25Q16   容量为 16M-Bit,32 Block,512 Sector,8192 Page
  W25Q32   容量为 32M-Bit,64 Block,1024 Sector,16384 Page
  W25Q64   容量为 64M-Bit,128 Block,2048 Sector,32768 Page
  W25Q128  容量为 128M-Bit,256 Block,4096 Sector,65536 Page

2、存储特点
Flash芯片内的数据只能由1变0,不能由0变1(这也是往FLASH写入数据先看是否全1,如果不是先擦除的原因)。擦除大小最小为4K。在Flash中,是按照Page进行写数据的,Page(256字节)是写的最小单位,写的起始地址也必须永远是Page的倍数。
5.2 数据格式
数据格式为数据长度8位大小,先发高位,再发低位

五、W25Q16的SPI指令

通过SPI给FLASH发送特定的数据使得FLASH完成特定功能,这些数据即W25Q16的SPI指令,这些指令在W25Q16数据手册讲解很详细,比如你可以通过阅读数据手册编程实现FLASH读取数据的功能,但由于正点原子已经将这些指令封装成了一堆库函数,你只需要知道库函数的功能就可以了,所以指令不再细讲。详解见下面大佬链接:
大佬博客:SPI指令详解

六、W25Q16的实时数据存储

要文件系统[链接],为啥??,其实不用,我只是想学学,所以找了下面几个原因:
1、难以记录有效数据的位置
2、难以确定存储介质的剩余空间
3、不明确应以何种格式来解读数据

文件系统FATFS创建及移植步骤:官网下载 -> 配置ffconf.h文件相关功能 -> 打开 diskio.c,进行底层驱动编写(官网有辅助文档)-> f_mkfs函数格式化-> f_mount函数注册工作区域,参考野火的文件系统教程,很详细。

移植过程详细配置步骤:
1、ffconf.h文件配置:

FF_USE_MKFS		1
FF_USE_FASTSEEK	1
FF_USE_LABEL	1
FF_CODE_PAGE	437
FF_USE_LFN		1
FF_VOLUMES		1
FF_MIN_SS		512
FF_MAX_SS		4096

2、diskio.c编写,参考野火视频讲解。
3、main函数编写测试文件(主要的测试包括格式化测试、文件写入测试和文件读取测试三个部分,主要程序都在main.c文件中实现。),参考野火视频教程。

下面是FATFS移植参考链接:
超详细的FATFS移植教程:链接
W25Q16移植文件系统:链接
正点原子文件过于冗余:链接

经过一星期的学习,我实现了Flash上文件系统的读写操作,但这里使用SPI Flash芯片作为物理设备,并不像SD卡那么方便直接用读卡器就可以在电脑端打开验证。另外一个问题,就目前来说,在SPI Flash芯片上挂载FatFs好像没有实际意义,无法发挥文件系统功能,但至少学会如何移植了。

七、在FLASH中存储小数

FLASH是一个物理设备,他的存储原理与场效应管差不多,只能存储0或1,所以存储在其中的数据没有类型可言,只有把数据读出来之后存储的地方才决定了如何解读这些数据。
例: 现在将int型 a1=2,float型 b1=3.3,double型 c1=4.4存储到的FLASH中,存储长度与变量类型长度相同。然后再从FLASH中读取相应数据到:int型a2,float型b2,double型c2,之后你会发现a2=a1、b2=b1、c2=c1,为啥呢?
因为不管要往FLASH写入什么类型的数据,传输的都是数据在MCU的内存中存储的机器数,拿 float型举例,float A = 66.8 ; 66.8存储在MCU就是一个由 0、1 组成长度为 32 位的机器数(大概第一位表示符号位,中间几位表示指数位,后面表示数值位,具体参考链接),这个 32 位的机器数8位8位的发送存储到FLASH没改变排列顺序。如果你用一个 float 型变量读取 FLASH 中的 32 位数据,其实就是把 FLASH 中的 32 位数据8位8位的传输到了float型变量在MCU的内存中,所以这个变量 B 依然表示66.8 。

  • 17
    点赞
  • 90
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SPI(Serial Peripheral Interface)是一种串行通信协议,可以用于与外设进行数据交互。W25Q64是一款64Mb的串行Flash存储器,支持SPI接口。 以下是使用C语言进行SPI读写W25Q64的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/spi/spidev.h> #define SPI_DEVICE "/dev/spidev0.0" // SPI设备节点路径 #define BUFFER_SIZE 256 // 缓冲区大小 int main() { int fd, ret; uint8_t tx_buffer[BUFFER_SIZE], rx_buffer[BUFFER_SIZE]; struct spi_ioc_transfer tr; // 打开SPI设备 fd = open(SPI_DEVICE, O_RDWR); if (fd < 0) { perror("Failed to open SPI device"); exit(1); } // 初始化SPI传输结构体 memset(&tr, 0, sizeof(tr)); tr.tx_buf = (unsigned long)tx_buffer; tr.rx_buf = (unsigned long)rx_buffer; tr.len = BUFFER_SIZE; tr.speed_hz = 10000000; tr.bits_per_word = 8; // 发送写命令 tx_buffer[0] = 0x06; // 写使能 ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); if (ret < 0) { perror("Failed to send write enable command"); exit(1); } tr.len = 4; tx_buffer[0] = 0x02; // 写指令 tx_buffer[1] = 0x00; // 地址高位 tx_buffer[2] = 0x00; // 地址中位 tx_buffer[3] = 0x00; // 地址低位 memcpy(tx_buffer + 4, "Hello", 5); // 写入数据 // 发送写数据命令 ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); if (ret < 0) { perror("Failed to send write command"); exit(1); } // 发送读命令 tr.len = 4; tx_buffer[0] = 0x03; // 读指令 tx_buffer[1] = 0x00; // 地址高位 tx_buffer[2] = 0x00; // 地址中位 tx_buffer[3] = 0x00; // 地址低位 ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); if (ret < 0) { perror("Failed to send read command"); exit(1); } printf("Data read from flash memory: %s\n", rx_buffer + 4); // 关闭SPI设备 close(fd); return 0; } ``` 以上代码演示了如何使用SPI接口读写W25Q64芯片。其中,首先通过ioctl函数设置SPI传输参数和指令,然后通过ioctl函数发送指令,并通过缓冲区读取或写入数据。 需要注意的是,通过SPI接口读写W25Q64芯片需要按照其通信协议进行操作,具体指令和数据格式可参考W25Q64的数据手册。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值