300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > STM32CbueMX之SPI_FLASH + FATFS + USB MSC + 虚拟扩容

STM32CbueMX之SPI_FLASH + FATFS + USB MSC + 虚拟扩容

时间:2020-01-23 04:50:38

相关推荐

STM32CbueMX之SPI_FLASH + FATFS + USB MSC + 虚拟扩容

前言:

做一个在spi flash 上挂一个文件系统,然后板子用USB线连接电脑能识别读出spi flash上的文件。

背景:

因为spi flash容量比较小,我使用的是32MB的,插上电脑,感觉不好看,显示容量太小了。

所以我打算虚拟扩容一下变成1GB,但是实际可用的还是32MB。把电脑的写权限取消,只读。

fatfs调用写函数

FRESULT f_write (

FIL* fp, /* Pointer to the file object */

const void* buff, /* Pointer to the data to be written */

UINT btw, /* Number of bytes to write */

UINT* bw /* Pointer to number of bytes written */

)

返回值正常,然后*bw = 0;表示无空间写入。

主要是我下面实现了在MCU的fatfs文件系统分配超过32MB的空间都会提示已满,不再写入数据。

毕竟真实物理空间是32MB.这样不会破坏文件系统的文件表,导致文件系统出错。

为什么取消电脑写权限呢?是因为电脑写入fatfs文件系统的数据超过32MB的时候会破坏文件系统的文件表。

或者可以再改进一下,可以自我尝试。

STM32CbueMX配置图

USB pack 大小 = 4096;包越大速度越快。

heap大小:比我们设置的USB pack大512字节就够了。

代码

spi flash 驱动以前文章有写。

user_diskio.c

DSTATUS USER_initialize (BYTE pdrv /* Physical drive nmuber to identify the drive */){Stat = BSP_W25Q256_Init();return Stat;}DSTATUS USER_status (BYTE pdrv /* Physical drive number to identify the drive */){return Stat;}DRESULT USER_read (BYTE pdrv,/* Physical drive nmuber to identify the drive */BYTE *buff,/* Data buffer to store read data */DWORD sector, /* Sector address in LBA */UINT count/* Number of sectors to read */){if(BSP_W25Q256_Read(buff, sector << 12, count << 12) != W25Q256_OK)return RES_ERROR;}DRESULT USER_write (BYTE pdrv,/* Physical drive nmuber to identify the drive */const BYTE *buff, /* Data to be written */DWORD sector, /* Sector address in LBA */UINT count/* Number of sectors to write */){if(BSP_W25Q256_Erase_Sector(sector << 12) != W25Q256_OK)return RES_ERROR;if(BSP_W25Q256_Write((uint8_t*)buff, sector << 12, count << 12) != W25Q256_OK)return RES_ERROR;return RES_OK;}DRESULT USER_ioctl (BYTE pdrv,/* Physical drive nmuber (0..) */BYTE cmd, /* Control code */void *buff/* Buffer to send/receive control data */){DRESULT res = RES_ERROR;if(pdrv != 0) return RES_PARERR;switch(cmd){case CTRL_SYNC:res = RES_OK;break;case GET_SECTOR_COUNT:*(DWORD*)buff = (W25Q256FV_FLASH_SIZE / W25Q256FV_SECTOR_SIZE);res = RES_OK;break;case GET_SECTOR_SIZE:*(WORD*)buff = W25Q256FV_SECTOR_SIZE;res = RES_OK;break;case GET_BLOCK_SIZE:*(DWORD*)buff = 1;res = RES_OK;break;default:res = RES_PARERR;break;}return res;}

usbd_storage_if.c

#define MYSTORAGE_LUN_NBR 1#define MYSTORAGE_BLK_NBR (W25Q256FV_FLASH_SIZE / W25Q256FV_SECTOR_SIZE);#define MYSTORAGE_BLK_SIZ W25Q256FV_SECTOR_SIZEint8_t STORAGE_Init_FS(uint8_t lun){return (USBD_OK);}int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size){*block_num = MYSTORAGE_BLK_NBR;*block_size = MYSTORAGE_BLK_SIZ;return (USBD_OK);}int8_t STORAGE_IsReady_FS(uint8_t lun){return (USBD_OK);}int8_t STORAGE_IsWriteProtected_FS(uint8_t lun){return (USBD_OK);}int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len){if(BSP_W25Q256_Read(buf, blk_addr << 12, blk_len << 12) != W25Q256_OK)return USBD_FAIL;return (USBD_OK);}int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len){if(BSP_W25Q256_Erase_Sector(blk_addr << 12) != W25Q256_OK)return USBD_FAIL;if(BSP_W25Q256_Write(buf, blk_addr << 12, blk_len << 12) != W25Q256_OK)return USBD_FAIL;return (USBD_OK);}int8_t STORAGE_GetMaxLun_FS(void){return (MYSTORAGE_LUN_NBR - 1);}

main.c

#include <stdio.h>#include "w25q256.h"FIL fil;FATFS spi_fs;unsigned char work[4096] = {0};unsigned char read_buf[50] = {0};unsigned char write_buf[4096] = "hello sudaroot\r\n";static void USB_GPIO_Init(void);int main(void){/* USER CODE BEGIN 1 */unsigned int res = 0;unsigned int count = 0;/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit */USB_GPIO_Init();/* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();MX_USB_DEVICE_Init();MX_SPI5_Init();MX_FATFS_Init();/* USER CODE BEGIN 2 */printf("sudaroot usb and fatfs msc\r\n");res = f_mount(&spi_fs, "0:", 1);if(res != FR_OK){printf("文件系统挂载失败,f_mount = %d\r\n", res);res = f_mkfs("0:", FM_ANY, 0, (void*)&work, 4096);if(res != FR_OK){printf("文件系统格式化失败,f_mkfs = %d\r\n", res);}else{printf("重新挂载文件系统\r\n");res = f_mount(&spi_fs, "0:", 1);if(res != FR_OK){printf("文件系统挂载失败,f_mount = %d\r\n", res);}else{printf("文件系统挂载成功\r\n");}}}else printf("文件系统挂载成功\r\n");/*----------------------- 文件系统测试:写测试 -----------------------------*/printf("\r\n****** 即将进行文件写入测试... ******\r\n");res = f_open(&fil, "0:sudaroot.txt", FA_OPEN_APPEND | FA_WRITE);if(res == FR_OK){res = f_write(&fil, write_buf, 4096, &count);if(res != FR_OK){printf("f_write 发生错误,err = %d, count = %d\r\n", res, count);printf("关闭打开的sudaroot.txt文件\r\n");count = 0;f_close(&fil);}else{if(count == 0){printf("没有空间写入数据了\r\n");}count = 0;f_close(&fil);}}else{printf("打开/创建sudaroot.txt文件失败,err = %d\r\n", res);}printf("\r\n****** 结束进行文件写入测试... ******\r\n");/*------------------- 文件系统测试:读测试 ------------------------------------*/printf("****** 即将进行文件读取测试... ******\r\n");res = f_open(&fil, "0:sudaroot.txt", FA_OPEN_EXISTING | FA_READ);if(res == FR_OK){printf("打开sudaroot.txt文件成功\r\n");res = f_read(&fil, read_buf, sizeof(read_buf), &count);if(res != FR_OK){printf("f_read 发生错误,err = %d\r\n", res);printf("关闭打开的sudaroot.txt文件\r\n");f_close(&fil);}else{printf("文件读取成功,读取字节数据:%d\n", count);printf("向文件读取的数据为:\r\n%s\r\n", read_buf);printf("关闭打开的sudaroot.txt文件\r\n");f_close(&fil);}}else printf("打开sudaroot.txt文件失败,err = %d\r\n", res);/*------------------- 不再使用文件系统,取消挂载文件系统 ------------------------------------*/printf("不再使用文件系统,取消挂载文件系统\r\n");res = f_mount(NULL, "0:", 1);if(res == FR_OK) printf("取消挂载文件系统成功\r\n");else printf("取消挂载文件系统失败,err = %d\r\n", res);printf("文件系统测试结束\r\n");printf("csize = 0x%X = %d\r\n", spi_fs.csize, spi_fs.csize);printf("ssize = 0x%X = %d\r\n", spi_fs.ssize, spi_fs.ssize);printf("n_fatent = 0x%lX = %lu\r\n", spi_fs.n_fatent, spi_fs.n_fatent);printf("database = 0x%lX = %lu\r\n", spi_fs.database, spi_fs.database);printf("fsize = 0x%lX = %lu\r\n", spi_fs.fsize, spi_fs.fsize);printf("last_clst = 0x%lX = %lu\r\n", spi_fs.last_clst, spi_fs.last_clst);printf("free_clst = 0x%lX = %lu\r\n", spi_fs.free_clst, spi_fs.free_clst);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */HAL_GPIO_TogglePin(RUN_LED_GPIO_Port, RUN_LED_Pin);HAL_Delay(500);}/* USER CODE END 3 */}int fputc(int ch, FILE *FILE){HAL_UART_Transmit(&huart1, (unsigned char *)&ch, 1, HAL_MAX_DELAY);return ch;}static void USB_GPIO_Init(void){GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11 | GPIO_PIN_12, GPIO_PIN_RESET);/*Configure GPIO pin : W25Q256_CS_Pin */GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_PULLDOWN;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);HAL_Delay(2);}

效果:

扩容:

先算一下1GB转换成4KB一个扇区的话一共有几个扇区。

1GB = 1024MB =1024 * 1024KB

总扇区数 =1024 * 1024KB / 4 KB =262144

修改user_diskio.c

DRESULT USER_ioctl (BYTE pdrv,/* Physical drive nmuber (0..) */BYTE cmd, /* Control code */void *buff/* Buffer to send/receive control data */){...case GET_SECTOR_COUNT:*(DWORD*)buff = 262144;res = RES_OK;break;...}

修改usbd_storage_if.c

#define MYSTORAGE_BLK_NBR 262144int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len){// if(BSP_W25Q256_Erase_Sector(blk_addr << 12) != W25Q256_OK)// return USBD_FAIL;// if(BSP_W25Q256_Write(buf, blk_addr << 12, blk_len << 12) != W25Q256_OK)// return USBD_FAIL;return (USBD_OK);}

main.c

#include <stdio.h>#include "w25q256.h"FIL fil;FATFS spi_fs;unsigned char work[4096] = {0};unsigned char read_buf[50] = {0};unsigned char write_buf[4096] = "hello sudaroot\r\n";static void USB_GPIO_Init(void);int main(void){/* USER CODE BEGIN 1 */unsigned int res = 0;unsigned int count = 0;/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit */USB_GPIO_Init();/* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();MX_USB_DEVICE_Init();MX_SPI5_Init();MX_FATFS_Init();/* USER CODE BEGIN 2 */printf("sudaroot usb and fatfs msc\r\n");res = f_mount(&spi_fs, "0:", 1);if(res != FR_OK){printf("文件系统挂载失败,f_mount = %d\r\n", res);res = f_mkfs("0:", FM_ANY, 0, (void*)&work, 4096);if(res != FR_OK){printf("文件系统格式化失败,f_mkfs = %d\r\n", res);}else{printf("重新挂载文件系统\r\n");res = f_mount(&spi_fs, "0:", 1);if(res != FR_OK){printf("文件系统挂载失败,f_mount = %d\r\n", res);}else{printf("文件系统挂载成功\r\n");}}}else printf("文件系统挂载成功\r\n");printf("csize = 0x%X = %d\r\n", spi_fs.csize, spi_fs.csize);printf("ssize = 0x%X = %d\r\n", spi_fs.ssize, spi_fs.ssize);printf("n_fatent = 0x%lX = %lu\r\n", spi_fs.n_fatent, spi_fs.n_fatent);printf("database = 0x%lX = %lu\r\n", spi_fs.database, spi_fs.database);printf("fsize = 0x%lX = %lu\r\n", spi_fs.fsize, spi_fs.fsize);printf("last_clst = 0x%lX = %lu\r\n", spi_fs.last_clst, spi_fs.last_clst);printf("free_clst = 0x%lX = %lu\r\n", spi_fs.free_clst, spi_fs.free_clst);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */HAL_GPIO_TogglePin(RUN_LED_GPIO_Port, RUN_LED_Pin);HAL_Delay(500);}/* USER CODE END 3 */}int fputc(int ch, FILE *FILE){HAL_UART_Transmit(&huart1, (unsigned char *)&ch, 1, HAL_MAX_DELAY);return ch;}static void USB_GPIO_Init(void){GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11 | GPIO_PIN_12, GPIO_PIN_RESET);/*Configure GPIO pin : W25Q256_CS_Pin */GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_PULLDOWN;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);HAL_Delay(2);}

编译烧录重启连接USB到PC

一切正常。

分析:

先分析一下FATFS结构体和容量相关的参数,然再改。

/* File system object structure (FATFS) */typedef struct {...WORD csize; / *簇大小[扇区] * /WORD ssize; / *扇区大小(512,1024,2048或4096)* /DWORD last_clst; / *最后分配的簇* /DWORD free_clst; / *没使用簇数量* /DWORD n_fatent; / * FAT条目数(簇数+ 2)* /DWORD fsize; / * FAT的大小[扇区] * /DWORD volbase; / *卷起始扇区* /DWORD fatbase; / * FAT起始扇区* /DWORD dirbase; / *根目录基本扇区* /DWORD database; / *数据起始扇区* /...} FATFS;

簇是文件系统的最小单位,spi_flash的最小擦除单位是扇区。

变量csize表示一个簇由几个扇区组成,ssize表示一个扇区大小。n_fatent表示可用于存数据簇的总数。

还有就是一般小于4GB的文件系统都会格式化成FAT12或者FAT16,这种方式扩容不支持FAT32。

由上面串口打印的信息我们可以看出

簇大小 =csize *ssize = 8 * 4KB = 32KB

那么1GB可以分成几个32KB的簇

簇总数 = 1GB / 32KB =1024 * 1024KB / 32KB =32768 = 0X‭8000‬

文件表和保留扇区用几个簇 =簇总数 -n_fatent = 32768 - 32759 = 9

本来是32MB的flash = 8192 * 4KB = 1024 * 32KB

所以我们使用更改n_fatent = 1024 - 9 = 1015

还要注意的是n_fatent会在实际可用簇的基础上+2。

但是直接更改n_fatent是不行的,因为n_fatent会写入分区表,这样子会破坏分区表。

所以换一种方法,看哪里用n_fatent分配空间,在那里把n_fatent修改成常量。

下面这个函数是分配新的簇函数

/*-----------------------------------------------------------------------*//* FAT handling - Stretch a chain or Create a new chain *//*-----------------------------------------------------------------------*/staticDWORD create_chain (/* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */_FDID* obj,/* Corresponding object */DWORD clst/* Cluster# to stretch, 0:Create a new chain */){DWORD cs, ncl, scl;FRESULT res;FATFS *fs = obj->fs;if (clst == 0) {/* Create a new chain */scl = fs->last_clst;/* Get suggested cluster to start from */if (scl == 0 || scl >= fs->n_fatent) scl = 1;}else {/* Stretch current chain */cs = get_fat(obj, clst);/* Check the cluster status */if (cs < 2) return 1;/* Invalid FAT value */if (cs == 0xFFFFFFFF) return cs;/* A disk error occurred */if (cs < fs->n_fatent) return cs;/* It is already followed by next cluster */scl = clst;}#if _FS_EXFATif (fs->fs_type == FS_EXFAT) {/* On the exFAT volume */ncl = find_bitmap(fs, scl, 1);/* Find a free cluster */if (ncl == 0 || ncl == 0xFFFFFFFF) return ncl;/* No free cluster or hard error? */res = change_bitmap(fs, ncl, 1, 1);/* Mark the cluster 'in use' */if (res == FR_INT_ERR) return 1;if (res == FR_DISK_ERR) return 0xFFFFFFFF;if (clst == 0) {/* Is it a new chain? */obj->stat = 2;/* Set status 'contiguous' */} else {/* It is a stretched chain */if (obj->stat == 2 && ncl != scl + 1) {/* Is the chain got fragmented? */obj->n_cont = scl - obj->sclust;/* Set size of the contiguous part */obj->stat = 3;/* Change status 'just fragmented' */}}if (obj->stat != 2) {/* Is the file non-contiguous? */if (ncl == clst + 1) {/* Is the cluster next to previous one? */obj->n_frag = obj->n_frag ? obj->n_frag + 1 : 2;/* Increment size of last framgent */} else {/* New fragment */if (obj->n_frag == 0) obj->n_frag = 1;res = fill_last_frag(obj, clst, ncl);/* Fill last fragment on the FAT and link it to new one */if (res == FR_OK) obj->n_frag = 1;}}} else#endif{/* On the FAT12/16/32 volume */ncl = scl;/* Start cluster */for (;;) {ncl++;/* Next cluster */if (ncl >= fs->n_fatent) {/* Check wrap-around */ncl = 2;if (ncl > scl) return 0;/* No free cluster */}cs = get_fat(obj, ncl);/* Get the cluster status */if (cs == 0) break;/* Found a free cluster */if (cs == 1 || cs == 0xFFFFFFFF) return cs;/* An error occurred */if (ncl == scl) return 0;/* No free cluster */}res = put_fat(fs, ncl, 0xFFFFFFFF);/* Mark the new cluster 'EOC' */if (res == FR_OK && clst != 0) {res = put_fat(fs, clst, ncl);/* Link it from the previous one if needed */}}if (res == FR_OK) {/* Update FSINFO if function succeeded. */fs->last_clst = ncl;if (fs->free_clst <= fs->n_fatent - 2) fs->free_clst--;fs->fsi_flag |= 1;} else {ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;/* Failed. Generate error status */}return ncl;/* Return new cluster number or error status */}#endif /* !_FS_READONLY */

修改一下

staticDWORD create_chain (/* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */_FDID* obj,/* Corresponding object */DWORD clst/* Cluster# to stretch, 0:Create a new chain */){...if (clst == 0) {/* Create a new chain */scl = fs->last_clst;/* Get suggested cluster to start from *///if (scl == 0 || scl >= fs->n_fatent) scl = 1;if (scl == 0 || scl >= 1015) scl = 1;}...//if (ncl >= fs->n_fatent) {/* Check wrap-around */if (ncl >= 1015) {/* Check wrap-around */ncl = 2;if (ncl > scl) return 0;/* No free cluster */}....}

把注释的两行的fs->n_fatent 换成我们算出来的 1015;

测试程序:

每次调用f_write()往缓存区写入4096个字节数据,统计能写多少次。

f_write(&fil, write_buf, 4096, &count); 函数返回值不等于FR_OK一般是配置出错,或者硬件出错。

而count写入字节统计为0的话才是没用多余的空间写入。

FIL fil;FATFS spi_fs;unsigned char read_buf[50] = {0};unsigned char work[4096] = {0};unsigned char write_buf[4096] = "\r\nhello sudaroot\r\n";/*** @brief The application entry point.* @retval int*/int main(void){/* USER CODE BEGIN 1 */unsigned int res = 0;unsigned int count = 0;unsigned int sum = 0;/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit */USB_GPIO_Init();/* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();MX_USB_DEVICE_Init();MX_SPI5_Init();MX_FATFS_Init();/* USER CODE BEGIN 2 */HAL_Delay(1000);BSP_W25Q256_Erase_Sector(0);HAL_Delay(100);printf("sudaroot usb and fatfs msc\r\n");res = f_mount(&spi_fs, "0:", 1);if(res != FR_OK){printf("文件系统挂载失败,f_mount = %d\r\n", res);res = f_mkfs("0:", FM_ANY, 0, (void*)&work, 4096);if(res != FR_OK){printf("文件系统格式化失败,f_mkfs = %d\r\n", res);}else{printf("重新挂载文件系统\r\n");res = f_mount(&spi_fs, "0:", 1);if(res != FR_OK){printf("文件系统挂载失败,f_mount = %d\r\n", res);}else{printf("文件系统挂载成功\r\n");}}}else printf("文件系统挂载成功\r\n");printf("csize = 0x%X = %d\r\n", spi_fs.csize, spi_fs.csize);printf("ssize = 0x%X = %d\r\n", spi_fs.ssize, spi_fs.ssize);printf("n_fatent = 0x%lX = %lu\r\n", spi_fs.n_fatent, spi_fs.n_fatent);printf("database = 0x%lX = %lu\r\n", spi_fs.database, spi_fs.database);printf("fsize = 0x%lX = %lu\r\n", spi_fs.fsize, spi_fs.fsize);printf("last_clst = 0x%lX = %lu\r\n", spi_fs.last_clst, spi_fs.last_clst);printf("free_clst = 0x%lX = %lu\r\n", spi_fs.free_clst, spi_fs.free_clst);/*----------------------- 文件系统测试:写测试 -----------------------------*/printf("\r\n****** 即将进行文件写入测试... ******\r\n");while(1){res = f_open(&fil, "0:sudaroot.txt", FA_OPEN_APPEND | FA_WRITE);if(res == FR_OK){res = f_write(&fil, write_buf, 4096, &count);if(res != FR_OK){printf("f_write 发生错误,err = %d, count = %d\r\n", res, count);printf("关闭打开的sudaroot.txt文件\r\n");count = 0;f_close(&fil);break;}else{if(count == 0){printf("没有空间写入数据了\r\n");break;}sum++;count = 0;f_close(&fil);}}else{printf("打开/创建sudaroot.txt文件失败,err = %d\r\n", res);break;}HAL_GPIO_TogglePin(RUN_LED_GPIO_Port, RUN_LED_Pin);HAL_Delay(1);}printf("总计:sum = %u\r\n", sum);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */HAL_GPIO_TogglePin(RUN_LED_GPIO_Port, RUN_LED_Pin);HAL_Delay(500);}/* USER CODE END 3 */}

效果:

电脑也能读取。

上图等值写入了8104次数据。每次写4KB字节。那么共写入了 8104 * 4KB =32,416KB数据。

计算一下,和上面数据对比。

我们上面计算出n_fatent = 1015;但是n_fatent会多加比实际可用簇多加2个簇。

故实际的簇是n_fatent - 2 = 1015 - 2 = 1013;

因为一簇 = 32KB;

故32MB实际可用 = 1013 * 32KB =32416KB;

对比发现,和计算结果和测试效果一致。

扩容成功。

全篇完。

本人是一个嵌入式未入门小白,博客仅仅代表我个人主观见解,记录成长笔记。

笔记是以最简单的方式,只展示最核心的原理。

若有与 大神大大 见解有歧义,我绝对坚信 大神大大 见解是对的,我的是错的。

若无积分等无法下载源码,可加入QQ群657407920下载交流经验。感谢~!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。