#include "W25Nxx.h"
#include "main.h"
#if (_W25NXX_DEBUG == 1)
#include <stdio.h>
#endif
#define W25NXX_DUMMY_BYTE 0xFF
#define BUF_SIZE 2048
uint8_t sbuf[2052];
uint8_t rbuf[16];
//extern SPI_HandleTypeDef hspi2;
W25Nxx_t W25Nxx;
uint32_t stmap=0;
//These two functions below must be defined somewhere else
uint32_t Get_Time_Stamp(void)
{
return HAL_GetTick()-stmap;
} // returns value of a variable that increments every millisecond
void Reset_Time_Stamp(void) // resets the variable
{
stmap=HAL_GetTick();
//hal_
}
uint32_t usticks;
void Test_Tick()
{
uint32_t ax=HAL_GetTick();
usticks=0;
while(ax==HAL_GetTick())
{
}
ax=HAL_GetTick();
while(ax==HAL_GetTick())
{
usticks++;
}
usticks/=1000;
}
void Delay_us(uint32_t us)
{
uint32_t tickcnt=0,bx,dx;
for(dx=0;dx<us;dx++)
{
tickcnt=0;
while(tickcnt!=usticks)
{
bx=HAL_GetTick();
tickcnt++;
}
}
}
void W25Nxx_Delay(int delay) //milliseconds
{
Reset_Time_Stamp();
while (delay > Get_Time_Stamp())
;
}
//###################################################################################################################
uint8_t spitr(uint8_t t)
{
uint8_t ax,r,bx;
SCK_L();
bx=0x80;
r=0;
for(ax=0;ax<8;ax++)
{
r<<=1;
if(t&bx)
MO_H();
else
MO_L();
//__NOP();
SCK_H();
if(MI())
r|=0x1;
//__NOP();
SCK_L();
bx>>=1;
}
return r;
}
uint8_t W25Nxx_Spi(uint8_t Data)
{
uint8_t ret;
//HAL_Delay(1);
ret=spitr(Data);
//HAL_SPI_TransmitReceive(&_W25NXX_SPI, &Data,&ret,1,TIME_T);
//HAL_Delay(1);
return ret;
}
//###################################################################################################################
uint32_t W25Nxx_ReadID(void)
{
uint32_t Temp = 0;
sbuf[0]=CMD_JDEC_ID;
sbuf[1]=W25NXX_DUMMY_BYTE;
sbuf[2]=W25NXX_DUMMY_BYTE;
sbuf[3]=W25NXX_DUMMY_BYTE;
sbuf[4]=W25NXX_DUMMY_BYTE;
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1,sbuf,sbuf,5,10);
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_SET);
Temp=sbuf[2];
Temp<<=8;
Temp|=sbuf[3];
Temp<<=8;
Temp|=sbuf[4];
return Temp;
}
//###################################################################################################################
void W25Nxx_ReadUniqID(void)
{
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_RESET);
W25Nxx_Spi(0x4B);
for (uint8_t i = 0; i < 4; i++)
W25Nxx_Spi(W25NXX_DUMMY_BYTE);
for (uint8_t i = 0; i < 8; i++)
W25Nxx.UniqID[i] = W25Nxx_Spi(W25NXX_DUMMY_BYTE);
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_SET);
;
}
//###################################################################################################################
void W25Nxx_WriteEnable(void)
{
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_RESET);
sbuf[0]=CMD_WRITE_ENABLE;
HAL_SPI_Transmit(&hspi1,sbuf,1,100);
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_SET);
;
Delay_us(1);
}
//###################################################################################################################
void W25Nxx_WriteDisable(void)
{
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_RESET);
W25Nxx_Spi(CMD_WRITE_DISABLE);
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_SET);
;
Delay_us(1);
}
//###################################################################################################################
uint8_t W25Nxx_ReadStatusRegister(uint8_t SelectStatusRegister_1_2_3)
{
uint8_t status = 0;
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_RESET);
sbuf[0]=CMD_READ_STATUS_R;
if (SelectStatusRegister_1_2_3 == 1)
{
sbuf[1]=ADDR_STATUS_R_1;
}
else if (SelectStatusRegister_1_2_3 == 2)
{
sbuf[1]=ADDR_STATUS_R_2;
}
else
{
sbuf[1]=ADDR_STATUS_R_3;
}
HAL_SPI_TransmitReceive(&hspi1,sbuf,sbuf,3,100);
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_SET);
;
status=sbuf[2];
return status;
}
//###################################################################################################################
void W25Nxx_WriteStatusRegister(uint8_t SelectStatusRegister_1_2_3, uint8_t Data)
{
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_RESET);
sbuf[0]=CMD_WRITE_STATUS_R;
if (SelectStatusRegister_1_2_3 == 1)
{
sbuf[1]=ADDR_STATUS_R_1;
W25Nxx.StatusRegister1 = Data;
}
else if (SelectStatusRegister_1_2_3 == 2)
{
sbuf[1]=ADDR_STATUS_R_2;
W25Nxx.StatusRegister2 = Data;
}
else
{
sbuf[1]=ADDR_STATUS_R_3;
W25Nxx.StatusRegister3 = Data;
}
sbuf[2]=Data;
HAL_SPI_TransmitReceive(&hspi1,sbuf,sbuf,3,100);
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_SET);
W25Nxx_WaitForWriteEnd();
}
//###################################################################################################################
void W25Nxx_WaitForWriteEnd(void)
{
//W25Nxx_Delay(1);
//HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_RESET);
HAL_StatusTypeDef spis=0;
Delay_us(1);
sbuf[0]=CMD_READ_STATUS_R;
sbuf[1]=0xc0;
sbuf[2]=0xff;
do
{
// HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_RESET);
//spis=HAL_SPI_Transmit(&hspi1,sbuf,2,100);
do{
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1,sbuf,2,100);
spis=HAL_SPI_Receive(&hspi1,rbuf,1,100);
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_SET);
}while(spis!=HAL_OK);
//HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_SET);
Delay_us(1);
W25Nxx.StatusRegister3 = rbuf[0];
} while ((rbuf[0] & 0x01) == 0x01);
//HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_SET);
//;
}
//###################################################################################################################
void W25Nxx_Reset(void)
{
W25Nxx_Delay(1);
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_RESET);
sbuf[0]=CMD_DEVICE_RESET;
HAL_SPI_TransmitReceive(&hspi1,sbuf,sbuf,1,100);
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_SET);
}
//###################################################################################################################
bool W25Nxx_Init(void)
{
W25Nxx.Lock = 1;
//GPIOA->BSRR = FLASH_WP;
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_SET);
W25Nxx_Delay(50);
W25Nxx_Reset();
W25Nxx_Delay(100);
W25Nxx_WaitForWriteEnd();
volatile uint32_t id;
id=0;
id = W25Nxx_ReadID();
W25Nxx.ID = 10;
W25Nxx.BlockCount = 1024;
W25Nxx.PageSize = 2048;
W25Nxx.SectorSize = 512;
W25Nxx.SectorCount = W25Nxx.BlockCount * 4;
W25Nxx.PageCount = (W25Nxx.SectorCount * W25Nxx.SectorSize) / W25Nxx.PageSize;
W25Nxx.BlockSize = W25Nxx.PageCount * 64;
W25Nxx.CapacityInKiloByte = 125000;
// W25Nxx_WriteStatusRegister(2,0x08);
W25Nxx_ReadStatusRegister(1);
W25Nxx_ReadStatusRegister(2);
W25Nxx_ReadStatusRegister(3);
W25Nxx_WriteStatusRegister(1,0);
W25Nxx.Lock = 0;
Test_Tick();
return true;
}
//###################################################################################################################
void W25Nxx_EraseChip(void)
{
uint16_t addr;
for (unsigned int i = 0; i < W25Nxx.BlockCount; i++)
{
addr = i * 64;
W25Nxx_WriteEnable();
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_RESET);
sbuf[0]=(CMD_BLOCK_ERASE);
sbuf[1]=(W25NXX_DUMMY_BYTE);
sbuf[2]=(addr >> 8); //page address
sbuf[3]=(addr&0x00FF);
HAL_SPI_TransmitReceive(&hspi1,sbuf,sbuf,4,100);
HAL_GPIO_WritePin(_W25NXX_CS_GPIO,_W25NXX_CS_PIN,GPIO_PIN_SET);
W25Nxx_WaitForWriteEnd();
W25Nxx_Delay(10);
W25Nxx.Lock = 0;
}
}
//###################################################################################################################
/*
void W25Nxx_EraseSector(uint32_t SectorAddr)
{
while (W25Nxx.Lock == 1)
W25Nxx_Delay(1);
W25Nxx.Lock = 1;
#if (_W25NXX_DEBUG == 1)
uint32_t StartTime = Get_Time_Stamp();
printf("W25Nxx EraseSector %d Begin...\r\n", SectorAddr);
#endif
W25Nxx_WaitForWriteEnd();
SectorAddr = SectorAddr * W2
华邦nand flash 驱动
需积分: 0 38 浏览量
更新于2024-12-28
收藏 5KB ZIP 举报
华邦nand flash驱动程序主要针对华邦公司生产的W系列nand flash产品,例如W25N01、W25N02和W25N04。这些驱动程序都是基于SPI(Serial Peripheral Interface)通讯协议设计的,能够实现对这些nand flash芯片的读取、写入以及擦除操作。这类芯片广泛应用于嵌入式系统,存储管理程序或者其他需要大量数据保存和读写的场合。
文件列表中的“w25nxx.c”文件应该是C语言编写的驱动程序的源代码文件,而“w25nxx.h”是相应的头文件,通常包含了驱动程序中使用到的数据结构、宏定义、函数原型等声明信息。开发者在使用这些文件时,需要将它们包含到自己的工程中,然后通过编程调用其中定义的函数接口来实现对华邦nand flash的控制。
根据描述,这些驱动程序已经在W25N系列芯片上进行了验证,能够正常工作。此外,驱动程序被特别指出是适用于STM32系列单片机的。STM32是一种广泛使用的ARM Cortex-M微控制器,由意法半导体生产,广泛应用于各种嵌入式应用中。因此,如果开发者使用的是STM32系列的单片机,那么这些驱动程序可以直接使用。
如果开发者使用的是非STM32系列的单片机或者其他类型的微控制器,文件描述中提到可以联系开发者进行适配修改。这表示该驱动程序具有一定的可移植性,通过简单的修改和适配工作,可以使其在其他平台上运行。这为开发者提供了一定的灵活性,可以根据自己的需求来调整驱动程序,以适应不同的硬件平台。
对于“nandflash”这一标签,它直接指向了这些驱动程序所针对的硬件类型,即NAND闪存。NAND闪存是一种非易失性的存储器,具有擦写速度快、存储密度高等优点,广泛应用于固态硬盘、USB闪存驱动器和嵌入式设备中作为大容量存储解决方案。
华邦nand flash驱动程序是针对特定的nand flash芯片系列设计的,基于SPI通讯协议,并且适用于STM32系列微控制器。这些驱动程序提供了基础的读、写、擦除操作,同时具有一定的可移植性,可以针对不同的硬件平台进行必要的修改。开发者在使用这些驱动时,需要结合具体的硬件环境和需求,进行适当的适配和调整,以确保驱动程序能够正确运行。

korei_little_man
- 粉丝: 13