STM32CubeMX+w25qxx

发布时间:2024-08-13  

一、w25qxx驱动原理

w25qxx使用spi接口驱动,下面是它的时序图

从图上看,spi有两种配置模式:
1、低电平,第一个边缘;
2、高电平,第二个边缘;


二、stm32CubeMx配置:

三、w25qxx驱动代码:

1、w25qxx.h


#ifndef __W25QXX_H__

#define __W25QXX_H__


#include

#include 'spi.h'


#define SPI_FLASH_PageSize                  256

#define SPI_FLASH_PerWritePageSize          256


#define W25X_WriteEnable               0x06 

#define W25X_WriteDisable               0x04 

#define W25X_ReadStatusReg1               0x05 

#define W25X_WriteStatusReg1               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 

#define WIP_Flag                              0x01  /* Write In Progress (WIP) flag */

#define W25QXX_DUMMY_BYTE   0xFF


#pragma pack(1)


typedef enum

{

W25Q10=1,

W25Q20,

W25Q40,

W25Q80,

W25Q16,

W25Q32,

W25Q64,

W25Q128,

W25Q256,

W25Q512,

}W25QXX_ID_t;


typedef struct

{

W25QXX_ID_t ID;

uint8_t UniqID[8];

uint16_t PageSize;

uint32_t PageCount;

uint32_t SectorSize;

uint32_t SectorCount;

uint32_t BlockSize;

uint32_t BlockCount;

uint32_t CapacityInKiloByte;

uint8_t StatusRegister1;

uint8_t StatusRegister2;

uint8_t StatusRegister3;

uint8_t Lock;

}w25qxx_t;


#pragma pack()


extern w25qxx_t w25qxx;


/************************************************用户API*******************************************/

bool W25qxx_Init(void);


void W25qxx_EraseChip(void);

void W25qxx_EraseSector(uint32_t SectorAddr);

void W25qxx_EraseBlock(uint32_t BlockAddr);


uint32_t W25qxx_PageToSector(uint32_t PageAddress);

uint32_t W25qxx_PageToBlock(uint32_t PageAddress);

uint32_t W25qxx_SectorToBlock(uint32_t SectorAddress);

uint32_t W25qxx_SectorToPage(uint32_t SectorAddress);

uint32_t W25qxx_BlockToPage(uint32_t BlockAddress);


void W25qxx_WriteByte(uint8_t pBuffer, uint32_t WriteAddr);

void W25qxx_WritePage(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);

void W25qxx_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);


void W25qxx_ReadBuffer(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead);


#endif

2、w25qxx.c


#include 'w25qxx.h'

#include 'w25qxx_config.h'


#if (_W25QXX_DEBUG == 1)

#include

#endif


#define W25QXX_CS_H HAL_GPIO_WritePin(_W25QXX_CS_GPIO, _W25QXX_CS_PIN, GPIO_PIN_SET);

#define W25QXX_CS_L HAL_GPIO_WritePin(_W25QXX_CS_GPIO, _W25QXX_CS_PIN, GPIO_PIN_RESET);


w25qxx_t w25qxx;


#if (_W25QXX_USE_FREERTOS == 1)

#define W25qxx_Delay(delay) osDelay(delay)

#include 'cmsis_os.h'

#else

#define W25qxx_Delay(delay) for(uint8_t i=0;i<255;i++);;

#endif


//###################################################################################################################

uint8_t W25qxx_Spi(uint8_t Data)

{

uint8_t ret;

HAL_SPI_TransmitReceive(&_W25QXX_SPI, &Data, &ret, 1, 100);

return ret;

}

//###################################################################################################################

uint32_t W25qxx_ReadID(void)

{

uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;

W25QXX_CS_L;

W25qxx_Spi(W25X_JedecDeviceID);

Temp0 = W25qxx_Spi(W25QXX_DUMMY_BYTE);

Temp1 = W25qxx_Spi(W25QXX_DUMMY_BYTE);

Temp2 = W25qxx_Spi(W25QXX_DUMMY_BYTE);

W25QXX_CS_H;

Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;

return Temp;

}

//###################################################################################################################

void W25qxx_ReadUniqID(void)

{

W25QXX_CS_L;

W25qxx_Spi(0x4B);

for(uint8_t i = 0; i < 4; i++)

{

W25qxx_Spi(W25QXX_DUMMY_BYTE);

}

for(uint8_t i = 0; i < 8; i++)

{

w25qxx.UniqID[i] = W25qxx_Spi(W25QXX_DUMMY_BYTE);

}

W25QXX_CS_H;

}

//###################################################################################################################

void W25qxx_WriteEnable(void)

{

W25QXX_CS_L;

W25qxx_Spi(W25X_WriteEnable);

W25QXX_CS_H;

W25qxx_Delay(1);

}

//###################################################################################################################

void W25qxx_WriteDisable(void)

{

W25QXX_CS_L;

W25qxx_Spi(W25X_WriteDisable);

W25QXX_CS_H;

W25qxx_Delay(1);

}

//###################################################################################################################

uint8_t W25qxx_ReadStatusRegister(uint8_t SelectStatusRegister_1_2_3)

{

uint8_t status=0;

W25QXX_CS_L;

if(SelectStatusRegister_1_2_3 == 1)

{

W25qxx_Spi(W25X_ReadStatusReg1);

status=W25qxx_Spi(W25QXX_DUMMY_BYTE);

w25qxx.StatusRegister1 = status;

}

else if(SelectStatusRegister_1_2_3 == 2)

{

W25qxx_Spi(0x35);

status=W25qxx_Spi(W25QXX_DUMMY_BYTE);

w25qxx.StatusRegister2 = status;

}

else

{

W25qxx_Spi(0x15);

status=W25qxx_Spi(W25QXX_DUMMY_BYTE);

w25qxx.StatusRegister3 = status;

}

W25QXX_CS_H;

return status;

}

//###################################################################################################################

void W25qxx_WriteStatusRegister(uint8_t SelectStatusRegister_1_2_3, uint8_t Data)

{

W25QXX_CS_L;

if(SelectStatusRegister_1_2_3 == 1)

{

W25qxx_Spi(W25X_WriteStatusReg1);

w25qxx.StatusRegister1 = Data;

}

else if(SelectStatusRegister_1_2_3 == 2)

{

W25qxx_Spi(0x31);

w25qxx.StatusRegister2 = Data;

}

else

{

W25qxx_Spi(0x11);

w25qxx.StatusRegister3 = Data;

}

W25qxx_Spi(Data);

W25QXX_CS_H;

}

//###################################################################################################################

void W25qxx_WaitForWriteEnd(void)

{

W25QXX_CS_L;

W25qxx_Spi(W25X_ReadStatusReg1);

do

{

w25qxx.StatusRegister1 = W25qxx_Spi(W25QXX_DUMMY_BYTE);

W25qxx_Delay(1);

}

while ((w25qxx.StatusRegister1 & WIP_Flag) == 0x01);

W25QXX_CS_H;


}

//###################################################################################################################

bool W25qxx_Init(void)

{

w25qxx.Lock=1;

// while(HAL_GetTick()<100)

// W25qxx_Delay(1);

W25QXX_CS_H;

//  W25qxx_Delay(100);

uint32_t id;

#if (_W25QXX_DEBUG==1)

printf('w25qxx Init Begin...rn');

#endif

id = W25qxx_ReadID();

#if (_W25QXX_DEBUG==1)

printf('w25qxx ID:0x%Xrn',id);

#endif

switch(id&0x0000FFFF)

{

case 0x401A: // w25q512

w25qxx.ID=W25Q512;

w25qxx.BlockCount=1024;

#if (_W25QXX_DEBUG==1)

printf('w25qxx Chip: w25q512rn');

#endif

break;

case 0x4019: // w25q256

w25qxx.ID=W25Q256;

w25qxx.BlockCount=512;

#if (_W25QXX_DEBUG==1)

printf('w25qxx Chip: w25q256rn');

#endif

break;

case 0x4018: // w25q128

w25qxx.ID=W25Q128;

w25qxx.BlockCount=256;

#if (_W25QXX_DEBUG==1)

printf('w25qxx Chip: w25q128rn');

#endif

break;

case 0x4017: // w25q64

w25qxx.ID=W25Q64;

w25qxx.BlockCount=128;

#if (_W25QXX_DEBUG == 1)

printf('w25qxx Chip: w25q64rn');

#endif

break;

case 0x4016: // w25q32

w25qxx.ID=W25Q32;

w25qxx.BlockCount=64;

#if (_W25QXX_DEBUG==1)

printf('w25qxx Chip: w25q32rn');

#endif

break;

case 0x4015: // w25q16

w25qxx.ID=W25Q16;

w25qxx.BlockCount=32;

#if (_W25QXX_DEBUG==1)

printf('w25qxx Chip: w25q16rn');

#endif

break;

case 0x4014: // w25q80

w25qxx.ID=W25Q80;

w25qxx.BlockCount=16;

#if (_W25QXX_DEBUG==1)

printf('w25qxx Chip: w25q80rn');

#endif

break;

case 0x4013: // w25q40

w25qxx.ID=W25Q40;

w25qxx.BlockCount=8;

#if (_W25QXX_DEBUG==1)

printf('w25qxx Chip: w25q40rn');

#endif

break;

case 0x4012: // w25q20

w25qxx.ID=W25Q20;

w25qxx.BlockCount=4;

#if (_W25QXX_DEBUG==1)

printf('w25qxx Chip: w25q20rn');

#endif

break;

case 0x4011: // w25q10

w25qxx.ID=W25Q10;

w25qxx.BlockCount=2;

#if (_W25QXX_DEBUG==1)

printf('w25qxx Chip: w25q10rn');

#endif

break;

default:

#if (_W25QXX_DEBUG==1)

printf('w25qxx Unknown IDrn');

#endif

w25qxx.Lock=0;

return false;

}

w25qxx.PageSize = 256;

w25qxx.SectorSize = 0x1000;

w25qxx.SectorCount = w25qxx.BlockCount * 16;

w25qxx.PageCount = (w25qxx.SectorCount * w25qxx.SectorSize) / w25qxx.PageSize;

w25qxx.BlockSize = w25qxx.SectorSize*16;

w25qxx.CapacityInKiloByte = (w25qxx.SectorCount * w25qxx.SectorSize) / 1024;

W25qxx_ReadUniqID();

W25qxx_ReadStatusRegister(1);

W25qxx_ReadStatusRegister(2);

W25qxx_ReadStatusRegister(3);

#if (_W25QXX_DEBUG == 1)

printf('w25qxx Page Size: %d Bytesrn',w25qxx.PageSize);

printf('w25qxx Page Count: %drn',w25qxx.PageCount);

printf('w25qxx Sector Size: %d Bytesrn',w25qxx.SectorSize);

printf('w25qxx Sector Count: %drn',w25qxx.SectorCount);

printf('w25qxx Block Size: %d Bytesrn',w25qxx.BlockSize);

printf('w25qxx Block Count: %drn',w25qxx.BlockCount);

printf('w25qxx Capacity: %d KiloBytesrn',w25qxx.CapacityInKiloByte);

printf('w25qxx Init Donern');

#endif

w25qxx.Lock = 0;

return true;

}

//###################################################################################################################

void W25qxx_EraseChip(void)

{

while(w25qxx.Lock==1)

{

W25qxx_Delay(1);

}

w25qxx.Lock=1;

#if (_W25QXX_DEBUG == 1)

uint32_t StartTime=HAL_GetTick();

printf('w25qxx EraseChip Begin...rn');

#endif

W25qxx_WriteEnable();

W25QXX_CS_L;

W25qxx_Spi(W25X_ChipErase);

W25QXX_CS_H;

W25qxx_WaitForWriteEnd();

#if (_W25QXX_DEBUG == 1)

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>