添加文件
- 获取FatFs库(官网)
- 将source文件夹全部复制到目标工程中
- 添加所有.c文件到工程中,添加相关路径
移植修改
需要修改的文件:
- integer.h:修改各种整型的宏定义(注:C99--long long对应64位整型)
- ffconf.h:修改各种设置:(全部宏定义意义见官网)
- FF_USE_STRFUNC设为1:开启字符串功能
- FF_USE_FIND设为1:开启查找功能
- FF_USE_MKFS设为1:开启格式化功能(在逻辑驱动器上创建一个FAT卷)
- FF_CODE_PAGE设为936:简体中文
- FF_STR_VOLUME_ID设为1:允许字符串卷ID
- FF_VOLUME_STRS设为"NODE":设定字符串卷ID
- FF_FS_NORTC设为1:禁用RTC(时间戳)功能,因为stm32不具备获取时间的功能
- diskio.c:修改各磁盘IO层操作函数
- 修改磁盘设备定义:#define DEV_SPI 1
- 修改各函数中case DEV_RAM的操作:stat = STA_NOINIT; 或res = RES_PARERR;
- 修改各函数中case DEV_SPI的操作:指向spi_disk.c中的各执行函数
- spi_disk.c:自定义文件,是diskio.c中各函数指向的执行函数
- 定义静态全局变量_s_SPI_Init_OK,用于指示当前磁盘初始化状态
- SPI_disk_status函数:获取驱动器状态。_s_SPI_Init_OK为0时返回STA_NOINIT。
- SPI_disk_initialize函数:驱动器初始化。执行SPIFlash初始化函数,执行完毕后将_s_SPI_Init_OK置1。
- SPI_disk_read函数:读磁盘驱动器。进行异常处理后,将所有数据读到指定的指针内。
-
1 DRESULT SPI_disk_read(BYTE *buff, DWORD sector, UINT count) { 2 if(sector > SEC_MAX || sector + count > SEC_MAX) return RES_PARERR; 3 if(CS_STATUS() == Bit_RESET) return RES_NOTRDY; 4 5 if(SSTF016B_RD(sector*SEC_SIZE, SEC_SIZE*count, buff) == ERR) { 6 return RES_ERROR; 7 } 8 return RES_OK; 9 }
-
- SPI_disk_write函数:写磁盘驱动器。进行异常处理后,将所有数据写入指定的扇区内。
-
1 DRESULT SPI_disk_write(const BYTE *buff, DWORD sector, UINT count) { 2 if(sector > SEC_MAX || sector + count > SEC_MAX) return RES_PARERR; 3 if(CS_STATUS() == Bit_RESET) return RES_NOTRDY; 4 5 6 if(SSTF016B_Erase(sector, sector + count - 1) == ERR) { 7 return RES_ERROR; 8 } 9 if(SSTF016B_WR(sector*SEC_SIZE, buff, SEC_SIZE*count) == ERR){ 10 return RES_ERROR; 11 } 12 return RES_OK; 13 }
-
- SPI_disk_ioctl函数:执行ioctl命令。因为没有开启强制擦除的功能,强制擦除指令不执行任何操作。
-
1 DRESULT SPI_disk_ioctl(BYTE cmd, void *buff) { 2 DWORD *pdword = NULL; 3 WORD *pword = NULL; 4 5 switch(cmd) { 6 case CTRL_SYNC://确保写入操作已完成 7 return RES_OK; 8 9 case GET_SECTOR_COUNT://获取扇区数量 10 pdword = (DWORD *)buff; 11 *pdword = SEC_MAX + 1; 12 return RES_OK; 13 14 case GET_SECTOR_SIZE://获取单个扇区大小 15 pword = (WORD *)buff; 16 *pword = SEC_SIZE; 17 return RES_OK; 18 19 case GET_BLOCK_SIZE://获取擦除块大小 20 pdword = (DWORD *)buff; 21 *pdword = SEC_SIZE; 22 return RES_OK; 23 24 case CTRL_TRIM://强制擦除 25 return RES_PARERR; 26 } 27 return RES_PARERR; 28 }
-
- user_fatfs_app.c:自定义文件,定义fatfs的应用函数。
- 注意事项:
- 在单个扇区设为4k时,创建文件系统需要4k的ram(FATFS对象),工作缓冲区需要4k的ram,每一个文件对象需要4k的ram(FIL对象)。当硬件sram不大时,应仅在需要时创建文件对象并使用、使用后马上释放该对象。
- 执行写入操作后,如果不关闭文件对象(f_close),则必须执行f_sync函数刷新文件。否则如果意外断电,会发生不可预知的错误。
- f_open的第三参数:FA_OPEN_ALWAYS--存在则打开、不存在则创建;FA_OPEN_APPEND--同上,但指针指向文件尾;FA_WRITE--要写入必须带此参数;FA_READ--要读取必须带此参数。
- 如何判断f_open函数执行的到底是打开操作还是创建操作?用f_size判断文件大小即可。
-
1 #include "user_fatfs_app.h" 2 3 extern uint8_t g_User_Data[sizeof(t_g_Statistical_Data)]; 4 extern t_g_Statistical_Data *pg_User_Data; 5 extern uint8_t g_History_Data[sizeof(t_g_History_Data)]; 6 extern t_g_History_Data *pg_History_Data; 7 8 FATFS g_Fatfs; 9 BYTE work_buffer[FF_MAX_SS]; 10 11 12 void fatfs_Init(void) { 13 f_mkfs("", FM_FAT, 0, work_buffer, FF_MAX_SS); 14 f_mount(&g_Fatfs, "", 0); 15 memset(g_User_Data, 0, sizeof(g_User_Data)); 16 memset(g_History_Data, 0, sizeof(g_History_Data)); 17 fatfs_Get_Statistical_Data(); 18 } 19 20 21 int8_t fatfs_Get_Statistical_Data(void) { 22 FIL statistical_data; 23 UINT len = 0; 24 int8_t result = 0; 25 26 result = f_open(&statistical_data, "statistical_data.bin", FA_OPEN_ALWAYS | FA_WRITE | FA_READ);//指针指向文件头 27 if(result == FR_OK) { 28 if(f_size(&statistical_data) < sizeof(t_g_Statistical_Data)) { //初次创建 29 f_write(&statistical_data, g_User_Data, sizeof(t_g_Statistical_Data), &len); 30 f_lseek(&statistical_data, 0); 31 } 32 result = f_read(&statistical_data, g_User_Data, sizeof(t_g_Statistical_Data), &len); 33 } else { 34 result = -1; 35 } 36 f_close(&statistical_data); 37 free(&statistical_data); 38 39 return result; 40 } 41 42 43 int8_t fatfs_Update_Statistical_Data(void) { 44 FIL statistical_data; 45 UINT len = 0; 46 int8_t result = 0; 47 48 result = f_open(&statistical_data, "statistical_data.bin", FA_OPEN_ALWAYS | FA_WRITE);//指针指向文件头 49 if(result == FR_OK) { 50 result = f_write(&statistical_data, g_User_Data, sizeof(t_g_Statistical_Data), &len); 51 } else { 52 result = -1; 53 } 54 f_close(&statistical_data); 55 free(&statistical_data); 56 57 return result; 58 } 59 60 61 int8_t fatfs_Add_Historical_Data(void) { 62 FIL historical_data; 63 char node_type[2][7] = {"Zigbee", "LoRa"}; 64 char test_result[2][8] = {"Fail", "Success"}; 65 int8_t result = 0; 66 67 result = f_open(&historical_data, "historical_data.csv", FA_OPEN_APPEND | FA_WRITE);//指针指向文件尾 68 if(result == FR_OK) { 69 result = f_printf(&historical_data, \ 70 "%u,%s,%s,%08x%08x%08x,%04u/%02u/%02u,%02u:%02u:%02u\r\n", \ 71 pg_History_Data->index, node_type[pg_History_Data->type], \ 72 test_result[pg_History_Data->result], pg_History_Data->id[0], \ 73 pg_History_Data->id[1], pg_History_Data->id[2], pg_History_Data->year,\ 74 pg_History_Data->month, pg_History_Data->day, pg_History_Data->hour, \ 75 pg_History_Data->min, pg_History_Data->sec); 76 } else { 77 result = -2; 78 } 79 f_close(&historical_data); 80 free(&historical_data); 81 82 return result; 83 }
- 注意事项:
本文参照了csdn博客https://blog.csdn.net/little_shrimp/article/details/53214120。