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;}
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
- spi flash驱动代码分析(二)
- spi flash驱动代码分析(一)
- SPI总线(二):驱动分析篇
- SPI专题(二)——STM32驱动FLASH(W25Q64)
- linux内核SPI总线驱动分析(二)
- linux内核SPI总线驱动分析(二)
- spi flash 驱动
- spi flash控制驱动
- SPI FLASH 驱动
- SPI Flash驱动目录
- spi nor flash驱动
- spi flash驱动
- Linux spi驱动(二)
- 读写SPI FLASH--驱动部分
- spi flash驱动开发注意事项
- SPI实现SST25VF016B驱动(Flash)
- SylixOS SPI Flash驱动移植
- ARM9 ADS8344 SPI驱动移植 (二)
- how to make the XVim still available on xcode7
- 1049. Counting Ones (30)
- Linux /etc/hosts文件
- 用独立键盘实现数码管计数的启动与停止
- iOS 国际化简单记录
- spi flash驱动代码分析(二)
- 相同的雪花
- Newstate: 对新闻点击流数据的可视分析
- Linux键盘快捷键
- eclipse安装svn插件图文
- Android初学之路(二)
- 什么是设计模式?为什么要使用设计模式?有什么好处?
- iOS如何在一个图标上加上气泡,显示数字
- 程序运行闪图界面以及传感器