#include "W25Q64.h"
void W25Q64_Config(void)
{
W25Q64_CS_OUT_H();
}
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] W25164C在发送数据的同时接收指定长度的数据
* @param dat —— 接收数据缓冲区首地址
* @param recv_buf —— 接收数据缓冲区首地址
* @param —— 要发送/接收数据的字节数
* @retval 成功返回HAL_OK
*/
uint8_t SPI_FLASH_SendByte(uint8_t byte)
{
uint8_t recv_buf = 0;
HAL_SPI_TransmitReceive(&hspi1, &byte, &recv_buf, 1, 10000);
return recv_buf;
}
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] 读取FLASH Device ID
* @param 无
* @retval FLASH Device ID
*/
uint32_t SPI_FLASH_ReadDeviceID(void)
{
uint32_t flash_id;
//使能W25Q64_CS,拉低CS
W25Q64_CS_OUT_L();
SPI_FLASH_SendByte(W25X_JedecDeviceID);
//SPI_Receive(recv_buf,3);
flash_id=SPI_FLASH_SendByte(Dummy_Byte);
flash_id <<=8;
flash_id|=SPI_FLASH_SendByte(Dummy_Byte);
flash_id <<=8;
flash_id|=SPI_FLASH_SendByte(Dummy_Byte);
//W25Q64_CS,拉高CS
W25Q64_CS_OUT_H();
return flash_id;
}
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] 擦除FLASH扇区
* @param SectorAddr:要擦除的扇区地址
* @retval 无
*/
void SPI_FLASH_SectorErase(uint32_t SectorAddr)
{
/* 发送FLASH写使能命令 */
SPI_FLASH_WriteEnable();
SPI_FLASH_WaitForWriteEnd();
//使能W25Q64_CS,拉低CS
W25Q64_CS_OUT_L();
SPI_FLASH_SendByte(W25X_SectorErase);
/** 发送地址 **/
SPI_FLASH_SendByte((SectorAddr>>16)&0xff);
SPI_FLASH_SendByte((SectorAddr>>8)&0xff);
SPI_FLASH_SendByte((SectorAddr)&0xff);
//W25Q64_CS,拉高CS
W25Q64_CS_OUT_H();
SPI_FLASH_WaitForWriteEnd();
}
/**
* @brief 等待WIP(BUSY)标志被置0,即等待到FLASH内部数据写入完毕
* @param none
* @retval none
*/
void SPI_FLASH_WaitForWriteEnd(void)
{
uint8_t status_reg=0;
//使能W25Q64_CS,拉低CS
W25Q64_CS_OUT_L();
SPI_FLASH_SendByte(W25X_ReadStatusReg);
do
{
status_reg = SPI_FLASH_SendByte(Dummy_Byte);
}while((status_reg & 0x01)== 1); //
//W25Q64_CS,拉高CS
W25Q64_CS_OUT_H();
}
/**
* @brief 读取FLASH数据
* @param pBuffer,存储读出数据的指针
* @param ReadAddr,读取地址
* @param NumByteToRead,读取数据长度
* @retval 无
*/
void SPI_FLASH_BufferRead(uint32_t ReadAddr,uint8_t* pBuffer, uint16_t NumByteToRead)
{
//使能W25Q64_CS,拉低CS
W25Q64_CS_OUT_L();
SPI_FLASH_SendByte(W25X_ReadData);
/** 发送地址 **/
SPI_FLASH_SendByte((ReadAddr>>16)&0xff);
SPI_FLASH_SendByte((ReadAddr>>8)&0xff);
SPI_FLASH_SendByte((ReadAddr)&0xff);
while(NumByteToRead--)
{
*pBuffer = SPI_FLASH_SendByte(Dummy_Byte);
pBuffer++;
}
//W25Q64_CS,拉高CS
W25Q64_CS_OUT_H();
}
/**
* @brief 向FLASH发送 写使能 命令
* @param none
* @retval none
*/
void SPI_FLASH_WriteEnable(void)
{
//使能W25Q64_CS,拉低CS
W25Q64_CS_OUT_L();
SPI_FLASH_SendByte(W25X_WriteEnable);
//W25Q64_CS,拉高CS
W25Q64_CS_OUT_H();
}
/**
* @brief 对FLASH按页写入数据,调用本函数写入数据前需要先擦除扇区
* @param pBuffer,要写入数据的指针
* @param WriteAddr,写入地址
* @param NumByteToWrite,写入数据长度,必须小于等于SPI_FLASH_PerWritePageSize
* @retval 无
*/
void SPI_FLASH_PageWrite( uint32_t WriteAddr,uint8_t* pBuffer, uint16_t NumByteToWrite)
{
/* 发送FLASH写使能命令 */
SPI_FLASH_WriteEnable();
//使能W25Q64_CS,拉低CS
W25Q64_CS_OUT_L();
SPI_FLASH_SendByte(W25X_PageProgram);
/** 发送地址 **/
SPI_FLASH_SendByte((WriteAddr>>16)&0xff);
SPI_FLASH_SendByte((WriteAddr>>8)&0xff);
SPI_FLASH_SendByte((WriteAddr)&0xff);
while(NumByteToWrite--)
{
SPI_FLASH_SendByte(*pBuffer);
pBuffer++;
}
//W25Q64_CS,拉高CS
W25Q64_CS_OUT_H();
/* 等待写入完毕*/
SPI_FLASH_WaitForWriteEnd();
}
/**
* @brief 对FLASH写入数据,调用本函数写入数据前需要先擦除扇区
* @param pBuffer,要写入数据的指针
* @param WriteAddr,写入地址
* @param NumByteToWrite,写入数据长度
* @retval 无
*/
void SPI_FLASH_BufferWrite( uint32_t WriteAddr,uint8_t* pBuffer, uint16_t NumByteToWrite)
{
uint8_t addr=0,NumOfPage = 0, NumOfSingle = 0,count = 0,temp = 0;
/*mod运算求余,若writeAddr是SPI_FLASH_PageSize(256)整数倍,运算结果Addr值为0*/
addr = WriteAddr%SPI_FLASH_PageSize;
/*差count个数据值,刚好可以对齐到页地址*/
count = SPI_FLASH_PageSize - addr;
/*计算出要写多少整数页*/
NumOfPage = NumByteToWrite /SPI_FLASH_PageSize;
/*mod运算求余,计算出剩余不满一页的字节数*/
NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
/* addr=0,则WriteAddr 刚好按页对齐 aligned */
if(addr==0)
{
/* NumByteToWrite < SPI_FLASH_PageSize 数据长度小于256,直接写入*/
if(NumOfPage == 0)
{
SPI_FLASH_PageWrite(WriteAddr,pBuffer,NumByteToWrite);
}
else/* NumByteToWrite > SPI_FLASH_PageSize数据长度大于256, */
{
/*先把整数页都写了*/
while(NumOfPage--)
{
SPI_FLASH_PageWrite(WriteAddr,pBuffer,SPI_FLASH_PageSize);
WriteAddr+= SPI_FLASH_PageSize;
pBuffer += SPI_FLASH_PageSize;
}
if(NumOfSingle != 0)
{
/*若有多余的不满一页的数据,把它写完*/
SPI_FLASH_PageWrite(WriteAddr,pBuffer,NumOfSingle);
}
}
}
/* 若地址与 SPI_FLASH_PageSize 不对齐 */
else
{
/* NumByteToWrite < SPI_FLASH_PageSize数据长度小于256,直接写入 */
if(NumOfPage == 0)
{
/*当前页剩余的count个位置比NumOfSingle小,一页写不完*/
if (NumOfSingle > count)
{
temp = NumOfSingle - count;
/*先写满当前页*/
SPI_FLASH_PageWrite( WriteAddr,pBuffer, count);
WriteAddr += count;
pBuffer += count;
/*再写剩余的数据*/
SPI_FLASH_PageWrite(WriteAddr,pBuffer,temp);
}
else /*当前页剩余的count个位置能写完NumOfSingle个数据*/
{
SPI_FLASH_PageWrite(WriteAddr,pBuffer, NumByteToWrite);
}
}
/* NumByteToWrite > SPI_FLASH_PageSize 数据长度大于256*/
else
{
/*地址不对齐多出的count分开处理,不加入这个运算*/
NumByteToWrite -= count;
NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;
NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
/* 先写完count个数据,为的是让下一次要写的地址对齐 */
SPI_FLASH_PageWrite( WriteAddr,pBuffer, count);
/* 接下来就重复地址对齐的情况 */
WriteAddr += count;
pBuffer += count;
/*把整数页都写了*/
while (NumOfPage--)
{
SPI_FLASH_PageWrite(WriteAddr,pBuffer, SPI_FLASH_PageSize);
WriteAddr += SPI_FLASH_PageSize;
pBuffer += SPI_FLASH_PageSize;
}
/*若有多余的不满一页的数据,把它写完*/
if (NumOfSingle != 0)
{
SPI_FLASH_PageWrite( WriteAddr,pBuffer, NumOfSingle);
}
}
}
}
/***********************end***************************************/