stm32 W25Q64Word格式.docx
《stm32 W25Q64Word格式.docx》由会员分享,可在线阅读,更多相关《stm32 W25Q64Word格式.docx(11页珍藏版)》请在冰豆网上搜索。
//PB12推挽
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
//推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&
GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_12);
}//读取SPI_FLASH的状态寄存器
//BIT
//SPRRVTBBP2BP1BP0WELBUSY
//SPR:
默认0,状态寄存器保护位,配合WP使用
//TB,BP2,BP1,BP0:
FLASH区域写保护设置
//WEL:
写使能锁定
//BUSY:
忙标记位(1,忙;
0,空闲)
//默认:
0x00
u8SPI_Flash_ReadSR(void){u8byte=0;
}//写SPI_FLASH状态寄存器
//只有SPR,TB,BP2,BP1,BP0(bit7,5,4,3,2)可以写!
!
voidSPI_FLASH_Write_SR(u8sr){SPI_FLASH_CS=0;
//使能器件
}SPI2_ReadWriteByte(W25X_WriteStatusReg);
//发送写取状态寄存器命令
SPI2_ReadWriteByte(sr);
//写入一个字节
SPI_FLASH_CS=1;
//取消片选
SPI_FLASH_CS=0;
SPI2_ReadWriteByte(W25X_ReadStatusReg);
//发送读取状态寄存器命令
byte=SPI2_ReadWriteByte(0Xff);
//读取一个字节
returnbyte;
SPI2_Init();
//初始化SPI
SPI2_SetSpeed(SPI_BaudRatePrescaler_2);
//设置为18M时钟,高速模式
SPI_FLASH_TYPE=SPI_Flash_ReadID();
//读取FLASHI
D.
//SD卡片选信号
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
//PD2推挽
GPIO_Init(GPIOD,&
GPIO_SetBits(GPIOD,GPIO_Pin_2);
//
2.4G无线片选信号
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
//PG7推挽
GPIO_Init(GPIOG,&
GPIO_SetBits(GPIOG,GPIO_Pin_7);
//SPI_FLASH写使能
//将WEL置位
voidSPI_FLASH_Write_Enable(void){SPI_FLASH_CS=0;
SPI2_ReadWriteByte(W25X_WriteEnable);
//发送写使能
//取消片选}//SPI_FLASH写禁止
//将WEL清零
voidSPI_FLASH_Write_Disable(void){SPI_FLASH_CS=0;
SPI2_ReadWriteByte(W25X_WriteDisable);
//发送写禁止指令
//取消片选}//读取芯片IDW25X16的ID:
0XEF14
u16SPI_Flash_ReadID(void){u16Temp=0;
SPI2_ReadWriteByte(0x90);
//发送读取ID命令
SPI2_ReadWriteByte(0x00);
Temp|=SPI2_ReadWriteByte(0xFF)<
<
8;
Temp|=SPI2_ReadWriteByte(0xFF);
SPI_FLASH_CS=1;
returnTemp;
}//读取SPIFLASH
//在指定地址开始读取指定xx的数据
//pBuffer:
数据存储区
//ReadAddr:
开始读取的地址(24bit)
//NumByteToRead:
要读取的字节数(最大65535)
//2^10=10241K=1024字节
//8M最大能读到2^23也就是24位
voidSPI_Flash_Read(u8*pBuffer,u32ReadAddr,u16NumByteToRead){u16i;
SPI2_ReadWriteByte(W25X_ReadData);
//发送读取命令
SPI2_ReadWriteByte((u8)((ReadAddr)>
>
16));
//发送24bit地址
8));
SPI2_ReadWriteByte((u8)ReadAddr);
for(i=0;
i<
NumByteToRead;
i++){pBuffer[i]=SPI2_ReadWriteByte(0XFF);
//循环读数}SPI_FLASH_CS=1;
//取消片选}//SPI在一页(0~65535)内写入少于256个字节的数据
//在指定地址开始写入最大256字节的数据
//WriteAddr:
开始写入的地址(24bit)
//NumByteToWrite:
要写入的字节数(最大256),该数不应该超过该页的剩余字节数!
voidSPI_Flash_Write_Page(u8*pBuffer,u32WriteAddr,u16NumByteToWrite){u16i;
SPI_FLASH_Write_Enable();
//SETWEL
SPI2_ReadWriteByte(W25X_PageProgram);
//发送写页命令
SPI2_ReadWriteByte((u8)((WriteAddr)>
//发送24bit地址
SPI2_ReadWriteByte((u8)WriteAddr);
NumByteToWrite;
i++)
SPI2_ReadWriteByte(pBuffer[i]);
//循环写数
}SPI_FLASH_CS=1;
SPI_Flash_Wait_Busy();
//等待写入结束
//无检验写SPIFLASH
//必须确保所写的地址范围内的数据全部为0XFF,否则在非0XFF处写入的数据将失败!
//具有自动换页功能
//在指定地址开始写入指定长度的数据,但是要确保地址不越界!
要写入的字节数(最大65535)
//每页256个字节
voidSPI_Flash_Write_NoCheck(u8*pBuffer,u32WriteAddr,u16NumByteToWrite){u16YeSengYu;
YeSengYu=256-WriteAddr%256;
//单页剩余的字节数
if(NumByteToWrite<
=YeSengYu)
YeSengYu=NumByteToWrite;
//不大于256个字节
while
(1){SPI_Flash_Write_Page(pBuffer,WriteAddr,YeSengYu);
if(NumByteToWrite==YeSengYu)
break;
//写入结束了
else//NumByteToWrite>
YeSengYu{}pBuffer+=YeSengYu;
WriteAddr+=YeSengYu;
NumByteToWrite-=YeSengYu;
if(NumByteToWrite>
256)
YeSengYu=256;
//一次可以写入256个字节
else
//不够256个字节了
//减去已经写入了的字节数}}//写SPIFLASH
//在指定地址开始写入指定xx的数据
//该函数带擦除操作!
u8SPI_FLASH_BUF[4096];
voidSPI_Flash_Write(u8*pBuffer,u32WriteAddr,u16NumByteToWrite){u32secpos;
u16secoff;
u16secremain;
u16i;
secpos=WriteAddr/4096;
//扇区地址0~2047forw25x64
secoff=WriteAddr%4096;
//在扇区内的偏移
secremain=4096-secoff;
//扇区剩余空间大小
=secremain)
secremain=NumByteToWrite;
//不大于4096个字节
(1){SPI_Flash_Read(SPI_FLASH_BUF,secpos*4096,4096);
//读出整个扇区的内容for(i=0;
secremain;
i++)//校验数据{if(SPI_FLASH_BUF[secoff+i]!
=0XFF)
//需要擦除}if(i<
secremain)//需要擦除{SPI_Flash_Erase_Sector(secpos);
//擦除这个扇区
i++)//复制{}
SPI_Flash_Write_NoCheck(SPI_FLASH_BUF,secpos*4096,4096);
//写入整个扇区SPI_FLASH_BUF[i+secoff]=pBuffer[i];
}else
SPI_Flash_Write_NoCheck(pBuffer,WriteAddr,secremain);
//写已经擦除了的,直接写入扇区剩余区间.
if(NumByteToWrite==secremain)
else//写入未结束{secpos++;
//扇区地址增1
secoff=0;
//偏移位置为0
pBuffer+=secremain;
//指针偏移
WriteAddr+=secremain;
//写地址偏移
NumByteToWrite-=secremain;
//字节数递减
}if(NumByteToWrite>
4096)
secremain=4096;
//下一个扇区还是写不完
//下一个扇区可以写完了
}}
//擦除整个芯片
//整片擦除时间:
//W25X16:
25s
//W25X32:
40s
//W25X64:
//等待时间超长...
voidSPI_Flash_Erase_Chip(void){SPI_FLASH_Write_Enable();
SPI2_ReadWriteByte(W25X_ChipErase);
//发送片擦除命令
//等待芯片擦除结束}//擦除一个扇区
//Dst_Addr:
扇区地址0~511forw25x16
扇区地址0~2047forw25x64
//擦除一个xx的最少时间:
150ms
voidSPI_Flash_Erase_Sector(u32Dst_Addr){Dst_Addr*=4096;
SPI2_ReadWriteByte(W25X_SectorErase);
//发送扇区擦除指令
SPI2_ReadWriteByte((u8)((Dst_Addr)>
SPI2_ReadWriteByte((u8)Dst_Addr);
}//等待空闲//等待擦除完成
voidSPI_Flash_Wait_Busy(void){}while((SPI_Flash_ReadSR()&
0x01)==0x01);
//等待BUSY位清空
//进入掉电模式
voidSPI_Flash_PowerDown(void){SPI_FLASH_CS=0;
SPI2_ReadWriteByte(W25X_PowerDown);
//发送掉电命令
delay_us
(3);
}//唤醒
voidSPI_Flash_WAKEUP(void){SPI_FLASH_CS=0;
SPI_FLASH_CS=1;
//等待TRES1
}.H文件
#ifndef__FLASH_H
#define__FLASH_H
sys.h"
//W25X系列/Q系列芯片列表
//W25Q80ID0XEF13
//W25Q16ID0XEF14
//W25Q32ID0XEF15
//W25Q32ID0XEF16
#defineW25Q800XEF13
#defineW25Q160XEF14
#defineW25Q320XEF15
#defineW25Q640XEF16
externu16SPI_FLASH_TYPE;
//定义我们使用的flash芯片型号
#defineSPI_FLASH_CSPBout
(12)//选中FLASH
////////////////////////////////////////////////////////////////////////////
//指令表
#defineW25X_WriteEnable
#defineW25X_WriteDisable
#defineW25X_ReadStatusReg
#defineW25X_WriteStatusReg
#defineW25X_ReadData
#defineW25X_FastReadData
#defineW25X_FastReadDual
#defineW25X_PageProgram
#defineW25X_BlockErase
#defineW25X_SectorErase
#defineW25X_ChipErase0x06
0x04
0x05
0x01
0x0B//写使能
//写失能
//读状态寄存器
//写状态寄存器
0x03
////读数据
0x3B
0x02
0xD8
0x20
0xC7
0xB9
0xAB
#defineW25X_PowerDown
#defineW25X_ReleasePowerDown//掉电
//唤醒
#defineW25X_DeviceID
#defineW25X_ManufactDeviceID0x90
#defineW25X_JedecDeviceID
voidSPI_Flash_Init(void);
0x9F
u16SPI_Flash_ReadID(void);
//读取FLASHID
u8SPI_Flash_ReadSR(void);
//读取状态寄存器
voidSPI_FLASH_Write_SR(u8sr);
voidSPI_FLASH_Write_Enable(void);
//写使能
voidSPI_FLASH_Write_Disable(void);
//写保护
voidSPI_Flash_Write_NoCheck(u8*pBuffer,u32WriteAddr,u16NumByteToWrite);
voidSPI_Flash_Read(u8*pBuffer,u32ReadAddr,u16NumByteToRead);
//读取flashvoidSPI_Flash_Write(u8*pBuffer,u32WriteAddr,u16NumByteToWrite);
//写入flash
voidSPI_Flash_Erase_Chip(void);
//整片擦除
voidSPI_Flash_Erase_Sector(u32Dst_Addr);
//扇区擦除
voidSPI_Flash_Wait_Busy(void);
//等待空闲
voidSPI_Flash_PowerDown(void);
voidSPI_Flash_WAKEUP(void);
#endif//唤醒