----------------------------------------------------------------------------------------------------------------------------------------- 关于W25X16 SPI型FLASH的手册在附件中,这里主要是W25X16的驱动程序的书写,通过配合STM32主机的SPI模式,读写FLASH
w25x16.h
#ifndef __W25X16_H
#define __W25X16_H
#include "stm32f10x_lib.h"
/****************************************************************************
-W25X16的宏定义
-片选信号CS
-PA2的宏定义
****************************************************************************/
#define SPI_FLASH_CS_PORT GPIOA
#define SPI_FLASH_CS_CLK RCC_APB2Periph_GPIOA
#define SPI_FLASH_CS_PIN GPIO_Pin_2
#define Set_SPI_FLASH_CS {GPIO_SetBits(SPI_FLASH_CS_PORT,SPI_FLASH_CS_PIN);}
#define Clr_SPI_FLASH_CS {GPIO_ResetBits(SPI_FLASH_CS_PORT,SPI_FLASH_CS_PIN);} //W25X16读写
#define FLASH_ID 0XEF14/*********************************************
- W25X16的操作指令表,STM32通过向W25X16
发送以下指令就可以对W25X16进行以下的操作
*********************************************/
#define W25X_WriteEnable 0x06
#define W25X_WriteDisable 0x04
#define W25X_ReadStatusReg 0x05
#define W25X_WriteStatusReg 0x01
#define W25X_ReadData 0x03
#define W25X_FastReadData 0x0B
#define W25X_FastReadDual 0x3B
#define W25X_PageProgram 0x02
#define W25X_BlockErase 0xD8
#define W25X_SectorErase 0x20
容量为
4M
字节
,
共有
64
个
Block,
1024
个
Sector
,16384
个
Page
- W25X64
容量为
8M
字节
,
共有
128
个
Block,2048
个
Sector
,32768
个
Page
***************************************************************************/
void
SPI_Flash_Init(void)
{
SPIx_Init();
//
初始化
SPI
}
/***************************************************************************
-
功能描述:读
w25x16
Flash
状态寄存器的函数
-
隶属模块:
w25x16
Flash
操作
-
函数属性:外部,使用户使用
-
参数说明:无
-
返回说明:返回
w25x16
Flash
的当前状态
------------------------------------------------------
|
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,
空闲
)
|
|
默认
:0x00
|
|
只有
SPR,TB,BP2,BP1,BP0(bit
7,5,4,3,2)
可以写
!!!
|
-----------------------------------------------------
-
操作说明:
CS
电平先拉低、
STM32
利用
SPI
发送读
FLASH
状态寄存器命令、
STM32
读取数据、
CS
拉
高,发送的命令被采集
如果
CS
不拉高,则
FLASH
的状态会不断发送出来。根据读出的字节就可以判断当前的
FLASH
的工作准状态。
***************************************************************************/
u8
SPI_Flash_ReadSR(void)
{
u8
byte=0;
Clr_SPI_FLASH_CS;
//
使能器件
SPIx_ReadWriteByte(W25X_ReadStatusReg);
//
发送读取状态寄存器命令
byte=SPIx_ReadWriteByte(0Xff);
//
读取一个字节
Set_SPI_FLASH_CS;
//
取消片选
return
byte;
}
NumByteToWrite-=pageremain;
//
减去已经写入了的字节数
if(NumByteToWrite>256)
pageremain=256;
//
一次可以写入
256
个字节
else
pageremain=NumByteToWrite;
//
不够
256
个字节了
}
}
}
/***************************************************************************
-
功能描述:
写扇区
w25x16
Flash
操作函数,
在指定地址开始写入指定长度的数据,
该函数带擦除操作
!
-
隶属模块:
w25x16
Flash
操作
-
函数属性:外部,使用户使用
-
参数说明:
pBuffer:
数据存储区
WriteAddr:
开始写的地址
(24bit)
NumByteToWrite:
要写入的字节数
(
最大
65535)
-
返回说明:无
-
操作说明:
-
每
256bytes
为一个
Page
,每
4Kbytes
为一个
Sector
,每
16
个扇区为
1
个
Block
- W25X16
容量为
2M
字节
,
共有
32
个
Block,
512
个
Sector
,
8192
个
Page
- W25X32
容量为
4M
字节
,
共有
64
个
Block,
1024
个
Sector
,16384
个
Page
- W25X64
容量为
8M
字节
,
共有
128
个
Block,2048
个
Sector
,32768
个
Page
***************************************************************************/
u8
SPI_FLASH_BUF[4096];
void
SPI_Flash_Write(u8*
pBuffer,u32
WriteAddr,u16
NumByteToWrite)
{
u32
secpos;
u16
secoff;
u16
secremain;
u16
i;
secpos=WriteAddr/4096;//
扇区地址
0~511
for
w25x16
secoff=WriteAddr%4096;//
在扇区内的偏移
secremain=4096-secoff;//
扇区剩余空间大小
if(NumByteToWrite<=secremain)
secremain=NumByteToWrite;//
不大于
4096
个字节
while(1)
{
SPI_Flash_Read(SPI_FLASH_BUF,secpos*4096,4096);//
读出整个扇区的内容
NumByteToWrite-=pageremain; //减去已经写入了的字节数 if(NumByteToWrite>256)
pageremain=256; //一次可以写入256个字节 else
pageremain=NumByteToWrite; //不够256个字节了 } } }
/***************************************************************************
- 功能描述:写扇区w25x16 Flash操作函数,在指定地址开始写入指定长度的数据,该函数带擦除操作! - 隶属模块:w25x16 Flash操作 - 函数属性:外部,使用户使用 - 参数说明:pBuffer:数据存储区 WriteAddr:开始写的地址(24bit)
NumByteToWrite:要写入的字节数(最大65535) - 返回说明:无 - 操作说明:
- 每256bytes为一个Page,每4Kbytes为一个Sector,每16个扇区为1个Block - W25X16容量为2M字节,共有32个Block, 512个Sector , 8192个Page - W25X32容量为4M字节,共有64个Block, 1024个Sector ,16384个Page - W25X64容量为8M字节,共有128个Block,2048个Sector ,32768个Page
***************************************************************************/ u8 SPI_FLASH_BUF[4096];
if(SPI_FLASH_BUF[secoff+i]!=0XFF) break;//需要擦除 }
if(i
SPI_Flash_Write_NoCheck(SPI_FLASH_BUF,secpos*4096,4096);//写入整个扇区 } else
SPI_Flash_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间. if(NumByteToWrite==secremain) break;//写入结束了 else//写入未结束 {
secpos++;//扇区地址增1 secoff=0;//偏移位置为0 pBuffer+=secremain; //指针偏移 WriteAddr+=secremain;//写地址偏移 NumByteToWrite-=secremain; //字节数递减 if(NumByteToWrite>4096)
secremain=4096; //下一个扇区还是写不完 else
secremain=NumByteToWrite; //下一个扇区可以写完了 } }; }
/*************************************************************************** - 功能描述:w25x16 Flash擦除整个芯片操作函数 - 隶属模块:w25x16 Flash操作 - 函数属性:外部,使用户使用 - 参数说明:无
- 返回说明:无
- 操作说明:W25X16:25s W25X32:40s W25X64:40s 等待时间超长... 擦除完以后,所有字节数据为0XFF
(1)因为要擦除FLASH芯片,所以要发送写使能命令 (2)读状态寄存器状态,通过BUSY位判断指令是否写完。 (3)片选拉低,选中FLASH (4)发送擦除芯片命令 (5)片选拉高,指令发送完成
(6)检查BUSY位,等待芯片擦除结束
***************************************************************************/ void SPI_Flash_Erase_Chip(void) {
SPI_FLASH_Write_Enable(); //SET WEL SPI_Flash_Wait_Busy();
Clr_SPI_FLASH_CS; //使能器件
SPIx_ReadWriteByte(W25X_ChipErase); //发送片擦除命令 Set_SPI_FLASH_CS; //取消片选 SPI_Flash_Wait_Busy(); //等待芯片擦除结束 }
/*************************************************************************** - 功能描述:w25x16 Flash擦除一个扇区操作函数 - 隶属模块:w25x16 Flash操作 - 函数属性:外部,使用户使用
- 参数说明:Dst_Addr:扇区地址 0~511 for w25x16 - 返回说明:无
- 操作说明:擦除一个山区的最少时间:150msXFF
- 每256bytes为一个Page,每4Kbytes为一个Sector,每16个扇区为1个Block - W25X16容量为2M字节,共有32个Block, 512个Sector , 8192个Page - W25X32容量为4M字节,共有64个Block, 1024个Sector ,16384个Page - W25X64容量为8M字节,共有128个Block,2048个Sector ,32768个Page (1)发送写使能命令
(2)等待发送完成,通过检测状态寄存器的最低位是否为0 (3)CS拉低,选中芯片 (4)发送擦除命令 (5)CS拉高,取消片选
(6)等待擦除结束,如果结束BUSY会为0
***************************************************************************/
void SPI_Flash_Erase_Sector(u32 Dst_Addr) {
Dst_Addr*=4096;
SPI_FLASH_Write_Enable(); //SET WEL SPI_Flash_Wait_Busy();
Clr_SPI_FLASH_CS; //使能器件
SPIx_ReadWriteByte(W25X_SectorErase); //发送扇区擦除指令 SPIx_ReadWriteByte((u8)((Dst_Addr)>>16)); //发送24bit地址 SPIx_ReadWriteByte((u8)((Dst_Addr)>>8)); SPIx_ReadWriteByte((u8)Dst_Addr);
Set_SPI_FLASH_CS; //取消片选 SPI_Flash_Wait_Busy(); //等待擦除完成 }
/*************************************************************************** - 功能描述:w25x16 Flash等待空闲操作函数 - 隶属模块:w25x16 Flash操作 - 函数属性:外部,使用户使用 - 参数说明:无 - 返回说明:无
- 操作说明:就是检查FLASH的最低位是否为1
***************************************************************************/ void SPI_Flash_Wait_Busy(void)
{
while ((SPI_Flash_ReadSR()&0x01)==0x01); // 等待BUSY位清空 }***************************************************************************/ void SPI_Flash_PowerDown(void)
{
Clr_SPI_FLASH_CS;
//
使能器件
SPIx_ReadWriteByte(W25X_PowerDown);
//
发送掉电命令
Set_SPI_FLASH_CS;
//
取消片选
delay_us(3);
//
等待
TPD
}
/***************************************************************************
-
功能描述:
w25x16
Flash
唤醒操作函数
-
隶属模块:
w25x16
Flash
操作
-
函数属性:外部,使用户使用
-
参数说明:无
-
返回说明:无
-
操作说明:
(
1
)
CS
拉低,选中芯片。
(
2
)
STM32
发送
W25X_ReleasePowerDown
指令
(
3
)
CS
拉高,取消芯片。
(
4
)延时
tres
个延时
***************************************************************************/
void
SPI_Flash_WAKEUP(void)
{
Clr_SPI_FLASH_CS;
//
使能器件
SPIx_ReadWriteByte(W25X_ReleasePowerDown);
//
send
W25X_PowerDown
command
0xAB
Set_SPI_FLASH_CS;
//
取消片选
delay_us(3);
//
等待
TRES1
}
有了以上的驱动函数,
STM32
在
SPI
模式下就可以和
W25X16
进行通信了