STM32CubeMx入门教程(6):SPI读写FLAH的应用_第1页
STM32CubeMx入门教程(6):SPI读写FLAH的应用_第2页
STM32CubeMx入门教程(6):SPI读写FLAH的应用_第3页
STM32CubeMx入门教程(6):SPI读写FLAH的应用_第4页
STM32CubeMx入门教程(6):SPI读写FLAH的应用_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第第页STM32CubeMx入门教程(6):SPI读写FLAH的应用

导语“本(教程)将使用CubeMX初始化SPI,使用SPI对W25Q64FLASH进行读写操作,通过HAL库的读写应用来数据FLASH的操作细节。”

01系统要求

•(硬件)

野火指南者开发板

•软件

CubeMx"class="hljscsharpvditor-linenumber">//指令表#defineW25X_Wri(te)Enable0x06#defineW25X_WriteDisable0x04#defineW25X_Re(ad)StatusReg0x05#defineW25X_WriteStatusReg0x01#defineW25X_ReadData0x03#defineW25X_FastReadData0x0B#defineW25X_FastReadDual0x3B#defineW25X_PageProg(ram)0x02#defineW25X_BlockErase0xD8#defineW25X_SectorErase0x20#defineW25X_ChipErase0xC7#defineW25X_PowerDown0xB9#defineW25X_ReleasePowerDown0xAB#defineW25X_DeviceIDxAB#defineW25X_ManufactDeviceID0x90#defineW25X_JedecDeviceID0x9F//othe(rs)defined#definesFLASH_ID0XEF4017#defineDummy_Byte0XFF#defineSPI_FLASH_PageSize256#defineSPI_FLASH_PerWritePageSize256#defineSPI1_(TI)ME_OUT0xFFFF并且申明应用的操作函数:

voidSPI_FLASH_SectorErase(uint32_tSectorAddr);uint32_tSPI_Flash_Re(adI)D(void);voidSPI_Flash_Erase_Chip(void);voidSPI_Flash_Read(uint32_tReadAddr,uint16_tNumByteToRead,uint8_t*pBuffer);voidSPI_Flash_Write(uint32_tWriteAddr,uint16_tNumByteToWrite,uint8_t*pBuffer);voidSPI_Flash_Write_Page(uint32_tWriteAddr,uint16_tNumByteToWrite,uint8_t*pBuffer);下面我们在spi.c中实现读写FLASH的相关函数:

(1)对片选的信号引脚进行宏定义操作:

#defineSPI_FLASH_CS_H()HAL_GPIO_Write(Pi)n(GPIOC,GPIO_PIN_0,GPIO_PIN_SET)#defineSPI_FLASH_CS_L()HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_RESET)根据原理图使用的PC0引脚

(2)SPI读写个字节函数

/**function:SPI读一个数据**/uint8_tSPI1_ReadByte(void){uint8_tRxData;HAL_SPI_Receive(returnRxData;//返回通过SPIx接收的数据}我们使用了HAL封装的HALSPIReceive("class="hljslessvditor-linenumber">/**function:SPI写一个数据**/voidSPI1_WriteByte(uint8_tTxData){HAL_SPI_Transmit(//通过外设SPIx发送一个数据}(4)FLASH的写使能和非使能/**function:SPI_FLASH写使能,将WEL置位**/voidSPI_FLASH_Write_Enable(void){SPI_FLASH_CS_L();//使能器件SPI1_WriteByte(W25X_WriteEnable);//发送写使能SPI_FLASH_CS_H();//取消片选}/**function:SPI_FLASH写禁止,将WEL清零**/voidSPI_FLASH_Write_Disable(void){SPI_FLASH_CS_L();//使能器件SPI1_WriteByte(W25X_WriteDisable);//发送写禁止指令SPI_FLASH_CS_H();//取消片选}(5)读取SPI_FLASH的状态(寄存器),通过这个函数我们可以判断FLASH的状态,一般用到的忙和空闲两种状态,这儿也实现了等待空闲函数。

/**function:读取SPI_FLASH的状态寄存器**/////BIT76543210//SPRRVTBBP2BP1BP0WELBUSY//SPR:默认0,状态寄存器保护位,配合WP使用//TB,BP2,BP1,BP0:FLASH区域写保护设置//WEL:写使能锁定//BUSY:忙标记位(1,忙;0,空闲)//默认:0x00uint8_tSPI_Flash_ReadSR(void){uint8_tbyte=0;SPI_FLASH_CS_L();//使能器件SPI1_WriteByte(W25X_ReadStatusReg);//发送读取状态寄存器命令byte=SPI1_ReadByte();//读取一个字节SPI_FLASH_CS_H();//取消片选returnbyte;}/**function:等待空闲**/voidSPI_Flash_W(ai)t_Busy(void){while((SPI_Flash_ReadSR()//等待BUSY位清空}(6)读取(芯片)IDW25Q64的ID函数,这个函数也是一般判断是否FLASH正常的方式。查看手册可以知道ID是0XEF4017

/**function:读取芯片IDW25Q64的ID**/uint32_tSPI_Flash_ReadID(void){uint32_tTemp=0,Temp0=0,Temp1=0,Temp2=0;SPI_FLASH_Write_Enable();SPI_FLASH_CS_L();SPI1_WriteByte(W25X_JedecDeviceID);//发送读取ID命令Temp0=SPI1_ReadByte();Temp1=SPI1_ReadByte();Temp2=SPI1_ReadByte();/*把数据组合起来,作为函数的返回值*/Temp=(Temp0(7)flash扇区擦除函数,FLASH和EEP(ROM)不同,在写之前一定要进行擦除,否则不能正常写入。这儿实现了扇区擦除和正片擦除两个函数:

/**function:擦除整个芯片**///整片擦除时间://W25X16:25s//W25X32:40s//W25X64:40s//等待时间超长...voidSPI_Flash_Erase_Chip(void){SPI_FLASH_Write_Enable();//SETWELSPI_Flash_Wait_Busy();SPI_FLASH_CS_L();//使能器件SPI1_WriteByte(W25X_ChipErase);//发送片擦除命令SPI_FLASH_CS_H();//取消片选SPI_Flash_Wait_Busy();//等待芯片擦除结束}/**function:SPI_FLASH_SectorEraseannotation:Flash的一个扇区是4K,所以输入的地址要和4K对其。**/voidSPI_FLASH_SectorErase(uint32_tSectorAddr){SPI_FLASH_Write_Enable();SPI_Flash_Wait_Busy();SPI_FLASH_CS_L();SPI1_WriteByte(W25X_SectorErase);SPI1_WriteByte((SectorAddrSPI1_WriteByte((SectorAddrSPI1_WriteByte(SectorAddrSPI_FLASH_CS_H();SPI_Flash_Wait_Busy();}(8)读取FLASH函数,FLASH的读操作步骤很简单

/**function:读取SPIFLASH**///在指定地址开始读取指定长度的数据//pBuffer:数据存储区//ReadAddr:开始读取的地址(24bit)//NumByteToRead:要读取的字节数(最大65535)voidSPI_Flash_Read(uint32_tReadAddr,uint16_tNumByteToRead,uint8_t*pBuffer){uint16_ti;SPI_FLASH_CS_L();//使能器件SPI1_WriteByte(W25X_ReadData);//发送读取命令SPI1_WriteByte((uint8_t)((ReadAddr)>

>16));//发送24bit地址SPI1_WriteByte((uint8_t)((ReadAddr)>

>8));SPI1_WriteByte((uint8_t)ReadAddr);f(or)(i=0;i{pBuffer[i]=SPI1_ReadByte();//循环读数}SPI_FLASH_CS_H();//取消片选}(9)flash的按页写入数据,FLASH的数据的写入不是随机可以任意写入,按页写入,一页最大的数据是256个字节。

/**function:SPI在一页(0~65535)内写入少于256个字节的数据annotation:一页最大256个字节**///在指定地址开始写入最大256字节的数据//pBuffer:数据存储区//WriteAddr:开始写入的地址(24bit)//NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!voidSPI_Flash_Write_Page(uint32_tWriteAddr,uint16_tNumByteToWrite,uint8_t*pBuffer){uint16_ti;SPI_FLASH_Write_Enable();//SETWELSPI_FLASH_CS_L();//使能器件SPI1_WriteByte(W25X_PageProgram);//发送写页命令SPI1_WriteByte((uint8_t)((WriteAddr)>

>16));//发送24bit地址SPI1_WriteByte((uint8_t)((WriteAddr)>

>8));SPI1_WriteByte((uint8_t)WriteAddr);for(i=0;i(10)flash的随机的多字节写入,通过按页写入实现的函数来实现

/**@function不定量的写入数据,先确保写入前擦出扇区@annotation@param@retval**/voidSPI_Flash_Write(uint32_tWriteAddr,uint16_tNumByteToWrite,uint8_t*pBuffer){uint8_tNumOfPage=0,NumOfSingle=0,Addr=0,count=0,temp=0;/*计算Addr,写入的地址是否和PageSize对齐*/Addr=WriteAddr%SPI_FLASH_PageSize;/*count为剩余的地址*/count=SPI_FLASH_PageSize-Addr;/*计算能写入多少整数页*/NumOfPage=NumByteToWrite%SPI_FLASH_PageSize;/*计算不满一页的数据*/NumOfSingle=NumByteToWrite%SPI_FLASH_PageSize;/*Addr=0,则WriteAddr刚好按页对齐aligned*/if(Addr==0){/*NumByteToWriteSPI_FLASH_PageSize,一页写不完,先写整数页,在写剩下的*/{/*先把整数页都写了*/while(NumOf){SPI_Flash_Write_Page(WriteAddr,SPI_FLASH_PageSize,pBuffer);WriteAddr+=SPI_FLASH_PageSize;//flash的地址加一页的大小pBuffer+=SPI_FLASH_PageSize;//写缓存数据的地址加一页的大小}/*若有多余的不满一页的数据,把它写完*/SPI_Flash_Write_Page(WriteAddr,NumOfSingle,pBuffer);}}else/*若地址与SPI_FLASH_PageSize不对齐*/{/*NumByteToWritecount){temp=NumOfSingle-count;/*先写满当前页*/SPI_Flash_Write_Page(WriteAddr,count,pBuffer);WriteAddr+=count;pBuffer+=count;/*再写剩余的数据*/SPI_Flash_Write_Page(WriteAddr,temp,pBuffer);}else/*当前页剩余的count个位置能写完NumOfSingle个数据*/{SPI_Flash_Write_Page(WriteAddr,NumByteToWrite,pBuffer);}}else/*NumByteToWrite>SPI_FLASH_PageSize*/{/*地址不对齐多出的count分开处理,不加入这个运算*/NumByteToWrite-=count;NumOfPage=NumByteToWrite/SPI_FLASH_PageSize;NumOfSingle=NumByteToWrite%SPI_FLASH_PageSize;/*先写完count个数据,为的是让下一次要写的地址对齐*/SPI_Flash_Write_Page(WriteAddr,count,pBuffer);/*接下来就重复地址对齐的情况*/WriteAddr+=count;pBuffer+=count;/*把整数页都写了*/while(NumOf){SPI_Flash_Write_Page(WriteAddr,SPI_FLASH_PageSize,pBuffer);WriteAddr+=SPI_FLASH_PageSize;pBuffer+=SPI_FLASH_PageSize;}/*若有多余的不满一页的数据,把它写完*/if(NumOfSingle!=0){SPI_Flash_Write_Page(WriteAddr,NumOfSingle,pBuffer);}}}}通过上面的函数实现,我们就可以基本的来完成FLASH的读写操作了。有些函数参考了野火标准

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论