现在能读取设备ID、寄存器的值,可是写进去的值读出来都是0xFF,已去除写保护。还有一的个问题是为什么原子哥在写数据时要从W25的最后地址位开始写,而不从0x000000开始写呢?以下是代码:
[mw_shl_code=c,true]void sFLASH_ReadStatusRegiter(uint32_t SectorAddr) //ed
{
/*!< Select the FLASH: Chip Select low */
sFLASH_CS_LOW();
//sFLASH_SendByte(sFLASH_CMD_READ_STATUS); // 0x00
flashstatus1 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
sFLASH_CS_HIGH();
}
void TEST_SPIFLASH_writeandread(void)
{
//sFLASH_Init();
//要写入到W25Q16的字符串数组
uint64_t FLASH_Addr;
sFLASH_Init(); //W25QXX初始化
FLASH_Addr = 0x000100; //FLASH 大小为1Gb 0x000064
//HAL_GPIO_WritePin(GPIOC,sFLASH_SPI_WP_PIN,GPIO_PIN_SET);
//sFLASH_ReadStatusRegiter(FLASH_Addr);
sFLASH_EraseSubSector(FLASH_Addr);Delayms(50);
sFLASH_WritePage(TEXT_Buffer,FLASH_Addr,BufferSize); //从倒数第100个地址处开始,写入SIZE长度的数据
Delayms(190);
sFLASH_ReadBuffer(datatemp1,FLASH_Addr,BufferSize); //从倒数第100个地址处开始,读出SIZE个字节
sFLASH_EraseSubSector(FLASH_Addr);Delayms(100);
sFLASH_WriteBuffer(TEXT_Buffer,FLASH_Addr,BufferSize); //从倒数第100个地址处开始,写入SIZE长度的数据
Delayms(290);
sFLASH_ReadBuffer(datatemp2,FLASH_Addr,BufferSize);
FLASH_Addr = 0x07FFF000;
//sFLASH_EraseSubSector(FLASH_Addr+100);Delayms(50);
W25QXX_Write((uint8_t*)TEXT_Buffer,FLASH_Addr,SIZE);
Delayms(90);
sFLASH_ReadBuffer(datatemp3,FLASH_Addr,SIZE);
sFLASH_EraseSubSector(FLASH_Addr);Delayms(150);
W25QXX_Write_Page((uint8_t*)TEXT_Buffer,FLASH_Addr,SIZE);
Delayms(90);
sFLASH_ReadBuffer(datatemp4,FLASH_Addr,SIZE);
}
void sFLASH_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
Addr = WriteAddr % sFLASH_SPI_PAGESIZE; //某页中的第Addr个地址
count = sFLASH_SPI_PAGESIZE - Addr; //某页中还剩余count个地址空间
NumOfPage = NumByteToWrite / sFLASH_SPI_PAGESIZE; //待写数据占用了页数
NumOfSingle = NumByteToWrite % sFLASH_SPI_PAGESIZE; //待写数据写了整数页大小的数据量后还剩多少字节要写
if (Addr == 0) /*!< WriteAddr is sFLASH_PAGESIZE aligned */ //待写的地址刚好在下页地址首地址
{
if (NumOfPage == 0) /*!< NumByteToWrite < sFLASH_PAGESIZE */ //待写入的数据小于一页的容量256
{
sFLASH_WritePage(pBuffer, WriteAddr, NumByteToWrite); //直接写一页就行
}
else /*!< NumByteToWrite > sFLASH_PAGESIZE */
{
while (NumOfPage--) //不止一页,一页一页地写
{
sFLASH_WritePage(pBuffer, WriteAddr, sFLASH_SPI_PAGESIZE);
WriteAddr += sFLASH_SPI_PAGESIZE;
pBuffer += sFLASH_SPI_PAGESIZE;
}
sFLASH_WritePage(pBuffer, WriteAddr, NumOfSingle);
}
}
else /*!< WriteAddr is not sFLASH_PAGESIZE aligned */ //待写入的地址不在某页的首地址
{
if (NumOfPage == 0) /*!< NumByteToWrite < sFLASH_PAGESIZE */
{
if (NumOfSingle > count) /*!< (NumByteToWrite + WriteAddr) > sFLASH_PAGESIZE */
{
temp = NumOfSingle - count;
sFLASH_WritePage(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;
sFLASH_WritePage(pBuffer, WriteAddr, temp);
}
else
{
sFLASH_WritePage(pBuffer, WriteAddr, NumByteToWrite);
}
}
else /*!< NumByteToWrite > sFLASH_PAGESIZE */ //待写入的数据>256字节
{
NumByteToWrite -= count;
NumOfPage = NumByteToWrite / sFLASH_SPI_PAGESIZE;
NumOfSingle = NumByteToWrite % sFLASH_SPI_PAGESIZE;
sFLASH_WritePage(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;
while (NumOfPage--)
{
sFLASH_WritePage(pBuffer, WriteAddr, sFLASH_SPI_PAGESIZE);
WriteAddr += sFLASH_SPI_PAGESIZE;
pBuffer += sFLASH_SPI_PAGESIZE;
}
if (NumOfSingle != 0)
{
sFLASH_WritePage(pBuffer, WriteAddr, NumOfSingle);
}
}
}
}
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; //小扇区地址 4KB
secoff=WriteAddr%4096; //在扇区内的偏移
secremain=4096-secoff; //扇区剩余空间大小
if(NumByteToWrite<=secremain){secremain = NumByteToWrite;} //不大于4096个字节
while(1)
{
sFLASH_ReadBuffer(W25QXX_BUF,secpos*4096,4096); //读出整个扇区的内容
for(i=0;i<secremain;i++)//校验数据
{
if(W25QXX_BUF[secoff+i]!=0XFF)break; //需要擦除
}
if(i<secremain)//需要擦除
{
sFLASH_EraseSubSector(secpos); //擦除这个扇区
for(i=0;i<secremain;i++) //复制
{
W25QXX_BUF[i+secoff]=pBuffer;
}
W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区
}else W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间.
if(NumByteToWrite==secremain)break;//写入结束了
else//写入未结束
{
secpos++;//扇区地址增1
secoff=0;//偏移位置为0
pBuffer+=secremain; //指针偏移
WriteAddr+=secremain;//写地址偏移
NumByteToWrite-=secremain; //字节数递减
if(NumByteToWrite>4096)secremain=4096; //下一个扇区还是写不完
else secremain=NumByteToWrite; //下一个扇区可以写完了
}
};
}
void sFLASH_WritePage(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
/*!< Enable the write access to the FLASH */
sFLASH_WriteEnable();
/*!< Select the FLASH: Chip Select low */
sFLASH_CS_LOW();
/*!< Send "Write to Memory " instruction */
sFLASH_SendByte(sFLASH_CMD_PAGE_PROGRAM);
/*!< Send WriteAddr high nibble address byte to write to */
sFLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
/*!< Send WriteAddr medium nibble address byte to write to */
sFLASH_SendByte((WriteAddr & 0xFF00) >> 8);
/*!< Send WriteAddr low nibble address byte to write to */
sFLASH_SendByte(WriteAddr & 0xFF);
/*!< while there is data to be written on the FLASH */
while (NumByteToWrite--)
{
/*!< Send the current byte */
sFLASH_SendByte(*pBuffer);
/*!< Point on the next byte to be written */
pBuffer++;
}
/*!< Deselect the FLASH: Chip Select high */
sFLASH_CS_HIGH();
/*!< Wait the end of Flash writing */
sFLASH_WaitForWriteEnd();
}
void W25QXX_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
uint16_t i;
sFLASH_WriteEnable(); //SET WEL
sFLASH_CS_LOW(); //使能器件
sFLASH_SendByte(sFLASH_CMD_PAGE_PROGRAM); //发送写页命令
sFLASH_SendByte((uint8_t)((WriteAddr)>>16)); //发送24bit地址
sFLASH_SendByte((uint8_t)((WriteAddr)>>8));
sFLASH_SendByte((uint8_t)WriteAddr);
for(i=0;i<NumByteToWrite;i++)sFLASH_SendByte(pBuffer);//循环写数
sFLASH_CS_HIGH(); //取消片选
sFLASH_WaitForWriteEnd(); //等待写入结束
}
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;//不大于256个字节
while(1)
{
sFLASH_WritePage(pBuffer,WriteAddr,pageremain);
if(NumByteToWrite==pageremain)break;//写入结束了
else //NumByteToWrite>pageremain
{
pBuffer+=pageremain;
WriteAddr+=pageremain;
NumByteToWrite-=pageremain; //减去已经写入了的字节数
if(NumByteToWrite>256)pageremain=256; //一次可以写入256个字节
else pageremain=NumByteToWrite; //不够256个字节了
}
};
}
void sFLASH_ReadBuffer(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) /*ed*/
{
/*!< Select the FLASH: Chip Select low */
sFLASH_CS_LOW();
/*!< Send "Read from Memory " instruction */
sFLASH_SendByte(sFLASH_CMD_READ); /* 24位地址 */
/*!< Send ReadAddr high nibble address byte to read from */
sFLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
/*!< Send ReadAddr medium nibble address byte to read from */
sFLASH_SendByte((ReadAddr& 0xFF00) >> 8);
/*!< Send ReadAddr low nibble address byte to read from */
sFLASH_SendByte(ReadAddr & 0xFF);
while (NumByteToRead--) /*!< while there is data to be read */
{
/*!< Read a byte from the FLASH */
*pBuffer = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
/*!< Point to the next location where the byte read will be saved */
pBuffer++;
}
/*!< Deselect the FLASH: Chip Select high */
sFLASH_CS_HIGH();
}
/* @brief Erases the specified FLASH subsector(4KB=4096). ed
* @param SectorAddr: address of the subsector to erase.
* @retval None
*/
void sFLASH_EraseSubSector(uint32_t SectorAddr)
{
/*!< Send write enable instruction */
sFLASH_WriteEnable();
/*!< Sector Erase */
/*!< Select the FLASH: Chip Select low */
sFLASH_CS_LOW();
/*!< Send Sector Erase instruction */
sFLASH_SendByte(sFLASH_CMD_SUBSECTOR_ERASE);
/*!< Send SectorAddr high nibble address byte */ //发送24位地址
sFLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
/*!< Send SectorAddr medium nibble address byte */
sFLASH_SendByte((SectorAddr & 0xFF00) >> 8);
/*!< Send SectorAddr low nibble address byte */
sFLASH_SendByte(SectorAddr & 0xFF);
/*!< Deselect the FLASH: Chip Select high */
sFLASH_CS_HIGH();
/*!< Wait the end of Flash writing */
sFLASH_WaitForWriteEnd(); //等待擦除完成
}
/*--------------------------------------------*/
/*---------N25Q FLASH 读取设备ID 函数---------*/
uint32_t N25Q_ReadDeviceID(void)
{
uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
/*!< Select the FLASH: Chip Select low */
sFLASH_CS_LOW();
/*!< Send "RDID " instruction */
sFLASH_SendByte(SFLASH_CMD_DEVICEID);
/*!< Read a byte from the FLASH */
Temp0 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
/*!< Read a byte from the FLASH */
Temp1 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
/*!< Read a byte from the FLASH */
Temp2 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
/*!< Deselect the FLASH: Chip Select high */
sFLASH_CS_HIGH();
Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
return Temp;
}
/**
* @brief Reads FLASH identification.
* @param None
* @retval FLASH identification
*/
uint32_t sFLASH_ReadID(void)
{
uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
/*!< Select the FLASH: Chip Select low */
sFLASH_CS_LOW();
/*!< Send "RDID " instruction */
sFLASH_SendByte(SFLASH_CMD_DEVICEID);
/*!< Read a byte from the FLASH */
Temp0 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
/*!< Read a byte from the FLASH */
Temp1 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
/*!< Read a byte from the FLASH */
Temp2 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
/*!< Deselect the FLASH: Chip Select high */
sFLASH_CS_HIGH();
Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
return Temp;
}
uint32_t FLASH_READID(void)
{
uint32_t DeviceID2=0,DeviceID1=0;
sFLASH_Init(); // 初始化了SPI-FLASH
DeviceID1 = N25Q_ReadDeviceID(); //第一次结果就是不对,不知道为啥
DeviceID2 = sFLASH_ReadID(); //第二次结果是正确的
return DeviceID2;
}
/********************************初始化程序***********************************/
void sFLASH_gpio_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*--##-1- Enable peripherals and GPIO Clocks--*/
__SPI4_CLK_ENABLE(); /*!< Enable the SPI clock */
__GPIOE_CLK_ENABLE(); /*!< Enable GPIO clocks */
__GPIOC_CLK_ENABLE(); /*!< Enable GPIO clocks */
//HAL_GPIO_StructInit(GPIOE, &GPIO_InitStructure); //配置缺省值
/*--##-2 - Configure peripheral GPIO --*/
GPIO_InitStructure.Pin = sFLASH_SPI_SCK_PIN|sFLASH_SPI_MISO_PIN|sFLASH_SPI_MOSI_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; //复用推挽输出
GPIO_InitStructure.Pull = GPIO_PULLUP; //上拉输入??SCK为1
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
GPIO_InitStructure.Alternate = GPIO_AF5_SPI4;
HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
/*!< Configure sFLASH Card NSS pin in output pushpull mode ********************/
GPIO_InitStructure.Pin = sFLASH_NSS_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; //通用推挽输出
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
/* ( W# )Write protect Control Input* PC5 */
GPIO_InitStructure.Pin = sFLASH_SPI_WP_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; //通用推挽输出
GPIO_InitStructure.Pull = GPIO_PULLUP; //带上拉,让其一直无效
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
HAL_GPIO_WritePin(GPIOC,sFLASH_SPI_WP_PIN,GPIO_PIN_SET); //置高,无效
/* ( HOLD# ) HOLD Control Input* PC6 */
GPIO_InitStructure.Pin = sFLASH_SPI_HOLD_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; //通用推挽输出
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
HAL_GPIO_WritePin(GPIOC,sFLASH_SPI_HOLD_PIN,GPIO_PIN_SET); //置高,无效
}
void SPI_SetSpeed(uint8_t SPI_BaudRateprescaler)
{
SPI4->CR1 &= 0xFFC7; /* 位3-5清零,用来设置波特率 */
SPI4->CR1 |= SPI_BaudRateprescaler;
SPI4->CR1|=(1<<6);
}
void sFLASH_Init(void)
{
/*--##-4 - Configure peripheral SPI --*/
SPI_HandleTypeDef SPI_InitStructure;
//__SPI4_CLK_ENABLE(); /*!< Enable the SPI clock */
sFLASH_gpio_Init();
//HAL_SPI_DeInit(&SPI_InitStructure);
sFLASH_CS_HIGH(); /*!< Deselect the FLASH: Chip Select high 取消片选*/
/*!< SPI configuration */
SPI_InitStructure.Instance = SPI4;
SPI_InitStructure.Init.Mode = SPI_MODE_MASTER;
SPI_InitStructure.Init.NSS = SPI_NSS_SOFT;
SPI_InitStructure.Init.Direction = SPI_DIRECTION_2LINES;
SPI_InitStructure.Init.DataSize = SPI_DATASIZE_8BIT; // ??
SPI_InitStructure.Init.CLKPolarity = SPI_POLARITY_HIGH; // CPOL==1
SPI_InitStructure.Init.CLKPhase = SPI_PHASE_2EDGE; // CPOH==1
//SPI_SetSpeed(SPI_BAUDRATEPRESCALER_256);
SPI_InitStructure.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; // ??
SPI_InitStructure.Init.FirstBit = SPI_FIRSTBIT_MSB;
SPI_InitStructure.Init.TIMode = SPI_TIMODE_DISABLE;
SPI_InitStructure.Init.CRCPolynomial = 7;
HAL_SPI_Init(&SPI_InitStructure);
/*!< 5 Enable the sFLASH_SPI */
SPI4->CR1|=(1<<6); //使能SPI
sFLASH_CS_LOW();
sFLASH_SendByte(0xff); //启动传输
}
/***************** (C) COPYRIGHT STMicroelectronics ********END OF FILE*****/
[/mw_shl_code]写保护。
原子哥,数据出来了,泪奔,原来只是不先操作擦除就可以了,,不知道为什么,,,,,谢谢原子哥
一周热门 更多>