nandflash时序

合集下载

怎么看时序图--nand flash的读操作详解

怎么看时序图--nand flash的读操作详解

这篇文章不是介绍nand flash的物理结构和关于nand flash的一些基本知识的。

你需要至少了解你手上的nand flash的物理结构和一些诸如读写命令操作的大概印象,你至少也需要看过s3c2440中关于nand flash控制寄存器的说明。

由于本人也没有专门学过这方面的知识,下面的介绍也是经验之谈。

这里我用的K9F2G08-SCB0 这款nand flash 来介绍时序图的阅读。

不同的芯片操作时序可能不同,读的命令也会有一些差别。

当然其实有时候像nand flash这种s3c2440内部集成了他的控制器的外设。

具体到读写操作的细节时序(比如CLE/ALE的建立时间,写脉冲的宽度。

数据的建立和保持时间等),不明白前期也没有多大的问题。

因为s3c2440内部的nand flash控制器做了大部分的工作,你需要做的基本就是设置几个时间参数而已。

然后nand flash会自动进行这些细节操作。

当然如果处理器上没有集成nand flash的控制器那么久必须要自己来写时序操作了。

所以了解最底层的时序操作总是好的但是上层一点的,比如读写操作的步骤时序(比如读操作,你要片选使能,然后发命令,然后发地址,需要的话还需发一个命令,然后需要等待操作完成,然后再读书数据)。

是必须要明白的。

这都不明白的话,怎么进行器件的操作呢也就是说s3c2440 可以说在你设置很少的几个时间参数后,将每一个步骤中细微的操作都替你做好了。

(比如写命令,你只要写个命令到相应寄存器中,cpu内部就会协各个引脚发出适应的信号来实现写命令的操作)。

而我们所需要做的就是把这些写命令,写地址,等待操作完成。

等步骤组合起来。

从而完成一个读操作就像上面说的,虽然我们不会需要去编写每个步骤中的最细微的时序。

但是了解下。

会让你对每个操作步骤的底层细节更加明了先来看一个命令锁存的时序。

也就是上面说的读nand flash操作中不是有一个写命令步骤吗。

nandflash的原理及运行时序

nandflash的原理及运行时序

nandflash的原理及运行时序NAND Flash(非与非闪存)是一种主要用于存储数据的闪存类型,广泛应用于各种存储设备中,如固态硬盘(SSD)、USB闪存驱动器(U盘)以及移动设备中的存储卡等。

NAND Flash的原理:NAND Flash中的基本存储单元是晶体管,每个晶体管可以存储一个或多个bit的数据,通过对晶体管的电荷状态进行读取和写入来实现数据的存储和读取。

NAND Flash的存储单元结构主要有两种类型:单栅结构和多栅结构。

单栅结构中每个晶体管只有一个控制栅(Control Gate)和一个栅介电层(Oxide Layer),而多栅结构中每个晶体管有一个控制栅和多个叠加的栅介电层。

NAND Flash的存储单元编址是按行和列进行的。

每一行包含一个选择门(Word Line),每一列包含一个位线(Bit Line)。

数据的读取和写入都是通过对选择门和位线的控制来实现的。

NAND Flash的运行时序:1.写入时序:(1)输入地址:将要写入的存储单元的地址输入到NAND Flash中。

(2)擦除块的选择:选择需要写入数据的块进行擦除。

(3)擦除块的擦除:对选择的块进行擦除操作,将存储单元中的数据清除。

(4)写入数据:将要写入的数据输入到NAND Flash中。

(5)写入选择门:通过选择门将输入的数据写入到相应的存储单元中。

2.读取时序:(1)输入地址:将要读取的存储单元的地址输入到NAND Flash中。

(2)读取选择门:通过选择门将存储单元中的数据读出。

(3)读取数据:将读取的数据输出。

需要注意的是,NAND Flash的擦除操作是以块为单位进行的,而写入操作是以页为单位进行的。

擦除块的大小通常为64KB或128KB,一页的大小通常为2KB或4KB。

此外,NAND Flash还包含了一些管理区域,用于存储元数据和管理信息。

总结:NAND Flash是一种基于晶体管的闪存类型,通过对晶体管的电荷状态进行读取和写入来实现数据的存储和读取。

nand flash时序图详解

nand flash时序图详解

怎么看时序图--nand flash的读操作详解 2013-11-16 10:25:36分类:嵌入式这篇文章不是介绍 nand flash的物理结构和关于nand flash的一些基本知识的。

你需要至少了解你手上的 nand flash的物理结构和一些诸如读写命令操作的大概印象,你至少也需要看过 s3c2440中关于nand flash控制寄存器的说明。

由于本人也没有专门学过这方面的知识,下面的介绍也是经验之谈。

这里我用的 K9F2G08-SCB0 这款nand flash 来介绍时序图的阅读。

不同的芯片操作时序可能不同,读的命令也会有一些差别。

当然其实有时候像nand flash这种 s3c2440内部集成了他的控制器的外设。

具体到读写操作的细节时序(比如 CLE/ALE的建立时间,写脉冲的宽度。

数据的建立和保持时间等),不明白前期也没有多大的问题。

因为s3c2440内部的nand flash控制器做了大部分的工作,你需要做的基本就是设置几个时间参数而已。

然后nand flash会自动进行这些细节操作。

当然如果处理器上没有集成 nand flash的控制器那么久必须要自己来写时序操作了。

所以了解最底层的时序操作总是好的但是上层一点的,比如读写操作的步骤时序(比如读操作,你要片选使能,然后发命令,然后发地址,需要的话还需发一个命令,然后需要等待操作完成,然后再读书数据)。

是必须要明白的。

这都不明白的话,怎么进行器件的操作呢也就是说 s3c2440 可以说在你设置很少的几个时间参数后,将每一个步骤中细微的操作都替你做好了。

(比如写命令,你只要写个命令到相应寄存器中,cpu内部就会协各个引脚发出适应的信号来实现写命令的操作)。

而我们所需要做的就是把这些写命令,写地址,等待操作完成。

等步骤组合起来。

从而完成一个读操作就像上面说的,虽然我们不会需要去编写每个步骤中的最细微的时序。

但是了解下。

会让你对每个操作步骤的底层细节更加明了先来看一个命令锁存的时序。

NADN FLASH时序详解

NADN FLASH时序详解

NADN FLASH时序详解怎么看时序图--nand flash的读操作详解这篇文章不是介绍 nand flash的物理结构和关于nand flash的一些基本知识的。

你需要至少了解你手上的 nand flash的物理结构和一些诸如读写命令操作的大概印象,你至少也需要看过 s3c2440中关于nand flash控制寄存器的说明。

由于本人也没有专门学过这方面的知识,下面的介绍也是经验之谈。

这里我用的 K9F2G08-SCB0 这款nand flash 来介绍时序图的阅读。

不同的芯片操作时序可能不同,读的命令也会有一些差别。

当然其实有时候像nand flash这种 s3c2440内部集成了他的控制器的外设。

具体到读写操作的细节时序(比如 CLE/ALE的建立时间,写脉冲的宽度。

数据的建立和保持时间等),不明白前期也没有多大的问题。

因为s3c2440内部的nand flash控制器做了大部分的工作,你需要做的基本就是设置几个时间参数而已。

然后nand flash会自动进行这些细节操作。

当然如果处理器上没有集成 nand flash的控制器那么久必须要自己来写时序操作了。

所以了解最底层的时序操作总是好的但是上层一点的,比如读写操作的步骤时序(比如读操作,你要片选使能,然后发命令,然后发地址,需要的话还需发一个命令,然后需要等待操作完成,然后再读书数据)。

是必须要明白的。

这都不明白的话,怎么进行器件的操作呢也就是说 s3c2440 可以说在你设置很少的几个时间参数后,将每一个步骤中细微的操作都替你做好了。

(比如写命令,你只要写个命令到相应寄存器中,cpu内部就会协各个引脚发出适应的信号来实现写命令的操作)。

而我们所需要做的就是把这些写命令,写地址,等待操作完成。

等步骤组合起来。

从而完成一个读操作就像上面说的,虽然我们不会需要去编写每个步骤中的最细微的时序。

但是了解下。

会让你对每个操作步骤的底层细节更加明了先来看一个命令锁存的时序。

Nand flash工作原理

Nand flash工作原理

Nand flash芯片工作原理------------------------------------Nand flash芯片型号为Samsung K9F1208U0B,数据存储容量为64MB,采用块页式存储管理。

8个I/O引脚充当数据、地址、命令的复用端口。

芯片内部存储布局及存储操作特点:一片Nand flash为一个设备(device), 其数据存储分层为:1 (Device) = 4096 (Blocks)1 (Block) -= 32 (Pages/Rows) 页与行是相同的意思,叫法不一样1 (Page) = 528 (Bytes) = 数据块大小(512Bytes) + OOB 块大小(16Bytes)在每一页中,最后16个字节(又称OOB)用于Nand Flash命令执行完后设置状态用,剩余512个字节又分为前半部分和后半部分。

可以通过Nand Flash命令00h/01h/50h分别对前半部、后半部、OOB进行定位通过Nand Flash内置的指针指向各自的首地址。

存储操作特点:1. 擦除操作的最小单位是块。

2. Nand Flash芯片每一位(bit)只能从1变为0,而不能从0变为1,所以在对其进行写入操作之前要一定将相应块擦除(擦除即是将相应块得位全部变为1).3. OOB部分的第六字节(即517字节)标志是否是坏块,如果不是坏块该值为FF,否则为坏块。

(转载注:应该是每块的第一页的第六个字节。

)4. 除OOB第六字节外,通常至少把OOB的前3个字节存放Nand Flash硬件ECC码NAND FLASH的工作原理- to beginner2007-04-23 23:43NAND FLASH 是一种大容量、高速的存储技术。

其接口较为简单,如果没有专门的nand flash控制器,甚至可以用io口与之对接。

其编程也相对简单,只要了解如下关键概念就可以:1.nand flash内部有管理单元,管理单元负责对nand flash的实际单元的操作。

nand flash时序图详解

nand flash时序图详解

怎么看时序图--nand flash的读操作详解 2013-11-16 10:25:36分类:嵌入式这篇文章不是介绍 nand flash的物理结构和关于nand flash的一些基本知识的。

你需要至少了解你手上的 nand flash的物理结构和一些诸如读写命令操作的大概印象,你至少也需要看过 s3c2440中关于nand flash控制寄存器的说明。

由于本人也没有专门学过这方面的知识,下面的介绍也是经验之谈。

这里我用的 K9F2G08-SCB0 这款nand flash 来介绍时序图的阅读。

不同的芯片操作时序可能不同,读的命令也会有一些差别。

当然其实有时候像nand flash这种 s3c2440内部集成了他的控制器的外设。

具体到读写操作的细节时序(比如 CLE/ALE的建立时间,写脉冲的宽度。

数据的建立和保持时间等),不明白前期也没有多大的问题。

因为s3c2440内部的nand flash控制器做了大部分的工作,你需要做的基本就是设置几个时间参数而已。

然后nand flash会自动进行这些细节操作。

当然如果处理器上没有集成 nand flash的控制器那么久必须要自己来写时序操作了。

所以了解最底层的时序操作总是好的但是上层一点的,比如读写操作的步骤时序(比如读操作,你要片选使能,然后发命令,然后发地址,需要的话还需发一个命令,然后需要等待操作完成,然后再读书数据)。

是必须要明白的。

这都不明白的话,怎么进行器件的操作呢也就是说 s3c2440 可以说在你设置很少的几个时间参数后,将每一个步骤中细微的操作都替你做好了。

(比如写命令,你只要写个命令到相应寄存器中,cpu内部就会协各个引脚发出适应的信号来实现写命令的操作)。

而我们所需要做的就是把这些写命令,写地址,等待操作完成。

等步骤组合起来。

从而完成一个读操作就像上面说的,虽然我们不会需要去编写每个步骤中的最细微的时序。

但是了解下。

会让你对每个操作步骤的底层细节更加明了先来看一个命令锁存的时序。

NandFlash驱动(实现初始化以及读操作)

NandFlash驱动(实现初始化以及读操作)

NandFlash驱动(实现初始化以及读操作)本节来学习裸机下的Nand Flash驱动,本节学完后,再来学习Linux下如何使⽤Nand Flash驱动Linux中的Nand Flash驱动,链接如下:(只需要初始化Flash以及读Flash)打开2440芯⽚⼿册,K9F2G08U0M芯⽚⼿册(因为2440中Nand Flash是⽤的256MB(2Gb)内存,8个数据引脚)在芯⽚⼿册中得到K9F2G08U0M=2048块Block=128K页Pages=256MB=2Gb1个设备=2048块Block1块Block=64页Pages1页=(2K+64)B (因为每个地址⾥都存放了⼀个字节,所以⽤B表⽰)其中64B是存放ECC的OOB地址,(ECC:存放判断位反转的校验码)Nand Flash 缺点:读数据容易位反转可以通过ECC编码器值来判断读数据是否位反转,若位反转则重新读数据写过程:1)写页数据2)然后⽣成ECC3)将ECC写⼊到OBB页地址⾥(写数据是不会出现位反转)读过程:1)读出页数据,然后⽣成临时ECC(此时ECC可能有错)2)然后读出OOB页地址⾥的ECC3)⽐较两个ECC,判断是否出现位反转读OOB⽅法:读整个Nand Flash时,是读不出页⾥⾯的OBB地址,⽐如读2049这个地址数据时,是读的第⼆页上的第2个地址:只有读某⼀页时,才能读出这个页⾥⾯的OOB地址, ⽐如读第0页的2049这个地址数据时,才是读的第0页OOB的第2个地址:Nand Flash芯⽚硬件引脚图:RnB:就绪(ready)/忙(busy)输出信号,需要采⽤上拉电阻(1:表⽰写⼊数据成功,0:表⽰正在写⼊)CLE:命令(command)锁存(latch)使能,(1:表⽰当前传的是命令值)ALE:地址锁存使能,(1:表⽰当前传的是地址值,当CLE=0和ALE=0,表⽰传的是数据)nCE:芯⽚使能(低电平使能) (n:表⽰低电平有效)nWE:写使能 ,⽐如写命令时,当CLE=1,ALE=0时,当nWE来个上升沿,则会将IO数据写⼊flash中nRE:读使能,和we类似nWP:写保护(protect) (1:不保护,0:只能读不能写),默认接⾼电平.1.编写nand_init()函数1.1设置通信时序图1(nandflash时序表):图2(nandflash时序图):通过图2和图1可以看出:tCS是等待芯⽚使能CE的时间, tCS=20nStCLS和tALS是等待WE(写信号)结束的时间, tCLS=tALS=15nStWP是WE(写信号)维持时间, tWP=15nStALH是等待命令写⼊成功的时间, tALH=5nStCLH是等待地址写⼊成功的时间, tCLH=5nS图3(2440-nandflash时序图):⾸先查看2440芯⽚⼿册⾥nandflash时序图,如上图,可以看出需要设置TACLS,TWRPH0和TWRPH1,这三个参数TACLS:属于等待WE(写信号)就绪的时间,对⽐图2得出TACLS= tCLS- tWP=0nSTWRPH0:属于WE(写信号)的时间, 对⽐图2得出TWRPH0= tWP=15nSTWRPH1:属于等待命令写⼊成功的时间,对⽐图2得出TWRPH1=tALH=tCLH=5nS最后,在NFCONF寄存器中设置这三个参数TACLS[13:12]表⽰Duration(持续时间)=HCLK*TACLS,由于Duration=0nS,所以TACLS=0TWRPH0 [10:8]表⽰Duration(持续时间)=HCLK*( TWRPH0+1),由于Duration=15nS,HCLK=10nS(100Mhz),所以TWRPH0 =1. TWRPH1 [6:4]表⽰Duration(持续时间)= HCLK*( TWRPH1 +1),由于Duration=5nS,HCLK=10nS(100Mhz),所以TWRPH1 =0 1.2然后定义全局变量,并实现nand_init()初始化:/* nand flash 时序 */#define TACLS 0#define TWRPH0 1#define TWRPH1 0/* nand flash 寄存器 */#define NFCONF *((unsigend int *)0X4E000000); //配置寄存器(⽤来设置时序)#define NFCONT *((unsigend int *)0X4E000000); //控制寄存器(⽤来使能nandflash控制器以及ECC编码器,还有控制芯⽚使能CE脚)#define NFCMMD *((unsigend char *)0X4E000000);//发送命令寄存器(命令只有8位)#define NFADDR *((unsigend char *)0X4E000000);//发送地址寄存器(地址只有8位)#define NFDATA *((unsigend int *)0X4E000000);//读/写数据寄存器(数据只有8位)#define NFSTAT *((unsigend int *)0X4E000000);//运⾏状态寄存器(⽤于判断RnB脚)/*因为Nand Flash只有8位I/O脚,所以NFCMMD/ NFADDR/ NFDATA三个寄存器值都是unsigend char型 */1.3 nand_init()函数初始化void nand_init(void){/* 设置时序 */NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);/* bit4=1:初始化ECC, bit1=1:禁⽌⽚选 bit0=1:启动nandflash控制器*/NFCONT = (1<<4)|(1<<1)|(1<<0);}2编写nand_read()函数2.1编写nand_read()函数需要以下⼏个⼦函数:2.1.1⽚选使能函数(在读写FLASH之前都要选中⽚选)nand_select() //使能⽚选{int i;NFCONT&=~(1<<1); // NFCONT控制器位1置0for(i=0;i<10;i++); //等待芯⽚使能成功}2.1.2取消⽚选函数(退出读写FLASH时需要取消⽚选)nand_deselect() //取消⽚选{int i;NFCONT&=~(1<<1); // NFCONT控制器位1置0for(i=0;i<10;i++); //等待芯⽚使能成功}2.1.3读命令函数nand_cmd(unsigned char cmd){int i;NFCMMD= cmd; // 向NFCMMD寄存器写⼊命令for(i=0;i<10;i++); //等待写⼊命令成功}2.1.4判断RnB状态函数(在写⼊所有命令后都要判断RnB脚是否为⾼电平就绪)nand_waite_idle(){int i;while(!(NFSTAT&0X01)) // 等待NFSTAT寄存器位0置1for(i=0;i<10;i++);}2.1.5读数据函数nand_read_data(){unsigend char p=NFDATA; //读取NFDATA寄存器return p; //返回}2.1.6 编写写⼊地址函数(分5个周期)⾸先Nand Flash引脚只有8位,然⽽地址共有2048(块)*64(页)*2KB,为了读出多个地址,如下图,所以需要分5个周期来实现发送地址如上图,其中 A10~A0对应页⼤⼩(列),由于nandflash每页2048B,所以只⽤到A10~A0 A28~A11对应页⽬录(⾏),表⽰共有2048块*64(每块有64页)个⽬录例如,4097 地址就是:A10~A0=4097%2048= 1(A0=1,其余为0)A28~A11=4097/2048=2(A13=1,其余为0)所以nand_write_nand()函数如下:void nand_read_addr(unsigned int addr){unsigned int col = addr % 2048;unsigned int page = addr / 2048;volatile int i;NFADDR=(col>>0)&0xff; //A7~A0,第1周期for(i=0;i<10;i++);NFADDR=(col>>8)&0x0f; //A10~A8,第2周期for(i=0;i<10;i++);NFADDR=(page>>0)&0xff; //A18~A11,第3周期for(i=0;i<10;i++);NFADDR=(page>>8)&0xff; //A26~A19,第4周期for(i=0;i<10;i++);NFADDR=(page>>16)&0xff; //A27~A28,第5周期for(i=0;i<10;i++);}2.2Nand Flash命令图:如上图,例如:当要reset复位nand flash时1) 使能⽚选nand_select();2) 发送0XFF复位命令nand_cmd(0xFF);3) 等待RnB状态是否就绪 nand_wait_idle();4) 取消⽚选 nand_deselect();2.3Nand Flash读数据时序图:从上图可以看出nand flash 读数据分为了以下⼏个步骤:(1) 使能⽚选CE,将CLE置1,等待发送命令(2) 将WE置低,将IO置为0X00,然后拉⾼WE,触发⼀次上升沿,则将把0x00写⼊flash中(3) 将CLE置0,表⽰发送地址(分为5个周期)(4) 发送读命令0X30(5) 等待RnB信号为⾼电平(6) 读数据(在同⼀页⾥,数据可以连续读,读下⼀页时,需要重新发送新的地址才⾏例如:读1000地址到2050地址时,1.发出1000地址,到达页0的1000地址上,然后再连续读(2048-1000)次,直到读到页0的2047处.2.再发出2048地址,到达页1的0地址上,然后连续读(2051-2048)次,直到读到2050为⽌)(7) 取消⽚选nCE2.4 所以nand_read()函数如下:void nand_read(unsigned int src,unsigned char *dest,unsigned int len)/* src:源地址,为32位地址,所以⽤unsigend int表⽰*dest:⽬的地址内容,由于这⾥是将数据读出到⽬的地址内容中,所以需要⽤到*指针,因为每个地址⾥存的是⼀个字节,所以⽤unsigend char 型 */ {int col=src%2048; //第⼀次读,可能不是读的页⾸地址,所以需要记录当前页的位置int i=0; //当前读了0次nand_select(); //1使能⽚选nCEwhile(i<len){ nand_cmd(0X00); //2发送读命令0X00nand_write_addr(src); // 3发送yuan地址(分为5个周期)nand_cmd(0X30); //4发送读命令0X30nand_wait_idle(); //5等待RnB信号为⾼电平for(;(col<2048)&&(i<len);col++) //连续读页内数据{dest[i]=nand_read_data(); //6.读数据i++;src++;}col=0;}nand_deselect(); // 取消⽚选nCE }。

三星K9F1G08U0E(128MB,NANDFLASH)STM32平台驱动程序(模拟时序)

三星K9F1G08U0E(128MB,NANDFLASH)STM32平台驱动程序(模拟时序)

三星K9F1G08U0E(128MB,NANDFLASH)STM32平台驱动程序(模拟时序)STM32平台下模拟时序驱动K9F1G08U0E,主要⽬的为了解、学习NAND FLASH的功能特性,没有使⽤STM32的FSMC(⽕龙开发板硬件为模拟时序驱动),纯粹⾃娱⾃乐,如对你有帮助,不胜荣幸,呵呵。

C⽂件内容:1 #include "NAND512W3A2C.h"2/*3作者:毕⼩乐4⽇期:2019.01.245版本:V1.0067驱动代码针对K9F1G08U0E时序⽽写,K9F1G08U0E与NAND512W3A2C,Pin to Pin兼容。

8驱动运⾏平台STM32F103。

9驱动实现功能:101)Page Read112) Page Program123) Block Erase134) Read Status145) Read ID15PE0~PE7 -> DB00~DB0716PD6 -> CL17PD5 -> AL18PD14 -> W19PD15 -> R20PD7 -> CS21PB5 -> R/B22*/23static void NAND512_Delay_uS(int tick)24 {25int i;26while(tick>0)27 {28 tick--;29for(i=0;i<10;i++)30 __nop();31 }32 }33void NAND512_DB_OutPut(void)34 {35 GPIO_InitTypeDef GPIO_InitStructure;3637 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_338 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;39 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;40 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;41 GPIO_Init(GPIOE, &GPIO_InitStructure);42 }43void NAND512_DB_InPut(void)44 {45 GPIO_InitTypeDef GPIO_InitStructure;4647 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_348 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;49 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;50 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;51 GPIO_Init(GPIOE, &GPIO_InitStructure);52 }53char NAND512_DB_Read(void)54 {55char dat;56 NAND512_DB_InPut();57 __nop();58 dat = GPIO_ReadInputData(GPIOE) & 0x00FF;59return dat;60 }61void NAND512_DB_Write(char Data)62 {63 u16 temp;64 NAND512_DB_OutPut();65// __nop();71void NAND512_IO_Init(void)72 {73 GPIO_InitTypeDef GPIO_InitStructure;7475 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD76 | RCC_APB2Periph_GPIOE, ENABLE);7778/*CL*/79 GPIO_InitStructure.GPIO_Pin = NAND512_CL_PIN;80 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;81 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;82 GPIO_Init(NAND512_CL_PORT, &GPIO_InitStructure);8384/*AL*/85 GPIO_InitStructure.GPIO_Pin = NAND512_AL_PIN;86 GPIO_Init(NAND512_AL_PORT, &GPIO_InitStructure);8788/*W*/89 GPIO_InitStructure.GPIO_Pin = NAND512_W_PIN;90 GPIO_Init(NAND512_W_PORT, &GPIO_InitStructure);9192/*R*/93 GPIO_InitStructure.GPIO_Pin = NAND512_R_PIN;94 GPIO_Init(NAND512_R_PORT, &GPIO_InitStructure);9596/*CE*/97 GPIO_InitStructure.GPIO_Pin = NAND512_CE_PIN;98 GPIO_Init(NAND512_CE_PORT, &GPIO_InitStructure);99100/*R/B*/101 GPIO_InitStructure.GPIO_Pin = NAND512_RB_PIN;102 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;103 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;104 GPIO_Init(NAND512_RB_PORT, &GPIO_InitStructure);105106 NAND512_CL_LOW;107 NAND512_AL_LOW;108 NAND512_R_HIGH;109 NAND512_W_HIGH;110 NAND512_CE_HIGH;111 }112113//读状态寄存器信息114char NAND512_Read_Status(void)115 {116char dat;117118 NAND512_CL_LOW;119 NAND512_W_HIGH;120 NAND512_R_HIGH;121 NAND512_CE_HIGH;122 NOP;123124 NAND512_Delay_uS(5);125 NAND512_CL_HIGH;126 NOP;127 NOP;128 NAND512_CE_LOW;129 NOP;130 NOP;131 NOP;132 NAND512_W_LOW;133 NAND512_DB_Write(0x70);134 NOP;135 NAND512_W_HIGH;136137 NAND512_Delay_uS(5);138 NAND512_CL_LOW;139 NOP;140 NOP;141//CE状态保持不变142143 NAND512_Delay_uS(10);144 NAND512_R_LOW;145 NOP;146 dat = NAND512_DB_Read();147 NAND512_Delay_uS(5);148 NAND512_R_LOW;149 NAND512_Delay_uS(5);155156void NAND512_Read_ID(char* Buf)157 {158char i = 0;159160 NAND512_CL_LOW;161 NAND512_AL_LOW;162 NAND512_R_HIGH;163 NAND512_W_HIGH;164 NAND512_CE_HIGH;165 NAND512_Delay_uS(5);166167 NAND512_CL_HIGH;168 NAND512_W_LOW;169 NAND512_Delay_uS(5);170 NAND512_CE_LOW;171 NAND512_DB_Write(0x90);172 NAND512_Delay_uS(5);173 NAND512_W_HIGH;174 NAND512_Delay_uS(5);175176 NAND512_CL_LOW;177 NAND512_Delay_uS(20);178 NAND512_AL_HIGH;179 NAND512_Delay_uS(20);180 NAND512_W_LOW;181 NAND512_DB_Write(0x00); //写地址0182 NAND512_Delay_uS(5);183 NAND512_W_HIGH;184 NAND512_Delay_uS(10);185 NAND512_AL_LOW;186 NAND512_Delay_uS(20);187188for(i=0;i<5;i++)189 {190 NAND512_R_LOW;191 NAND512_Delay_uS(10);192 Buf[i] = NAND512_DB_Read();193 NAND512_R_HIGH;194 NAND512_Delay_uS(10);195 }196197return ;198 }199200void NAND512_Page_Read(char* Buf,int Len,int Add)201 {202int Bank_Index,Page_Index,Page_Start_Add;203int Add_New,j;204char i;205206 Bank_Index = Add / BANK_SIZE;207 Page_Index = (Add % BANK_SIZE) / PAGE_SIZE;208 Page_Start_Add = Add % PAGE_SIZE;209 Add_New = (((Bank_Index<<6) | Page_Index)<<16) | Page_Start_Add; 210211 NAND512_CL_LOW;212 NAND512_AL_LOW;213 NAND512_W_HIGH;214 NAND512_R_HIGH;215 NAND512_CE_HIGH;216 NAND512_Delay_uS(10);217218 NAND512_CE_LOW;219 NAND512_Delay_uS(5);220 NAND512_CL_HIGH;221 NAND512_W_LOW;222 NAND512_DB_Write(0x00);223 NAND512_Delay_uS(5);224 NAND512_W_HIGH;225 NAND512_Delay_uS(5);226 NAND512_CL_LOW;227 NAND512_Delay_uS(5);228 NAND512_AL_HIGH;229 NAND512_Delay_uS(5);230231//发送地址232for(i=0;i<4;i++)233 {239 NAND512_Delay_uS(10);240 }241 NAND512_AL_LOW;242 NAND512_Delay_uS(5);243 NAND512_CL_HIGH;244 NAND512_Delay_uS(5);245 NAND512_W_LOW;246 NAND512_Delay_uS(5);247 NAND512_DB_Write(0x30);248 NAND512_Delay_uS(5);249 NAND512_W_HIGH;250 NAND512_Delay_uS(5);251 NAND512_CL_LOW;252 NAND512_Delay_uS(5);253254while(NAND512_RB_STATUS == 0);255 NAND512_Delay_uS(5);256257for(j=0;j<Len;j++)258 {259 NAND512_R_LOW;260 NAND512_Delay_uS(5);261 Buf[j] = NAND512_DB_Read();262 NAND512_Delay_uS(5);263 NAND512_R_HIGH;264 NAND512_Delay_uS(10);265 }266267return;268 }269270char NAND512_Page_Write(char* Buf,int Len,int Add)271 {272int Bank_Index,Page_Index,Page_Start_Add;273int Add_New,j;274char i,Status;275276 Bank_Index = Add / BANK_SIZE;277 Page_Index = (Add % BANK_SIZE) / PAGE_SIZE;278 Page_Start_Add = Add % PAGE_SIZE;279 Add_New = (((Bank_Index<<6) | Page_Index)<<16) | Page_Start_Add; 280281 NAND512_CL_LOW;282 NAND512_AL_LOW;283 NAND512_W_HIGH;284 NAND512_R_HIGH;285 NAND512_CE_HIGH;286 NAND512_Delay_uS(10);287288 NAND512_CE_LOW;289 NAND512_Delay_uS(5);290 NAND512_CL_HIGH;291 NAND512_W_LOW;292 NAND512_DB_Write(0x80);293 NAND512_Delay_uS(5);294 NAND512_W_HIGH;295 NAND512_Delay_uS(5);296 NAND512_CL_LOW;297 NAND512_Delay_uS(5);298 NAND512_AL_HIGH;299 NAND512_Delay_uS(5);300301//发送地址302for(i=0;i<4;i++)303 {304 NAND512_W_LOW;305 NAND512_Delay_uS(5);306 NAND512_DB_Write(Add_New>>8*i);307 NAND512_Delay_uS(10);308 NAND512_W_HIGH;309 NAND512_Delay_uS(10);310 }311 NAND512_AL_LOW;312 NAND512_Delay_uS(5);313314for(j=0;j<Len;j++)315 {316 NAND512_W_LOW;317 NAND512_Delay_uS(5);324 NAND512_CL_HIGH;325 NAND512_Delay_uS(5);326 NAND512_W_LOW;327 NAND512_Delay_uS(5);328 NAND512_DB_Write(0x10);329 NAND512_Delay_uS(5);330 NAND512_W_HIGH;331 NAND512_Delay_uS(5);332333while(NAND512_RB_STATUS == 0);334 NAND512_Delay_uS(5);335336 Status = NAND512_Read_Status();337338if((Status & 0x01) == 0)339return1;340else341return0;342 }343344char NAND512_Block_Erase(int Add)345 {346int Bank_Index,Page_Index;347int Add_New;348char i,Status;349350 Bank_Index = Add / BANK_SIZE;351 Page_Index = (Add % BANK_SIZE) / PAGE_SIZE; 352 Add_New = (Bank_Index<<6) | Page_Index;353354 NAND512_CL_LOW;355 NAND512_AL_LOW;356 NAND512_W_HIGH;357 NAND512_R_HIGH;358 NAND512_CE_HIGH;359 NAND512_Delay_uS(10);360361 NAND512_CE_LOW;362 NAND512_Delay_uS(5);363 NAND512_CL_HIGH;364 NAND512_W_LOW;365 NAND512_DB_Write(0x60);366 NAND512_Delay_uS(5);367 NAND512_W_HIGH;368 NAND512_Delay_uS(5);369 NAND512_CL_LOW;370 NAND512_Delay_uS(5);371 NAND512_AL_HIGH;372 NAND512_Delay_uS(5);373374//发送地址375for(i=0;i<2;i++)376 {377 NAND512_W_LOW;378 NAND512_Delay_uS(5);379 NAND512_DB_Write(Add_New>>8*i);380 NAND512_Delay_uS(10);381 NAND512_W_HIGH;382 NAND512_Delay_uS(10);383 }384 NAND512_AL_LOW;385 NAND512_Delay_uS(5);386387 NAND512_CL_HIGH;388 NAND512_Delay_uS(5);389 NAND512_W_LOW;390 NAND512_Delay_uS(5);391 NAND512_DB_Write(0xD0);392 NAND512_Delay_uS(5);393 NAND512_W_HIGH;394 NAND512_Delay_uS(5);395 NAND512_CL_LOW;396 NAND512_Delay_uS(5);397398while(NAND512_RB_STATUS == 0);399 NAND512_Delay_uS(5);400401 Status = NAND512_Read_Status();H⽂件内容:1 #ifndef NAND512W3A2C__H2#define NAND512W3A2C__H34 #include "stm32f10x.h"56#define NAND512_CL_PORT GPIOD7#define NAND512_AL_PORT GPIOD8#define NAND512_W_PORT GPIOD9#define NAND512_R_PORT GPIOD10#define NAND512_CE_PORT GPIOD11#define NAND512_RB_PORT GPIOB12#define NAND512_WP_PORT /*GPIOD*/1314#define NAND512_CL_PIN GPIO_Pin_615#define NAND512_AL_PIN GPIO_Pin_516#define NAND512_W_PIN GPIO_Pin_1417#define NAND512_R_PIN GPIO_Pin_1518#define NAND512_CE_PIN GPIO_Pin_719#define NAND512_RB_PIN GPIO_Pin_520#define NAND512_WP_PIN /*GPIO_Pin_5*/2122#define NAND512_CL_CLK RCC_APB2Periph_GPIOD23#define NAND512_AL_CLK RCC_APB2Periph_GPIOD24#define NAND512_W_CLK RCC_APB2Periph_GPIOD25#define NAND512_R_CLK RCC_APB2Periph_GPIOD26#define NAND512_CE_CLK RCC_APB2Periph_GPIOD27#define NAND512_RB_CLK RCC_APB2Periph_GPIOB28#define NAND512_WP_CLK /*RCC_APB2Periph_GPIOD*/2930#define NAND512_CE_LOW GPIO_ResetBits(NAND512_CE_PORT,NAND512_CE_PIN)31#define NAND512_CE_HIGH GPIO_SetBits(NAND512_CE_PORT,NAND512_CE_PIN)32#define NAND512_CL_LOW GPIO_ResetBits(NAND512_CL_PORT,NAND512_CL_PIN)33#define NAND512_CL_HIGH GPIO_SetBits(NAND512_CL_PORT,NAND512_CL_PIN)34#define NAND512_AL_LOW GPIO_ResetBits(NAND512_AL_PORT,NAND512_AL_PIN)35#define NAND512_AL_HIGH GPIO_SetBits(NAND512_AL_PORT,NAND512_AL_PIN)36#define NAND512_W_LOW GPIO_ResetBits(NAND512_W_PORT,NAND512_W_PIN)37#define NAND512_W_HIGH GPIO_SetBits(NAND512_W_PORT,NAND512_W_PIN)38#define NAND512_R_LOW GPIO_ResetBits(NAND512_R_PORT,NAND512_R_PIN)39#define NAND512_R_HIGH GPIO_SetBits(NAND512_R_PORT,NAND512_R_PIN)4041#define NAND512_RB_STATUS GPIO_ReadInputDataBit(NAND512_RB_PORT,NAND512_RB_PIN) 4243#define NOP __nop()44#define BANK_SIZE 13107245#define PAGE_SIZE 20484647extern void NAND512_IO_Init(void);48extern char NAND512_Read_Status(void);49extern void NAND512_Read_ID(char* Buf);50extern void NAND512_Page_Read(char* Buf,int Len,int Add);51extern char NAND512_Page_Write(char* Buf,int Len,int Add);52extern char NAND512_Block_Erase(int Add);53#endif。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

三星系列的NAND FLASH芯片容量从8MB到256MB(最近听说有1G容量的了),对于需要大容量数据存储的嵌入式系统是一个很好的选择,尤其是其接近1MB/元的高性价比,更是普通nor flash 无法比拟的。

本文以K9F2808U0C为例,采用AVR芯片连接,进行了初步的读写试验,完成了芯片的ID读出功能。

电路连接如下图:
左边是所使用的AVR芯片ATmega16L的局部电路,右边是K9F2808芯片的连接图,数据/地址总线使用ATmega16的PORTB端口连接,其它全部所需信号线使用IO连接,组成了IO模拟方式。

K9F2808芯片的全部命令字如下:
其中,Read1读取的是普通数据存储区域的数据,Read2读取的是每页存储器附加的16Bytes区域的数据;Page Program可以编程一页最大528Bytes的数据,Block Erase擦除指定页面数据,Read Status可以读取芯片状态。

芯片的整个读写时序可以分解为4个基本步骤,即1、命令写入,2、数据写入,3、数据读出,4、地址写入。

1、命令写入时序如下:
对应函数为:
void WriteCmd(unsigned char cmd) {
nandPortD = 0xFF;
ClsLine(nandSPortO,nandALE); ClsLine(nandSPortO,nandnCE); SetLine(nandSPortO,nandCLE); ClsLine(nandSPortO,nandnWE); nandPortO = cmd;
SetLine(nandSPortO,nandnWE); ClsLine(nandSPortO,nandCLE); SetLine(nandSPortO,nandALE);
}
2、数据写入时序如下:
对应函数为:
void WriteByte(unsigned char Wdata)
{
nandPortD = 0xFF;
SetLine(nandSPortO,nandnWE);
ClsLine(nandSPortO,nandCLE);
ClsLine(nandSPortO,nandnCE);
ClsLine(nandSPortO,nandALE);
ClsLine(nandSPortO,nandnWE);
while((nandSPortI & nandRnB) != nandRnB); // wait busy end nandPortO = Wdata;
while((nandSPortI & nandRnB) != nandRnB); // wait busy end SetLine(nandSPortO,nandnWE);
}
3、数据读出时序如下:
对应函数为:
unsigned char ReadByte(void)
{
unsigned char Rdata;
nandPortD = 0x00;
SetLine(nandSPortO,nandnWE);
ClsLine(nandSPortO,nandCLE);
ClsLine(nandSPortO,nandALE);
ClsLine(nandSPortO,nandnCE);
ClsLine(nandSPortO,nandnRE);
while((nandSPortI & nandRnB) != nandRnB); // wait busy end Rdata = nandPortI;
while((nandSPortI & nandRnB) != nandRnB); // wait busy end SetLine(nandSPortO,nandnRE);
return Rdata;
}
4、地址写入时序如下:
对应函数为:
void WriteByteAdd(unsigned char Add)
{
nandPortD = 0xFF;
SetLine(nandSPortO,nandnWE);
ClsLine(nandSPortO,nandnCE);
ClsLine(nandSPortO,nandCLE);
SetLine(nandSPortO,nandALE);
ClsLine(nandSPortO,nandnWE);
nandPortO = Add;
SetLine(nandSPortO,nandnWE);
while((nandSPortI & nandRnB) != nandRnB); // wait busy end
ClsLine(nandSPortO,nandALE);
}
其余操作方式均从这四种基本操作组合变化而来,适当调用或者重新编写其中的某些语句就能完成全部的K9F2808芯片读写操作。

下面以读K9F2808芯片ID为例调用以上函数完成。

读芯片ID的时序如下图:
实现函数编写为:
void ReadId(unsigned char *ptr)
{
WriteCmd(0x90);
WriteByteAdd(0x00);
*ptr++ = ReadByte();
*ptr = ReadByte();
SetLine(nandSPortO,nandnCE);
}
函数调用后,*ptr的值为0xEC,即厂家代码;*(ptr+1)的值为0x73,即设备代码。

实际在芯片的读写操作中,还要注意对坏扇区进行检错,并将检错结果存入芯片的第一个块中,以确保数据的读写地址均为有效地址。

相关文档
最新文档