Rdzleo dbdd304905 代码初始化:
本项目为触摸版项目代码复制而来,基于此版本进行按键功能的适配!
2026-03-23 11:14:56 +08:00

249 lines
7.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file fatfs.c
* @brief SPIFFS 文件系统管理模块(从 dzbj 移植)
*
* 提供 SPIFFS 挂载、文件读写、JPEG 解码等功能。
*/
#include "esp_err.h"
#include "esp_log.h"
#include "esp_spiffs.h"
#include "fatfs.h"
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
static const char *TAG = "FATFS";
// 初始化SPIFFS文件系统
void fatfs_init(void) {
esp_vfs_spiffs_conf_t conf = {
.base_path = "/spiflash",
.partition_label = "storage",
.max_files = 5,
.format_if_mount_failed = true,
};
esp_err_t err = esp_vfs_spiffs_register(&conf);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to mount SPIFFS (%s)", esp_err_to_name(err));
return;
}
size_t total = 0, used = 0;
err = esp_spiffs_info("storage", &total, &used);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to get SPIFFS info (%s)", esp_err_to_name(err));
} else {
ESP_LOGI(TAG, "SPIFFS: Total size: %d, Used: %d", total, used);
}
}
// 读取图片数据到内存
void read_img(uint8_t *img_p) {
FILE *f = fopen("/spiflash/img.bin", "r");
if (f == NULL) {
ESP_LOGE(TAG, "OPEN ERROR");
return;
}
size_t size = fread(img_p, sizeof(uint8_t), 129600 * 2, f);
fclose(f);
if (size != 0) {
ESP_LOGI(TAG, "read success!");
}
}
// 测试FATFS文件系统
void fs_test(void) {
FILE *f = fopen("/spiflash/img.bin", "r");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for reading");
return;
}
uint8_t line[2];
fread(line, sizeof(uint8_t), 2, f);
fclose(f);
ESP_LOGI(TAG, "Read from file: %x %x", line[0], line[1]);
}
// 列出目录下所有文件名
void fatfs_list_all_filenames(const char *dir_path, bool recursive) {
DIR *dir = opendir(dir_path);
if (dir == NULL) {
ESP_LOGE(TAG, "无法打开目录: %s", dir_path);
return;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
char full_path[512];
snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, entry->d_name);
struct stat file_stat;
if (stat(full_path, &file_stat) == 0 && S_ISDIR(file_stat.st_mode)) {
if (recursive) {
fatfs_list_all_filenames(full_path, recursive);
}
} else if (stat(full_path, &file_stat) == 0 && S_ISREG(file_stat.st_mode)) {
ESP_LOGI(TAG, "文件名: %s, 大小:%d", full_path, (int)file_stat.st_size);
}
}
closedir(dir);
}
// 删除目录下所有空文件
void fatfs_remove_nullData(const char *dir_path) {
DIR *dir = opendir(dir_path);
if (dir == NULL) {
ESP_LOGE(TAG, "无法打开目录: %s", dir_path);
return;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
char full_path[512];
snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, (char*)entry->d_name);
struct stat file_stat;
stat(full_path, &file_stat);
if ((int)file_stat.st_size == 0) {
remove(full_path);
ESP_LOGE(TAG, "删除空文件: %s", full_path);
}
}
closedir(dir);
}
// 删除目录下所有文件
void fatfs_remove_allData(const char *dir_path) {
DIR *dir = opendir(dir_path);
if (dir == NULL) {
ESP_LOGE(TAG, "无法打开目录: %s", dir_path);
return;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
char full_path[512];
snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, (char*)entry->d_name);
remove(full_path);
ESP_LOGE(TAG, "删除文件: %s", full_path);
}
closedir(dir);
}
// 检查图片是否有效文件大小不为0
bool fats_img_isOK(char* img_path) {
struct stat file_stat;
stat(img_path, &file_stat);
return file_stat.st_size > 0;
}
// JPEG 解码:从 SPIFFS 读取 JPEG 并解码为 RGB565
esp_err_t DecodeImg(char *imgpath, uint8_t** imgData, esp_jpeg_image_output_t *outimage) {
FILE *f = fopen(imgpath, "rb");
if (f == NULL) {
ESP_LOGE(TAG, "OPEN ERROR: %s", imgpath);
return ESP_FAIL;
}
struct stat file_stat;
stat(imgpath, &file_stat);
// 分配输出缓冲区360×360 RGB565
*imgData = malloc(360 * 360 * 2);
if (*imgData == NULL) {
ESP_LOGE(TAG, "输出缓冲区分配失败");
fclose(f);
return ESP_FAIL;
}
// 分配输入缓冲区JPEG 原始数据)
uint8_t *imgEncoderData = malloc(file_stat.st_size);
if (imgEncoderData == NULL) {
ESP_LOGE(TAG, "输入缓冲区分配失败(需%d字节", (int)file_stat.st_size);
free(*imgData);
*imgData = NULL;
fclose(f);
return ESP_FAIL;
}
size_t read_len = fread(imgEncoderData, sizeof(uint8_t), file_stat.st_size, f);
fclose(f);
if (read_len != (size_t)file_stat.st_size) {
ESP_LOGE(TAG, "文件读取不完整(预期:%d实际%zu",
(int)file_stat.st_size, read_len);
free(imgEncoderData);
free(*imgData);
*imgData = NULL;
return ESP_FAIL;
}
// 验证 JPEG 头
if (file_stat.st_size < 2 || imgEncoderData[0] != 0xFF || imgEncoderData[1] != 0xD8) {
ESP_LOGE(TAG, "不是有效JPEG文件: %s", imgpath);
free(imgEncoderData);
free(*imgData);
*imgData = NULL;
return ESP_FAIL;
}
uint32_t outbuf_size = 360 * 360 * sizeof(uint8_t) * 2;
esp_jpeg_image_cfg_t jpeg_cfg = {
.indata = imgEncoderData,
.indata_size = file_stat.st_size,
.outbuf = *imgData,
.outbuf_size = outbuf_size,
.out_format = JPEG_IMAGE_FORMAT_RGB565,
.flags = {
.swap_color_bytes = true,
},
};
esp_err_t ret = esp_jpeg_decode(&jpeg_cfg, outimage);
free(imgEncoderData);
return ret;
}
// 测试读取图片数据
void test_readimg(char *imgpath, uint16_t size) {
FILE *f = fopen(imgpath, "r");
if (f == NULL) {
ESP_LOGE(TAG, "OPEN ERROR");
return;
}
uint8_t *head = malloc(size);
if (head == NULL) {
fclose(f);
return;
}
fread(head, sizeof(uint8_t), size, f);
fclose(f);
for (int i = 0; i < size; i++) {
printf("%x ", *(head + i));
}
printf("\n");
free(head);
}
// 获取目录下所有图片文件名
void fat_getAllimgList(const char *dir_path, char** list, uint8_t* num) {
*num = 0;
DIR *dir = opendir(dir_path);
if (dir == NULL) {
ESP_LOGE(TAG, "无法打开目录: %s", dir_path);
return;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
list[*num] = strdup(entry->d_name);
(*num)++;
}
closedir(dir);
}