模拟SPI驱动W25Q16程序 (DSP 28X系列)

为了驱动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);
	}
}

 

你可能感兴趣的:(编程)