spi flash驱动代码分析(二)

来源:互联网 发布:java lamda表达式语法 编辑:程序博客网 时间:2024/06/05 23:03

一、spi flash裸机驱动代码


/**W25Q64一共8M容量?*分为128个快,每块大小为64K字节?*每块又可以分为16个扇区,每个扇区4K字节?//每次擦除最少一个扇区,也就是4K字节?//25Q64?一共有2048个扇区*一页256字节*/#define W25Q64_PAGE_SIZE    256                          //一页的大小,256字节#define W25Q64_SECTOR_SIZE (4*1024)                      //扇区大小,字节#define W25Q64_BLOCK_SIZE  (16*W25Q64_SECTOR_SIZE)#define W25Q64_SIZE        (128*W25Q64_BLOCK_SIZE)void W25q64_Init(void){    1.可以用GPIO模拟SPI    2.也可以用spi控制器<span style="white-space:pre"></span>}/******************************************************************************** Function Name  : W25q_ReadWriteByte * Description    : W25q芯片SPI读写接口函数* Input          : None* Output         : None* Return         : None* Date           : 2014-05-14* Author         : ADT LL*******************************************************************************/static uint8_t W25q_ReadWriteByte(uint8_t data){  return SSP_SendData(data);  }/******************************************************************************** Function Name  : W25q64_WaitForIdle* Description    : 读状态寄存器* Input          : None* Output         : None* Return         : None* Date           : 2014-10-24* Author         : ADT LL*******************************************************************************/void W25q64_WaitForIdle(void){  uint8_t status=0;  CS1_RESET;  W25q_ReadWriteByte(0x05);  do  {    status = W25q_ReadWriteByte(0xA5);  }while (status&0x01 == 0x01);  CS1_SET;  }/******************************************************************************** Function Name  : W25q64_WriteEnable* Description    : 写使能* Input          : None* Output         : None* Return         : None* Date           : 2014-10-24* Author         : ADT LL*******************************************************************************/void W25q64_WriteEnable(void){  CS1_RESET;  W25q_ReadWriteByte(0x06);  CS1_SET; }/******************************************************************************** Function Name  : W25q64_4KErase* Description    : 4K片擦除* Input          : addr:起始地址* Output         : None* Return         : None* Date           : 2014-10-24* Author         : ADT LL*******************************************************************************/void  W25q64_4KErase(uint32_t addr){  W25q64_WriteEnable();  CS1_RESET;  W25q_ReadWriteByte(0x20);  W25q_ReadWriteByte((addr & 0xFF0000)>>16);  W25q_ReadWriteByte((addr & 0x00FF00)>>8);  W25q_ReadWriteByte(addr & 0xFF);  CS1_SET;     W25q64_WaitForIdle(); }/******************************************************************************** Function Name  : W25q64_32KErase* Description    : 32K片擦除* Input          : addr:起始地址* Output         : None* Return         : None* Date           : 2014-10-24* Author         : ADT LL*******************************************************************************/void  W25q64_32KErase(uint32_t addr){  W25q64_WriteEnable();  CS1_RESET;  W25q_ReadWriteByte(0x52);  W25q_ReadWriteByte((addr & 0xFF0000)>>16);  W25q_ReadWriteByte((addr & 0x00FF00)>>8);  W25q_ReadWriteByte(addr & 0xFF);  CS1_SET;    W25q64_WaitForIdle();  }/******************************************************************************** Function Name  : W25q64_64KErase* Description    : 64K片擦除* Input          : addr:起始地址* Output         : None* Return         : None* Date           : 2014-10-24* Author         : ADT LL*******************************************************************************/void  W25q64_64KErase(uint32_t addr){  W25q64_WriteEnable();  CS1_RESET;  W25q_ReadWriteByte(0xD8);  W25q_ReadWriteByte((addr & 0xFF0000)>>16);  W25q_ReadWriteByte((addr & 0x00FF00)>>8);  W25q_ReadWriteByte(addr & 0xFF);  CS1_SET;    W25q64_WaitForIdle();  }/******************************************************************************** Function Name  : W25q64_ChipErase* Description    : Chip片擦除* Input          : addr:起始地址* Output         : None* Return         : None* Date           : 2014-10-24* Author         : ADT LL*******************************************************************************/void  W25q64_ChipErase(uint32_t addr){  W25q64_WriteEnable();  CS1_RESET;  W25q_ReadWriteByte(0xC7);  W25q_ReadWriteByte((addr & 0xFF0000)>>16);  W25q_ReadWriteByte((addr & 0x00FF00)>>8);  W25q_ReadWriteByte(addr & 0xFF);  CS1_SET;    W25q64_WaitForIdle();  }/******************************************************************************** Function Name  : W25q64_Erase* Description    : 擦除操作,最小以4K为单位进行,从擦除。* Input          : sectornum:块数,擦除的空间大小为sectornum*4K                    --例如:如果sectornum=1,则擦除4K字节,                      sectornum=3,则擦除12K=4K*3个字节                   addr:起始地址* Output         : None* Return         : 状态码* Date           : 2014-10-25* Author         : ADT LL*******************************************************************************/int W25q64_Erase(uint32_t base_addr,int sector_count){  if (base_addr % W25Q64_SECTOR_SIZE ) {  return -1;  }  if (base_addr>=W25Q64_SIZE) return -1;    while(sector_count = sector_count / 16) {   W25q64_64KErase(base_addr); base_addr += 16*W25Q64_SECTOR_SIZE;  }  while(sector_count = sector_count / 8) {   W25q64_32KErase(base_addr); base_addr += 8*W25Q64_SECTOR_SIZE;  }  while(sector_count--) {   W25q64_4KErase(base_addr); base_addr += W25Q64_SECTOR_SIZE;  }  return 0; }/******************************************************************************** Function Name  : W25q64_PageProgram* Description    : 页写* Input          : buf:要写内的数据                   len:数据长度                   add:起始地址* Output         : None* Return         : 状态码* Date           : 2014-10-24* Author         : ADT LL*******************************************************************************/static int  W25q64_PageProgram(uint8_t *buf, uint16_t len, uint32_t addr){  if (addr>=W25Q64_SIZE) return -1;  if (len<=0 || len>256) return -1;//没有数据不操作  W25q64_WriteEnable();  CS1_RESET;  W25q_ReadWriteByte(0x02);  W25q_ReadWriteByte((addr & 0xFF0000)>>16);  W25q_ReadWriteByte((addr & 0x00FF00)>>8);  W25q_ReadWriteByte(addr & 0xFF);  while (len--)  {    W25q_ReadWriteByte(*buf);    buf++;     }  CS1_SET;    W25q64_WaitForIdle();    return 0;   }/******************************************************************************** Function Name  : W25q64_Write* Description    : 数据存储,为防止意外的擦除* Input          : buf:要写内的数据                   len:数据长度                   add:起始地址* Output         : None* Return         : None* Date           : 2014-10-24* Author         : ADT LL*******************************************************************************/void W25q64_Write(uint8_t *buf, uint16_t len, uint32_t addr){  uint8_t pagenum;  uint8_t addrbyte;//最低八位地址    addrbyte = addr%W25Q64_PAGE_SIZE;  if (len > (W25Q64_PAGE_SIZE - addrbyte))//跨页了  {      W25q64_PageProgram(buf, W25Q64_PAGE_SIZE - addrbyte, addr);//写满本页      addr += W25Q64_PAGE_SIZE-addrbyte;      buf += W25Q64_PAGE_SIZE-addrbyte;      len -= W25Q64_PAGE_SIZE-addrbyte;      pagenum = len/W25Q64_PAGE_SIZE;       while (pagenum--)      {        W25q64_PageProgram(buf, W25Q64_PAGE_SIZE, addr);        addr += W25Q64_PAGE_SIZE;        buf += W25Q64_PAGE_SIZE;        len -= W25Q64_PAGE_SIZE;        }      W25q64_PageProgram(buf, len, addr);        }  else  {    W25q64_PageProgram(buf, len, addr);     } }/******************************************************************************** Function Name  : W25q64_WriteStatus* Description    : 写状态寄存器* Input          : status:状态值* Output         : None* Return         : None* Date           : 2014-10-24* Author         : ADT LL*******************************************************************************/void W25q64_WriteStatus(uint16_t status){  W25q64_WriteEnable();  CS1_RESET;  W25q_ReadWriteByte(0x01);  W25q_ReadWriteByte(status & 0xFF);  W25q_ReadWriteByte((status>>8) & 0xFF);  CS1_SET;  W25q64_WaitForIdle();    }/******************************************************************************** Function Name  : W25q64_ReadStatus* Description    : 读状态寄存器* Input          : None* Output         : None* Return         : 状态寄存器值* Date           : 2014-10-24* Author         : ADT LL*******************************************************************************/uint16_t W25q64_ReadStatus(void){  uint16_t status=0;  CS1_RESET;  W25q_ReadWriteByte(0x05);  status = W25q_ReadWriteByte(0xFF);  CS1_SET;  CS1_RESET;  W25q_ReadWriteByte(0x35);  status |= W25q_ReadWriteByte(0xFF)<<8;  CS1_SET;    return status;  }/******************************************************************************** Function Name  : W25q64_ReadDeviceID* Description    : 读字库芯片ID* Input          : None* Output         : None* Return         : None* Date           : 2014-10-20* Author         : ADT LL*******************************************************************************/uint16_t W25q64_ReadDeviceID(void){  uint16_t DeviceID=0;  CS1_RESET;  W25q_ReadWriteByte(0x90);  W25q_ReadWriteByte(0x00);  W25q_ReadWriteByte(0x00);  W25q_ReadWriteByte(0x00);  DeviceID = W25q_ReadWriteByte(0xFF)<<8;  DeviceID |= W25q_ReadWriteByte(0xFF);  CS1_SET;  return DeviceID;}/******************************************************************************** Function Name  : W25q64_Read* Description    : 读数据* Input          : buf:数据缓冲区                   len:长度                   addr:起始地址* Output         : None* Return         : 返回状态,暂无意义* Date           : 2014-10-20* Author         : ADT LL*******************************************************************************/uint8_t W25q64_Read(uint8_t *buf, uint32_t len, uint32_t addr){  uint32_t i;  uint8_t status;  //if (addr>=W25Q64_TOPADDR) return W25Q64_ADDRERROR;  CS1_RESET;      status = W25q_ReadWriteByte(CODE_READDATA);  status = W25q_ReadWriteByte((addr & 0xFF0000)>>16);  status = W25q_ReadWriteByte((addr & 0x00FF00)>>8);  status = W25q_ReadWriteByte(addr & 0xFF);  for (i=0; i<len; i++)  {    buf[i] = W25q_ReadWriteByte(0xFF);  }  status = 0;  CS1_SET;  return status;}


二、SPI 接口驱动代码


1.如果是GPIO模拟SPI

/*GPIO模拟SPI协议读写函数*/uint8_t SPI_RW(uint8_t data){  char buf[24];uint8_t bit_ctr;   for(bit_ctr=0;bit_ctr<8;bit_ctr++)   // output 8-bit   {if((data & 0x80)) {MOSI_H;} else {MOSI_L;}data = (data << 1); SCK_H;delayUs(1);data |= MISO ? 1 : 0;SCK_L;delayUs(1);   }    return(data);    }
2.如果是spi控制器读写spi

spi flash的CS片选如果接spi接口的SSEL要注意,由于 spi控制器的SSEL端不受代码控制的,这里我单独用了一个gpio来做CS片选。

uint8_t  SSP_SendData(uint8_t data){  #ifndef GPIO_SPI    LPC_SSP1->DR = data;    while( (LPC_SSP1->SR & 0x01) == 0 );   /* 等待TFE置位,即发送FIFO空    */    while((LPC_SSP1->SR & 0x04) == 0);    /*等待接收fifo不为空*/    return (LPC_SSP1->DR);#else    return SPI_RW(data);#endif}



0 0
原创粉丝点击