W25Q128的SPI 驱动,没测试。
自己加了点注释和几个函数。
/*****************************************************************************
** 文件名称:flash.h (芯片为W25Q128)
** 功 能:
** 修改日志:
******************************************************************************/
#ifndef __FLASH_H
#define __FLASH_H
typedef unsigned char uint8_t; /* 8 bits */
typedef unsigned short int uint16_t; /* 16 bits */
typedef unsigned int uint32_t; /* 32 bits */
/******************************************************************************
** SPI_FLASH
********************************************************************************/
typedef enum
{
RET_SUCCESS = 0,
RET_FlashRead_ERROR,
RET_WriteCmd_ERROR,
RET_WaitBusy_ERROR
}
}SpiRetValueType;
/*****************************************************************************
** 管脚定义
*****************************************************************************/
#define SPIFlash_Enable_CS (P8OUT &= 0XFE) //CS CS = 1 //打开spiflash片选使能
#define SPIFlash_Disable_CS (P8OUT |= 0X01) //CS CS = 0 //关闭spiflash片选使能
#define SPIFlash_Set_SCLK (P7OUT |= 0X08) //CLK //上升沿写入 ,下降沿输出(读) //拉高spiflash时钟线
#define SPIFlash_Clr_SCLK (P7OUT &= 0Xf7) //CLK //拉低spiflash时钟线
#define SPIFlash_Set_DO (P8OUT |= 0X04) //D0 D0 = 1 //MOSI数据线置1,即输出1高电平
#define SPIFlash_Clr_DO (P8OUT &= 0XFB) //D0 D0 = 0 //MOSI数据线清0,即输出0低电平
/*
#define SPIFlash_Enable_CS 7引脚 = 1 //CS = 1 //打开spiflash片选使能
#define SPIFlash_Disable_CS 7引脚 = 0 //CS CS = 0 //关闭spiflash片选使能
#define SPIFlash_Set_SCLK 16引脚 = 1 //CLK //上升沿写入 ,下降沿输出(读) //拉高spiflash时钟线
#define SPIFlash_Clr_SCLK 16引脚 = 0 //CLK //拉低spiflash时钟线
#define SPIFlash_Set_DO 8引脚 = 1 //D0 D0 = 1 //MOSI数据线置1,即输出1高电平
#define SPIFlash_Clr_DO 8引脚 = 0 //D0 D0 = 0 //MOSI数据线清0,即输出0低电平
*/
#define SPIFlash_Get_DI SPIFlash_GPIO_GetBit()
#define SPIFLASH_CMD_LENGTH 0x03
#define SPIFLASH_WRITE_BUSYBIT 0X01 //状态寄存器Busy位(状态寄存器的0位为 BUSY位)
#define SPIFlash_ReadData_CMD 0x03 //读数据
#define SPIFlash_WriteEnable_CMD 0x06 //写使能 会使“状态寄存器”WEL为置位。在执行“擦除”前,需要置位WEL
#define SPIFlash_WriteDisable_CMD 0x04 //写使能关闭
#define SPIFlash_PageProgram_CMD 0x02 //页编程指令 (页256字节)
#define SPIFlash_WriteSR_CMD 0x01 //写状态寄存器
#define SPIFlash_ReadSR_CMD 0x05 //读状态寄存器 当CS低位,05H送入引脚,在CLK上升沿数据被芯片采集,芯片会把“状态寄存器”的值从DO输出,数据在CLK下降沿输出,高位在前.
#define SPIFlash_SecErase_CMD 0x20 //扇区擦除指令 (一扇区 4K)
#define SPIFlash_BlockErase_CMD 0xD8 //块擦除指令 将一块区(64K)全部变成1,即FFH
#define SPIFlash_ChipeErase_CMD 0xC7 //芯片擦除指令
#define SPIFLASH_ReadChipId_CMD 0x90 //读芯片ID
#define SPIFlash_PAGEBYTE_LENGTH 256
#define SPIFlash_SECBYTE_LENGTH (1024*4)
/*******************************************************************************
** 函数声明
*******************************************************************************/
void SpiFlash_WriteOneByte(uint8_t DataBuffer); //写入Flash一个字节(byte),DataBuffer为要写入的内容
uint8_t SpiFlash_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum);
uint8_t SpiFlash_Write_MorePage(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum);
uint8_t SpiFlash_Write_MoreSector(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum);
void SpiFlash_Write_Sector_Data(char *pBuffer,uint8_t Block_Num,uint8_t Sector_Num,uint32_t WriteBytesNum);
void SpiFlash_Write_Data(char *pBuffer,uint8_t Block_Num,uint8_t Page_Num,uint32_t WriteBytesNum);
uint8_t SpiFlash_ReadOneByte(void); //从Flash读出一个字节(Byte),返回值为 retValue(uint8_t)
uint8_t SpiFlash_Read(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t ReadBytesNum);
void SpiFlash_Read_Data(uint8_t *pBuffer,uint8_t Block_Num ,uint8_t Page_Num ,uint32_t ReadBytesNum);
void SpiFlash_Read_Sector_Data(char *pBuffer,uint8_t Block_Num ,uint8_t Sector_Num,uint32_t ReadBytesNum);
void SPIFlash_Erase_Block(uint8_t BlockNum);
void SPIFlash_Erase_Sector(uint8_t Block_Num,uint8_t Sector_Number);
void SPIFlash_Erase_Chip(void); //擦除整个芯片
void Spi_Flash_Init(void);
uint16_t SPIFlash_GPIO_GetBit(void);
#endif
/*****************************************************************************
** 文件名称:flash.c
** 功 能:
** 修改日志:
******************************************************************************/
#include "includes.h"
/*****************************************************************************
** 文件名称:uint8_t SpiFlash_ReadOneByte(void)
** 功 能:从Flash读出一个字节(Byte),返回值为 retValue(uint8_t)
** 修改日志:
** 附 录:先把CLK = 1 ,CLK = 0 下降沿 读取
******************************************************************************/
uint8_t SpiFlash_ReadOneByte(void)
{
uint8_t BitCount = 0;
uint8_t retValue = 0;
SPIFlash_Set_SCLK; //时钟线拉高,恢复时钟线为高电平 cs = 1
for(BitCount = 0;BitCount < 8; BitCount++)
{
retValue <<= 1;
SPIFlash_Set_SCLK; //时钟线拉高,恢复时钟线为高电平
if(SPIFlash_Get_DI)
{
retValue |= 0x01;
}
else
{
retValue &= 0xFE;
}
SPIFlash_Clr_SCLK; //时钟线拉低,产生下降沿读出数据 // cs = 0 产生下降沿 读出数据
}
SPIFlash_Set_SCLK;
return (retValue);
}
/*****************************************************************************
** 文件名称:void SpiFlash_WriteOneByte(uint8_t DataBuffer)
** 功 能:写入Flash一个字节(byte),DataBuffer为要写入的内容
** 修改日志:
** 附 录:先把CS拉低(拉低选中)CS = 0 设备被选中,可以写入和读取
******************************************************************************/
void SpiFlash_WriteOneByte(uint8_t DataBuffer)
{
uint8_t BitCount = 0;
SPIFlash_Clr_SCLK; //时钟线拉低,恢复时钟线为低电平
for(BitCount = 0;BitCount < 8; BitCount++)
{
SPIFlash_Clr_SCLK; //时钟线拉低,恢复时钟线为低电平
if(DataBuffer & 0x80)
{
SPIFlash_Set_DO; //MOSI数据线置1,即输出1高电平
}
else
{
SPIFlash_Clr_DO;
}
DataBuffer <<= 1;
SPIFlash_Set_SCLK; //时钟线拉高,产生上升沿写入数据
}
SPIFlash_Clr_SCLK;
SPIFlash_Set_DO; //一字节数据传送完毕,MOSI数据线置高表示空闲状态
}
/*****************************************************************************
** 文件名称:static uint8_t SpiFlash_Write_CMD(uint8_t *CMD)
** 功 能:写入 “读数据” 命令
** 修改日志:
** 附 录:当CS拉低之后,把03H从DI引脚输入到Flash芯片,之后送入24位地址,这些数据在CLK上升沿,数据写入Flash。当芯片接收完24位地址后,会把相应地址的数据,在CLK的下降沿输出,
从DO输出。高位在前。当读完这个数据后,地址自动增加,然后通过DO引脚把下一个地址的数据送出,形成一个数据流。因此,只要时钟在工作,通过一条读指令就能把整个芯片的存储器
读出来。
CS拉高,“读数据”指令结束。
******************************************************************************/
static uint8_t SpiFlash_Write_CMD(uint8_t *CMD)
{
uint32_t i = 0;
for(i = 0;i < SPIFLASH_CMD_LENGTH; i++)
{
SpiFlash_WriteOneByte(CMD[i]); //打开SD卡的片选信号并写入命令数据
}
return RET_SUCCESS;
}
/*****************************************************************************
** 文件名称:static uint8_t SpiFlash_ReadSR(void)
** 功 能:“读状态寄存器”命令,retValue为读到的数值
** 修改日志:
** 附 录:当CS拉低之后,把05H从DI引脚输入到Flash芯片,CLK上升沿,数据写入Flash,当Flash收到05H后,会把“状态寄存器”的值,从D0引脚输出,CLK下降沿输出。
******************************************************************************/
static uint8_t SpiFlash_ReadSR(void)
{
uint8_t retValue = 0;
SPIFlash_Enable_CS; //CS使能
SpiFlash_WriteOneByte(SPIFlash_ReadSR_CMD);
retValue = SpiFlash_ReadOneByte();
SPIFlash_Disable_CS;//CS关闭
return retValue;
}
/*****************************************************************************
** 文件名称:static uint8_t SpiFlash_Wait_Busy(void)
** 功 能:判断Flash是否busy。
** 修改日志:
:SPIFLASH_WRITE_BUSYBIT 写状态寄存器
******************************************************************************/
static uint8_t SpiFlash_Wait_Busy(void)
{
sDelayT.cDelay_Count=0;
while((SpiFlash_ReadSR()&SPIFLASH_WRITE_BUSYBIT) == 0X01) //状态寄存器0位为Busy位
{
if(sDelayT.cDelay_Count==100)
break;
}
return RET_SUCCESS;
}
/*****************************************************************************
** 文件名称:uint8_t SpiFlash_Read(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t ReadBytesNum)
** 功 能:读Flash的某地址ReadAddr,读多大ReadByteNum,的数值。
** 修改日志:
******************************************************************************/
uint8_t SpiFlash_Read(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t ReadBytesNum)
{
uint32_t i = 0;
uint8_t pcmd[SPIFLASH_CMD_LENGTH] = {0};
uint8_t ret = 0;
SPIFlash_Enable_CS; //打开CS spiflash片选
SpiFlash_WriteOneByte(SPIFlash_ReadData_CMD);
pcmd[0] = (uint8_t)((ReadAddr&0x00ff0000)>>16);
pcmd[1] = (uint8_t)((ReadAddr&0x0000ff00)>>8);
pcmd[2] = (uint8_t)ReadAddr;
/*
// send cmd
BSP_SpiWriteByte(FLASH_CMD_CARLF);
BSP_SpiWriteByte((FlashAdr>>16) & 0xFF);
BSP_SpiWriteByte((FlashAdr>>8) & 0xFF);
BSP_SpiWriteByte(FlashAdr & 0xFF);
*/
ret = SpiFlash_Write_CMD(pcmd);
if(ret != RET_SUCCESS)
{
return RET_WriteCmd_ERROR;
}
for(i = 0;i < ReadBytesNum; i++)
{
pBuffer[i] = SpiFlash_ReadOneByte(); //读取SPIflash中指定bytes字节数据
}
SPIFlash_Disable_CS; //关闭CS spiflash片选
return RET_SUCCESS;
}
/*****************************************************************************
** 文件名称:static void SpiFlash_Write_Enable(void)
** 功 能:
** 修改日志:
SPIFlash_WriteEnable_CMD 写使能 会使“状态寄存器”WEL为置位。在执行“擦除”前,需要置位WEL。
******************************************************************************/
static void SpiFlash_Write_Enable(void)
{
SPIFlash_Enable_CS;
SpiFlash_WriteOneByte(SPIFlash_WriteEnable_CMD);
SPIFlash_Disable_CS;
}
/*****************************************************************************
** 文件名称: void SPIFlash_Erase_Sector(uint8_t Block_Num,uint8_t Sector_Number)
** 功 能: 擦除扇区 擦除某块Block,某扇区Sector
** 修改日志:
** 附 录: SPIFlash_SecErase_CMD 扇区擦除指令,将一个扇区(4k)擦除。擦除后都为1,扇区字节都为FFH。在执行“扇区擦除”前,需执行“写指令”
SpiFlash_Write_Enable(),然后拉低CS,写入擦除命令,然后把24位扇区地址写入芯片。然后拉高CS。在执行命令期间,BUSY位为1。执行完,
BUSY位为0,WEL为0。
******************************************************************************/
void SPIFlash_Erase_Sector(uint8_t Block_Num,uint8_t Sector_Number)
{
uint8_t pcmd[3] = {0};
SpiFlash_Write_Enable();
SPIFlash_Enable_CS;
SpiFlash_WriteOneByte(SPIFlash_SecErase_CMD);
pcmd[0] = Block_Num;
pcmd[1] = Sector_Number<<4;
pcmd[2] = 0;
SpiFlash_Write_CMD(pcmd);
SPIFlash_Disable_CS;
SpiFlash_Wait_Busy(); //每次擦除数据都要延时等待写入结束
return ;
}
/*****************************************************************************
** 文件名称:uint8_t SpiFlash_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
** 功 能:从pBuffer内,向某页上的一地址的写入数据
** 修改日志:
** 附 加:一页大小 256 bytes(a page)
******************************************************************************/
uint8_t SpiFlash_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
{
uint32_t i = 0;
uint8_t pcmd[SPIFLASH_CMD_LENGTH] = {0};
uint8_t ret = 0;
SpiFlash_Write_Enable();
SPIFlash_Enable_CS;
SpiFlash_WriteOneByte(SPIFlash_PageProgram_CMD);
pcmd[0] = (uint8_t)((WriteAddr&0x00ff0000)>>16);
pcmd[1] = (uint8_t)((WriteAddr&0x0000ff00)>>8);
pcmd[2] = (uint8_t)WriteAddr;
ret = SpiFlash_Write_CMD(pcmd);
if(ret != RET_SUCCESS)
{
return RET_WriteCmd_ERROR;
}
for(i = 0;i < WriteBytesNum; i++)
{
SpiFlash_WriteOneByte(pBuffer[i]); //向SPIflash中写入最大一页256bytes字节数据
}
SPIFlash_Disable_CS;
ret = SpiFlash_Wait_Busy(); //每次写入一定数量的数据都要延时等待写入结束
if(ret != RET_SUCCESS)
return RET_WaitBusy_ERROR;
return RET_SUCCESS;
}
/*****************************************************************************
** 文件名称:uint8_t SpiFlash_Write_MorePage(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
** 功 能:pBuffer数据存储器,WriteAddr开始写入的地址(24bit),要写入的字节数WriteBytesNum(最大65536)
** 修改日志:
******************************************************************************/
uint8_t SpiFlash_Write_MorePage(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
{
uint16_t PageByteRemain = 0;
PageByteRemain = SPIFlash_PAGEBYTE_LENGTH - WriteAddr%SPIFlash_PAGEBYTE_LENGTH;//单页剩余的字节数
if(WriteBytesNum <= PageByteRemain)//不大于256个字节
{
PageByteRemain = WriteBytesNum;
}
while(1)
{
SpiFlash_Write_Page(pBuffer,WriteAddr,PageByteRemain);
if(WriteBytesNum == PageByteRemain) //写入结束
{
break;
}
else
{
pBuffer += PageByteRemain;
WriteAddr += PageByteRemain;
WriteBytesNum -= PageByteRemain; //减去已经写入的字节数
if(WriteBytesNum > SPIFlash_PAGEBYTE_LENGTH) //一次可以写入256个字节
{
PageByteRemain = SPIFlash_PAGEBYTE_LENGTH;
}
else //不够256个字节
{
PageByteRemain = WriteBytesNum;
}
}
}
return RET_SUCCESS;
}
//
///*****************************************************************************
//** 文件名称:uint8_t SpiFlash_Write_MoreSector(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
//** 功 能:pBuffer数据存储器,WriteAddr开始写入的地址(24bit),要写入的字节数WriteBytesNum(最大65536).以扇区为单位写入。
//** 修改日志:
//******************************************************************************/
//uint8_t SpiFlash_Write_MoreSector(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t WriteBytesNum)
//{
// uint32_t Secpos = 0;
// uint16_t Secoff = 0;
// uint16_t Secremain = 0;
// uint32_t i = 0;
// uint8_t SPIBufferTemp[SPIFlash_SECBYTE_LENGTH] = {0}; //SPIFlash_SECBYTE_LENGTH 4096
// Secpos = WriteAddr/SPIFlash_SECBYTE_LENGTH;//扇区地址
// Secoff = WriteAddr%SPIFlash_SECBYTE_LENGTH; //扇区内偏移量
// Secremain = SPIFlash_SECBYTE_LENGTH - Secoff;//扇区剩余空间
// if(WriteBytesNum <= Secremain)
// {
// Secremain = WriteBytesNum;
// }
//
// while(1)
// {
// if(SpiFlash_Read(SPIBufferTemp,Secpos*SPIFlash_SECBYTE_LENGTH,SPIFlash_SECBYTE_LENGTH) != RET_SUCCESS) //读出整个扇区内容
// {
// return RET_FlashRead_ERROR;
// }
// for(i = 0;i < Secremain;i++) //检验数据
// {
// if(SPIBufferTemp[Secoff+i] != 0xFF)
// break; //需要擦除一个扇区
// }
// if(i < Secremain) //需要擦除一个扇区
// {
// SPIFlash_Erase_Sector(Secpos); //擦除这个扇区
// for(i = 0;i < Secremain;i++) //复制
// {
// SPIBufferTemp[i+Secoff] = pBuffer[i];
// }
// SpiFlash_Write_MorePage(SPIBufferTemp,Secpos*SPIFlash_SECBYTE_LENGTH,SPIFlash_SECBYTE_LENGTH); //写入整个扇区
// }
// else
// {
// SpiFlash_Write_MorePage(pBuffer,WriteAddr,Secremain);//写已经擦除的了的,直接写入扇区剩余的空间
// }
//
// if(WriteBytesNum == Secremain) //写入结束
// {
// break;
// }
// else
// {
// Secpos++;//扇区地址增1
// Secoff = 0;//偏移位置为0
// pBuffer += Secremain;//指针偏移
// WriteAddr += Secremain;//便宜位置为0
// WriteBytesNum -=Secremain;//字节数递减
// if(WriteBytesNum > SPIFlash_SECBYTE_LENGTH) //下一个扇区还没写完
// {
// Secremain = SPIFlash_SECBYTE_LENGTH;
// }
// else//下一个扇区写完
// {
// Secremain = WriteBytesNum;
// }
// }
// }
// return RET_SUCCESS;
//}
//
/*****************************************************************************
** 文件名称:uint16_t SPIFlash_GPIO_GetBit(void)
** 功 能:
** 修改日志:
******************************************************************************/
uint16_t SPIFlash_GPIO_GetBit(void)
{
uint16_t retValue = 0;
uint16_t valueTemp = 0;
valueTemp = P8IN;
retValue = (valueTemp &= BIT1)>>0x01; //BIT1即是0x02
return retValue;
}
/*****************************************************************************
** 文件名称:void SPIFlash_Erase_Block(uint8_t BlockNum)
** 功 能:擦除BLOCK
** 修改日志:
******************************************************************************/
void SPIFlash_Erase_Block(uint8_t BlockNum)
{
uint8_t pcmd[3] = {0};
SpiFlash_Write_Enable(); //写使能
SPIFlash_Enable_CS; //片选拉低
SpiFlash_WriteOneByte(SPIFlash_BlockErase_CMD); //传输Block擦除指令
pcmd[0] =BlockNum ; //传24位地址 因为单片机为16位 所以分两次传
SpiFlash_Write_CMD(pcmd);
SPIFlash_Disable_CS;
SpiFlash_Wait_Busy(); //每次擦除数据都要延时等待写入结束
return ;
}
/*****************************************************************************
** 文件名称:void SPIFlash_Erase_Chip(void)
** 功 能:擦除整个芯片
** 修改日志:
******************************************************************************/
void SPIFlash_Erase_Chip(void)
{
SpiFlash_Write_Enable(); //写使能
SpiFlash_Wait_Busy();
SPIFlash_Enable_CS; //片选拉低
SpiFlash_WriteOneByte(SPIFlash_ChipeErase_CMD); //传输Block擦除指令
SPIFlash_Disable_CS;
SpiFlash_Wait_Busy();
}
/*****************************************************************************
** 文件名称:uint8_t SpiFlash_Write_Data(uint8_t *pBuffer,uint8_t Block_Num,int8_t Page_Num,uint32_t WriteBytesNum)
** 功 能:写哪个块中哪一页的数据
** 修改日志:
******************************************************************************/
void SpiFlash_Write_Data(char *pBuffer,uint8_t Block_Num,uint8_t Page_Num,uint32_t WriteBytesNum)
{
uint8_t pcmd[3] = {0};
SpiFlash_Write_Enable();
SPIFlash_Enable_CS;
SpiFlash_WriteOneByte(SPIFlash_PageProgram_CMD);
pcmd[0] = Block_Num;
pcmd[1] = Page_Num;
pcmd[2] = 0;
SpiFlash_Write_CMD(pcmd);
for(uint32_t i = 0;i < WriteBytesNum; i++)
{
SpiFlash_WriteOneByte(pBuffer[i]); //向SPIflash中写入最大一页256bytes字节数据
}
SPIFlash_Disable_CS;
SpiFlash_Wait_Busy(); //每次写入一定数量的数据都要延时等待写入结束
return ;
}
/*****************************************************************************
** 文件名称:void SpiFlash_Write_Sector_Data(uint8_t *pBuffer,uint8_t Block_Num,int8_t Sector_Num,uint32_t WriteBytesNum)
** 功 能:写扇区数据
** 修改日志:
******************************************************************************/
void SpiFlash_Write_Sector_Data(char *pBuffer,uint8_t Block_Num,uint8_t Sector_Num,uint32_t WriteBytesNum)
{
uint8_t Write_Page_Num=0;
Write_Page_Num = WriteBytesNum/256;
if((WriteBytesNum%256)!=0) Write_Page_Num+=1;
for(uint8_t i=0;i<Write_Page_Num;i++)
{
SpiFlash_Write_Data(pBuffer,Block_Num,i+(Sector_Num<<4),256);
pBuffer=pBuffer+256;
}
return ;
}
/*****************************************************************************
** 文件名称:void SpiFlash_Read_Sector_Data(uint8_t *pBuffer,uint8_t Block_Num ,uint8_t Sector_Num ,uint32_t ReadBytesNum)
** 功 能:读扇区数据
** 修改日志:
******************************************************************************/
void SpiFlash_Read_Sector_Data(char *pBuffer,uint8_t Block_Num ,uint8_t Sector_Num,uint32_t ReadBytesNum)
{
uint32_t i = 0;
uint8_t pcmd[SPIFLASH_CMD_LENGTH] = {0};
SPIFlash_Enable_CS; //打开spiflash片选
SpiFlash_WriteOneByte(SPIFlash_ReadData_CMD);
pcmd[0] =Block_Num ;
pcmd[1] =Sector_Num<<4;
pcmd[2] = 0;
SpiFlash_Write_CMD(pcmd);
for(i = 0;i < ReadBytesNum; i++)
{
pBuffer[i] = SpiFlash_ReadOneByte(); //读取SPIflash中指定bytes字节数据
}
SPIFlash_Disable_CS;
return ;
}
/*****************************************************************************
** 文件名称:uint8_t SpiFlash_Read_Data(uint8_t *pBuffer,uint8_t Block_Num ,uint8_t Page_Num ,uint32_t ReadBytesNum)
** 功 能:
** 修改日志:
******************************************************************************/
void SpiFlash_Read_Data(uint8_t *pBuffer,uint8_t Block_Num ,uint8_t Page_Num ,uint32_t ReadBytesNum)
{
uint8_t pcmd[SPIFLASH_CMD_LENGTH] = {0};
SPIFlash_Enable_CS; //打开spiflash片选
SpiFlash_WriteOneByte(SPIFlash_ReadData_CMD);
pcmd[0] =Block_Num ;
pcmd[1] =Page_Num ;
pcmd[2] = 0;
SpiFlash_Write_CMD(pcmd);
for(uint32_t i = 0 ;i < ReadBytesNum; i++)
{
pBuffer[i] = SpiFlash_ReadOneByte(); //读取SPIflash中指定bytes字节数据
}
SPIFlash_Disable_CS;
return ;
}
/*****************************************************************************
** 文件名称:uint8_t SpiFlash_Read_Data(uint8_t *pBuffer,uint8_t Block_Num ,uint8_t Page_Num ,uint32_t ReadBytesNum)
** 功 能:
** 修改日志:
******************************************************************************/
SPIFLASH_ReadChipId_CMD
uint16_t SpiFlash_ReadChipId(void)
{
uint16_t Temp = 0;
SPIFlash_Enable_CS; //cs = 0
SpiFlash_WriteOneByte(SPIFLASH_ReadChipId_CMD);
SpiFlash_WriteOneByte(0x00);
SpiFlash_WriteOneByte(0x00);
SpiFlash_WriteOneByte(0x00);
Temp |= SpiFlash_ReadOneByte(0xFF)<<8;
Temp |= SpiFlash_ReadOneByte(0xFF);
SPIFlash_Disable_CS;
return Temp;
}
/*******************************************************************************
** 函数名称:void Spi_Flash_init(void)
** 功 能:
** 修改日志:
*******************************************************************************/
void Spi_Flash_Init(void)
{
P7DIR &= 0XF7; //设置P7.3为IO模式
P7DIR |= 0x08; //设置CLK引脚为强输出模式
P8SEL &= 0XF8; //设置P8.0,P8.1,P8.2为IO模式
P8DIR &= 0XFD; //设置MCU端的DI为输入模式
P8DIR |= 0X05; //设置MCU端的CS#,DO为强输出模式
P8REN &= 0XFD; //设为不用上拉电阻和下拉电阻的普通输入模式
P8OUT |=BIT0; //根据芯片数据手册 cs脚需上拉(因硬件上没有所以这用软件)
}
#if 0
void Spi_Flash_Init(void)
{
SPIFlash_Disable_CS;
}
#endif