STM32F407ZGT6 fatfs出现挂载成功,但是文件读写失败的原因

2024-05-10 08:32

本文主要是介绍STM32F407ZGT6 fatfs出现挂载成功,但是文件读写失败的原因,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

使用正点原子的板子f407,使用野火代码参考博客 2021-07-25 野火板子25MHz晶振改为正点原子8MH晶振_Car12-CSDN博客

参考源码 修复了野火的bug,使用cubemx初始化代码STM32F407ZGT6.zip-嵌入式文档类资源-CSDN下载

主题开始

fatfs 出现挂载成功,但是文件读写失败的原因可能

原因1:

是文件系统损坏,需要在首次挂载文件系统以后重新格式化文件系统

文件系统测试代码
 

void testfatfs()
{printf("****** 这是一个SPI FLASH 文件系统实验 ******\r\n");SPI_FLASH_Init();HAL_Delay(500);uint32_t id = SPI_FLASH_ReadID();printf("flash id =%x \r\n",id);//在外部SPI Flash挂载文件系统,文件系统挂载时会对SPI设备初始化res_flash = f_mount(&fs,"1:",1);/* 在此处强制格式化一次问价系统 格式化 */
//	res_flash=f_mkfs("1:",0,0);	
//		res_flash = f_mount(NULL,"1:",1);			
//      /* 重新挂载	*/			
//			res_flash = f_mount(&fs,"1:",1);
/*----------------------- 格式化测试 ---------------------------*/  /* 如果没有文件系统就格式化创建创建文件系统 */if(res_flash == FR_NO_FILESYSTEM){printf("》FLASH还没有文件系统,即将进行格式化...\r\n");/* 格式化 */res_flash=f_mkfs("1:",0,0);							if(res_flash == FR_OK){printf("》FLASH已成功格式化文件系统。\r\n");/* 格式化后,先取消挂载 */res_flash = f_mount(NULL,"1:",1);			/* 重新挂载	*/			res_flash = f_mount(&fs,"1:",1);}else{printf("《《格式化失败。》》\r\n");while(1);}}else if(res_flash!=FR_OK){printf("!!外部Flash挂载文件系统失败。(%d)\r\n",res_flash);printf("!!可能原因:SPI Flash初始化不成功。\r\n");while(1);}else{printf("》文件系统挂载成功,可以进行读写测试\r\n");}/*----------------------- 文件系统测试:写测试 -----------------------------*//* 打开文件,如果文件不存在则创建它 */printf("\r\n****** 即将进行文件写入测试... ******\r\n");	res_flash = f_open(&fnew, "1:FatFs读写测试文件.txt",FA_CREATE_ALWAYS | FA_WRITE );if ( res_flash == FR_OK ){printf("》打开/创建FatFs读写测试文件.txt文件成功,向文件写入数据。\r\n");/* 将指定存储区内容写入到文件内 */res_flash=f_write(&fnew,WriteBuffer,sizeof(WriteBuffer),&fnum);if(res_flash==FR_OK){printf("》文件写入成功,写入字节数据:%d\n",fnum);printf("》向文件写入的数据为:\r\n%s\r\n",WriteBuffer);}else{printf("!!文件写入失败:(%d)\n",res_flash);}    /* 不再读写,关闭文件 */f_close(&fnew);}else{	printf("!!打开/创建文件失败。\r\n");}

 此处强制格式化文件系统,文件系统在使用中断电或者其他原因可能对导致文件系统损坏

//     强制格式化后重新挂载
//	res_flash=f_mkfs("1:",0,0);	
//	res_flash = f_mount(NULL,"1:",1);			
//      /* 重新挂载	*/			
//      res_flash = f_mount(&fs,"1:",1);

 原因2:

下面的SPITimeout是一个全局变量,在等待fash执行的时间就是不确定的;影响等待时间,在使用文件系统fatfs时,频繁的写入,就会导致下一次写入数据时,上一次还没有写入完成;这是野火参考代码的坑

 以下是野火代码,略有修改,特别是发送函数;使用野火的等待执行完成函数就是右图导致下边代码无法使用在文件系统(fatfs),只能使用它的代码

 /*** @brief  使用SPI发送一个字节的数据* @param  byte:要发送的数据* @retval 返回接收到的数据*/
uint8_t SPI_FLASH_SendByte(uint8_t byte)
{uint8_t data;HAL_SPI_TransmitReceive(&SpiHandle,&byte,&data,1,0x1000);return data;}

修改后代码:初始化使用cubumx生成的代码

bsp_spi_w25qxx.c

 /********************************************************************************* @file    bsp_spi_flash.c* @author  fire* @version V1.0* @date    2015-xx-xx* @brief   spi flash 底层应用函数bsp ******************************************************************************* @attention** 实验平台:野火STM32 F407 开发板* 论坛    :http://www.firebbs.cn* 淘宝    :https://fire-stm32.taobao.com********************************************************************************/#include "bsp_spi_flash.h"SPI_HandleTypeDef SpiHandle;static __IO uint32_t  SPITimeout = SPIT_LONG_TIMEOUT;   static uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode);/*** @brief SPI MSP Initialization *        This function configures the hardware resources used in this example: *           - Peripheral's clock enable*           - Peripheral's GPIO Configuration  * @param hspi: SPI handle pointer* @retval None*/
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
//  GPIO_InitTypeDef  GPIO_InitStruct;
//  
//  /*##-1- Enable peripherals and GPIO Clocks #################################*/
//  /* Enable GPIO TX/RX clock */
//  SPIx_SCK_GPIO_CLK_ENABLE();
//  SPIx_MISO_GPIO_CLK_ENABLE();
//  SPIx_MOSI_GPIO_CLK_ENABLE();
//  SPIx_CS_GPIO_CLK_ENABLE();
//  /* Enable SPI clock */
//  SPIx_CLK_ENABLE(); 
//  
//  /*##-2- Configure peripheral GPIO ##########################################*/  
//  /* SPI SCK GPIO pin configuration  */
//  GPIO_InitStruct.Pin       = SPIx_SCK_PIN;
//  GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
//  GPIO_InitStruct.Pull      = GPIO_PULLUP;
//  GPIO_InitStruct.Speed     = GPIO_SPEED_FAST;
//  GPIO_InitStruct.Alternate = SPIx_SCK_AF;
//  
//  HAL_GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStruct);
//    
//  /* SPI MISO GPIO pin configuration  */
//  GPIO_InitStruct.Pin = SPIx_MISO_PIN;
//  GPIO_InitStruct.Alternate = SPIx_MISO_AF;
//  
//  HAL_GPIO_Init(SPIx_MISO_GPIO_PORT, &GPIO_InitStruct);
//  
//  /* SPI MOSI GPIO pin configuration  */
//  GPIO_InitStruct.Pin = SPIx_MOSI_PIN;
//  GPIO_InitStruct.Alternate = SPIx_MOSI_AF;  
//  HAL_GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStruct);   //  GPIO_InitStruct.Pin = FLASH_CS_PIN ;
//  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
//  HAL_GPIO_Init(FLASH_CS_GPIO_PORT, &GPIO_InitStruct); 
//	GPIO_InitTypeDef GPIO_InitStruct = {0};if(hspi->Instance==SPI1){/* USER CODE BEGIN SPI1_MspInit 0 *//* USER CODE END SPI1_MspInit 0 *//* SPI1 clock enable */__HAL_RCC_SPI1_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/**SPI1 GPIO ConfigurationPB3     ------> SPI1_SCKPB4     ------> SPI1_MISOPB5     ------> SPI1_MOSI*/GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/* USER CODE BEGIN SPI1_MspInit 1 *//* USER CODE END SPI1_MspInit 1 */}
}void SPI_FLASH_Init(void)
{/*##-1- Configure the SPI peripheral #######################################*//* Set the SPI parameters */SpiHandle.Instance = SPI1;SpiHandle.Init.Mode = SPI_MODE_MASTER;SpiHandle.Init.Direction = SPI_DIRECTION_2LINES;SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT;SpiHandle.Init.CLKPolarity = SPI_POLARITY_HIGH;SpiHandle.Init.CLKPhase = SPI_PHASE_2EDGE;//	  SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW;
//  SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE;SpiHandle.Init.NSS = SPI_NSS_SOFT;SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB;SpiHandle.Init.TIMode = SPI_TIMODE_DISABLE;SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;SpiHandle.Init.CRCPolynomial = 7;if (HAL_SPI_Init(&SpiHandle) != HAL_OK){//Error_Handler();}/* USER CODE BEGIN SPI1_Init 2 */
__HAL_SPI_ENABLE(&SpiHandle); /* USER CODE END SPI1_Init 2 */
}/*** @brief  擦除FLASH扇区* @param  SectorAddr:要擦除的扇区地址* @retval 无*/
void SPI_FLASH_SectorErase(uint32_t SectorAddr)
{/* 发送FLASH写使能命令 */SPI_FLASH_WriteEnable();SPI_FLASH_WaitForWriteEnd();/* 擦除扇区 *//* 选择FLASH: CS低电平 */SPI_FLASH_CS_LOW();/* 发送扇区擦除指令*/SPI_FLASH_SendByte(W25X_SectorErase);/*发送擦除扇区地址的高位*/SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);/* 发送擦除扇区地址的中位 */SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);/* 发送擦除扇区地址的低位 */SPI_FLASH_SendByte(SectorAddr & 0xFF);/* 停止信号 FLASH: CS 高电平 */SPI_FLASH_CS_HIGH();/* 等待擦除完毕*/SPI_FLASH_WaitForWriteEnd();
}/*** @brief  擦除FLASH扇区,整片擦除* @param  无* @retval 无*/
void SPI_FLASH_BulkErase(void)
{/* 发送FLASH写使能命令 */SPI_FLASH_WriteEnable();/* 整块 Erase *//* 选择FLASH: CS低电平 */SPI_FLASH_CS_LOW();/* 发送整块擦除指令*/SPI_FLASH_SendByte(W25X_ChipErase);/* 停止信号 FLASH: CS 高电平 */SPI_FLASH_CS_HIGH();/* 等待擦除完毕*/SPI_FLASH_WaitForWriteEnd();
}/*** @brief  对FLASH按页写入数据,调用本函数写入数据前需要先擦除扇区* @param	pBuffer,要写入数据的指针* @param WriteAddr,写入地址* @param  NumByteToWrite,写入数据长度,必须小于等于SPI_FLASH_PerWritePageSize* @retval 无*/
void SPI_FLASH_PageWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{/* 发送FLASH写使能命令 */SPI_FLASH_WriteEnable();/* 选择FLASH: CS低电平 */SPI_FLASH_CS_LOW();/* 写页写指令*/SPI_FLASH_SendByte(W25X_PageProgram);/*发送写地址的高位*/SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);/*发送写地址的中位*/SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);/*发送写地址的低位*/SPI_FLASH_SendByte(WriteAddr & 0xFF);if(NumByteToWrite > SPI_FLASH_PerWritePageSize){NumByteToWrite = SPI_FLASH_PerWritePageSize;FLASH_ERROR("SPI_FLASH_PageWrite too large!");}/* 写入数据*/while (NumByteToWrite--){/* 发送当前要写入的字节数据 */SPI_FLASH_SendByte(*pBuffer);/* 指向下一字节数据 */pBuffer++;}/* 停止信号 FLASH: CS 高电平 */SPI_FLASH_CS_HIGH();/* 等待写入完毕*/SPI_FLASH_WaitForWriteEnd();
}/*** @brief  对FLASH写入数据,调用本函数写入数据前需要先擦除扇区* @param	pBuffer,要写入数据的指针* @param  WriteAddr,写入地址* @param  NumByteToWrite,写入数据长度* @retval 无*/
void SPI_FLASH_BufferWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;/*mod运算求余,若writeAddr是SPI_FLASH_PageSize整数倍,运算结果Addr值为0*/Addr = WriteAddr % SPI_FLASH_PageSize;/*差count个数据值,刚好可以对齐到页地址*/count = SPI_FLASH_PageSize - Addr;	/*计算出要写多少整数页*/NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;/*mod运算求余,计算出剩余不满一页的字节数*/NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;/* Addr=0,则WriteAddr 刚好按页对齐 aligned  */if (Addr == 0) {/* NumByteToWrite < SPI_FLASH_PageSize */if (NumOfPage == 0) {SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);}else /* NumByteToWrite > SPI_FLASH_PageSize */{/*先把整数页都写了*/while (NumOfPage--){SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);WriteAddr +=  SPI_FLASH_PageSize;pBuffer += SPI_FLASH_PageSize;}/*若有多余的不满一页的数据,把它写完*/SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);}}/* 若地址与 SPI_FLASH_PageSize 不对齐  */else {/* NumByteToWrite < SPI_FLASH_PageSize */if (NumOfPage == 0) {/*当前页剩余的count个位置比NumOfSingle小,写不完*/if (NumOfSingle > count) {temp = NumOfSingle - count;/*先写满当前页*/SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);WriteAddr +=  count;pBuffer += count;/*再写剩余的数据*/SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);}else /*当前页剩余的count个位置能写完NumOfSingle个数据*/{				SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);}}else /* NumByteToWrite > SPI_FLASH_PageSize */{/*地址不对齐多出的count分开处理,不加入这个运算*/NumByteToWrite -= count;NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);WriteAddr +=  count;pBuffer += count;/*把整数页都写了*/while (NumOfPage--){SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);WriteAddr +=  SPI_FLASH_PageSize;pBuffer += SPI_FLASH_PageSize;}/*若有多余的不满一页的数据,把它写完*/if (NumOfSingle != 0){SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);}}}
}/*** @brief  读取FLASH数据* @param 	pBuffer,存储读出数据的指针* @param   ReadAddr,读取地址* @param   NumByteToRead,读取数据长度* @retval 无*/
void SPI_FLASH_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{/* 选择FLASH: CS低电平 */SPI_FLASH_CS_LOW();/* 发送 读 指令 */SPI_FLASH_SendByte(W25X_ReadData);/* 发送 读 地址高位 */SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);/* 发送 读 地址中位 */SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);/* 发送 读 地址低位 */SPI_FLASH_SendByte(ReadAddr & 0xFF);/* 读取数据 */while (NumByteToRead--){/* 读取一个字节*/*pBuffer = SPI_FLASH_SendByte(Dummy_Byte);/* 指向下一个字节缓冲区 */pBuffer++;}/* 停止信号 FLASH: CS 高电平 */SPI_FLASH_CS_HIGH();
}/*** @brief  读取FLASH ID* @param 	无* @retval FLASH ID*/
uint32_t SPI_FLASH_ReadID(void)
{uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;/* 开始通讯:CS低电平 */SPI_FLASH_CS_LOW();/* 发送JEDEC指令,读取ID */SPI_FLASH_SendByte(W25X_JedecDeviceID);/* 读取一个字节数据 */Temp0 = SPI_FLASH_SendByte(Dummy_Byte);/* 读取一个字节数据 */Temp1 = SPI_FLASH_SendByte(Dummy_Byte);/* 读取一个字节数据 */Temp2 = SPI_FLASH_SendByte(Dummy_Byte);/* 停止通讯:CS高电平 */SPI_FLASH_CS_HIGH();/*把数据组合起来,作为函数的返回值*/Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;return Temp;
}/*** @brief  读取FLASH Device ID* @param 	无* @retval FLASH Device ID*/
uint32_t SPI_FLASH_ReadDeviceID(void)
{uint32_t Temp = 0;/* Select the FLASH: Chip Select low */SPI_FLASH_CS_LOW();/* Send "RDID " instruction */SPI_FLASH_SendByte(W25X_DeviceID);SPI_FLASH_SendByte(Dummy_Byte);SPI_FLASH_SendByte(Dummy_Byte);SPI_FLASH_SendByte(Dummy_Byte);/* Read a byte from the FLASH */Temp = SPI_FLASH_SendByte(Dummy_Byte);/* Deselect the FLASH: Chip Select high */SPI_FLASH_CS_HIGH();return Temp;
}
/*******************************************************************************
* Function Name  : SPI_FLASH_StartReadSequence
* Description    : Initiates a read data byte (READ) sequence from the Flash.
*                  This is done by driving the /CS line low to select the device,
*                  then the READ instruction is transmitted followed by 3 bytes
*                  address. This function exit and keep the /CS line low, so the
*                  Flash still being selected. With this technique the whole
*                  content of the Flash is read with a single READ instruction.
* Input          : - ReadAddr : FLASH's internal address to read from.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_StartReadSequence(uint32_t ReadAddr)
{/* Select the FLASH: Chip Select low */SPI_FLASH_CS_LOW();/* Send "Read from Memory " instruction */SPI_FLASH_SendByte(W25X_ReadData);/* Send the 24-bit address of the address to read from -----------------------*//* Send ReadAddr high nibble address byte */SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);/* Send ReadAddr medium nibble address byte */SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);/* Send ReadAddr low nibble address byte */SPI_FLASH_SendByte(ReadAddr & 0xFF);
}/*** @brief  使用SPI读取一个字节的数据* @param  无* @retval 返回接收到的数据*/
uint8_t SPI_FLASH_ReadByte(void)
{return (SPI_FLASH_SendByte(Dummy_Byte));
}/*** @brief  使用SPI发送一个字节的数据* @param  byte:要发送的数据* @retval 返回接收到的数据*/
uint8_t SPI_FLASH_SendByte(uint8_t byte)
{uint8_t data;HAL_SPI_TransmitReceive(&SpiHandle,&byte,&data,1,0x1000);return data;}/*******************************************************************************
* Function Name  : SPI_FLASH_SendHalfWord
* Description    : Sends a Half Word through the SPI interface and return the
*                  Half Word received from the SPI bus.
* Input          : Half Word : Half Word to send.
* Output         : None
* Return         : The value of the received Half Word.
*******************************************************************************/
uint16_t SPI_FLASH_SendHalfWord(uint16_t HalfWord)
{SPITimeout = SPIT_FLAG_TIMEOUT;/* Loop while DR register in not emplty */while (__HAL_SPI_GET_FLAG( &SpiHandle,  SPI_FLAG_TXE ) == RESET){if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(2);}/* Send Half Word through the SPIx peripheral */WRITE_REG(SpiHandle.Instance->DR, HalfWord);SPITimeout = SPIT_FLAG_TIMEOUT;/* Wait to receive a Half Word */while (__HAL_SPI_GET_FLAG( &SpiHandle, SPI_FLAG_RXNE ) == RESET){if((SPITimeout--) == 0) return SPI_TIMEOUT_UserCallback(3);}/* Return the Half Word read from the SPI bus */return READ_REG(SpiHandle.Instance->DR);
}/*** @brief  向FLASH发送 写使能 命令* @param  none* @retval none*/
void SPI_FLASH_WriteEnable(void)
{/* 通讯开始:CS低 */SPI_FLASH_CS_LOW();/* 发送写使能命令*/SPI_FLASH_SendByte(W25X_WriteEnable);/*通讯结束:CS高 */SPI_FLASH_CS_HIGH();
}/*** @brief  等待WIP(BUSY)标志被置0,即等待到FLASH内部数据写入完毕* @param  none* @retval none*/
void SPI_FLASH_WaitForWriteEnd(void)
{uint8_t FLASH_Status = 0;/* 选择 FLASH: CS 低 */SPI_FLASH_CS_LOW();/* 发送 读状态寄存器 命令 */SPI_FLASH_SendByte(W25X_ReadStatusReg);//此处必须长时间等待,//否者机会导致数写入出错,原来的等待时间仅仅是SPIT_FLAG_TIMEOUT(4096)uint32_t cnt=SPIT_FLAG_TIMEOUT*10; /* 若FLASH忙碌,则等待 */do{/* 读取FLASH芯片的状态寄存器 */FLASH_Status = SPI_FLASH_SendByte(Dummy_Byte);	 {if((cnt--) == 0) {SPI_TIMEOUT_UserCallback(4);return;}} }while ((FLASH_Status & WIP_Flag) == SET); /* 正在写入标志 *//* 停止信号  FLASH: CS 高 */SPI_FLASH_CS_HIGH();
}//进入掉电模式
void SPI_Flash_PowerDown(void)   
{ /* 选择 FLASH: CS 低 */SPI_FLASH_CS_LOW();/* 发送 掉电 命令 */SPI_FLASH_SendByte(W25X_PowerDown);/* 停止信号  FLASH: CS 高 */SPI_FLASH_CS_HIGH();
}   //唤醒
void SPI_Flash_WAKEUP(void)   
{/*选择 FLASH: CS 低 */SPI_FLASH_CS_LOW();/* 发上 上电 命令 */SPI_FLASH_SendByte(W25X_ReleasePowerDown);/* 停止信号 FLASH: CS 高 */SPI_FLASH_CS_HIGH();                   //等待TRES1
}   /*** @brief  等待超时回调函数* @param  None.* @retval None.*/
static  uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode)
{/* 等待超时后的处理,输出错误信息 */FLASH_ERROR("SPI 等待超时!errorCode = %d",errorCode);return 0;
}/*********************************************END OF FILE**********************/

bsp_spi_w25qxx.h

#ifndef __SPI_FLASH_H
#define __SPI_FLASH_H#include "stm32f4xx.h"
#include <stdio.h>/* Private typedef -----------------------------------------------------------*/
//#define  sFLASH_ID                       0xEF3015     //W25X16
//#define  sFLASH_ID                       0xEF4015	    //W25Q16
//#define  sFLASH_ID                        0XEF4017     //W25Q64
#define  sFLASH_ID                       0XEF4018     //W25Q128//#define SPI_FLASH_PageSize            4096
#define SPI_FLASH_PageSize              256
#define SPI_FLASH_PerWritePageSize      256/* Private define ------------------------------------------------------------*/
/*命令定义-开头*******************************/
#define W25X_WriteEnable		      0x06 
#define W25X_WriteDisable		      0x04 
#define W25X_ReadStatusReg		    0x05 
#define W25X_WriteStatusReg		  0x01 
#define W25X_ReadData			        0x03 
#define W25X_FastReadData		      0x0B 
#define W25X_FastReadDual		      0x3B 
#define W25X_PageProgram		      0x02 
#define W25X_BlockErase			      0xD8 
#define W25X_SectorErase		      0x20 
#define W25X_ChipErase			      0xC7 
#define W25X_PowerDown			      0xB9 
#define W25X_ReleasePowerDown	  0xAB 
#define W25X_DeviceID			        0xAB 
#define W25X_ManufactDeviceID   	0x90 
#define W25X_JedecDeviceID		    0x9F #define WIP_Flag                  0x01  /* Write In Progress (WIP) flag */
#define Dummy_Byte                0xFF
/*命令定义-结尾*******************************///SPI号及时钟初始化函数
#define SPIx                             SPI1
#define SPIx_CLK_ENABLE()                __HAL_RCC_SPI1_CLK_ENABLE()
#define SPIx_SCK_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOB_CLK_ENABLE()
#define SPIx_MISO_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOB_CLK_ENABLE() 
#define SPIx_MOSI_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOB_CLK_ENABLE() 
#define SPIx_CS_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOG_CLK_ENABLE() #define SPIx_FORCE_RESET()               __HAL_RCC_SPI1_FORCE_RESET()
#define SPIx_RELEASE_RESET()             __HAL_RCC_SPI1_RELEASE_RESET()//SCK引脚
#define SPIx_SCK_PIN                     GPIO_PIN_3
#define SPIx_SCK_GPIO_PORT               GPIOB
#define SPIx_SCK_AF                      GPIO_AF5_SPI1
//MISO引脚
#define SPIx_MISO_PIN                    GPIO_PIN_4
#define SPIx_MISO_GPIO_PORT              GPIOB
#define SPIx_MISO_AF                     GPIO_AF5_SPI1
//MOSI引脚
#define SPIx_MOSI_PIN                    GPIO_PIN_5
#define SPIx_MOSI_GPIO_PORT              GPIOB
#define SPIx_MOSI_AF                     GPIO_AF5_SPI1
//CS(NSS)引脚
#define FLASH_CS_PIN                     GPIO_PIN_14               
#define FLASH_CS_GPIO_PORT               GPIOB                     
//设置为高电平	
#define	digitalHi(p,i)			    {p->BSRR=i;}		
//输出低电平
#define digitalLo(p,i)			    {p->BSRR=(uint32_t)i << 16;}				
#define SPI_FLASH_CS_LOW()      digitalLo(FLASH_CS_GPIO_PORT,FLASH_CS_PIN )
#define SPI_FLASH_CS_HIGH()     digitalHi(FLASH_CS_GPIO_PORT,FLASH_CS_PIN )
/*SPI接口定义-结尾****************************//*等待超时时间*/
#define SPIT_FLAG_TIMEOUT         ((uint32_t)0x1000)
#define SPIT_LONG_TIMEOUT         ((uint32_t)(10 * SPIT_FLAG_TIMEOUT))/*信息输出*/
#define FLASH_DEBUG_ON         1#define FLASH_INFO(fmt,arg...)           printf("<<-FLASH-INFO->> "fmt"\n",##arg)
#define FLASH_ERROR(fmt,arg...)          printf("<<-FLASH-ERROR->> "fmt"\n",##arg)
#define FLASH_DEBUG(fmt,arg...)          do{\if(FLASH_DEBUG_ON)\printf("<<-FLASH-DEBUG->> [%d]"fmt"\n",__LINE__, ##arg);\}while(0)void SPI_FLASH_Init(void);
void SPI_FLASH_SectorErase(uint32_t SectorAddr);
void SPI_FLASH_BulkErase(void);
void SPI_FLASH_PageWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
void SPI_FLASH_BufferWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
void SPI_FLASH_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead);
uint32_t SPI_FLASH_ReadID(void);
uint32_t SPI_FLASH_ReadDeviceID(void);
void SPI_FLASH_StartReadSequence(uint32_t ReadAddr);
void SPI_Flash_PowerDown(void);
void SPI_Flash_WAKEUP(void);uint8_t SPI_FLASH_ReadByte(void);
uint8_t SPI_FLASH_SendByte(uint8_t byte);
uint16_t SPI_FLASH_SendHalfWord(uint16_t HalfWord);
void SPI_FLASH_WriteEnable(void);
void SPI_FLASH_WaitForWriteEnd(void);#endif /* __SPI_FLASH_H */

这篇关于STM32F407ZGT6 fatfs出现挂载成功,但是文件读写失败的原因的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/975951

相关文章

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

10. 文件的读写

10.1 文本文件 操作文件三大类: ofstream:写操作ifstream:读操作fstream:读写操作 打开方式解释ios::in为了读文件而打开文件ios::out为了写文件而打开文件,如果当前文件存在则清空当前文件在写入ios::app追加方式写文件ios::trunc如果文件存在先删除,在创建ios::ate打开文件之后令读写位置移至文件尾端ios::binary二进制方式

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

ORACLE 11g 创建数据库时 Enterprise Manager配置失败的解决办法 无法打开OEM的解决办法

在win7 64位系统下安装oracle11g,在使用Database configuration Assistant创建数据库时,在创建到85%的时候报错,错误如下: 解决办法: 在listener.ora中增加对BlueAeri-PC或ip地址的侦听,具体步骤如下: 1.启动Net Manager,在“监听程序”--Listener下添加一个地址,主机名写计

STM32 ADC+DMA导致写FLASH失败

最近用STM32G070系列的ADC+DMA采样时,遇到了一些小坑记录一下; 一、ADC+DMA采样时进入死循环; 解决方法:ADC-dma死循环问题_stm32 adc dma死机-CSDN博客 将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size); 的ADC_Bu

开发板NFS挂载文件目录

文章目录 序NFS1. 安装 NFS 服务器和客户端在服务器上(NFS 服务器端)在客户端上(NFS 客户端) 2. 配置 NFS 服务器创建共享目录编辑 `/etc/exports` 文件启动 NFS 服务 3. 在客户端挂载 NFS 共享创建挂载点挂载 NFS 共享验证挂载 4. 设置开机自动挂载5. 解决权限问题 序 本节主要实现虚拟机(服务器)与开发板(客户端)通过N

DAY16:什么是慢查询,导致的原因,优化方法 | undo log、redo log、binlog的用处 | MySQL有哪些锁

目录 什么是慢查询,导致的原因,优化方法 undo log、redo log、binlog的用处  MySQL有哪些锁   什么是慢查询,导致的原因,优化方法 数据库查询的执行时间超过指定的超时时间时,就被称为慢查询。 导致的原因: 查询语句比较复杂:查询涉及多个表,包含复杂的连接和子查询,可能导致执行时间较长。查询数据量大:当查询的数据量庞大时,即使查询本身并不复杂,也可能导致

关于使用cspreadsheet读写EXCEL表格数据的问题

前几天项目有读写EXCEL表格的需求,我就找了大概有几种,大致分为:COM方法、ODBC方法、OLE方法、纯底层格式分析方法。由于COM方法要求必须安装有OFFICE的EXCEL组件,纯底层格式分析方法又很多功能需要自行去完善,所有最终选择了数据库的方法,用数据库的方法去存取xls格式的数据。网上有一个高手写的CSpreedSheet,看了一下提供的接口,感觉挺好用的。在使用的过程中发现几个

flume系列之:记录一次flume agent进程被异常oom kill -9的原因定位

flume系列之:记录一次flume agent进程被异常oom kill -9的原因定位 一、背景二、定位问题三、解决方法 一、背景 flume系列之:定位flume没有关闭某个时间点生成的tmp文件的原因,并制定解决方案在博主上面这篇文章的基础上,在机器内存、cpu资源、flume agent资源都足够的情况下,flume agent又出现了tmp文件无法关闭的情况 二、