/************************************************************************************
* Copyright (c), 2006-2007, C8051F网络
* All rights reserved.
*
* Http: www.c8051f.com
* Email: mite@vip.qq.com
*
* File name: SPIFLASH.c
* Project : C8051F020DK
* Processor: C8051F020
* Compiler : Keil C51 Compiler
*
* Description: 本文件是SPI接口FLASH硬件驱动程序文件;适用器件AT25F512、AT25F1024;
*
* author: glacier
* QQ: 252858144
* date: 2009.04.02
*
* Others: none;
*
* Function List:
* 1. void SPIFlash_Init(void)
* 2. bool SPIFlash_Erase(void)
* 3. bool SPIFlash_EraseSector(unsigned char sector)
* 4. bool SPIFlash_WriteByte(unsigned long addr, unsigned char val)
* 5. bool SPIFlash_Write(unsigned long addr, unsigned char *p, unsigned int len)
* 6. bool SPIFlash_ReadByte(unsigned long addr, unsigned char *val)
* 7. bool SPIFlash_Read(unsigned long addr, unsigned char *p, unsigned int len)
* 8. bool SPIFlash_ReadID(unsigned char *ManufacturerID, unsigned char *ProductID)
*
*************************************************************************************/
/************************************************************************************/
// 引用外部头文件
/************************************************************************************/
#include "..\config\c8051f020.h"
#include "..\config\const.h"
#include "..\driver\spi.h"
#include "..\driver\SPIFlash.h"
#include "..\driver\Delay.h"
/************************************************************************************/
// 常量及全局变量定义
/************************************************************************************/
#define SPIFLASH_FREQ 2000000 // SCK freq (Hz)
#define PAGE_SIZE 0x80 // 定义页大小
#define SECTOR_SIZE 0x8000 // 定义扇区大小
// SPI FLASH操作指令定义
#define CMD_WRSR 0x01 // Write Status Register Command
#define CMD_WRITE 0x02 // Write Command
#define CMD_READ 0x03 // Read Command
#define CMD_WRDI 0x04 // Reset Write Enable Latch Command
#define CMD_RDSR 0x05 // Read Status Register Command
#define CMD_WREN 0x06 // Set Write Enable Latch Command
#define CMD_RDID 0x15 // Read Manufacturer and Product ID
#define CMD_SECTOR_ERASE 0x15 // Erase One Sector in Memory Array
#define CMD_CHIP_ERASE 0x62 // Erase All Sectors in Memory Array
/*************************************************************************************/
//
// SPI接口FLASH(AT25F512、AT25F1024)硬件驱动程序函数定义
//
/*************************************************************************************/
/***********************************************************************************
* Function: SPIFlash_CS;
*
* Description: SPI接口Flash芯片片选使能函数;
*
* Input: flag=true, 使能芯片操作; flag=false, 禁止芯片操作;
*
* Output: none;
*
* Return: none;
*
* Note: none;
************************************************************************************/
void SPIFlash_CS(bool flag)
{
if(flag)
NSSMD0 = 0;
else
NSSMD0 = 1;
}
/***********************************************************************************
* Function: SPIFlash_WP;
*
* Description: SPI接口Flash芯片片选使能函数;
*
* Input: flag=true, 使能芯片操作; flag=false, 禁止芯片操作;
*
* Output: none;
*
* Return: none;
*
* Note: none;
************************************************************************************/
void SPIFlash_WP(bool flag)
{
SPIFlash_CS(true); // 使能芯片操作
if(flag)
SPI_WriteData(CMD_WREN); // 写使能
else
SPI_WriteData(CMD_WRDI); // 写禁止
SPIFlash_CS(false); // 禁止芯片操作
}
/***********************************************************************************
* Function: SPIFlash_Busy;
*
* Description: 判断FLASH是否忙函数;
*
* Input: none;
*
* Output: none;
*
* Return: true,FLASH忙,不能进行操作; false,FLASH空闲,可以进行操作;
*
* Note: none;
************************************************************************************/
bool SPIFlash_Busy(void)
{
unsigned char val;
SPIFlash_CS(true); // 使能芯片操作
SPI_WriteData(CMD_RDSR); // 写读状态命令
SPI_ReadData(&val); // 读数据命令
SPIFlash_CS(false); // 禁止芯片操作
if (val&0x01)
return true;
else
return false;
}
/***********************************************************************************
* Function: SPIFlash_Init;
*
* Description: SPI接口Flash初始化函数;
*
* Input: none;
*
* Output: none;
*
* Return: none;
*
* Note: none;
************************************************************************************/
void SPIFlash_Init(void)
{
SPI_Init(SPIFLASH_FREQ);
}
/***********************************************************************************
* Function: SPIFlash_Erase;
*
* Description: Flash芯片擦除程序;
*
* Input: none;
*
* Output: none;
*
* Return: true,芯片擦除成功; false,芯片擦除失败;
*
* Note: none;
************************************************************************************/
bool SPIFlash_Erase(void)
{
SPIFlash_WP(true);
SPIFlash_CS(true); // 使能芯片操作
SPI_WriteData(CMD_CHIP_ERASE); // 擦除芯片
SPIFlash_CS(false); // 禁止芯片操作
while(SPIFlash_Busy()); // 等待芯片不忙
return true;
}
/***********************************************************************************
* Function: SPIFlash_EraseSector;
*
* Description: Flash芯片扇区擦除程序, 每32KB为一个扇区;
*
* Input: 扇区索引号
* AT25F512,扇区索引号范围:0~1;
* AT25F1024,扇区索引号范围:0~3;
*
* Output: none;
*
* Return: true,芯片扇区擦除成功; false,芯片扇区擦除失败;
*
* Note: none;
************************************************************************************/
bool SPIFlash_EraseSector(unsigned char sector)
{
unsigned long addr;
unsigned char adr[3];
SPIFlash_WP(true);
addr = (unsigned long)sector*SECTOR_SIZE;
adr[2] = (addr>>16)&0xFF;
adr[1] = (addr>>8)&0xFF;
adr[0] = addr&0xFF;
SPIFlash_CS(true); // 使能芯片操作
SPI_WriteData(CMD_SECTOR_ERASE); // 擦除扇区
SPI_WriteData(adr[2]); // 写地址
SPI_WriteData(adr[1]); // 写地址
SPI_WriteData(adr[0]); // 写地址
SPIFlash_CS(false); // 禁止芯片操作
while(SPIFlash_Busy()); // 等待芯片不忙
return true;
}
/***********************************************************************************
* Function: SPIFlash_WriteByte;
*
* Description: 向FLASH的某个地址写入字节数据;
*
* Input: addr,flash地址; val,写入的字节数据;
* AT25F512, 地址范围: 0x000000~0x00ffff;
* AT25F1024, 地址范围: 0x000000~0x01ffff;
*
* Output: none;
*
* Return: true,写入数据成功; false,写入数据失败;
*
* Note: 本函数不做地址范围范围检查,所以不要超过范围;
************************************************************************************/
bool SPIFlash_WriteByte(unsigned long addr, unsigned char val)
{
unsigned char adr[3];
adr[2] = (addr>>16)&0xFF;
adr[1] = (addr>>8)&0xFF;
adr[0] = addr&0xFF;
SPIFlash_WP(true);
SPIFlash_CS(true); // 使能芯片操作
SPI_WriteData(CMD_WRITE); // 写指令
SPI_WriteData(adr[2]); // 写地址
SPI_WriteData(adr[1]); // 写地址
SPI_WriteData(adr[0]); // 写地址
SPI_WriteData(val); // 写地址
SPIFlash_CS(false); // 禁止芯片操作
while(SPIFlash_Busy()); // 等待芯片不忙
return true;
}
/***********************************************************************************
* Function: SPIFlash_Write;
*
* Description: 写入FLASH一段数据;
*
* Input: addr,写入flash数据的起始地址; *p, 要写入数据的指针; len,要写入数据的长度;
*