最近做一个外挂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 时钟 模式 #elseSSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,SSI_MODE_MASTER, 1000000, 8); #endifSSIEnable(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
原理图
chao tang1:
使用逻辑分析仪分析的时候。发现所有数据均为0x00
chao tang1:
回复 chao tang1:
xyz549040622:
回复 chao tang1:
楼主找到问题了没,应该还是你的SPI没有配置对吧。
xyz549040622:
回复 chao tang1:
好一个大坑。。。时序一定要和数据手册再三的比对,差一点都是不可以的。
user4310042:
回复 chao tang1:
那这个怎么处理?