为了驱动SPI FLASH而写的驱动程序,写的时候主要是板子的自带SPI接口被占用,只好使用IO口模拟一个SPI接口程序;
w25q16 芯片工作在SPI工作模式0和模式3中;在此spi的原理不多做说明,只需知道模式0和模式3主要是在时钟的上升沿采样即可。(时钟空闲时电平为低,则为模式1;时钟空闲时电平为高,则为模式3)
下面直接贴代码:
#define W25Q16_PAGE_SIZE 256 //一页的大小,256字节
#define W25Q16_SECTOR_SIZE (4*1024) //扇区大小,字节
#define W25Q16_BLOCK_SIZE (16*W25Q16_SECTOR_SIZE)
#define W25Q16_SIZE (32*W25Q16_BLOCK_SIZE)
#define MOSI_H (GpioDataRegs.GPASET.bit.GPIO16 = 1)
#define MOSI_L (GpioDataRegs.GPACLEAR.bit.GPIO16 = 1)
#define SPICLK_H (GpioDataRegs.GPASET.bit.GPIO17 = 1)
#define SPICLK_L (GpioDataRegs.GPACLEAR.bit.GPIO17 = 1)
#define FLASH_CS_SET (GpioDataRegs.AIOSET.bit.AIO12 = 1)
#define FLASH_CS_RESET (GpioDataRegs.AIOCLEAR.bit.AIO12 = 1)
#define READ_MISO GpioDataRegs.GPADAT.bit.GPIO6
const Uint8 byDUMMY = 0xff;
void SPI_Init(void)
{
FLASH_CS_SET;
SPICLK_L;
MOSI_H;
}
static void SPI_Set_MOSI(Uint8 val)
{
if(val)
MOSI_H;
else
MOSI_L;
}
/*******************************************************************************
* Function Name : SPIReadWriteByte
* Description : SPI读写函数
* Input : val 传输数据
* Output : RevData 接收数据
* Return : None
*******************************************************************************/
static Uint8 SPIReadWriteByte(Uint8 val)
{
Uint16 i;
Uint8 RevData = 0;
//Uint16 wReadDO;
for(i=0; i<8; i++)
{
SPICLK_L;
SPI_Set_MOSI(val & 0x80);
DSP28x_usDelay(1);
val <<= 1;
SPICLK_H;
RevData <<= 1;
//wReadDO = GpioDataRegs.GPADAT.bit.GPIO6;
RevData |=READ_MISO;
DSP28x_usDelay(1);
}
return RevData;
}
/*******************************************************************************
* Function Name : W25Q16_ReadWriteDate
* Description : SPIFLASH 读写函数
* Input : None
* Output : None
* Return : None
*******************************************************************************/
Uint8 W25Q16_ReadWriteDate(Uint8 val)
{
return SPIReadWriteByte(val);
}
/*******************************************************************************
* Function Name : W25q64_WriteEnable
* Description : 写使能
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void W25q16_WriteEnable(void)
{
FLASH_CS_RESET;
W25Q16_ReadWriteDate(0x06);
FLASH_CS_SET;
}
/*******************************************************************************
* Function Name : W25Q16_WaitForWriteEnd
* Description : 等待FLASH内部时序操作完成
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void W25Q16_WaitForWriteEnd(void)
{
Uint8 status = 0;
FLASH_CS_RESET;
W25Q16_ReadWriteDate(0x05);
do
{
status = W25Q16_ReadWriteDate(byDUMMY);
}
while((status & 0x01) == 1);
FLASH_CS_SET;
}
/*******************************************************************************
* Function Name : W25q16_WriteStatusReg1
* Description : 写状态寄存器1
* Input : status:状态值
* Output : None
* Return : None
*******************************************************************************/
void W25q16_WriteStatusReg1(Uint16 status)
{
W25q16_WriteEnable();
FLASH_CS_RESET;
W25Q16_ReadWriteDate(0x01);
W25Q16_ReadWriteDate(status & 0xFF);
W25Q16_ReadWriteDate((status>>8) & 0xFF);
FLASH_CS_SET;
W25Q16_WaitForWriteEnd();
}
/*******************************************************************************
* Function Name : W25q16_ReadStatus
* Description : 读状态寄存器
* Input : None
* Output : None
* Return : 状态寄存器值
*******************************************************************************/
Uint16 W25q16_ReadStatus(void)
{
Uint16 status=0;
FLASH_CS_RESET;
W25Q16_ReadWriteDate(0x05);
status = W25Q16_ReadWriteDate(byDUMMY);
FLASH_CS_SET;
FLASH_CS_RESET;
W25Q16_ReadWriteDate(0x35);
status |= W25Q16_ReadWriteDate(byDUMMY)<<8;
FLASH_CS_SET;
return status;
}
/*******************************************************************************
* Function Name : W25q16_ReadDeviceID
* Description : 读芯片ID
* Input : None
* Output : None
* Return : None
*******************************************************************************/
Uint16 W25q16_ReadDeviceID(void)
{
Uint8 DeviceID=0;
FLASH_CS_RESET;
W25Q16_ReadWriteDate(0xAB);
W25Q16_ReadWriteDate(byDUMMY);
W25Q16_ReadWriteDate(byDUMMY);
W25Q16_ReadWriteDate(byDUMMY);
DeviceID = W25Q16_ReadWriteDate(0X00);
FLASH_CS_SET;
return DeviceID;
}
/*******************************************************************************
* Function Name : W25q16_ReadJEDE_ID
* Description : 读芯片ID
* Input : None
* Output : None
* Return : None
*******************************************************************************/
Uint16 W25q16_ReadJEDE_ID(void)
{
Uint16 DeviceID=0;
FLASH_CS_RESET;
W25Q16_ReadWriteDate(0x9F);
W25Q16_ReadWriteDate(byDUMMY);
// W25Q16_ReadWriteDate(byDUMMY);
// W25Q16_ReadWriteDate(0x00);
DeviceID = W25Q16_ReadWriteDate(byDUMMY)<<8;
DeviceID |= W25Q16_ReadWriteDate(byDUMMY);
FLASH_CS_SET;
return DeviceID;
}
/*******************************************************************************
* Function Name : W25q16_Read
* Description : 读数据
* Input : buf:数据缓冲区
len:长度
addr:起始地址
* Output : None
* Return : None
*******************************************************************************/
void W25q16_Read(Uint8 *buf, Uint32 len, Uint32 addr)
{
Uint32 i;
FLASH_CS_RESET;
W25Q16_ReadWriteDate(0x03);
W25Q16_ReadWriteDate((addr & 0xFF0000)>>16);
W25Q16_ReadWriteDate((addr & 0x00FF00)>>8);
W25Q16_ReadWriteDate(addr & 0xFF);
for (i=0; i>16);
W25Q16_ReadWriteDate((addr & 0x00FF00)>>8);
W25Q16_ReadWriteDate(addr & 0xFF);
FLASH_CS_SET;
W25Q16_WaitForWriteEnd();
}
/*******************************************************************************
* Function Name : W25q16_32KErase
* Description : 32K片擦除
* Input : addr:起始地址
* Output : None
* Return : None
*******************************************************************************/
void W25q16_32KErase(Uint32 addr)
{
W25q16_WriteEnable();
FLASH_CS_RESET;
W25Q16_ReadWriteDate(0x52);
W25Q16_ReadWriteDate((addr & 0xFF0000)>>16);
W25Q16_ReadWriteDate((addr & 0x00FF00)>>8);
W25Q16_ReadWriteDate(addr & 0xFF);
FLASH_CS_SET;
W25Q16_WaitForWriteEnd();
}
/*******************************************************************************
* Function Name : W25q16_64KErase
* Description : 64K片擦除
* Input : addr:起始地址
* Output : None
* Return : None
* Date : 2014-10-24
* Author : ADT LL
*******************************************************************************/
void W25q16_64KErase(Uint32 addr)
{
W25q16_WriteEnable();
FLASH_CS_RESET;
W25Q16_ReadWriteDate(0xD8);
W25Q16_ReadWriteDate((addr & 0xFF0000)>>16);
W25Q16_ReadWriteDate((addr & 0x00FF00)>>8);
W25Q16_ReadWriteDate(addr & 0xFF);
FLASH_CS_SET;
W25Q16_WaitForWriteEnd();
}
/*******************************************************************************
* Function Name : W25q16_PageProgram
* Description : 页写
* Input : buf:要写内的数据
len:数据长度
add:起始地址
* Output : None
* Return : 状态码
*******************************************************************************/
static void W25q16_PageProgram(Uint8 *buf, Uint16 len, Uint32 addr)
{
//是否判断len 与addr 超限问题???
//......
W25q16_WriteEnable();
FLASH_CS_RESET;
W25Q16_ReadWriteDate(0x02);
W25Q16_ReadWriteDate((addr & 0xFF0000)>>16);
W25Q16_ReadWriteDate((addr & 0x00FF00)>>8);
W25Q16_ReadWriteDate(addr & 0xFF);
while (len--)
{
W25Q16_ReadWriteDate(*buf);
buf++;
}
FLASH_CS_SET;
W25Q16_WaitForWriteEnd();
}
/*******************************************************************************
* Function Name : W25q64_Write
* Description : 数据存储
* Input : buf:要写内的数据
len:数据长度
add:起始地址
* Output : None
* Return : None
*******************************************************************************/
void W25q16_Write(Uint8 *buf, Uint16 len, Uint32 addr)
{
Uint8 pagenum;
Uint8 addrbyte;//最低八位地址
addrbyte = addr%W25Q16_PAGE_SIZE;
if (len > (W25Q16_PAGE_SIZE - addrbyte))//跨页了
{
W25q16_PageProgram(buf, W25Q16_PAGE_SIZE - addrbyte, addr);//写满本页
addr += W25Q16_PAGE_SIZE-addrbyte;
buf += W25Q16_PAGE_SIZE-addrbyte;
len -= W25Q16_PAGE_SIZE-addrbyte;
pagenum = len/W25Q16_PAGE_SIZE;
while (pagenum--)
{
W25q16_PageProgram(buf, W25Q16_PAGE_SIZE, addr);
addr += W25Q16_PAGE_SIZE;
buf += W25Q16_PAGE_SIZE;
len -= W25Q16_PAGE_SIZE;
}
W25q16_PageProgram(buf, len, addr);
}
else
{
W25q16_PageProgram(buf, len, addr);
}
}