SPI_FLASH时序描述及驱动编程

Ⅰ、写在前面

前面文章讲述过关于SPI的驱动(硬件SPI 和 软件模拟SPI),本文接着那篇文章来讲述关于SPI应用中【FLASH时序描述及驱动编程】

写这篇文章的目的有两点:1.让大家知道SPI在实际应用开发中的重要意义; 2.让大家掌握SPI FLASH存储芯片的时序及驱动编程。

市面上的SPI FLASH类型很多,但是绝大部的芯片在硬件软件上都是兼容的。虽然本文是以华邦的W25X16芯片为例来讲述时序。其实,其它大部分SPI FLASH都适用。

有必要看芯片手册,按照手册一步一步写程序吗?

1、如果你是初学者,而且还有很多时间,建议花些时间掌握一下! 原因在于作为嵌入式开发者,需要对芯片的编程有一定了解,在以后工作项目中如果有使用新的芯片,自己就能很容易编写驱动(如果没有现成的驱动)。

2、如果你是工作了一断时间,自己对芯片驱动编程有一些经验,在需要使用新的芯片,如果有现成的、比较成熟的驱动,那么,你可以不用再话费时间自己亲自编写驱动(编写驱动很费时间,还需要花费一定时间验证)。

关于本文的更多详情请往下看。

 

Ⅱ、实例工程下载

笔者针对于初学者提供的例程都是去掉了许多不必要的功能,精简了官方的代码,对初学者一看就明白,以简单明了的工程供大家学习。

笔者提供的实例工程都是在板子上经过多次测试并没有问题才上传至360云盘,欢迎下载测试、参照学习。

提供下载的软件工程是基于Keil(MDK-ARM) V5版本、STM32F103ZE芯片,但F1其他型号也适用(适用F1其他型号: 关注微信,回复“修改型号”)。

STM32F10x_SPI(硬件接口)读写Flash(25Q16)实例源代码工程:

https://yunpan.cn/c6mfRJWva6AJ2  访问密码

STM32F10x_SPI(软件模拟)读写Flash(25Q16)实例源代码工程:

https://yunpan.cn/c6mf6zyzCaMwd  访问密码

SPI FLASH资料:

https://yunpan.cn/c6Yi3agWUnGNQ  访问密码 d790

STM32F1资料:

https://yunpan.cn/crBUdUGdYKam2  访问密码 ca90

Ⅲ、关于SPI FLASH

1.SPI FLASH芯片系列

SPI FLASH的种类及型号有很多,但根据笔者的了解及经验,虽然存在这些差异,但他们之间的兼容性是很好的。

如:W25Xxx系列、W25Qxx系列、GD25Qxx系列、M25Pxx系列、KM25Lxx系列、SST25VFxx系列、AT25F系列等。

2.SPI FLASH命名

每一家公司的芯片型号命名可能略有差异,但看手册就能明白。我们以华邦的W25系列芯片来举例说明:

W:代表华邦公司

25X:代表SPI FLASH类型(25X是基本芯片, 25Q是快速芯片)

16:代表16MBit,即2M字节(64代表8M字节, 128代表16M字节,依次下去)

这个需要大家了解的(主要在项目研发初级阶段对芯片的选型上使用到)。其他公司的芯片,查看方法类似.对比如图是ST公司的M25PExx系列芯片:

3.W25Xxx读写特性

读:无要求

写:需要擦除才能写,一次最多可写入256字节(可编程页)。

擦除:最小扇区擦除(4K)、可块擦除(64K)、 可整个芯片擦除。

Ⅳ、SPI FLASH时序及编程

这里还是以华邦的W25X16为例来说明(其他大部分兼容),请下载手册【W25Xxx手册(英文版)】参考。

1.预先了解W25Xxx

A.控制和状态寄存器命令(默认:0x00)

BIT位  7   6   5   4   3   2   1   0

SPR  RV  TB  BP2 BP1 BP0 WEL BUSY

SPR:默认0,状态寄存器保护位,配合WP使用

TB,BP2,BP1,BP0:FLASH区域写保护设置

WEL:写使能锁定

BUSY:忙标记位(1,忙;0,空闲)

B.指令集表

编程主要就围绕这些“指令”来编程。在我提供的软件工程代码“sflash.h”文件中就定义了和手册对应的指令,如下图:

2.写使能(0x06)

在操作(控制、数据)之前,都需要发送一条“写使能”指令。

时序如下图

源代码程序:

3.写失能(0x04)

和“写使能”类似,要失能写,在操作(控制、数据)之后,都需要发送一条“写失能”指令。

时序如下图

源代码程序:

4.读状态/控制(0x05)

W25X芯片唯一的状态寄存器,各个位的意思请看上面的介绍,比如判断忙不忙,就需要读状态。

时序如下图

源代码程序:

5.写状态/控制(0x01)

写状态/控制 和 读状态/控制类似。

时序如下图

源代码程序:

6.读数据(0x03)

这个就是我们重要的读数据指令。1.写入指令0x03; 2.写入24位地址; 3.连续读出N字节数据(只要有时钟,可以连续读出多字节);

时序如下图

源代码程序:

7.快速读数据(0x0B)

“快速读数据”和“读数据”类似,但它的区别:1.读数据速度更快; 2.需要在写入地址之后需要8个时钟的等待。

1.写入指令0x0B; 2.写入24位地址; 3.写入8个时钟; 4.连续读出N字节数据(只要有时钟,可以连续读出多字节);

时序如下图

源代码程序:

8.快速双通道读数据(0x3B)

“快速双通道读数据”和“快速读数据”类似,但它的区别:在读数据的时候是两条通道,也就是我们平时主机的输出引脚(MOSI)在这个时候拿来当做输入引脚读数据。

注意:

使用该指令功能,需要改变SPI底层驱动(即需要改变MOSI引脚的输入输出状态)。针对初学者,我提供的工程也没有写的那么复杂,即该指令功能没有(感兴趣的朋友可研究一下)。

9.写数据(页编程)(0x02)

“写数据”和“读数据”类似,但写数据都是在同一条数据(DIO)线上,读数据在地址之后是在DO数据上。

1.写入指令0x02; 2.写入24位地址; 3.连续写入N字节数据(只要有时钟,可以连续写入多字节,注意这里一次不能超过256字节数据);

时序如下图

源代码程序:

10.块擦除(0xD8)

W25Xxx块的多少有芯片型号决定,一块数据大小64K。

W25X16共2M字节,有16块(2M/64K = 16)

W25X64共8M字节,有64块(8M/64K = 64)

以此类推...

注意:这个块的地址是和数据的地址对应,我们程序块擦除中将块区分开来。

时序如下图

源代码程序:

11.扇区擦除(0x20)

W25Xxx扇区的多少有芯片型号决定,扇区数据大小4K。

W25X16共2M字节,有256块(2M/4K = 256)

W25X64共8M字节,有1024块(8M/4K = 1024)

以此类推...

同样,我们程序扇区擦除中将扇区以扇区的形式区分开来。

时序如下图

源代码程序:

12.芯片擦除(0xC7)

这条指令是擦除整个芯片内容,如果要继续操作芯片,需要等待擦除完成(检查忙信号)。

时序如下图

源代码程序:

13.掉电(低功耗)(0xB9)

需要将芯片处于低功耗,发送该指令。

时序如下图

源代码程序:

14.唤醒/ID(0xAB)

该指令有两个功能:1.将处于低功耗的芯片唤醒(常用); 2.读取设备ID(不常用)。

发送该指令可以将芯片唤醒,继续发送3字节无效数据,可继续读出设备ID.由于读取设备ID有单独的指令,这里基本不常用于读设备ID(程序中也没有该功能)。

时序如下图

源代码程序:

15.读取ID(0x90)

这个指令读取两字节数据(ID):高字节是厂家Manufacturer,低字节是芯片型号ID.

如我开发板上是W25Q128,读到的ID是:0XEF17

W25X16读到的ID是:EF14

时序如下图

源代码程序:

16.JEDEC_ID(0x9F)

出于兼容性考虑,有些芯片厂家使用该指令读取ID,这条指令和上一条指令类似。

与上一条指令不同点:1.不用发送3字节无效数据;  2.读出来的ID是3字节(依次是:厂家ID、批次ID、型号ID)。

时序如下图

源代码程序:

以上就是关于W25Xxx芯片所有的指令,其他厂家芯片或许还有一些指令,请根据情况看手册编写相应代码。

Ⅴ、说明

本文主要是为初学者提供一个编程的思路,及如何根据时序编程。

以上总结仅供参考,若有不对之处,敬请谅解。

、最后

更多精彩文章我将第一时间在微信公众号里面分享,该文有什么疑问可留言。

本着免费分享的原则,方便大家手机学习知识,定期在微信平台分享技术知识。如果你觉得分享的内容对你有用,又想了解更多相关的文章,请用微信搜索“EmbeddDeveloper” 或者扫描下面二维码、关注,将有更多精彩内容等着你。

时间: 2024-08-08 05:36:09

SPI_FLASH时序描述及驱动编程的相关文章

【原创】Linux环境的图形系统和AMD显卡驱动编程(2)——Framebuffer、DRM、EXA和Mesa简介

1. Framebuffer Framebuffer驱动提供基本的显示,framebuffer驱动操作的硬件就是一个显示控制器和帧缓存(一片位于系统主存或者显卡显存).Framebuffer驱动向应用程序提供/dev/fbx的设备接口,应用程序通过读写这个设备节点实现对显示控制器和帧缓存. 下面这个程序显示了应用程序操作操作framebuffer节点的过程.运行这个程序,将在屏幕上方显示一个正方形(这里省略了错误检查代码). 1 #include <stdio.h> 2 #include &l

驱动编程思想之初体验 --------------- 嵌入式linux驱动开发之点亮LED

这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的住,不然真像一些人说的,学了一年嵌入式感觉还没找到门. 不能再扯了,涉及到linux的驱动开发知识面灰常广,再扯文章就会变得灰常长.首先还是回到led驱动的本身上,自从linux被移植到arm上后,做驱动开发的硬件知识要求有所降低,很多都回归到了软件上,这是系统编程的一大特点,当然 ,也不排除有很多

【原创】Linux环境的图形系统和AMD显卡驱动编程(1)——Linux环境下的图形系统简介

Linux/Unix环境下最早的图形系统是Xorg图形系统,Xorg图形系统通过扩展的方式以适应显卡和桌面图形发展的需要,然而随着软硬件的发展,特别是嵌入式系统的发展,Xorg显得庞大而落后.开源社区开发开发了一些新的图形系统,比如Wayland图形系统. 由于图形系统.3D图形本身的复杂以及历史原因,Linux下的图形系统相关的源码庞大而且复杂,而且缺少学习的资料(所有源代码分析或者驱动编程的书籍都很少介绍显卡驱动).在后续一系列文章中,笔者将从对AMD硬件编程的角度出发对部分问题做一个简单的

编程技巧之表格驱动编程

/* Image format-dependent operations. */ typedef struct { jas_image_t *(*decode)(jas_stream_t *in, char *opts); /* Decode image data from a stream. */ int (*encode)(jas_image_t *image, jas_stream_t *out, char *opts); /* Encode image data to a stream.

嵌入式linux驱动开发之点亮led未遂(驱动编程思想之初体验)

有了上两篇文章的基础,我们就可以开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的住,不然真像一些人说的,学了一年嵌入式感觉还没找到门. 另外实践很重要,一年多以前就知道了arm,那时整天用单片机的思维去yy着arm,直到前段时间弄来一块arm板,烧上linux系统后才知道,坑呀!根本不是那回事,所以实践是学习计算机类最重要的基本素质,如果整天看书,那基本上

(转)Windows驱动编程基础教程

版权声明 本书是免费电子书. 作者保留一切权利.但在保证本书完整性(包括版权声明.前言.正文内容.后记.以及作者的信息),并不增删.改变其中任何文字内容的前提下,欢迎任何读者 以任何形式(包括各种格式的文档)复制和转载本书.同时不限制利用此书赢利的行为(如收费注册下载,或者出售光盘或打印版本).不满足此前提的任何转载. 复制.赢利行为则是侵犯版权的行为. 发现本书的错漏之处,请联系作者.请不要修改本文中任何内容,不经过作者的同意发布修改后的版本. 作者信息 作者网名楚狂人.真名谭文.在上海从事W

第6章 Android驱动编程

第6章  Android驱动编程 通过介绍本章设备驱动.字符设备驱动编程.GPIO驱动程序实例和4*4扫描键盘驱动等内容,熟练掌握了Android驱动编程.Android内核内核模块编程中包括设备驱动和内核模块.模块相关命令.Android内核内核模块编程和内核模块实例程序.Android内核中采用可加载的模块化设计,一般情况下编译的Android内核是支持可插入式模块的,也就是将最基本的核心代码编译在内核中.模块相关命令中lsmod列出了当前系统中加载的模块,rmmood用于当前模块卸载,in

14、字符驱动编程模型

字符驱动编程模型 上面就是内核的cdev的结构.他只有6个成员.有一些是内核自己回去用的,有一些是我们程序员要去用的.例如:count,表明设备有几个可以用.例如,我的开发板支持三个串口.所以count=3.还有设备号:查看设备文件: 我们从前面知道,我们是通过字符设备文件来访问我们的字符设备驱动的.两者是通过主设备号来建立联系的. 一个主设备好可以对应多个此设备号.他们是同一类型的设备.驱动程序就是通过次设备号来区分是串口1还是串口2的 设备号的操作 设备号分配 设备号-注销 这是一个很重要的

Linux内核驱动编程

Linux内核驱动编程 2015-02-12 驱动程序基础的东西这儿就不罗嗦了,百度上有更好的资料,此处我们只是注重实际用处. 下面我们开始写程序: 一.初步helloword程序 首先是来一个简单的hello. hello.c代码: 1 /****************************** 2 3 the first program 4 5 Hello World! 6 7 ******************************/ 8 9 #include <linux/mod