📄 sst25vf016bdrv.c
字号:
/****************************************Copyright (c)**************************************************
** Guangzou ZLG-MCU Development Co.,LTD.
** graduate school
** http://www.zlgmcu.com
**
**--------------File Info-------------------------------------------------------------------------------
** File name: SST25VF016BDrv.c
** Descriptions: SPI下的SST25VF016B操作函数库
**
**------------------------------------------------------------------------------------------------------
** Created by: Litiantian
** Created date: 2007-04-16
** Version: 1.0
** Descriptions: The original version
**
**------------------------------------------------------------------------------------------------------
** Modified by: 柴利明
** Modified date: 2008-07-18
** Version: 1.1
** Descriptions:
********************************************************************************************************/
#include "config.h"
/* 移植本软件包时需要修改以下的函数或宏 */
/*********************************************************************************************************
** 函数名称: SPIInit
** 函数功能: 初始化控制SSI的管脚
** 入口参数: 无
** 出口参数: 无
** 返回值: 无
*********************************************************************************************************/
void SPI_Init(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI); /* 为SSI提供时钟 */
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); /* 使能GPIOA */
/* 配置SPI为模式0,主机模式,波特率,数据宽度为8位 */
SSIConfig(SSI_BASE, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, BitRate, DataWidth);
SSIEnable(SSI_BASE); /* 允许对SSI进行操作 */
/* 设置GPIOA2,4,5引脚为SSI配置功能 */
GPIOPinTypeSSI(GPIO_PORTA_BASE, (GPIO_PIN_2 | GPIO_PIN_4 |
GPIO_PIN_5));
GPIODirModeSet(GPIO_PORTA_BASE, PINS, GPIO_DIR_MODE_OUT); /* 配置片选管脚为输出 */
GPIOPadConfigSet(GPIO_PORTA_BASE, PINS, GPIO_STRENGTH_2MA,
GPIO_PIN_TYPE_STD); /* 配置片选管脚为上拉,2MA输出*/
CE_High();
}
/*********************************************************************************************************
** 函数名称: Send_Byte
** 函数功能: 通过硬件SPI发送一个字节到SST25VF016B
** 入口参数: data 发送的数据
** 出口参数: 无
** 返回值: 无
*********************************************************************************************************/
void Send_Byte(uint8 data)
{
uint32 NullData;
SSIDataPut(SSI_BASE, data);
SSIDataGet(SSI_BASE, &NullData);
}
/*********************************************************************************************************
** 函数名称: Get_Byte
** 函数功能: 通过硬件SPI接口接收一个字节到处理器
** 入口参数: 无
** 出口参数: 无
** 返回值: ReadData 读回的数据
*********************************************************************************************************/
uint8 Get_Byte(void)
{
uint32 ReadData;
SSIDataPut(SSI_BASE, 0xFF); /* 发送一个无效字节,以产生接收时钟*/
SSIDataGet(SSI_BASE, &ReadData);
return (uint8)ReadData;
}
/************************************************************************
** 函数名称:SSTF016B_RD
** 函数功能:SST25VF016B的读函数,可选择读ID和读数据操作
** 入口参数:
** uint32 Dst:目标地址,范围 0x0 - MAX_ADDR(MAX_ADDR = 0x1FFFFF)
** uint32 NByte: 要读取的数据字节数
** uint8* RcvBufPt:接收缓存的指针
** 出口参数:操作成功则返回OK,失败则返回ERROR
** 注 意:若某功能下,某一入口参数无效,可在该入口参数处填Invalid,该参数将被忽略
************************************************************************/
uint8 SSTF016B_RD(uint32 Dst, uint32 NByte,uint8* RcvBufPt)
{
uint32 i = 0;
if ((Dst+NByte > MAX_ADDR)||(NByte == 0)) return (ERROR); // 检查入口参数
CE_Low();
Send_Byte(0x0B); // 发送读命令
Send_Byte(((Dst & 0xFFFFFF) >> 16)); // 发送地址信息:该地址由3个字节组成
Send_Byte(((Dst & 0xFFFF) >> 8));
Send_Byte(Dst & 0xFF);
Send_Byte(0xFF); // 发送一个哑字节以读取数据
for (i = 0; i < NByte; i++)
{
RcvBufPt[i] = Get_Byte();
}
CE_High();
return (OK);
}
/************************************************************************
** 函数名称:SSTF016B_RdID
** 函数功能:SST25VF016B的读ID函数,可选择读ID和读数据操作
** 入口参数:
** idtype IDType:ID类型。用户可在Jedec_ID,Dev_ID,Manu_ID三者里选择
** uint32* RcvbufPt:存储ID变量的指针
** 出口参数:操作成功则返回OK,失败则返回ERROR
** 注 意:若填入的参数不符合要求,则返回ERROR
************************************************************************/
uint8 SSTF016B_RdID(idtype IDType,uint32* RcvbufPt)
{
uint32 temp = 0;
if (IDType == Jedec_ID)
{
CE_Low();
Send_Byte(0x9F); /* 发送读JEDEC ID命令(9Fh) */
temp = (temp | Get_Byte()) << 8; /* 接收数据 */
temp = (temp | Get_Byte()) << 8;
temp = (temp | Get_Byte()); /* 在本例中,temp的值应为0xBF2541 */
CE_High();
*RcvbufPt = temp;
return (OK);
}
if ((IDType == Manu_ID) || (IDType == Dev_ID) )
{
CE_Low();
Send_Byte(0x90); /* 发送读ID命令 (90h or ABh) */
Send_Byte(0x00); /* 发送地址 */
Send_Byte(0x00); /* 发送地址 */
Send_Byte(IDType); /* 发送地址 - 不是00H就是01H */
temp = Get_Byte(); /* 接收获取的数据字节 */
CE_High();
*RcvbufPt = temp;
return (OK);
}
else
{
return (ERROR);
}
}
/************************************************************************
** 函数名称:SSTF016B_WR
** 函数功能:SST25VF016B的写函数,可写1个和多个数据到指定地址
** 入口参数:
** uint32 Dst:目标地址,范围 0x0 - MAX_ADDR(MAX_ADDR = 0x1FFFFF)
** uint8 SndbufPt:发送的数据
** 出口参数:操作成功则返回OK,失败则返回ERROR
** 注 意:若某功能下,某一入口参数无效,可在该入口参数处填Invalid,该参数将被忽略
************************************************************************/
uint8 SSTF016B_WR(uint32 Dst,uint8 SendData)
{
CE_Low();
Send_Byte(0x06); /* 发送写使能命令 */
CE_High();
CE_Low();
Send_Byte(0x02); /* 发送字节数据烧写命令 */
Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* 发送3个字节的地址信息 */
Send_Byte(((Dst & 0xFFFF) >> 8));
Send_Byte(Dst & 0xFF);
Send_Byte(SendData); /* 发送被烧写的数据 */
CE_High();
return (OK);
}
/*******************************************************************************
** 函数名称:SSTF016B_WRSTART
** 函数功能:SST25VF016B的起始函数
** 入口参数: 无
** 出口参数:操作成功则返回OK,失败则返回ERROR
********************************************************************************/
uint8 SSTF016B_WRSTART()
{
CE_Low();
Send_Byte(0x05); /* 发送读状态寄存器命令 */
/* 保存读得的状态寄存器值 */
CE_High();
CE_Low();
Send_Byte(0x50); /* 使状态寄存器可写 */
CE_High();
CE_Low();
Send_Byte(0x01); /* 发送写状态寄存器指令 */
Send_Byte(0); /* 清0BPx位,使Flash芯片全区可写 */
CE_High();
return (OK);
}
/************************************************************************
** 函数名称:SSTF016B_Erase
** 函数功能:根据指定的扇区号选取最高效的算法擦除
** 入口参数:
** uint32 sec1:起始扇区号,范围(0~499)
** uint32 sec2:终止扇区号,范围(0~499)
** 出口参数:操作成功则返回OK,失败则返回ERROR
************************************************************************/
uint8 SSTF016B_Erase(uint32 sec1, uint32 sec2)
{
uint8 temp1 = 0,temp2 = 0,StatRgVal = 0;
uint32 SecnHdAddr = 0;
uint32 no_SecsToEr = 0; /* 要擦除的扇区数目 */
uint32 CurSecToEr = 0; /* 当前要擦除的扇区号 */
/* 检查入口参数 */
if ((sec1 > SEC_MAX)||(sec2 > SEC_MAX))
{
return (ERROR);
}
CE_Low();
Send_Byte(0x05); /* 发送读状态寄存器命令 */
temp1 = Get_Byte(); /* 保存读得的状态寄存器值 */
CE_High();
CE_Low();
Send_Byte(0x50); /* 使状态寄存器可写 */
CE_High();
CE_Low();
Send_Byte(0x01); /* 发送写状态寄存器指令 */
Send_Byte(0); /* 清0BPx位,使Flash芯片全区可写 */
CE_High();
CE_Low();
Send_Byte(0x06); /* 发送写使能命令 */
CE_High();
/* 如果用户输入的起始扇区号大于终止扇区号,则在内部作出调整 */
if (sec1 > sec2)
{
temp2 = sec1;
sec1 = sec2;
sec2 = temp2;
}
/* 若起止扇区号相等则擦除单个扇区 */
if (sec1 == sec2)
{
SecnHdAddr = SEC_SIZE * sec1; /* 计算扇区的起始地址 */
CE_Low();
Send_Byte(0x20); /* 发送扇区擦除指令 */
Send_Byte(((SecnHdAddr & 0xFFFFFF) >> 16)); /* 发送3个字节的地址信息 */
Send_Byte(((SecnHdAddr & 0xFFFF) >> 8));
Send_Byte(SecnHdAddr & 0xFF);
CE_High();
do
{
CE_Low();
Send_Byte(0x05); /* 发送读状态寄存器命令 */
StatRgVal = Get_Byte(); /* 保存读得的状态寄存器值 */
CE_High();
}
while (StatRgVal == 0x03); /* 一直等待,直到芯片空闲 */
return (OK);
}
/* 根据起始扇区和终止扇区间距调用最快速的擦除功能 */
if (sec2 - sec1 == SEC_MAX)
{
CE_Low();
Send_Byte(0x60); /* 发送芯片擦除指令(60h or C7h) */
CE_High();
do
{
CE_Low();
Send_Byte(0x05); /* 发送读状态寄存器命令 */
StatRgVal = Get_Byte(); /* 保存读得的状态寄存器值 */
CE_High();
}
while (StatRgVal == 0x03); /* 一直等待,直到芯片空闲 */
return (OK);
}
no_SecsToEr = sec2 - sec1 +1; /* 获取要擦除的扇区数目 */
CurSecToEr = sec1; /* 从起始扇区开始擦除 */
/* 若两个扇区之间的间隔够大,则采取16扇区擦除算法 */
while (no_SecsToEr >= 16)
{
SecnHdAddr = SEC_SIZE * CurSecToEr; /* 计算扇区的起始地址 */
CE_Low();
Send_Byte(0xD8); /* 发送64KB块擦除指令 */
Send_Byte(((SecnHdAddr & 0xFFFFFF) >> 16)); /* 发送3个字节的地址信息 */
Send_Byte(((SecnHdAddr & 0xFFFF) >> 8));
Send_Byte(SecnHdAddr & 0xFF);
CE_High();
do
{
CE_Low();
Send_Byte(0x05); /* 发送读状态寄存器命令 */
StatRgVal = Get_Byte(); /* 保存读得的状态寄存器值 */
CE_High();
}
while (StatRgVal == 0x03); /* 一直等待,直到芯片空闲 */
CurSecToEr += 16; /* 计算擦除了16个扇区后,和擦除区域相邻的待擦除扇区号*/
no_SecsToEr -= 16; /* 对需擦除的扇区总数作出调整*/
}
/* 若两个扇区之间的间隔够大,则采取8扇区擦除算法 */
while (no_SecsToEr >= 8)
{
SecnHdAddr = SEC_SIZE * CurSecToEr; /* 计算扇区的起始地址 */
CE_Low();
Send_Byte(0x52); /* 发送32KB擦除指令 */
Send_Byte(((SecnHdAddr & 0xFFFFFF) >> 16)); /* 发送3个字节的地址信息 */
Send_Byte(((SecnHdAddr & 0xFFFF) >> 8));
Send_Byte(SecnHdAddr & 0xFF);
CE_High();
do
{
CE_Low();
Send_Byte(0x05); /* 发送读状态寄存器命令 */
StatRgVal = Get_Byte(); /* 保存读得的状态寄存器值 */
CE_High();
}
while (StatRgVal == 0x03); /* 一直等待,直到芯片空闲 */
CurSecToEr += 8;
no_SecsToEr -= 8;
}
/* 采用扇区擦除算法擦除剩余的扇区 */
while (no_SecsToEr >= 1)
{
SecnHdAddr = SEC_SIZE * CurSecToEr; /* 计算扇区的起始地址 */
CE_Low();
Send_Byte(0x20); /* 发送扇区擦除指令 */
Send_Byte(((SecnHdAddr & 0xFFFFFF) >> 16)); /* 发送3个字节的地址信息 */
Send_Byte(((SecnHdAddr & 0xFFFF) >> 8));
Send_Byte(SecnHdAddr & 0xFF);
CE_High();
do
{
CE_Low();
Send_Byte(0x05); /* 发送读状态寄存器命令 */
StatRgVal = Get_Byte(); /* 保存读得的状态寄存器值 */
CE_High();
}
while (StatRgVal == 0x03); /* 一直等待,直到芯片空闲 */
CurSecToEr += 1;
no_SecsToEr -= 1;
}
/* 擦除结束,恢复状态寄存器信息 */
CE_Low();
Send_Byte(0x06); /* 发送写使能命令 */
CE_High();
CE_Low();
Send_Byte(0x50); /* 使状态寄存器可写 */
CE_High();
CE_Low();
Send_Byte(0x01); /* 发送写状态寄存器指令 */
Send_Byte(temp1); /* 恢复状态寄存器设置信息 */
CE_High();
return (OK);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -