最近做一个外挂flash,使用的是w23q128,在初始化flash后写入数据和读出数据不对等。读出的数据全为0.下面是初始化和操作函数。
void init_spi(uint32_t ui32SysClock)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);//使能SPI2时钟
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);//使能GPIOD时钟
GPIOPinConfigure(GPIO_PD0_SSI2XDAT1);//SPI2 IO 口定义
GPIOPinConfigure(GPIO_PD1_SSI2XDAT0);
GPIOPinConfigure(GPIO_PD2_SSI2FSS);
GPIOPinConfigure(GPIO_PD3_SSI2CLK);
GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 |
GPIO_PIN_3);
#if defined(TARGET_IS_TM4C129_RA0) || \
defined(TARGET_IS_TM4C129_RA1) || \
defined(TARGET_IS_TM4C129_RA2)
SSIConfigSetExpClk(SSI2_BASE, ui32SysClock, SSI_FRF_MOTO_MODE_0,
SSI_MODE_MASTER, 1000000, 8); //设置SSI 时钟 模式
#else
SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
SSI_MODE_MASTER, 1000000, 8);
#endif
SSIEnable(SSI2_BASE);//使能SPI2
while(SSIDataGetNonBlocking(SSI2_BASE, &SpiReviceBuf[0])) //清除缓冲区
{
}
}
下面是一些操作函数
void Spi_WriteByte(uint8_t TxData)
{
while(SSIBusy(SSI2_BASE))
{
}
SSIDataPut(SSI2_BASE,(uint32_t) TxData);
}
void Spi_Flash_Write_Enable(void)
{
Spi_WriteByte(W25X_WriteEnable);
}
void Spi_Flash_Write_Disable(void)
{
Spi_WriteByte(W25X_WriteDisable);
}
void W25QXX_Erase_Sector(uint32_t Dst_Addr)
{
Dst_Addr*=4096;
Spi_Flash_Write_Enable();
W25QXX_Wait_Busy();
Spi_WriteByte(W25X_SectorErase);
Spi_WriteByte((uint8_t)((Dst_Addr)>>16));
Spi_WriteByte((uint8_t)((Dst_Addr)>>8));
Spi_WriteByte((uint8_t)((Dst_Addr)>>0));
W25QXX_Wait_Busy();
}
uint8_t SPI_Flash_ReadSR(void)
{
uint32_t data;
Spi_WriteByte(W25X_ReadStatusReg);
Spi_WriteByte(0xFF);
while(SSIBusy(SSI2_BASE))
{
}
SSIDataGet(SSI2_BASE,&data);
return (uint8_t)data;
}
void W25QXX_Wait_Busy()
{
uint8_t Status;
do{
Status = SPI_Flash_ReadSR();
Status &= 0x01;
}while(Status != 0);
}
void W25QXX_Read(uint8_t *pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)
{
uint16_t i;
uint32_t data;
Spi_Flash_Write_Enable();
Spi_WriteByte(W25X_ReadData);
Spi_WriteByte((uint8_t)((ReadAddr)>>16));
Spi_WriteByte((uint8_t)((ReadAddr)>>8));
Spi_WriteByte((uint8_t)((ReadAddr)>>0));
for(i=0;i<NumByteToRead;i++)
{
Spi_WriteByte(0XFF); //循环读数,只需要不停的发送0xff,就可以读出数据
while(SSIBusy(SSI2_BASE))
{
}
// UARTprintf("%d \n ",data);
SSIDataGet(SSI2_BASE,&data);
pBuffer[i] = (uint8_t)data;
// UARTprintf("%x ",pBuffer[i]);
}
}
void W25QXX_Write_Page(uint8_t *pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
uint16_t i;
Spi_Flash_Write_Enable();
Spi_WriteByte(W25X_PageProgram);
Spi_WriteByte((uint8_t)((WriteAddr)>>16));
Spi_WriteByte((uint8_t)((WriteAddr)>>8));
Spi_WriteByte((uint8_t)((WriteAddr)>>0));
for(i = 0;i < NumByteToWrite;i++)
{
Spi_WriteByte(pBuffer[i]);
}
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 //NumByteToWrite>pageremain,如果要写入的数据大于单页剩余的字节数。
{
pBuffer+=pageremain;
WriteAddr+=pageremain;
NumByteToWrite-=pageremain; //减去已经写入了的字节数
if(NumByteToWrite>256)
pageremain=256; //一次可以写入256个字节
else
pageremain=NumByteToWrite; //不够256个字节了
}
}
}
mian函数中写入后读出的数据全为0
原理图

