stm32|【STM32】HAL库开发教程(九)—W25qxx使用

前言 不必害怕未知,无需恐惧犯错,做一个Creator!
本文主要介绍STM32_HAL库开发中W25qxx的配置使用
一、开发步骤 1.指令表配置 W25qxx的系列芯片的指令表大部分是互通,在参照芯片确定后,对指令进行宏指令配置。
定义包括:读指令,写指令,擦除指令

#define W25X_WriteEnable0x06 #define W25X_WriteDisable0x04 #define W25X_ReadStatusReg10x05 #define W25X_ReadStatusReg20x35 #define W25X_ReadStatusReg30x15 #define W25X_WriteStatusReg10x01 #define W25X_WriteStatusReg20x31 #define W25X_WriteStatusReg30x11 #define W25X_ReadData0x03 #define W25X_FastReadData0x0B #define W25X_FastReadDual0x3B #define W25X_PageProgram0x02 #define W25X_BlockErase0xD8 #define W25X_SectorErase0x20 #define W25X_ChipErase0xC7 #define W25X_PowerDown0xB9 #define W25X_ReleasePowerDown 0xAB #define W25X_DeviceID0xAB #define W25X_ManufactDeviceID 0x90 #define W25X_JedecDeviceID0x9F #define W25X_Enable4ByteAddr0xB7 #define W25X_Exit4ByteAddr0xE9

2.各功能函数
/*************************************************************\ Function Name:W25Q64使能写 \*************************************************************/ void W25QXX_Write_Enable(void) { CS(0); SPI1_ReadWriteByte(W25X_WriteEnable); //发送写使能 CS(1); } /*************************************************************\ Function Name:W25Q64禁止写 \*************************************************************/ void W25QXX_Write_Disable(void) { CS(0); SPI1_ReadWriteByte(W25X_WriteDisable); //发送写禁止指令 CS(1); }/*************************************************************\ Function Name:W25Q64读函数 Arguments:读取数据指针,读取首地址,读取长度(256字节) \*************************************************************/ void W25QXX_Read(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) { uint16_t i; CS(0); SPI1_ReadWriteByte(W25X_ReadData); //发送读取命令 SPI1_ReadWriteByte((uint8_t)((ReadAddr) >> 16)); //发送24bit地址 SPI1_ReadWriteByte((uint8_t)((ReadAddr) >> 8)); SPI1_ReadWriteByte((uint8_t)ReadAddr); for (i = 0; i < NumByteToRead; i++) { pBuffer[i] = SPI1_ReadWriteByte(0XFF); //循环读数 } CS(1); }/*************************************************************\ Function Name:W25Q64写函数 Function Description:按页写入 Arguments:写入数据指针,读取首地址,读取长度(256字节) \*************************************************************/ void W25QXX_Write_Page(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) { uint16_t i; W25QXX_Write_Enable(); //SET WEL CS(0); SPI1_ReadWriteByte(W25X_PageProgram); //发送写页命令 SPI1_ReadWriteByte((uint8_t)((WriteAddr) >> 16)); //发送24bit地址 SPI1_ReadWriteByte((uint8_t)((WriteAddr) >> 8)); SPI1_ReadWriteByte((uint8_t)WriteAddr); for (i = 0; i < NumByteToWrite; i++) SPI1_ReadWriteByte(pBuffer[i]); //循环写数 CS(1); W25QXX_Wait_Busy(); //等待写入结束 } /*************************************************************\ Function Name:W25Q64扇区擦除 Function Description:擦除一个扇区 Arguments:扇区地址 \*************************************************************/ void W25QXX_Erase_Sector(uint32_t Dst_Addr) { W25QXX_Write_Enable(); //SET WEL W25QXX_Wait_Busy(); CS(0); SPI1_ReadWriteByte(W25X_SectorErase); //发送扇区擦除指令 SPI1_ReadWriteByte((u8)((Dst_Addr) >> 16)); //发送24bit地址 SPI1_ReadWriteByte((u8)((Dst_Addr) >> 8)); SPI1_ReadWriteByte((u8)Dst_Addr); CS(1); W25QXX_Wait_Busy(); //等待擦除完成 } /*************************************************************\ Function Name:W25Q64等待空闲 \*************************************************************/ void W25QXX_Wait_Busy(void) { while ((W25QXX_ReadSR(1) & 0x01) == 0x01); // 等待BUSY位清空 }/*************************************************************\ Function Name:W25Q64读取状态函数 Function Description:读取W25QXX的状态寄存器,W25QXX一共有3个状态寄存器 Arguments:状态寄存器号码 Return Value:状态寄存器值 \*************************************************************/ uint8_t W25QXX_ReadSR(uint8_t regno) { uint8_t byte = 0, command = 0; switch (regno) { case 1: command = W25X_ReadStatusReg1; //读状态寄存器1指令 break; case 2: command = W25X_ReadStatusReg2; //读状态寄存器2指令 break; case 3: command = W25X_ReadStatusReg3; //读状态寄存器3指令 break; default: command = W25X_ReadStatusReg1; break; } CS(0); SPI1_ReadWriteByte(command); //发送读取状态寄存器命令 byte = SPI1_ReadWriteByte(0Xff); //读取一个字节 CS(1); return byte; } /*************************************************************\ Function Name:W25Q64芯片擦除 Function Description:擦除整个芯片,时间在十多秒 \*************************************************************/ void W25QXX_Erase_Chip(void) { W25QXX_Write_Enable(); //SET WEL W25QXX_Wait_Busy(); CS(0); //使能器件 SPI1_ReadWriteByte(W25X_ChipErase); //发送片擦除命令 CS(1); W25QXX_Wait_Busy(); //等待芯片擦除结束 }

二、使用示例 1.W25qxx数据写入管理
//将Flash看做一个FIFO,读写指针进行控制,每次先从读写指针地址中读出相应值void ReceiveInterMess(void) { uint8_tucData; uint8_tucaInterBuf[256]; uint8_tusInterPos = 0; uint8_tusRxLength = 0; if(InterFifo.RxLength > 0) //判断FIFO中是否有数据 { HAL_Delay(1000); __HAL_UART_DISABLE_IT(&huart2, UART_IT_RXNE); //延迟1S确保接收完全 usRxLength = InterFifo.RxLength; for ( ; usRxLength > 0; usRxLength--) //接收FIFO所以数据 { if (InterRxBufferRead(&ucData)) { ucaInterBuf[usInterPos++] = ucData; } } InterRxBufferClear(); __HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE); } if (usInterPos > 0) { //读取读写指针地址 W25QXX_Read(ucaWriteAddrValue, uiWriteSaveAddr, 3); uiUserWriteAddr = ucaWriteAddrValue[2] + (ucaWriteAddrValue[1] << 8) + (ucaWriteAddrValue[0] << 16); W25QXX_Read(ucaReadAddrValue, uiReadSaveAddr, 3); uiUserReadAddr = ucaReadAddrValue[2] + (ucaReadAddrValue[1] << 8) + (ucaReadAddrValue[0] << 16); //写入数据到Flash中 W25QXX_Write_Page(&usInterPos, uiUserWriteAddr, 1); W25QXX_Write_Page(ucaInterBuf, uiUserWriteAddr+W25X_INTER_PAGE_ADDR, usInterPos); W25QXX_Read(&ucDataCounter, uiDataCounterAddr, 1); //队列满了,全部擦除 if ((uiUserWriteAddr + W25X_INTER_SECTOR_ADDR) % W25X_SECTOR_ADDR_MAX == uiUserReadAddr) { #if TEST_FALG printf("队列满,全部擦除\r\n"); #endifW25QXX_ExceptionHandling(); return ; }//刷新写地址 uiUserWriteAddr = (uiUserWriteAddr + W25X_INTER_SECTOR_ADDR) % W25X_SECTOR_ADDR_MAX; ucaWriteAddrValue[0] = (uiUserWriteAddr >> 16); ucaWriteAddrValue[1] = (uiUserWriteAddr >> 8); ucaWriteAddrValue[2] = uiUserWriteAddr; W25QXX_Erase_Sector(uiWriteSaveAddr); W25QXX_Write_Page(ucaWriteAddrValue, uiWriteSaveAddr, 3); ucDataCounter++; W25QXX_Erase_Sector(uiDataCounterAddr); W25QXX_Write_Page(&ucDataCounter, uiDataCounterAddr, 1); #if TEST_FALG printf("捕获一条数据:"); for (int i = 0; i < usInterPos; i++) printf( " %02X", ucaInterBuf[i]); printf("\r\n待发数据条数:%d\r\n", ucDataCounter); printf("\r\nFlash读地址:%02X\r\n", uiUserReadAddr); printf("Flash写地址:%02X\r\n", uiUserWriteAddr); #endif } }

总结 本项目中W25qxx的使用主要可以归纳为:
1.熟知使用W25qxx的哪些指令
2.编写读、写、擦除功能基本函数
3.根据需求对各数据以及变量对操作
提示:若有错误不足,欢迎批评指正。该系列文章仅供参考,欢迎互相学习交流。
【stm32|【STM32】HAL库开发教程(九)—W25qxx使用】感谢你的阅读,期待你的关注收藏点赞!

    推荐阅读