STM32基于HAL库W25Q128驱动程序
在头文件中简单修改一下片选引脚IO即可使用。
源文件
#include "w25qxx.h"
#include "spi.h"
uint16_t W25QXX_TYPE = 0;
uint32_t W25QXX_SIZE = 0;
uint8_t W25QXX_UID[8];
static void delay_us(uint32_t us)
{
uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);
while (delay--)
{
;
}
}
static uint8_t W25QXX_SPI_ReadWriteByte(uint8_t TxData)
{
uint8_t RxData = 0X00;
if(HAL_SPI_TransmitReceive(W25QXX_SPI_Handle, &TxData, &RxData, 1, 10) != HAL_OK)
{
RxData = 0XFF;
}
return RxData;
}
int W25QXX_Init(void)
{
MX_SPI1_Init();
W25QXX_CS_L();
W25QXX_SPI_ReadWriteByte(0XFF);
W25QXX_CS_H();
W25QXX_TYPE = W25QXX_ReadID();
W25QXX_SIZE = W25QXX_ReadCapacity();
W25QXX_ReadUniqueID(W25QXX_UID);
if((W25QXX_TYPE & 0XEF00) != 0XEF00)
{
return -1;
}
return 0;
}
uint8_t W25QXX_ReadSR(void)
{
uint8_t byte = 0;
W25QXX_CS_L();
W25QXX_SPI_ReadWriteByte(W25X_ReadStatusReg);
byte = W25QXX_SPI_ReadWriteByte(0Xff);
W25QXX_CS_H();
return byte;
}
void W25QXX_Write_SR(uint8_t sr)
{
W25QXX_CS_L();
W25QXX_SPI_ReadWriteByte(W25X_WriteStatusReg);
W25QXX_SPI_ReadWriteByte(sr);
W25QXX_CS_H();
}
void W25QXX_Write_Enable(void)
{
W25QXX_CS_L();
W25QXX_SPI_ReadWriteByte(W25X_WriteEnable);
W25QXX_CS_H();
}
void W25QXX_Write_Disable(void)
{
W25QXX_CS_L();
W25QXX_SPI_ReadWriteByte(W25X_WriteDisable);
W25QXX_CS_H();
}
uint16_t W25QXX_ReadID(void)
{
uint16_t Temp = 0;
W25QXX_CS_L();
W25QXX_SPI_ReadWriteByte(0x90);
W25QXX_SPI_ReadWriteByte(0x00);
W25QXX_SPI_ReadWriteByte(0x00);
W25QXX_SPI_ReadWriteByte(0x00);
Temp |= W25QXX_SPI_ReadWriteByte(0xFF) << 8;
Temp |= W25QXX_SPI_ReadWriteByte(0xFF);
W25QXX_CS_H();
return Temp;
}
uint32_t W25QXX_ReadCapacity(void)
{
int i = 0;
uint8_t arr[4] = {0,0,0,0};
W25QXX_CS_L();
W25QXX_SPI_ReadWriteByte(0x5A);
W25QXX_SPI_ReadWriteByte(0x00);
W25QXX_SPI_ReadWriteByte(0x00);
W25QXX_SPI_ReadWriteByte(0x84);
W25QXX_SPI_ReadWriteByte(0x00);
for(i = 0; i < sizeof(arr); i++)
{
arr[i] = W25QXX_SPI_ReadWriteByte(0xFF);
}
W25QXX_CS_H();
return ((((*(uint32_t *)arr)) + 1) >> 3);
}
void W25QXX_ReadUniqueID(uint8_t UID[8])
{
int i = 0;
W25QXX_CS_L();
W25QXX_SPI_ReadWriteByte(0x4B);
W25QXX_SPI_ReadWriteByte(0x00);
W25QXX_SPI_ReadWriteByte(0x00);
W25QXX_SPI_ReadWriteByte(0x00);
W25QXX_SPI_ReadWriteByte(0x00);
for(i = 0; i < 8; i++)
{
UID[i] = W25QXX_SPI_ReadWriteByte(0xFF);
}
W25QXX_CS_H();
}
void W25QXX_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
uint16_t i;
W25QXX_CS_L();
W25QXX_SPI_ReadWriteByte(W25X_ReadData);
W25QXX_SPI_ReadWriteByte((uint8_t)((ReadAddr) >> 16));
W25QXX_SPI_ReadWriteByte((uint8_t)((ReadAddr) >> 8));
W25QXX_SPI_ReadWriteByte((uint8_t)ReadAddr);
for (i = 0; i < NumByteToRead; i++)
{
pBuffer[i] = W25QXX_SPI_ReadWriteByte(0XFF);
}
W25QXX_CS_H();
}
void W25QXX_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
uint16_t i;
W25QXX_Write_Enable();
W25QXX_CS_L();
W25QXX_SPI_ReadWriteByte(W25X_PageProgram);
W25QXX_SPI_ReadWriteByte((uint8_t)((WriteAddr) >> 16));
W25QXX_SPI_ReadWriteByte((uint8_t)((WriteAddr) >> 8));
W25QXX_SPI_ReadWriteByte((uint8_t)WriteAddr);
for (i = 0; i < NumByteToWrite; i++)
W25QXX_SPI_ReadWriteByte(pBuffer[i]);
W25QXX_CS_H();
W25QXX_Wait_Busy();
}
void W25QXX_Write_NoCheck(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
uint16_t pageremain;
pageremain = 256 - WriteAddr % 256;
if (NumByteToWrite <= pageremain)
pageremain = NumByteToWrite;
while (1)
{
W25QXX_Write_Page(pBuffer, WriteAddr, pageremain);
if (NumByteToWrite == pageremain)
break;
else
{
pBuffer += pageremain;
WriteAddr += pageremain;
NumByteToWrite -= pageremain;
if (NumByteToWrite > 256)
pageremain = 256;
else
pageremain = NumByteToWrite;
}
};
}
uint8_t W25QXX_BUFFER[4096];
void W25QXX_Write(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
uint32_t secpos;
uint16_t secoff;
uint16_t secremain;
uint16_t i;
uint8_t *W25QXX_BUF;
W25QXX_BUF = W25QXX_BUFFER;
secpos = WriteAddr / 4096;
secoff = WriteAddr % 4096;
secremain = 4096 - secoff;
if (NumByteToWrite <= secremain)
secremain = NumByteToWrite;
while (1)
{
W25QXX_Read(W25QXX_BUF, secpos * 4096, 4096);
for (i = 0; i < secremain; i++)
{
if (W25QXX_BUF[secoff + i] != 0XFF)
break;
}
if (i < secremain)
{
W25QXX_Erase_Sector(secpos);
for (i = 0; i < secremain; i++)
{
W25QXX_BUF[i + secoff] = pBuffer[i];
}
W25QXX_Write_NoCheck(W25QXX_BUF, secpos * 4096, 4096);
}
else
W25QXX_Write_NoCheck(pBuffer, WriteAddr, secremain);
if (NumByteToWrite == secremain)
break;
else
{
secpos++;
secoff = 0;
pBuffer += secremain;
WriteAddr += secremain;
NumByteToWrite -= secremain;
if (NumByteToWrite > 4096)
secremain = 4096;
else
secremain = NumByteToWrite;
}
};
}
void W25QXX_Erase_Chip(void)
{
W25QXX_Write_Enable();
W25QXX_Wait_Busy();
W25QXX_CS_L();
W25QXX_SPI_ReadWriteByte(W25X_ChipErase);
W25QXX_CS_H();
W25QXX_Wait_Busy();
}
void W25QXX_Erase_Sector(uint32_t Dst_Addr)
{
Dst_Addr *= 4096;
W25QXX_Write_Enable();
W25QXX_Wait_Busy();
W25QXX_CS_L();
W25QXX_SPI_ReadWriteByte(W25X_SectorErase);
W25QXX_SPI_ReadWriteByte((uint8_t)((Dst_Addr) >> 16));
W25QXX_SPI_ReadWriteByte((uint8_t)((Dst_Addr) >> 8));
W25QXX_SPI_ReadWriteByte((uint8_t)Dst_Addr);
W25QXX_CS_H();
W25QXX_Wait_Busy();
}
void W25QXX_Wait_Busy(void)
{
while ((W25QXX_ReadSR() & 0x01) == 0x01);
}
void W25QXX_PowerDown(void)
{
W25QXX_CS_L();
W25QXX_SPI_ReadWriteByte(W25X_PowerDown);
W25QXX_CS_H();
delay_us(3);
}
void W25QXX_WAKEUP(void)
{
W25QXX_CS_L();
W25QXX_SPI_ReadWriteByte(W25X_ReleasePowerDown);
W25QXX_CS_H();
delay_us(3);
}
头文件
#ifndef __W25QXX_H
#define __W25QXX_H
#include <main.h>
#define W25QXX_SPI_Handle (&hspi1)
#define W25Q80 0XEF13
#define W25Q16 0XEF14
#define W25Q32 0XEF15
#define W25Q64 0XEF16
#define W25Q128 0XEF17
#define W25QXX_CS_L() HAL_GPIO_WritePin(W25QXX_CS_GPIO_Port, W25QXX_CS_Pin, GPIO_PIN_RESET)
#define W25QXX_CS_H() HAL_GPIO_WritePin(W25QXX_CS_GPIO_Port, W25QXX_CS_Pin, GPIO_PIN_SET)
extern uint16_t W25QXX_TYPE;
extern uint32_t W25QXX_SIZE;
extern uint8_t W25QXX_UID[8];
#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
#define W25X_ChipErase 0xC7
#define W25X_PowerDown 0xB9
#define W25X_ReleasePowerDown 0xAB
#define W25X_DeviceID 0xAB
#define W25X_ManufactDeviceID 0x90
#define W25X_JedecDeviceID 0x9F
int W25QXX_Init(void);
void W25QXX_ReadUniqueID(uint8_t UID[8]);
uint16_t W25QXX_ReadID(void);
uint8_t W25QXX_ReadSR(void);
void W25QXX_Write_SR(uint8_t sr);
void W25QXX_Write_Enable(void);
void W25QXX_Write_Disable(void);
void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead);
void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
void W25QXX_Erase_Chip(void);
void W25QXX_Erase_Sector(uint32_t Dst_Addr);
void W25QXX_Wait_Busy(void);
void W25QXX_PowerDown(void);
void W25QXX_WAKEUP(void);
uint32_t W25QXX_ReadCapacity(void);
#endif
|