📄 sst_spi_w25x.c
字号:
/****************************************************************************/
/****************************************************************************/
#include <SST89x5xxRD2.H>
#include <W25X.H>
#include <intrins.h>
#define SST_SPI
extern uint8 upper_128[16];
extern uint8 tx_buff[16];
//=================================================================================================
void delay_nms(uchar i)
{ uchar j;
i=i*2;
for(;i>0;i--) { j = 246; while(--j); }
}
void delay(uchar tt)
{ while(tt--);}
//=================================================================================================
//SPI_Read_StatusReg Reads the status register of the serial flash
//SPI_Write_StatusReg Performs a write to the status register
//SPI_Write_Enable Write enables the serial flash
//SPI_Write_Disable Write disables the serial flash
//SPI_Read_ID1 Reads the device ID using the instruction 0xAB
//SPI_Read_ID2 Reads the manufacturer ID and device ID with 0x90
//SPI_Read_ID3() Reads the JedecDevice ID
//SPI_Read_Byte Reads one byte from the serial flash and returns byte(max of 20 MHz CLK frequency)
//SPI_Read_nBytes Reads multiple bytes(max of 20 MHz CLK frequency)
//SPI_FastRead_Byte Reads one byte from the serial flash and returns byte(max of 33 MHz CLK frequency)
//SPI_FastRead_nBytes Reads multiple bytes(max of 33 MHz CLK frequency)
//SPI_Write_Byte Program one byte to the serial flash
//SPI_Write_nBytes Program n bytes to the serial flash, n<=256
//SPI_Erase_Chip Erases entire serial flash
//SPI_Erase_Sector Erases one sector (64 KB) of the serial flash
//SPI_Wait_Busy Polls status register until busy bit is low
//=================================================================================================
uchar SPI_Read_StatusReg()
{ uchar byte = 0;
W25X_CS = 0; // enable device
SPI_Send_Byte(W25X_ReadStatusReg); // send Read Status Register command
byte = SPI_Get_Byte(); // receive byte
W25X_CS = 1; // disable device
return byte;
}
void SPI_Write_StatusReg(byte)
{ W25X_CS = 0; // enable device
SPI_Send_Byte(W25X_WriteStatusReg); // select write to status register
SPI_Send_Byte(byte); // data that will change the status(only bits 2,3,7 can be written)
W25X_CS = 1; // disable the device
}
void SPI_Write_Enable()
{ W25X_CS = 0; // enable device
SPI_Send_Byte(W25X_WriteEnable); // send W25X_Write_Enable command
W25X_CS = 1; // disable device
}
void SPI_Write_Disable()
{ W25X_CS = 0; // enable device
SPI_Send_Byte(W25X_WriteDisable); // send W25X_WriteW25X_DIsable command
W25X_CS = 1; // disable device
}
uchar SPI_Read_ID1()
{ uchar byte;
W25X_CS = 0; // enable device
SPI_Send_Byte(W25X_DeviceID); // send read device ID command (ABh)
SPI_Send_Byte(0); // send address
SPI_Send_Byte(0); // send address
SPI_Send_Byte(0); // send 3_Dummy address
byte = SPI_Get_Byte(); // receive Device ID byte
W25X_CS = 1; // disable device
delay(4); // remain CS high for tRES2 = 1.8uS
return byte;
}
uint SPI_Read_ID2(uchar ID_Addr)
{ uint IData16;
W25X_CS = 0; // enable device
SPI_Send_Byte(W25X_ManufactDeviceID); // send read ID command (90h)
SPI_Send_Byte(0x00); // send address
SPI_Send_Byte(0x00); // send address
SPI_Send_Byte(ID_Addr); // send W25Pxx selectable ID address 00H or 01H
IData16 = SPI_Get_Byte()<<8; // receive Manufature or Device ID byte
IData16 |= SPI_Get_Byte(); // receive Device or Manufacture ID byte
W25X_CS = 1; // disable device
return IData16;
}
uint SPI_Read_ID3()
{ uint IData16;
W25X_CS = 0; // enable device
SPI_Send_Byte(W25X_JedecDeviceID); // send read ID command (9Fh)
IData16 = SPI_Get_Byte()<<8; // receive Manufature or Device ID byte
IData16 |= SPI_Get_Byte(); // receive Device or Manufacture ID byte
tx_buff[2] = SPI_Get_Byte();
W25X_CS = 1; // disable device
return IData16;
}
uchar SPI_Read_Byte(uint32 Dst_Addr)
{ uchar byte = 0;
W25X_CS = 0; // enable device
SPI_Send_Byte(W25X_ReadData); // read command
SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFFFF) >> 16));// send 3 address bytes
SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFF) >> 8));
SPI_Send_Byte((uchar)(Dst_Addr & 0xFF));
byte = SPI_Get_Byte();
W25X_CS = 1; // disable device
return byte; // return one byte read
}
void SPI_Read_nBytes(uint32 Dst_Addr, uchar nBytes_128)
{ uint32 i = 0;
W25X_CS = 0; // enable device
SPI_Send_Byte(W25X_ReadData); // read command
SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16)); // send 3 address bytes
SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8));
SPI_Send_Byte(Dst_Addr & 0xFF);
for (i = 0; i < nBytes_128; i++) // read until no_bytes is reached
upper_128[i] = SPI_Get_Byte(); // receive byte and store at address 80H - FFH
W25X_CS = 1; // disable device
}
uchar SPI_FastRead_Byte(uint32 Dst_Addr)
{ uchar byte = 0;
W25X_CS = 0; // enable device
SPI_Send_Byte(W25X_FastReadData); // fast read command
SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16)); // send 3 address bytes
SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8));
SPI_Send_Byte(Dst_Addr & 0xFF);
SPI_Send_Byte(0xFF); // dummy byte
byte = SPI_Get_Byte();
W25X_CS = 1; // disable device
return byte; // return one byte read
}
void SPI_FastRead_nBytes(uint32 Dst_Addr, uchar nBytes_128)
{ uchar i = 0;
W25X_CS = 0; // enable device
SPI_Send_Byte(W25X_FastReadData); // read command
SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16)); // send 3 address bytes
SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8));
SPI_Send_Byte(Dst_Addr & 0xFF);
SPI_Send_Byte(0xFF); // dummy byte
for (i = 0; i < nBytes_128; i++) // read until no_bytes is reached
upper_128[i] = SPI_Get_Byte(); // receive byte and store at address 80H - FFH
W25X_CS = 1; // disable device
}
void SPI_Write_Byte(uint32 Dst_Addr, uchar byte)
{ W25X_CS = 0; // enable device
SPI_Write_Enable(); // set WEL
SPI_Wait_Busy();
W25X_CS = 0;
SPI_Send_Byte(W25X_PageProgram); // send Byte Program command
SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16)); // send 3 address bytes
SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8));
SPI_Send_Byte(Dst_Addr & 0xFF);
SPI_Send_Byte(byte); // send byte to be programmed
W25X_CS = 1; // disable device
}
void SPI_Write_nBytes(uint32 Dst_Addr, uchar nBytes_128)
{
uchar i, byte;
W25X_CS = 0; /* enable device */
SPI_Write_Enable(); /* set WEL */
W25X_CS = 0;
SPI_Send_Byte(W25X_PageProgram); /* send Byte Program command */
SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16)); /* send 3 address bytes */
SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8));
SPI_Send_Byte(Dst_Addr & 0xFF);
for (i = 0; i < nBytes_128; i++)
{
byte = upper_128[i];
SPI_Send_Byte(byte); /* send byte to be programmed */
}
W25X_CS = 1; /* disable device */
}
void SPI_Erase_Chip()
{
W25X_CS = 0; // enable device
SPI_Write_Enable(); // set WEL
W25X_CS = 0;
SPI_Wait_Busy();
W25X_CS = 0;
SPI_Send_Byte(W25X_ChipErase); // send Chip Erase command
W25X_CS = 1; // disable device
}
void SPI_Erase_Sector(uint32 Dst_Addr)
{ W25X_CS = 0; // enable device
SPI_Write_Enable(); // set WEL
W25X_CS = 0;
SPI_Send_Byte(W25X_SectorErase); // send Sector Erase command
SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFFFF) >> 16));// send 3 address bytes
SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFF) >> 8));
SPI_Send_Byte((uchar)Dst_Addr & 0xFF);
W25X_CS = 1; // disable device
}
void SPI_Wait_Busy()
{ while (SPI_Read_StatusReg() == 0x03)
SPI_Read_StatusReg(); // waste time until not busy WEL & Busy bit all be 1 (0x03)
}
void SPI_PowerDown()
{ W25X_CS = 0; // enable device
SPI_Send_Byte(W25X_PowerDown); // send W25X_PowerDown command 0xB9
W25X_CS = 1; // disable device
delay(6); // remain CS high for tPD = 3uS
}
void SPI_ReleasePowerDown()
{ W25X_CS = 0; // enable device
SPI_Send_Byte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB
W25X_CS = 1; // disable device
delay(6); // remain CS high for tRES1 = 3uS
}
#ifdef SST_SPI
void SPI_init()
{ P1 = 0xFF;
SPCR = 0x50;
}
void SPI_Send_Byte(uchar out)
{ unsigned char temp;
SPDR = out;
do { temp = SPSR & 0x80; } while (temp != 0x80);
SPSR = SPSR & 0x7F;
}
uchar SPI_Get_Byte()
{ unsigned char temp;
SPDR = 0x00;
do { temp = SPSR & 0x80; } while (temp != 0x80);
SPSR = SPSR & 0x7F;
return SPDR;
}
#endif
#ifndef SST_SPI
void SPI_init()
{ W25X_CLK = 0; // set clock to low initial state for SPI operation mode 0
// W25X_CLK = 1; // set clock to High initial state for SPI operation mode 3
// _hold = 1;
W25X_WP = 1;
W25X_CS = 1;
SPI_Write_Disable();
}
void SPI_Send_Byte(uchar out)
{ uchar i = 0;
for (i = 0; i < 8; i++)
{ if ((out & 0x80) == 0x80) // check if MSB is high
W25X_DI = 1;
else
W25X_DI = 0; // if not, set to low
W25X_CLK = 1; // toggle clock high
out = (out << 1); // shift 1 place for next bit
nop();nop();nop();nop();
W25X_CLK = 0; // toggle clock low
}
}
uchar SPI_Get_Byte()
{ uchar i = 0, in = 0, temp = 0;
for (i = 0; i < 8; i++)
{ in = (in << 1); // shift 1 place to the left or shift in 0
temp = W25X_DO; // save input
W25X_CLK = 1; // toggle clock high
if (temp == 1) // check to see if bit is high
in |= 0x01; // if high, make bit high
W25X_CLK = 0; // toggle clock low
}
return in;
}
#endif
//=================================================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -