STM32-串行SPI nor
源:FLASH 存储学习-串行SPI nor
1.1 SST25VF080B简介1.1.1 主要特性
关键点:容量、速度(时钟速度、读写速度)、功耗。
l 容量:8MBit;
l 最高SPI时钟频率:50MHz;
l 低功耗模式下电流消耗:5uA,正常读模式电流:15mA;低功耗!采用不同的制造技术功耗要低很多。
l 整片擦除:35ms;扇区/块擦除:18ms;字节编程:7us;整片擦除的速度要快很多!
1.2 系统框图与电路1.2.1 系统框图
关于内部存储矩阵的访问和存储结构同并行NorFlash的一致,只不过多了个串行接口,用于实现对串行数据的解码。
1.2.2 存储组织
扇区大小4KB,块大小:32/64KB;页大小为字节或字。
1.2.3 引脚及封装
引脚说明:
l SCK、SI、SO、CE – SPI接口控制线
l WP# -- 用于使能状态寄存器中的BPL位,有效时只允许锁定BPL,而不允许解锁BPL。不是说明使能保护!BPL位用于锁定控制扇区保护的相应位。
l HOLD# -- 用于暂停与SPI的通信,而不需要复位器件;
1.2.4 典型电路
使用STM32F103驱动该器件时,典型的电路如图所示。
注意,WP为低,判定寄存器的锁定功能将启用。但不会太影响片内块的保护。
1.3 保护机制
l 软件写保护:状态寄存器中的BP3—BP0、BPL提供片内块、状态寄存器的写保护。
l 硬件保护:WP#引脚—低电平,用于锁定状态寄存位7—BPL。由表2,WP#为高时,可以执行状态寄存器写命令,可随时更改状态寄存器。为低时,只能将BPL置为1,而不能从1置为0,即置1后,状态寄存器将锁定不变。
WP# àBPL、BP3—BP0
BPLàBP3、BP0
1.4 编程接口1.4.1 状态寄存器
状态寄存器用于用于获取FLASH的当前工作状态。
l BUSY位:指示是否正在编程或擦除操作;
l WEL位:指示器件是否处理可写的状态。RESET状态(0)指示不可写,默认在上电、完成写操作后,器件自行返回到不可写状态,以保护器件不受意外的擦写。因而每次写FLASH前,都必须先清除(写1),以使能器件的写。软件可控写。
l AAI位:指示器件是否处理地址自动增加模式或者是字节编程模式。
l BPL位:用于控制BPX是否可写。
l BPX位:用于控制保护块的范围,属于软件保护,扇区保护如下。
这里的扇区保护比较简单,更为复杂的扇区保护机制可针对每个扇区进行保护。
1.4.2 命令接口
通信过程中,仅仅只有读ID、读数据、读状态寄存器需要在可保护CS不变而继续写数据。其它的则需要写完后接CS线。
1.5 通信时序1. 单字SPI通信时序
无论SPI总线空闲时SCK为高或为低,保证在上升沿采样数据,下降沿输出数据。先传送高位,每次传送8位。
2. 读命令
3. 快速读模式
有可能内部使用了缓冲模式,可在更高的时钟速度(50MHz)下读数据。
4. 写使能
该命令可设置状态寄存器中的WEL位,使得可执行擦除和编程命令。
5. 写禁能
6. 字节编程
7. AAI编程
即自动地址增量的字编程,每个周期写1个字。
在最后,通过WRDI返回来正常模式。在每写完两个字后,需查询害怕状态。
在写字的过程中,有三种方式检测是否完成字编程。其中硬件检测:读SO的状态。可在写AAI命令之前,通过命令配置SO口为RD/BY#状态。或者也可通过读取状态寄存器来检测是否完成写操作。
8. 4KB的扇区擦除
9. 32K块擦除
10. 64K块擦除
11. 整片擦除
12. 读状态寄存器
13. 使能写状态寄存器和写状态寄存器
两条命令必须连续写,不允许被打断?以避免意外写状态寄存器。
l 当WP#为低电平时,BPL只能写1,不可写0.;此时若BPL位为高时,写状态寄存器命令将被忽略。即此时,状态寄存器只能被锁定(写1),而不能再解锁(写0)!锁定后将不能再任意改高保护方式,相当于将当前的保护方式给固定下来!
l 而若WP#为高电平,BPL位失效,状态寄存器不再被锁定,此时BPL、BPX可被更改。BPL位可设置为1,也可设置为0。可任意更改保护方式。
WP#的作用,锁定BPL为1。一旦BPL锁定为1,则BPX将不可再更改,即软件保护将被锁定。当WP#无效时,BPL可随时、任意更改,同时更改软件保护。
14. JEDEC Read-ID
获取SST制造商的ID和SST FLASH器件的ID。
1.6 驱动设计
驱动框架如下图:
算法编写原则:
(1) 可以为每一种SPI Flash针对性的写一份驱动源码,但是当更换Flash时,需要修改的地方很多;当系统中有多个设备时,显示这不够用,因而最好的方法是实现面向对像的封装,将与Flash设备相关的信息封装在一个结构体内,具体的算法根据结构体中相关的数据来决定如何访问硬件,做到过程可以不依赖于实际的硬件;
(2) 尽量按标准的初始化、读写、关闭、控制接口设计API,这样可统一抽像出相应的结构,也易于使用和理解。留给最终用户调用的API应该尽量的少和易于理解;
(3) SPI Flash接口为SPI,操作方法与并行接口一致,但其扇区组织类似,从最大到最小区域分为芯片-块-扇区-页。编程算法则也是通过写命令序列的方式,如发送命令字-发送字节-发送数据-查询状态寄存器。保护方式是通过存储器中的一些非易失性的位置0或置1选择性地以扇区或块为保护单位。
1.7 驱动代码
//SST25VF080B驱动接口//By:lstzixing At ZLG//Date: 2011-1 #include "STM32Lib\\stm32f10x.h"#include"hal.h"typedef unsignedlonguint32; typedef unsignedshortuint16; typedef unsignedcharuint8;#define SPI_FLASH_SIZE (1024*1024*2) //SPI Flash容量 #define SPI_FLASH_OK 0 #define SPI_FLASH_ERR_PARA 3 //SPI Flash参数错误//SPI Flash擦除操作码 #define SPI_FLASH_ERASE_CHIP 0 //整片擦除 #define SPI_FLASH_ERASE_SECTOR 1 //扇区擦除 #define SPI_FLASH_ERASE_BLOCK 2 //块擦除//SPI状态寄存器和位 #define SPI_FLASH_REG_BIT_BUSY (1 << 0) #define SPI_FLASH_REG_BIT_WEL (1 << 1) #define SPI_FLASH_REG_BIT_BPX (0xF << 2) #define SPI_FLASH_REG_BIT_AAI (1 << 6) #define SPI_FLASH_REG_BIT_BPL (1 << 7)#define SPIFlashSelect() GPIO_ResetBits(GPIOC, GPIO_Pin_13) /* SST CS = L */ #define SPIFlashDeSelect() GPIO_SetBits(GPIOC, GPIO_Pin_13) /* SST CS = H *//********************************************************************************************************* ** Function name: SPIFlashInit ** Descriptions: 初始化SPI硬件,设置相关的GPIO口、SPI控制器 ** Input parameters: none ** Output parameters: None ** Returned value: none *********************************************************************************************************/ void SPIFlashInit(void) {//打开SPI1和GPIO时钟RCC->APB2ENR |= RCC_APB2ENR_SPI1EN |RCC_APB2ENR_IOPAEN|RCC_APB2ENR_IOPBEN|RCC_APB2ENR_IOPCEN|RCC_APB2ENR_IOPDEN|RCC_APB2ENR_IOPEEN|RCC_APB2ENR_IOPFEN;//PA5/6/7为复用模式, 50MHZGPIOA->CRL &= ~(GPIO_CRL_CNF5 | GPIO_CRL_CNF6 | GPIO_CRL_CNF7 |GPIO_CRL_MODE5| GPIO_CRL_MODE6 |GPIO_CRL_MODE7);GPIOA->CRL |= GPIO_CRL_MODE5 | GPIO_CRL_MODE6 | GPIO_CRL_MODE7 |GPIO_CRL_CNF5_1| GPIO_CRL_CNF6_1 |GPIO_CRL_CNF7_1;//配置PC.13为输出片选线GPIOC->CRH &= ~(GPIO_CRH_CNF13 |GPIO_CRH_MODE13);GPIOC->CRH |=GPIO_CRH_MODE13;//配置SPI1,第一个时钟沿采样、主机、分频最大、使能、软件从机管理SPI1->CR1 = //SPI_CR1_CPHA |SPI_CR1_MSTR |//SPI_CR1_BR |SPI_CR1_SSI |SPI_CR1_SPE|SPI_CR1_SSM; SPI1->CR2 = 0;SPIFlashDeSelect(); }/********************************************************************************************************* ** Function name: SPIWriteReadByte ** Descriptions: 向SPI发送并读取一数据 ** Input parameters: data 要发送的数据 ** Output parameters: None ** Returned value: uint16 读取的数据 *********************************************************************************************************/ staticuint16 SPIWriteReadByte(uint16 data) {//发送一字节while((SPI1->SR & SPI_I2S_FLAG_TXE) ==RESET);SPI1->DR =data;//接收一字节while((SPI1->SR & SPI_I2S_FLAG_RXNE) ==RESET);return(SPI1->DR); }/********************************************************************************************************* ** Function name: SPIFlashReadstatusReg ** Descriptions: 读状态寄存器 ** Input parameters: none ** Output parameters: 当前状态寄存器的值 ** BIT0 -- BUSY位,写忙标志 ** BIT1 -- WEL位,FLASH处于写保护状态 ** BIT6[5..2]--BP [3..0],扇区保护位 ** BIT6 -- 指示正在自动自境编程中 ** BIT7 -- BPL,BPX的保护位 ** Returned value: none *********************************************************************************************************/ static uint8 SPIFlashReadstatusReg (void) {uint8 uByte;//发送读状态寄存器命令 SPIFlashSelect();{SPIWriteReadByte(0x5);uByte= SPIWriteReadByte(0xFF);}SPIFlashDeSelect();returnuByte; }/********************************************************************************************************* ** Function name: SPIFlashWritestatusReg ** Descriptions: 写状态寄存器 ** Input parameters: status 要写入的值 ** Output parameters: none ** Returned value: none *********************************************************************************************************/ static voidSPIFlashWritestatusReg (uint8 status) {//发送使能状态寄存器写命令 SPIFlashSelect();{SPIWriteReadByte(0x50);}SPIFlashDeSelect();//写命令和状态值 SPIFlashSelect();{SPIWriteReadByte(0x1);SPIWriteReadByte(status);}SPIFlashDeSelect(); }/********************************************************************************************************* ** Function name: SPIFlashReadID ** Descriptions: 读SPI FLASH的JEDEC ID ** Input parameters: none ** Output parameters: 读的ID,从最高字节到最低字节:制造商ID(1B)-存储类型(1B)-存储容量(1B) ** Returned value: none *********************************************************************************************************/uint32 SPIFlashReadID (void) {uint32 spiID;//发送低速读命令0x9F,3字节地址,写入的字节 SPIFlashSelect();{SPIWriteReadByte(0x9F);spiID= SPIWriteReadByte(0xff) << 16;spiID|= SPIWriteReadByte(0xff) << 8;spiID|= SPIWriteReadByte(0xff);}SPIFlashDeSelect();returnspiID; }/********************************************************************************************************* ** Function name: SPIFlashRead ** Descriptions: 以低速方式(<=25MHZ)从SPI FLASH读数据 ** Input parameters: readBuf 读数据存储的缓冲区首址 ** readCnt 要读取的数据量 ** Output parameters: uint32 实际读得的数据量。当读地址超出芯片容量时,将只读在芯片地址范围内 ** 的数据 ** Returned value: none *********************************************************************************************************/uint32 SPIFlashRead (uint32 readAddr, uint8*readBuf, uint32 readCnt) {uint32 i;uint8 addr[3];//检查参数if (readAddr >= SPI_FLASH_SIZE ||readBuf== 0 ||readCnt== 0) {returnSPI_FLASH_ERR_PARA;}//校正要读的数据总量if (readAddr + readCnt >=SPI_FLASH_SIZE) {readCnt= SPI_FLASH_SIZE -readAddr;}//将地址转换为字节数组addr[0] = (uint8)(readAddr >> 16);addr[1] = (uint8)(readAddr >> 8);addr[2] = (uint8)(readAddr & 0xff);//等待SPI Flash完成写操作while (SPIFlashReadstatusReg() &SPI_FLASH_REG_BIT_BUSY );SPIFlashSelect();{//发送低速读命令0x3,3字节地址SPIWriteReadByte(0x3);SPIWriteReadByte(addr[0]);SPIWriteReadByte(addr[1]);SPIWriteReadByte(addr[2]);//依次读readCnt个数据for (i = 0; i < readCnt; i++) {readBuf[i]= SPIWriteReadByte(0xff);}}SPIFlashDeSelect();returni; }/********************************************************************************************************* ** Function name: SPIFlashFastRead ** Descriptions: 以高速方式(<=50MHZ)从SPI FLASH读数据 ** Input parameters: readBuf 读数据存储的缓冲区首址 ** readCnt 要读取的数据量 ** Output parameters: uint32 实际读得的数据量。当读地址超出芯片容量时,将只读在芯片地址范围内 ** 的数据 ** Returned value: none *********************************************************************************************************/uint32 SPIFlashFastRead (uint32 readAddr, uint8*readBuf, uint32 readCnt) {uint32 i;uint8 addr[3];//检查参数if (readAddr >= SPI_FLASH_SIZE ||readBuf== 0 ||readCnt== 0) {returnSPI_FLASH_ERR_PARA;}//校正要读的数据总量if (readAddr + readCnt >=SPI_FLASH_SIZE) {readCnt= SPI_FLASH_SIZE -readAddr;}//将地址转换为字节数组addr[0] = (uint8)(readAddr >> 16);addr[1] = (uint8)(readAddr >> 8);addr[2] = (uint8)(readAddr & 0xff);//等待SPI Flash完成写操作while (SPIFlashReadstatusReg() &SPI_FLASH_REG_BIT_BUSY );SPIFlashSelect();{//发送低速读命令0x3,3字节地址,dummy字节SPIWriteReadByte(0xB);SPIWriteReadByte(addr[0]);SPIWriteReadByte(addr[1]);SPIWriteReadByte(addr[2]);SPIWriteReadByte(0xff);//依次读readCnt个数据for (i = 0; i < readCnt; i++) {readBuf[i]= SPIWriteReadByte(0xff);}}SPIFlashDeSelect();returni; }/********************************************************************************************************* ** Function name: SPIFlashWriteByte ** Descriptions: 向SPI Flash指定地址处写一字节数据 ** Input parameters: writeAddr 写入的地址 ** udata 写入的值 ** Output parameters: none ** Returned value: none ** Notes: 写之前必须注意到写保护的存储影响 *********************************************************************************************************/uint32 SPIFlashWriteByte (uint32 writeAddr, uint8 uByte) {uint8 addr[3];//检查写地址是否越界if (writeAddr >=SPI_FLASH_SIZE) {returnSPI_FLASH_ERR_PARA;}//将地址转换为字节数组addr[0] = (uint8)(writeAddr >> 16);addr[1] = (uint8)(writeAddr >> 8);addr[2] = (uint8)(writeAddr & 0xff);//等待SPI Flash完成写操作while (SPIFlashReadstatusReg() &SPI_FLASH_REG_BIT_BUSY );//发送写使能命令 SPIFlashSelect();{SPIWriteReadByte(0x06);}SPIFlashDeSelect();//写入实际要写入的数据 SPIFlashSelect();{//发送低速读命令0x3,3字节地址,写入的字节SPIWriteReadByte(0x2);SPIWriteReadByte(addr[0]);SPIWriteReadByte(addr[1]);SPIWriteReadByte(addr[2]);SPIWriteReadByte(uByte);}SPIFlashDeSelect();returnSPI_FLASH_OK; }/********************************************************************************************************* ** Function name: SPIFlashFastWrite ** Descriptions: 以地址自增方式向指定FLASH地址处连续写字数据 ** Input parameters: writeAddr 写入的起始地址 ** writeBuferr 写数据存储的缓冲区 ** uWord 写入的数据量,以字为单位 ** Output parameters: none ** Returned value: none ** Notes: 写之前必须注意到写保护的存储影响 *********************************************************************************************************/uint32 SPIFlashFastWrite (uint32 writeAddr, uint16*writeBuferr, uint16 uWord) {uint16 i;uint8 addr[3];//检查参数if (writeAddr >= SPI_FLASH_SIZE ||writeBuferr== 0 ||uWord== 0) {returnSPI_FLASH_ERR_PARA;}//检查写地址是否越界if (writeAddr + (uWord << 1) >=SPI_FLASH_SIZE) {uWord= (SPI_FLASH_SIZE - writeAddr) >> 1; }//将地址转换为字节数组addr[0] = (uint8)(writeAddr >> 16);addr[1] = (uint8)(writeAddr >> 8);addr[2] = (uint8)(writeAddr & 0xff);//等待SPI Flash完成写操作while (SPIFlashReadstatusReg() &SPI_FLASH_REG_BIT_BUSY );//发送写使能命令 SPIFlashSelect();{SPIWriteReadByte(0x06);}SPIFlashDeSelect();//发送低速读命令0xAD,3字节地址,写入的字节 SPIFlashSelect();{SPIWriteReadByte(0xAD);SPIWriteReadByte(addr[0]);SPIWriteReadByte(addr[1]);SPIWriteReadByte(addr[2]);SPIWriteReadByte(writeBuferr[0] >> 0x08);SPIWriteReadByte(writeBuferr[0] & 0xFF);}SPIFlashDeSelect();//发送其它字节for (i = 1; i < uWord; i++) {//等待SPI Flash完成写操作while (SPIFlashReadstatusReg() &SPI_FLASH_REG_BIT_BUSY );SPIFlashSelect();{//发送引导命令和编程字数据SPIWriteReadByte(0xAD);SPIWriteReadByte(writeBuferr[i]>> 0x08);SPIWriteReadByte(writeBuferr[i]& 0xFF); }SPIFlashDeSelect();}//等待SPI Flash完成写操作while (SPIFlashReadstatusReg() &SPI_FLASH_REG_BIT_BUSY );//发送写禁能命令,退出该模式 SPIFlashSelect();{SPIWriteReadByte(0x04);}SPIFlashDeSelect();returnSPI_FLASH_OK; }/********************************************************************************************************* ** Function name: SPIFlashChipErase ** Descriptions: 擦除整块芯片 ** Input parameters: none ** Output parameters: none ** Returned value: none ** Note: 如果sectorAaddr *********************************************************************************************************/ voidSPIFlashErase (uint8 eraseType, uint32 eraseAddr) {uint8 addr[3];//等待SPI Flash完成写操作while (SPIFlashReadstatusReg() &SPI_FLASH_REG_BIT_BUSY );//发送写使能命令 SPIFlashSelect();{SPIWriteReadByte(0x06);}SPIFlashDeSelect();//根据类型选择擦除方式switch(eraseType) {//选择整片擦除方式caseSPI_FLASH_ERASE_CHIP:SPIFlashSelect();{SPIWriteReadByte(0x60);}SPIFlashDeSelect();break;//扇区擦除方式caseSPI_FLASH_ERASE_SECTOR:if (eraseAddr <SPI_FLASH_SIZE) {//将地址转换为字节数组addr[0] = (uint8)(eraseAddr >> 16);addr[1] = (uint8)(eraseAddr >> 8);addr[2] = (uint8)(eraseAddr & 0xff);//发送扇区擦除命令,擦除的扇区地址 SPIFlashSelect();{SPIWriteReadByte(0x20);SPIWriteReadByte(addr[0]);SPIWriteReadByte(addr[1]);SPIWriteReadByte(addr[2]);}SPIFlashDeSelect();}break;//32K块擦除方式caseSPI_FLASH_ERASE_BLOCK:if (eraseAddr <SPI_FLASH_SIZE) {//将地址转换为字节数组addr[0] = (uint8)(eraseAddr >> 16);addr[1] = (uint8)(eraseAddr >> 8);addr[2] = (uint8)(eraseAddr & 0xff);//发送块擦除命令,擦除的块地址 SPIFlashSelect();{SPIWriteReadByte(0x52);SPIWriteReadByte(addr[0]);SPIWriteReadByte(addr[1]);SPIWriteReadByte(addr[2]);}SPIFlashDeSelect();}break;default:break;}}/********************************************************************************************************* ** Function name: SPIFlashSetProtection ** Descriptions: 设定SPI存储器的保护模式,加保护或解保护 ** Input parameters: isProtect 保护的模式,1--加保护, 0 -- 解保护 ** startAddr 保护区域的起始地址 ** stopAddr 保护区域的结束地址 ** Output parameters: 0 -- 操作成功, 1 -- 操作失败(当为解保护时,硬件保护阻止了解保护) ** Returned value: none *********************************************************************************************************/uint32 SPIFlashSetProtection (uint8 isProtect, uint32 startAddr, uint32 stopAddr) {uint8 BPXMask;uint8 status;//等待SPI Flash完成写操作while (SPIFlashReadstatusReg() &SPI_FLASH_REG_BIT_BUSY );if(isProtect) {//清除所有的保护位SPIFlashWritestatusReg(0);//如果BPL只读,即不可更改BPX位if (SPIFlashReadstatusReg() &SPI_FLASH_REG_BIT_BPL) {//当该区域已经加保护时,正确返回if ((status & SPI_FLASH_REG_BIT_BPX) >BPXMask) {return 0;}else{//当未加保护时,返回错误,不可更改保护模式return 1;}}else{//计算保护模式位if (startAddr >SPI_FLASH_SIZE) {return 0;}else if (startAddr >= 0xF0000) {BPXMask= 0x1 << 2; }else if (startAddr >= 0xE0000) {BPXMask= 0x2 << 2; }else if (startAddr >= 0xC0000) {BPXMask= 0x3 << 2; }else if (startAddr >= 0x80000) {BPXMask= 0x4 << 2; }else{BPXMask= 0x5 << 2; }//BPL写读写,此时加上保护位即可,但不锁定BPL,以妨不可恢复 SPIFlashWritestatusReg(BPXMask);return 0;}}else{//解除保护,写BPL位为0,解除保护SPIFlashWritestatusReg(0);//读保护位,如果值不为全0,则可能硬件加保护,解保护失败if (SPIFlashReadstatusReg() &SPI_FLASH_REG_BIT_BPX) {return 1; }else{return 0;}} }/*-------------------------------------------------- 测试代码 ---------------------------------------*/uint32 id; uint8 writeBuffer[1024]; uint8 readBuffer[1024]; uint8 status;#define SPI_FLASH_SECTOR_SIZE (1024*4) #define SPI_FLASH_BLOCK_SIZE (1024*32)void SPIFlashTest (void) {uint32 i, j;//初始化SPI控制器 SPIFlashInit();//读ID测试,值应为0x00BF258Eid =SPIFlashReadID();if (id != 0x00BF258E) {return;}//先解除保护才可写SPIFlashSetProtection(0, 0xF0000, 0xFFFFF);//整片擦除测试SPIFlashErase(SPI_FLASH_ERASE_CHIP, 0);for (i = 0; i < SPI_FLASH_SIZE / sizeof(readBuffer); i++) {SPIFlashRead(i* sizeof(readBuffer), readBuffer, sizeof(readBuffer));for (j = 0; j < sizeof(readBuffer); j++) {if (readBuffer[j] != 0xff) {return;}} }//字节写和读测试for (i = 0; i < SPI_FLASH_SIZE; i++) {SPIFlashWriteByte(i, i); SPIFlashRead (i, readBuffer,1);if( readBuffer[0] != (i & 0xff)) {return;} }//扇区擦除测试for (i = 0; i < SPI_FLASH_SIZE / (4*1024); i++) {SPIFlashErase(SPI_FLASH_ERASE_SECTOR, i* (4*1024));}for (i = 0; i < SPI_FLASH_SIZE / sizeof(readBuffer); i++) {SPIFlashRead(i* sizeof(readBuffer), readBuffer, sizeof(readBuffer));for (j = 0; j < sizeof(readBuffer); j++) {if (readBuffer[j] != 0xff) {return;}} }//快速写测试for (i = 0; i < SPI_FLASH_SIZE / sizeof(writeBuffer); i++) {for (j = 0; j < sizeof(writeBuffer); j++) {writeBuffer[j]=j;}SPIFlashFastWrite( i* sizeof(writeBuffer), (uint16 *)writeBuffer, sizeof(writeBuffer) >> 1);SPIFlashFastRead ( i* sizeof(writeBuffer), (uint8 *)readBuffer, sizeof(readBuffer));//交换字节顺序再比较for (j = 0; j < sizeof(writeBuffer) >> 1; j++) {uint16* ptr = (uint16 *)&readBuffer[j << 1];*ptr = ((*ptr & 0xff) << 8) | (*ptr >> 8); }if( memcmp( writeBuffer, readBuffer, sizeof(readBuffer)) != 0) {return;}}//扇区擦除测试for (i = 0; i < SPI_FLASH_SIZE / (32*1024); i++) {SPIFlashErase(SPI_FLASH_ERASE_BLOCK, i* (32*1024));}for (i = 0; i < SPI_FLASH_SIZE / sizeof(readBuffer); i++) {SPIFlashRead(i* sizeof(readBuffer), readBuffer, sizeof(readBuffer));for (j = 0; j < sizeof(readBuffer); j++) {if (readBuffer[j] != 0xff) {return;}} }//保护测试SPIFlashSetProtection(1, 0xF0000, 0xFFFFF);SPIFlashSetProtection(1, 0x80000, 0xFFFFF);SPIFlashSetProtection(0, 0xF0000, 0xFFFFF); }
参考:
STM32之SPI_FLASH(实例)
W25X SPI Flash中文资料
转载于:https://www.cnblogs.com/LittleTiger/p/8301325.html
STM32-串行SPI nor相关推荐
- 串行 spi Flash 跨页编程的注意点
spi Flash 进行 page program的时候,编程的数据为1-256个字节不等.在Datasheet中,如果编程的数据为256个字节,那么,输入的起始地址需要256个字节对齐,即需要页对齐 ...
- 赛普拉斯代理4Mbit串行SPI铁电存储器CY15B104Q-LHXI
赛普拉斯型号CY15B104Q-LHXI主要采用先进铁电工艺的4Mbit非易失性存储器.铁电随机存取存储器或FRAM是非易失性的,并且执行类似于RAM的读取和写入操作.它提供了151年的可靠数据保留, ...
- STM32 串行FLASH文件系统FatFs
目录 一.Windows系统为例 二.文件系统的结构与特性 为什么要应用文件分配表? 三.FatFs文件系统 1- FatFs 文件系统源码介绍 2- FatFs在程序中的关系网 四.配置FatFs移 ...
- 串行MRAM消耗的能量
MR25H256是一个串行MRAM,具有使用串行外围设备接口的芯片选择(CS),串行输入(SI),串行输出(SO)和串行时钟(SCK)的四针接口在逻辑上组织为32Kx8的存储器阵列. SPI)总线.串 ...
- SPI应用——W25Q128串行FLASH
一.FLASH存储器介绍 FLASH存储器又称闪存,它与EEPROM都是掉电后数据不丢失的存储器,但FLASH存储器容量普遍大于EEPROM,现在基本取代了它的地位.在存储控制上,最主要的区别是FLA ...
- 第24章 SPI—读写串行FLASH—零死角玩转STM32-F429系列
第24章 SPI-读写串行FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/ ...
- SPI—读写串行FLASH(时序中的无关项)
SPI-读写串行FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege 本章 ...
- 25章 SPI—读写串行FLASH
SPI 协议简介 3 条总线分别为SCK(时钟).MOSI(主出从入).MISO(主入从出),片选线为SS1.2.3(从设备)(多少设备也就这三条ss) MOSI和MISO能看出是全双工(输入输出两条 ...
- ChibiOS系列:五、将STM32 USART与ChibiOS串行驱动程序配合使用
本文翻译自:http://www.playembedded.org/blog/stm32-usart-chibios-serial/ 将STM32 USART与ChibiOS串行驱动程序配合使用 发表 ...
- SPI—读写串行FLASH
1 SPI协议简介 SPI协议是由摩托罗拉公司提出的通讯协议(SerialPeripheralInterface),即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在ADC.LCD等设备 ...
最新文章
- tornado 学习笔记15 _ServerRequestAdapter分析
- 修改meta标签 查看源码没效果怎么办_Spring 源码学习(三)-自定义标签
- 易语言反截图_【易语言】模仿QQ截图
- 使用XML管理模版資源
- 学习韩立刚老师IT运维课程,成为韩立刚老师正式学生,在全国范围为你就近推荐工作。...
- [20180826]四校联考
- 第一个ncurses程序: hello world !!!
- bigdecimal判断等于0_Linux | shell脚本-比较判断和运算语句
- 流畅的python 函数
- Windows 环境变量的两点说明
- 了解一下运行软件的自我保护(RASP)
- 51c语言延时作用,51单片机C语言延时函数的使用 - 51单片机C语言延时函数怎么定义和使用...
- php 压缩动态gif,在PHP中压缩GIF图像质量?
- 开始启航:Redis中国用户会(CRUG)首次常委会召开 选出主席和校长
- ARM Cortex-M 调试器 - 基础知识
- 算法系列1《DES》
- 深入理解SD卡:协议
- VMware VCP-DCV认证课程概述
- C语言 学生管理系统 c++ 学生管理系统
- 分枝定界法求哈密尔登回路问题的由表及里
热门文章
- Understand-4.0.877-Linux-64bit.tgz最新版本2017年源代码阅读利器,养眼theme之配置
- Linux服务器安全之 fail2ban的安装与配置
- Codeforces Round #484 (Div. 2) D. Shark
- javasript深度拷贝
- js 中call,apply,bind的区别
- (转)Spring整合Jpa
- Jenkins随笔(四)常用插件-SVN
- Linux c/c++ IDE(开发环境)
- Java日期格式化之线程安全
- (7)zabbix资产清单inventory管理