func_record.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4. * @file : main.c
  5. * @brief : Main program body
  6. ******************************************************************************
  7. * @attention
  8. *
  9. * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  10. * All rights reserved.</center></h2>
  11. *
  12. * This software component is licensed by ST under BSD 3-Clause license,
  13. * the "License"; You may not use this file except in compliance with the
  14. * License. You may obtain a copy of the License at:
  15. * opensource.org/licenses/BSD-3-Clause
  16. *
  17. ******************************************************************************
  18. */
  19. /* USER CODE END Header */
  20. #include "main.h"
  21. #if USE_FATFS_RECORD
  22. /* Includes ------------------------------------------------------------------*/
  23. #include <stdint.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include <stdbool.h>
  27. #include "dev_spi_sdcard.h"
  28. #include "func_record.h"
  29. #include "Data_deal.h"
  30. /* Private includes ----------------------------------------------------------*/
  31. /* USER CODE BEGIN Includes */
  32. /* USER CODE END Includes */
  33. /* Private typedef -----------------------------------------------------------*/
  34. #define MAX_FILE_COUNT 20
  35. #define NUM_FILE_SET 16
  36. /* Private define ------------------------------------------------------------*/
  37. /* USER CODE BEGIN PD */
  38. /* USER CODE END PD */
  39. /* Private macro -------------------------------------------------------------*/
  40. /* USER CODE BEGIN PM */
  41. /* USER CODE END PM */
  42. /* Private variables ---------------------------------------------------------*/
  43. /* USER CODE BEGIN PV */
  44. /* USER CODE END PV */
  45. /* Private function prototypes -----------------------------------------------*/
  46. typedef struct fs_record_struct
  47. {
  48. int8_t fatfs_ok;
  49. int8_t path[32]; //操作路径
  50. int8_t name_new[32]; //最新的文件名
  51. int8_t name_send[32]; //最老的文件名
  52. FIL opt_file; //当前操作的文件
  53. FATFS fs;
  54. DIR dir; //操作的文件名
  55. uint32_t opt_len;
  56. int8_t read_buf[512];
  57. uint32_t read_len;
  58. int8_t write_buf[512];
  59. uint32_t write_len;
  60. uint32_t file_num;
  61. int8_t file_list[MAX_FILE_COUNT][30];//保存文件名
  62. }fs_record_OBJ;
  63. fs_record_OBJ fs_record_obj = {
  64. .fatfs_ok = true,
  65. .path = "JLRecord",
  66. .file_num = 0,
  67. };
  68. //add boly 20221020
  69. //uint8_t data_buf[16*1024] = {0};
  70. //end boly
  71. void func_record_Get_Capacity(void);
  72. void func_record_files_update(char * path);
  73. void func_record_dir_qsort(size_t fcount);
  74. extern SDateTime m_datetime;
  75. /* Private user code ---------------------------------------------------------*/
  76. uint8_t func_record_fatfs_isOK(void)
  77. {
  78. return fs_record_obj.fatfs_ok;
  79. }
  80. uint8_t func_record_fatfs_set_OK(uint8_t stat)
  81. {
  82. fs_record_obj.fatfs_ok = stat;
  83. return fs_record_obj.fatfs_ok;
  84. }
  85. void func_record_mk_fileName(char *buf)
  86. {
  87. fs_record_obj.path[12] = 0;
  88. sprintf(buf,"%s/%04d%02d%02d.txt",fs_record_obj.path,
  89. m_datetime.year%100 + 2000,
  90. m_datetime.month%100,
  91. m_datetime.day%100
  92. );
  93. return;
  94. }
  95. /**
  96. * @brief 指定长度len,buf内容写入文件
  97. * @retval int
  98. */
  99. uint32_t func_record_write(uint8_t *buf ,uint32_t len)
  100. {
  101. FRESULT res;
  102. UINT write_len = 0;
  103. //根据日期生成文件名,用于文件写入
  104. func_record_mk_fileName((char *)fs_record_obj.name_new);
  105. //打开当前存在的文件;
  106. res = f_open(&fs_record_obj.opt_file,(char *)fs_record_obj.name_new , FA_WRITE| FA_OPEN_EXISTING);
  107. if(FR_OK != res)
  108. {
  109. if(FR_NO_FILE == res)
  110. {
  111. //检查文件个数是否超限
  112. func_record_files_update((char *)fs_record_obj.path);
  113. //创建文件并写入
  114. res = f_open(&fs_record_obj.opt_file, (char*)fs_record_obj.name_new, FA_WRITE| FA_CREATE_NEW);
  115. if(FR_OK != res)
  116. {
  117. fs_record_obj.fatfs_ok = false;
  118. return 0;
  119. }
  120. }
  121. else
  122. {
  123. return 0;
  124. }
  125. }
  126. fs_record_obj.opt_len = f_size(&fs_record_obj.opt_file);
  127. //操作指针移动到文件末尾
  128. res = f_lseek(&fs_record_obj.opt_file, fs_record_obj.opt_len);
  129. res = f_write(&fs_record_obj.opt_file, buf, len, &write_len);
  130. res = f_sync (&fs_record_obj.opt_file ); //刷新文件
  131. res = f_close(&fs_record_obj.opt_file); //关闭文件
  132. return write_len;
  133. }
  134. void func_record_get_NameSend(void)
  135. {
  136. //发送文件是否存在
  137. if(strlen((char*)fs_record_obj.name_send) > 0)
  138. {
  139. if(strlen((char*)fs_record_obj.name_new) > 0)
  140. {
  141. strcpy((char*)fs_record_obj.name_send, (char*)fs_record_obj.name_new);
  142. }
  143. }
  144. else
  145. {
  146. //检查文件个数是否超限
  147. func_record_files_update((char *)fs_record_obj.path);
  148. }
  149. return;
  150. }
  151. /**
  152. * @brief The application entry point.
  153. * @retval int
  154. */
  155. uint32_t func_record_read(uint8_t *buf, uint32_t len)
  156. {
  157. FRESULT res;
  158. //uint32_t file_len = 0;
  159. uint32_t read_len = 0;
  160. func_record_get_NameSend();
  161. if(strlen((char *)fs_record_obj.name_send) > 0)
  162. {
  163. }
  164. else
  165. {
  166. return 0;
  167. }
  168. res = f_open(&fs_record_obj.opt_file, (char*)fs_record_obj.name_send, FA_READ | FA_OPEN_EXISTING);
  169. if(FR_OK != res)
  170. {
  171. return 0;
  172. }
  173. fs_record_obj.opt_len = f_size(&fs_record_obj.opt_file);
  174. //如果文件小于数据长度,则删除文件
  175. if(fs_record_obj.opt_len < len)
  176. {
  177. res = f_close(&fs_record_obj.opt_file);
  178. res = f_unlink((char*)fs_record_obj.name_send);
  179. if(res == FR_OK)
  180. {
  181. memset((char*)fs_record_obj.name_send, 0x00,sizeof(fs_record_obj.name_send));
  182. }
  183. return 0;
  184. };
  185. res = f_lseek(&fs_record_obj.opt_file, fs_record_obj.opt_len - len);
  186. res = f_read(&fs_record_obj.opt_file, buf, len, &read_len);
  187. res = f_close(&fs_record_obj.opt_file);
  188. return read_len;
  189. }
  190. uint32_t func_record_delete(uint8_t *buf,uint32_t len)
  191. {
  192. FRESULT res;
  193. //uint32_t file_len = 0;
  194. if(strlen((char *)fs_record_obj.name_send) > 0)
  195. {
  196. }
  197. else
  198. {
  199. return 0;
  200. }
  201. //打开文件
  202. res = f_open(&fs_record_obj.opt_file, (char*)fs_record_obj.name_send, FA_WRITE | FA_OPEN_EXISTING );
  203. if ( res != FR_OK )
  204. {
  205. if(res == FR_NO_FILE )
  206. {
  207. memset((char*)fs_record_obj.name_send, 0x00,sizeof(fs_record_obj.name_send));
  208. memset((char*)fs_record_obj.name_new, 0x00,sizeof(fs_record_obj.name_new));
  209. }
  210. return res;
  211. }
  212. fs_record_obj.opt_len = f_size(&fs_record_obj.opt_file);
  213. //如果文件小于数据长度,则删除文件
  214. if(fs_record_obj.opt_len <= len)
  215. {
  216. res = f_close(&fs_record_obj.opt_file);
  217. res = f_unlink((char*)fs_record_obj.name_send);
  218. if(res == FR_OK)
  219. {
  220. memset((char*)fs_record_obj.name_send, 0x00,sizeof(fs_record_obj.name_send));
  221. }
  222. return 0;
  223. };
  224. res = f_lseek(&fs_record_obj.opt_file, fs_record_obj.opt_len - len);
  225. res = f_truncate(&fs_record_obj.opt_file ); //截断后面的文件
  226. res = f_sync(&fs_record_obj.opt_file); //刷新关闭文件
  227. res = f_close(&fs_record_obj.opt_file);
  228. return res;
  229. }
  230. /**
  231. * 文件信息获取
  232. */
  233. FRESULT func_record_file_check(void)
  234. {
  235. FRESULT f_res; /* 文件操作结果 */
  236. static FILINFO finfo;
  237. /* 获取文件信息 */
  238. f_res=f_stat("TestDir/testdir.txt",&finfo);
  239. if(f_res==FR_OK)
  240. {
  241. printf("“testdir.txt”文件信息:\n");
  242. printf("》文件大小: %ld(字节)\n", finfo.fsize);
  243. printf("》时间戳: %u/%02u/%02u, %02u:%02u\n",
  244. (finfo.fdate >> 9) + 1980, finfo.fdate >> 5 & 15, finfo.fdate & 31,finfo.ftime >> 11, finfo.ftime >> 5 & 63);
  245. printf("》属性: %c%c%c%c%c\n\n",
  246. (finfo.fattrib & AM_DIR) ? 'D' : '-', // 是一个目录
  247. (finfo.fattrib & AM_RDO) ? 'R' : '-', // 只读文件
  248. (finfo.fattrib & AM_HID) ? 'H' : '-', // 隐藏文件
  249. (finfo.fattrib & AM_SYS) ? 'S' : '-', // 系统文件
  250. (finfo.fattrib & AM_ARC) ? 'A' : '-'); // 档案文件
  251. }
  252. return f_res;
  253. }
  254. /**
  255. * @brief scan_files 递归扫描FatFs内的文件
  256. * @param path:初始扫描路径
  257. * @retval result:文件系统的返回值
  258. */
  259. FRESULT func_record_scan_files (char* path)
  260. {
  261. FRESULT res; //部分在递归过程被修改的变量,不用全局变量
  262. FILINFO fno;
  263. DIR dir;
  264. int i;
  265. char *fn; // 文件名
  266. #if _USE_LFN
  267. /* 长文件名支持 */
  268. /* 简体中文需要2个字节保存一个“字”*/
  269. static char lfn[_MAX_LFN*2 + 1];
  270. fno.fname = lfn;
  271. fno.fsize = sizeof(lfn);
  272. #endif
  273. //打开目录
  274. res = f_opendir(&dir, path);
  275. if (res == FR_OK)
  276. {
  277. i = strlen(path);
  278. for (;;)
  279. {
  280. //读取目录下的内容,再读会自动读下一个文件
  281. res = f_readdir(&dir, &fno);
  282. //为空时表示所有项目读取完毕,跳出
  283. if (res != FR_OK || fno.fname[0] == 0) break;
  284. #if _USE_LFN
  285. fn = *fno.lfname ? fno.lfname : fno.fname;
  286. #else
  287. fn = fno.fname;
  288. #endif
  289. //点表示当前目录,跳过
  290. if (*fn == '.') continue;
  291. //目录,递归读取
  292. if (fno.fattrib & AM_DIR)
  293. {
  294. //合成完整目录名
  295. sprintf(&path[i], "/%s", fn);
  296. //递归遍历
  297. res = func_record_scan_files(path);
  298. path[i] = 0;
  299. //打开失败,跳出循环
  300. if (res != FR_OK)
  301. break;
  302. }
  303. else
  304. {
  305. printf("%s/%s\n", path, fn); //输出文件名
  306. /* 可以在这里提取特定格式的文件路径 */
  307. }//else
  308. } //for
  309. }
  310. return res;
  311. }
  312. /*------------------------------------------------------
  313. 读取指定目录下所有的文件
  314. 说明:
  315. f_readdir 按顺序读取目录内文件,
  316. 重复调用此函数可读取目录内所有文件;
  317. ---------------------------------------------------------*/
  318. void func_record_files_update(char * path)
  319. {
  320. char file_name[32] = {0};
  321. FRESULT res; //部分在递归过程被修改的变量,不用全局变量
  322. FILINFO fno = {0};
  323. fs_record_obj.file_num = 0;
  324. memset((void *)fs_record_obj.file_list, 0x00,sizeof(fs_record_obj.file_list));
  325. memset((void *)fs_record_obj.name_send, 0x00,sizeof(fs_record_obj.name_send));
  326. #if _USE_LFN//如果使能支持长文件名 先对下面两项初始化
  327. fileinfo.lfsize=_MAX_LFN * 2 + 1;//
  328. fileinfo.lfname=(TCHAR*)FileName;//
  329. #endif
  330. if(f_opendir(&fs_record_obj.dir,(const char*)path) != FR_OK)/* 打开文件夹目录成功,目录信息已经在dir结构体中保存 */
  331. {
  332. res = f_mkdir((const char*)path);
  333. if(res == FR_OK)
  334. {
  335. fs_record_obj.fatfs_ok = true;
  336. return;
  337. }
  338. else
  339. {
  340. return;
  341. }
  342. }
  343. fs_record_obj.fatfs_ok = true;
  344. //打开日志路径正常,获取路文件夹内的文件列表
  345. while(f_readdir(&fs_record_obj.dir, &fno) == FR_OK) //读文件信息到文件状态结构体中
  346. {
  347. if(!fno.fname[0]) break; //如果文件名为‘\0',说明读取完成结束
  348. if (fno.fattrib & AM_DIR) continue; //表示目录,跳过
  349. if (fno.fname[0] == '.') continue; //点表示当前目录,跳过
  350. if(fs_record_obj.file_num < MAX_FILE_COUNT)
  351. {
  352. sprintf((char *)fs_record_obj.file_list[fs_record_obj.file_num], "%s/%s", fs_record_obj.path,fno.fname);//将文件名存入列表中
  353. fs_record_obj.file_num ++;
  354. }
  355. else
  356. {
  357. /* 如果目录已经存在,关闭它 */
  358. res = f_closedir(&fs_record_obj.dir);
  359. sprintf((char *)file_name,"%s/%s",fs_record_obj.path, fno.fname); //输出文件名
  360. res = f_unlink(file_name);
  361. if(FR_OK != res)
  362. {
  363. fs_record_obj.fatfs_ok = false;
  364. return;
  365. }
  366. }
  367. }
  368. /* 如果目录已经存在,关闭它 */
  369. res = f_closedir(&fs_record_obj.dir);
  370. if(fs_record_obj.file_num > 0)
  371. {
  372. }
  373. else
  374. {
  375. memset((void *)fs_record_obj.name_send, 0x00,sizeof(fs_record_obj.name_send));
  376. return;
  377. }
  378. //按文件名最小到大排序;
  379. if(fs_record_obj.file_num > 1)
  380. {
  381. func_record_dir_qsort(fs_record_obj.file_num);
  382. }
  383. //获取最新的文件;
  384. uint8_t max_idx = fs_record_obj.file_num - 1;
  385. sprintf((char *)fs_record_obj.name_send,"%s", fs_record_obj.file_list[max_idx]);
  386. //如果文件个数超限,
  387. if(fs_record_obj.file_num > NUM_FILE_SET)
  388. {
  389. //删除日期最早的文件
  390. sprintf((char *)file_name,"%s", fs_record_obj.file_list[0]);
  391. res = f_unlink(file_name);
  392. if(FR_OK != res)
  393. {
  394. fs_record_obj.fatfs_ok = false;
  395. return;
  396. }
  397. }
  398. UNUSED(res);
  399. return;
  400. }
  401. int qsort_cmp(const void *a,const void *b)
  402. {
  403. return strcmp(( char * ) a, (const char* )b);
  404. }
  405. //(void * /*base*/, size_t /*nmemb*/, size_t /*size*/, int (* /*compar*/)(const void *, const void *)) __attribute__((__nonnull__(1,4)));
  406. void func_record_dir_qsort(size_t fcount)
  407. {
  408. qsort((void *)fs_record_obj.file_list, fcount, sizeof(fs_record_obj.file_list[0]), qsort_cmp);
  409. }
  410. void func_record_init(void)
  411. {
  412. memset(fs_record_obj.file_list, 0x00,sizeof(fs_record_obj.file_list)); //清空文件列表
  413. fs_record_obj.file_num = 0;
  414. fs_record_obj.fatfs_ok = true;
  415. func_record_files_update((char *)fs_record_obj.path);
  416. }
  417. typedef struct record_test_object
  418. {
  419. uint32_t cnts;
  420. uint8_t test_flag;
  421. char buf[32];
  422. }record_test_OBJ;
  423. record_test_OBJ record_test_obj;
  424. void func_record_test(void)
  425. {
  426. record_test_obj.cnts++;
  427. sprintf(record_test_obj.buf,"XX%08xXX",record_test_obj.cnts);
  428. switch(record_test_obj.test_flag)
  429. {
  430. case 0:
  431. {
  432. func_record_write((uint8_t *)record_test_obj.buf ,strlen(record_test_obj.buf));
  433. }break;
  434. case 1:
  435. {
  436. func_record_read((uint8_t *)record_test_obj.buf ,sizeof(record_test_obj.buf));
  437. func_record_delete((uint8_t *)record_test_obj.buf ,sizeof(record_test_obj.buf));
  438. func_record_read((uint8_t *)record_test_obj.buf ,sizeof(record_test_obj.buf));
  439. }break;
  440. default:
  441. {
  442. func_record_read((uint8_t *)record_test_obj.buf ,sizeof(record_test_obj.buf));
  443. }break;
  444. }
  445. }
  446. void func_record_main(void const *argument)
  447. {
  448. osDelay(1000);//
  449. func_record_init();
  450. while(1)
  451. {
  452. func_record_test();
  453. osDelay(1000);
  454. }
  455. }
  456. #endif //---------------------------USE_FATFS_RECORD----------------------------
  457. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/