华邦W25Q16存储器颗粒SPI编程_第1页
华邦W25Q16存储器颗粒SPI编程_第2页
华邦W25Q16存储器颗粒SPI编程_第3页
华邦W25Q16存储器颗粒SPI编程_第4页
华邦W25Q16存储器颗粒SPI编程_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

华邦W25Q16存储器颗粒SPI编程W25X16、W25X32 和 W25X64 系列 FLASH 存储器可以为用户提供存储解决方案,具有“PCB 板占用空间少”、“引脚数量少”、“功耗低”等特点。与普通串行 FLASH 相比,使 用更灵活,性能更出色。它非常适合做代码下载应用,例如存储声音,文本和数据。工作电 压在 2.7V-3.6V 之间,正常工作状态下电流消耗 0.5 毫安,掉电状态下电流消耗 1 微安。所 有的封装都是节省空间型的。W25X16、W25X32 和 W25X64 分别有 8192、16384 和 32768 可编程页,每页 256 字节。 用页编程指令每次就可以编程256个字节。用扇区(sector)擦除指令每次可以擦除 16 页,用“块(block)擦除指令”每次可以擦除 256 页,用“整片擦除指令”即可以擦除 整个芯片。W25X16、W25X32 和 W25X64 分别有 512、1024 和 2048 个可擦除扇区或 32、64 和 128 个可擦除“块”。W25X16、W25X32 和 W25X64 支持标准的 SPI 接口,传输速率最大 75MHz。四线制:串行时钟引脚 CLK;:芯片选择引脚 CS;:串行数据输出引脚 DO;:串行数据输入输出引脚 DIO。(注意:第引脚“串行数据输入输出引脚 DIO”的解释:在普通情况下,这根引脚是“串行输入引脚(DI),当使用了快读双输出指令(Fast Read Dual Output instruction)时,这根引脚就变成了 DO 引脚,这种情况下,芯片就有了两个 DO 引脚了,所以叫做双输出,这时,如果与芯片通信的速率相当于翻了一倍,所以传输速度更快。)另外,芯片还具有保持引脚(HOLD)、写保护引脚(WP)、可编程写保护位(位于状 态寄存器 bit1)、顶部和底部块的控制等特征,使得控制芯片更具灵活性。芯片支持 JEDEC 工业标准。引脚排布:原理图:控制和状态寄存器说明S7S6S5S4S3S2S1S0SRP(Reservd)TBBP2BP1BP0WELBUSY通过读状态寄存器指令读出的状态数据可以知道芯片存储器阵列是否可写或不可写,或是否处于写保护状态。通过写状态寄存器指令可以配置芯片写保护特征。状态寄存器:忙位(BUSY)BUSY 位是个只读位,位于状态寄存器中的 S0。当器件在执行页编程、扇区擦除、 块区擦除、芯片擦除、写状态寄存器指令时,该位自动置 1。这时,除了读状态寄 存器指令,其它指令部忽略。当编程、擦除和写状态寄存器指令执行完毕之后,该位自动 变为 0,表示芯片可以接收其它指令了。写保护位(WEL)WEL 位是个只读位,位于状态寄存器中的 S1。执行完写使能指令后,该位置 1。 当芯片处于写保护状态下,该位为0。在下面两种情况下,会进入写保护状态 掉电后 执行以下指令后写禁能、页编程、扇区擦除、块区擦除、芯片擦除和写状态寄存器块区保护位(BP2,BP1,BP0)BP2BP1BP0 位是可读可写位,分别位于状态寄存器的 S4S3S2。可以用写状态寄存器命令置位这些块区保护位。在默认状态下,这些位都为 0,即块区处于未保护状态下。 可以设置块区没有保护、部分保护或者是全部处于保护状态下。当 SPR 位为 1 或/WP 引脚 为低的时候,这些位不可以被更改。底部和顶部块区保护位(TB)TB 位是可读可写位,位于状态寄存器的 S5。该位默认为 0,表明顶部和底部块区处于未被保护状态下。可以用写状态寄存器命令置位该位。当 SPR 位为 1 或/WP 引脚为低 的时候,这些位不可以被更改。保留位状态寄存器的 S6 为保留位,读出状态寄存器值时,该位为 0。建议读状态寄存器值用于测试时将该位屏蔽。状态寄存器果护位(SRP)SRP 位是可读可写位,位于状态寄存器的 S7。该位结合/WP 引脚可以实现禁能写状态寄存器功能。该位默认值为 0。当 SRP 位=0 时,/WP 引脚不能控制状态寄存器的写禁能。当 SRP 位=1,/WP 引脚=0 时,写状态寄存器命令失效。当 SRP 位=1,/WP 引脚=1 时,可以执行写状态寄存器命令。状态寄存器存储保护模块:1、写使能时序图(指令:0x06):“写使能”指令将会使“状态寄存器”WEL位置位。在执行每个“页编程”、“扇区擦除”、“块区擦除”、“芯片擦除”、和“写状态寄存器”命令之前,都要先置位 WEL。/CS 引脚先拉低之后,“写使能”指令代码06h 从DI引脚输入,在CLK 上升沿采集,然后再拉高/CS 引脚 。程序设计流程:1、 使能片选位,拉低CS引脚;2、 CLK起始状态或高电平或低平,配置数据采集从CLK第一个上升沿开始;3、 等待发送缓冲区是否为空,SPI_SR的TXE位;4、 将数据赋值给SPI_DR寄存器;5、 等待接收缓冲区是否为空,SPI_SR的RXNE位;6、 返回接收到的数据;7、 禁能片选位,拉高CS引脚。例程:unsigned char SPI_SendByte(unsigned char byte)while(!(SPI_SR&0x02);/等待发送缓冲区为空SPI_DR=byte;/送值到数据寄存器whlie(!(SPI_SR&0x01);/等待接收缓冲区为空return SPI_DR;/返回接收的内容unsigned char SPI_WriteEnable()Flash_CS=0;/使能CS引脚SPI_SendByte(0x06)/写使能指令Flash_CS=1;/禁能片选引脚2、写禁能时序图(指令:0x04):“写禁能”指令将会使WEL位变为0。/CS引脚拉低之后,把04h 从DIO引脚送到芯片之后,拉高/CS,就完成了这个指令。在执行完“写状态寄存器”、“页编程”、“ 扇区擦除”、“块区擦除”、“芯片擦除”指令之后,WEL位就会自动变为0。程序设计流程:1、 使能片选位,拉低CS引脚;2、 CLK起始状态或高电平或低平,配置数据采集从CLK第一个上升沿开始;3、 等待发送缓冲区是否为空,SPI_SR的TXE位;4、 将数据赋值给SPI_DR寄存器;5、 等待接收缓冲区是否为空,SPI_SR的RXNE位;6、 返回接收到的数据;7、 禁能片选位,拉高CS引脚。例程:unsigned char SPI_SendByte(unsigned char byte)Flash_CS=0;/使能CS引脚while(!(SPI_SR&0x02);/等待发送缓冲区为空SPI_DR=byte;/送值到数据寄存器whlie(!(SPI_SR&0x01);/等待接收缓冲区为空return SPI_DR;/返回接收的内容Flash_CS=1;/禁能片选引脚unsigned char SPI_WriteEnable()Flash_CS=0;/使能CS引脚SPI_SendByte(0x04)/写禁能指令Flash_CS=1;/禁能片选引脚3、读状态时序(指令:0x05):当/CS 拉低之后,开始把 05h 从DIO引脚送到芯片,在 CLK 的上升沿数据被芯片采集,当芯片认出采集到的数据时05h 时,芯片就会把“状态寄存器”的值从DO引脚输出,数据在CLK 的下降沿输出,高位在前。“读状态寄存器”指令在任何时候都可以用,甚至在编程、擦除和写状态寄存器的过程中也可以用,这样,就可以从状态寄存器的BUSY位判断编程、擦除和写状态寄存器周期有没有结束,从而让我们知道芯片是否可以接收下一条指令了。如果/CS 不被拉高,状态寄存器的值将一直从DO引脚输出。/CS 拉高之后,读指令结束。程序设计流程:1、 使能片选,拉低CS引脚;2、 发送读取指令0x04;3、 循环发送读伪指令0xFF,等待非忙时跳出循环;4、 禁能片选,拉高CS引脚。例程:void SPI_ReadStatus()unsigned char Flash_Status;FLASH_CS=0;/使能片选引脚SPI_SendByte(0x05);/发送读状态指令doFlash_Status=SPI_SendByte(0xFF);/发送伪指令维持时钟等待非空跳出循环,伪指令任意写。while(!(Flash_Status&0x01);FLASH_CS=1;/禁能片选引脚4、写状态时序(指令:0x01)在执行“写状态寄存器”指令之前,需要先执行“写使能”指令。先拉低/CS 引脚,然 后把 01h 从 DIO 引脚送到芯片,然后再把你想要设置的状态寄存器值通过 DIO 引脚送到芯 片,拉高/CS 引脚,指令结束,如果此时没有把/CS 引脚拉高,或者是拉的晚了,值将不会 被写入,指令无效。只有“状态寄存器”当中的“SRP、TB、BP2、BP1、BP0 位”可以被写入,其它“只读位”值不会变。在该指令执行的过程中,状态寄存器中的 BUSY 位为 1,这时候可以用“读状态寄存器”指令读出状态寄存器的值判断,当指令执行完毕,BUSY 位将自动变为 0, WEL位也自动变为 0。通过对“TB”、“BP2”、“BP1”、“BP0”位写 1,就可以实现将芯片的部分或全部存储区域 设置为只读。通过对“SRP 位”写 1,再把/WP引脚拉低,就可以实现禁止写入状态寄存器的功能。程序设计流程:1、 使能片选,CS引脚拉低;2、 发送写状态指令0x01;3、 发送读取指令0x044、 禁能片选,CS引脚拉高。例程:void SPI_FLASH_WriteStatus()FLASH_CS=0;/使能片选引脚SPI_SendByte(0x06);/写使能指令SPI_SendByte(0x01);/写状态指令SPI_SendByte(0x00);/写入状态的数据FLASH_CS=1;/禁能片选引脚5、读数据时序图(指令:0x03):“读数据”指令允许读出一个字节或一个以上的字节被读出。先把/CS 引脚拉低,然后把03h通过DIO引脚送到芯片,之后再送入24位的地址,这些数据在CLK的上升沿被芯片采集。芯片接收完24位地址之后,就会把相应地址的数据在 CLK 引脚的下降沿从 DO 引脚送出去,高位在前。当读完这个地址的数据之后,地址自动增加,然后通过DO引脚把下一个地址的数据送出去,形成一个数据流。也就是说,只要时钟在工作,通过一条读指令,就可 以把整个芯片存储区的数据读出来。把/CS 引脚拉高,“读数据”指令结束。当芯片在执行编程、擦除和读状态寄存器指令的周期内,“读数据”指令不起作用。程序设计流程(指令:0x03):1、 使能片选,拉低CS引脚;2、 发送读数据指令0x03,紧接着发送24位地址; 3、 读以SPI_DR寄存器数据4、 禁能片选,拉高CS引脚例程:void SPI_FLASH_BufferRead(unsigned char* pBuffer, unsigned int ReadAddr, unsigned long int NumByteToRead) FLASH_CS=0;/拉低片选线选中芯片 SPI_SendByte(READ);/发送读数据命令 SPI_SendByte(ReadAddr & 0xFF0000)16);/发送24位FLASH地址,先发高8位 SPI_SendByte(ReadAddr & 0x00FF00)8);/再发中间8位 SPI_SendByte(ReadAddr &0x0000FF);/最后发低8位 while(NumByteToRead-)/计数 *pBuffer = SPI_SendByte(Dummy_Byte);/读一个字节的数据 pBuffer+;/指向下一个要读取的数据 FLASH_CS=1;/拉高片选线不选中芯片6、快读时序图(指令:0x0B):“快读”指令和“读数据”指令很相似,不过,“快读”指令可以运行在更高的传输速率下。先把/CS 引脚拉低,然后把 0Bh 通过引脚 DIO 送到芯片,然后把 24 位地址通过 DIO 引脚送到芯片,接着等待8个时钟,之后数据将会从 DO 引脚送出去。程序设计流程(指令:0x0B):1、 使能片选,拉低CS引脚;2、 发送快读数据指令0x0B,紧接着发送24位地址; 3、 发送8个字节伪指令等待8个时钟4、 读以SPI_DR寄存器数据5、 禁能片选,拉高CS引脚例程:void SPI_FLASH_BufferRead(unsigned char* pBuffer, unsigned int ReadAddr, unsigned long int NumByteToRead) FLASH_CS=0;/拉低片选线选中芯片 SPI_SendByte(READ);/发送读数据命令 SPI_SendByte(ReadAddr & 0xFF0000)16);/发送24位FLASH地址,先发高8位 SPI_SendByte(ReadAddr & 0x00FF00)8);/再发中间8位 SPI_SendByte(ReadAddr &0x0000FF);/最后发低8位SPI_SendByte(0xFF);/发送8个字节伪指令,等待8个时钟。 while(NumByteToRead-)/计数 *pBuffer = SPI_SendByte(Dummy_Byte);/发送伪指令读出一个字节的数据 pBuffer+;/指向下一个要读取的数据 FLASH_CS=1;/拉高片选线不选中芯片7、快速读双输出(指令:0x3B):“快读双输出”指令和“快读”指令很相似,不过,“快读双输出”指令是从两个引脚上输出数据:DI和DIO。这样,传输速率就相当于两倍于标准的SP看传输速率了。这个指令特别适合于需要在一上电就把代码从芯片下载到内存中的情况或者缓存代码段到内存中运行的情况。“快读双输出”指令和“快读”指令的时序差不多。先把/CS引脚拉低,然后把 3Bh通过引脚 DIO送到芯片,然后把 24 位地址通过 DIO 引脚送到芯片,接着等待8个时钟,之后数据将会分别从DO 引脚和 DIO 引脚送出去,DIO 送偶数位,DO 送寄数位。程序设计流程:1、 使能片选,拉低CS引脚;2、 写快读双输出指令0x3B,紧接着写24位地址;3、 写1个字节的伪指令,等待8个时钟;4、 读取SPI_DR寄存器5、 禁能片选,拉高CS引脚例程(参考完整例程):暂无。8、页编程时序图(指令:0x02):执行“页编程”指令之前,需要先执行“写使能”指令,而且要求待写入的区域位都为1,也就是需要先把待写入的区域擦除。先把/CS引脚拉低,然后把代码02h通过DIO引脚送到芯片,然后再把24位地址送到芯片,然后接着送要写的字节到芯片。在写完数据之后,把/CS引脚拉高。写完一页(256个字节)之后,必须把地址改为0,不然的话,如果时钟还在继续,地址将自动变为页的开始地址。在某些时候,需要写入的字节不足256个字节的话,其它写入的字节都是无意义的。如果写入的字节大于了256个字节,多余的字节将会加上无用的字节覆盖刚刚写入的的256个字节。所以需要保证写入的字节小于等于256个字节。在指令执行过程中,用“读状态寄存器”可以发现BUSY位为1,当指令执行完毕,BUSY位自动变为0。如果需要写入的地址处于“写保护”状态,“页编程”指令无效。程序设计流程:1、 写使能指令0x06,将芯片WEL位置0;2、 擦除芯片需要写入的区域,可以用扇区、块、芯片擦除指令; 3、 使能片选,拉低CS引脚 ;4、 发送“页编程”指令0x02,接着发送24位地址、发送要写入的数据;5、 发读状态指令0x05检查芯片BUSY位操作是否结束6、 禁能片选,拉高CS引脚。例程:void SPI_FLASH_PageWrite(unsigned char* pBuffer, unsigned long int WriteAddr, unsigned int NumByteToWrite) SPI_FLASH_WriteEnable();/先使能对FLASH芯片的操作 FLASH_CS=0;/拉低片选线选中芯片 SPI_SendByte(WRITE);/发送页写命令 SPI_SendByte(WriteAddr&0xFF0000)16);/发送24位FLASH地址,先发高8位 SPI_SendByte(WriteAddr&0xFF00)8);/再发中间8位 SPI_SendByte(WriteAddr&0xFF);/最后发低8位 while(NumByteToWrite-)/发送地址后紧跟欲写入数据 SPI_SendByte(*pBuffer);/发送欲写入FLASH的数据 pBuffer+;/指向下一个要写入的数据 FLASH_CS=1;/拉高片选线不选中芯片 SPI_FLASH_WaitForWriteEnd();/等待写操作结束程序说明:* pBuffer是一个指针,是读取数据后的存储区,通常指向一个数组;WriteAddr是24位芯片地址,需要把数据写到芯片什么位置就靠它了。NumByteToWrite是写入字节的数量,例如需要写入50个字节,这里就给50。写入的数据不可以大于256Byte,否则页地址会溢出,地址会从0开始,最前面写入的数据会被破坏,写入的数据大于256Byte时,重新用下一页的起始地址来写剩余的数据(处理翻页问题请在本章末尾查看完整例程)。页编程完整流程图:W25Q16总共有16Mbit空间,合计2MByte,共8192个页,每页256Byte。因为每页是一个独立的单元,所以在写入数据时不支持自动翻页,如果写入的数据超出256Byte,那么页地址就溢出归零,数据又从零开始写,也就是说最先写入的数据会被破坏。数据写入时可能碰到有几种情况,一种情况是:页地址对齐的情况,就是页地址可以被256整除,且写入的数据不够256Byte,这种情况直接写入即可,不需要考虑翻页问题;第二种情况是:写入的数据刚好是256Byte或者多一点点,这种情况写完一整页的数据后,就要把页地址加256跳到下一页的开始位置写剩余的数据;第三种情况是:页地址不对齐情况,也就是页地址不能被256整除,这种情况说明,某页被用掉一部分,现在从剩余的空间继续向下写,如果空间够写就直接写入,不需要考虑翻页问题,如果空间不够写就要将页地址加上剩余空间的数跳转到下一页写剩余的数据,如果剩余的数据等于或大于256Byte,页地址还需要 加256再向下进行翻页。9、扇区擦除时序图(指令:0x20):“扇区擦除”指令将一个扇区C4K字节)擦除,擦除后扇区位都为1,扇区字节都为FFh。在执行“扇区擦除”指令之前,需要先执行“写使能”指令,保证WEL位为1。先拉低属CS引脚,然后把指令代码20h通过DIO引脚送到芯片,然后接着把24位扇区地址送到芯片,然后拉高属CS引脚。如果没有及时把属CS引脚拉高,指令将不会起作用。在指令执行期间,BUSY位为1,可以通过“读状态寄存器”指令观察。当指令执行完毕,BUSY位变为0,WEL位也会变为0。如果需要擦除的地址处于只读状态,指令将不会起作用。程序设计流程:1、 先执行写使能指令;2、 使能片选,拉低CS引脚;3、 发送扇区擦除指令0x20,紧接着发送擦除的24位地址;4、 等待擦除指令结束,发送读状态指令查看BUSY位状态是否为0;5、 禁能片选,拉高CS引脚。例程:void SPI_FLASH_BlockErase(unsigned long int BlockAddr) SPI_FLASH_WriteEnable();/FLASH写使能(该函数请查阅完整例程) FLASH_CS=0;/拉低片选线选中芯片 SPI_SendByte(0xD8);/发送块或扇区(0x20)擦除命令 SPI_SendByte(BlockAddr&0xFF0000)16);/发送24位FLASH擦除地址,先发高8位 SPI_SendByte(BlockAddr&0x00FF00)8);/再发中间8位 SPI_SendByte(BlockAddr&0x0000FF);/最后发低8位 FLASH_CS=1;/拉高片选线不选中芯片 SPI_FLASH_WaitForWriteEnd();/等待块清除操作完成(该函数请查阅完整例程)10、芯片擦除时序图(指令:0xC7):“芯片擦除”指令将会使整个芯片的存储区位都变为 1,即字节都变位 FFh。在执行“芯片擦除”指令之前需要先执行写使能指令。先把/CS 引脚拉低,然后再把指令代码 C7h 通过 DIO 引脚送到芯片,然后拉高/CS 引脚。 如果没有及时拉高/CS 引脚,指令无效。在“芯片擦除”指令执行周期内,可以执行“读状态寄存器”指令访问 BUSY 位,这时 BUSY 位为 1,当“芯片擦除”指令执行完毕,BUSY 变为0,WEL位也变为 0。任何一个块区处于保护状态(BP2BP1BP0),指令都会失效。程序设计流程:1、 发送0x06写使能;2、 使能片选,拉低CS引脚;3、 发送擦除指令0xC7,紧接着发送24位擦除地址;4、 禁能片选,拉高CS引脚5、 等待操作完成。例程:void SPI_FLASH_ChipErase(void) SPI_FLASH_WriteEnable();/FLASH写使能 FLASH_CS=0;/拉低片选线选中芯片 SPI_SendByte(Chip_E);/发送芯片擦除命令 FLASH_CS=1;/拉高片选线不选中芯片 SPI_FLASH_WaitForWriteEnd();/等待写操作完成11、“释放掉电/器件ID”指令(命令:0xAB):这个指令有两个作用。一个是“释放掉电”,一个是读出“器件ID”。 当只需要发挥“释放掉电”用途时,指令时序是:先把/CS引脚拉低,然后把代码“ABh”通过 DIO 引脚送到芯片,然后拉高/CS引脚。然后经过tRES1时间间隔,芯片恢复正常工作状态。在编程、擦除和写状态寄存器指令执行周期内,执行该指令无效。程序设计流程:暂无例程:暂无12、掉电指令(指令:0xB9):尽管在待机状态下的电流消耗己经很低了,但“掉电”指令可以使得待机电流消耗更低。这个指令很适合在电池供电的场合。先把属CS 引脚拉低,然后把指令代码

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论