14 changed files with 1886 additions and 1637 deletions
File diff suppressed because it is too large
@ -0,0 +1,176 @@ |
|||
#include <rtthread.h> |
|||
#include "libcsv.h" |
|||
#include "lvgl.h" |
|||
|
|||
#define CSV_MAX_ROWS 260 // 最大行数
|
|||
#define CSV_MAX_COLS 48 // 每行最大列数
|
|||
#define CSV_MAX_FIELD 64 // 每个字段最大长度
|
|||
|
|||
// ============ 数据结构定义 ============
|
|||
typedef struct { |
|||
int row; // 当前行号
|
|||
int col; // 当前列号
|
|||
int total_rows; // 总行数
|
|||
int max_cols; // 最大列数
|
|||
char data[CSV_MAX_ROWS][CSV_MAX_COLS][CSV_MAX_FIELD]; // 固定二维数组
|
|||
} UserData; |
|||
|
|||
// ============ 字段回调函数 ============
|
|||
void field_callback(void *data, size_t size, void *user_data) { |
|||
UserData *user = (UserData *)user_data; |
|||
|
|||
// 检查边界
|
|||
if (user->row >= CSV_MAX_ROWS) { |
|||
//rt_kprintf("[W] 超出最大行数 %d\n", CSV_MAX_ROWS);
|
|||
return; |
|||
} |
|||
if (user->col >= CSV_MAX_COLS) { |
|||
//rt_kprintf("[W] 超出最大列数 %d\n", CSV_MAX_COLS);
|
|||
return; |
|||
} |
|||
|
|||
// 限制字段长度
|
|||
size_t copy_size = size; |
|||
if (copy_size >= CSV_MAX_FIELD) { |
|||
copy_size = CSV_MAX_FIELD - 1; |
|||
//rt_kprintf("[W] 字段截断\n");
|
|||
} |
|||
|
|||
// 复制数据到固定数组
|
|||
rt_memcpy(user->data[user->row][user->col], data, copy_size); |
|||
user->data[user->row][user->col][copy_size] = '\0'; |
|||
|
|||
// 调试输出
|
|||
//rt_kprintf("R:%d C:%d V:\"%s\"\n", user->row, user->col, user->data[user->row][user->col]);
|
|||
|
|||
// 列号+1
|
|||
user->col++; |
|||
|
|||
// 更新最大列数
|
|||
if (user->col > user->max_cols) { |
|||
user->max_cols = user->col; |
|||
} |
|||
|
|||
// 更新总行数
|
|||
if (user->row + 1 > user->total_rows) { |
|||
user->total_rows = user->row + 1; |
|||
} |
|||
} |
|||
|
|||
// ============ 行回调函数 ============
|
|||
void row_callback(int c, void *user_data) { |
|||
UserData *user = (UserData *)user_data; |
|||
|
|||
// 行结束,重置列号,行号+1
|
|||
user->row++; |
|||
user->col = 0; |
|||
} |
|||
|
|||
// ============ 获取指定单元格数据 ============
|
|||
const char* csv_get_cell(UserData *user, int row, int col) { |
|||
if (user == NULL) { |
|||
return NULL; |
|||
} |
|||
if (row < 0 || row >= user->total_rows) { |
|||
return NULL; |
|||
} |
|||
if (col < 0 || col >= user->max_cols) { |
|||
return NULL; |
|||
} |
|||
return user->data[row][col]; |
|||
} |
|||
|
|||
// ============ 获取行数 ============
|
|||
int csv_get_row_count(UserData *user) { |
|||
return user ? user->total_rows : 0; |
|||
} |
|||
|
|||
// ============ 获取列数 ============
|
|||
int csv_get_col_count(UserData *user) { |
|||
return user ? user->max_cols : 0; |
|||
} |
|||
|
|||
// ============ 清空数据 ============
|
|||
void csv_clear_data(UserData *user) { |
|||
if (user == NULL) { |
|||
return; |
|||
} |
|||
user->row = 0; |
|||
user->col = 0; |
|||
user->total_rows = 0; |
|||
user->max_cols = 0; |
|||
} |
|||
|
|||
// ============ 解析后创建 LVGL 表格 ============
|
|||
int parse_csv_string(lv_obj_t *container, const char *csv_data, UserData *user) |
|||
{ |
|||
if (csv_data == NULL) { |
|||
rt_kprintf("[E] NOT DATA\n"); |
|||
return -1; |
|||
} |
|||
|
|||
if (user == NULL) { |
|||
rt_kprintf("[E] NOT USER DATA\n"); |
|||
return -1; |
|||
} |
|||
|
|||
// 初始化 UserData
|
|||
csv_clear_data(user); |
|||
|
|||
if (container != NULL) { |
|||
lv_obj_set_size(container, LV_PCT(100), LV_SIZE_CONTENT); |
|||
lv_obj_set_style_pad_all(container, 0, LV_PART_MAIN); |
|||
} |
|||
|
|||
struct csv_parser parser; |
|||
csv_init(&parser, 0); |
|||
|
|||
size_t data_len = rt_strlen(csv_data); |
|||
if (csv_parse(&parser, csv_data, data_len, field_callback, row_callback, user) != data_len) { |
|||
rt_kprintf("[E] ERR: %s\n", csv_strerror(csv_error(&parser))); |
|||
csv_fini(&parser, field_callback, row_callback, user); |
|||
csv_free(&parser); |
|||
return -1; |
|||
} |
|||
|
|||
csv_fini(&parser, field_callback, row_callback, user); |
|||
csv_free(&parser); |
|||
//rt_kprintf("ROW: %d\n COL:%d", user->total_rows,user->max_cols);
|
|||
return 0; |
|||
} |
|||
|
|||
// ============ 全局指针 ============
|
|||
static UserData *user = NULL; |
|||
extern struct rt_memheap sdram_heap; |
|||
|
|||
int parse_csv_to_table(lv_obj_t *container, const char *csv_data) { |
|||
if (container == NULL || csv_data == NULL) { |
|||
return -1; |
|||
} |
|||
|
|||
user = (UserData *)rt_memheap_alloc(&sdram_heap, sizeof(UserData)); |
|||
|
|||
// 解析 CSV
|
|||
if (parse_csv_string(container, csv_data, user) != 0) { |
|||
return -1; |
|||
} |
|||
|
|||
// 表格
|
|||
lv_obj_set_size(container, LV_PCT(100), LV_SIZE_CONTENT); |
|||
lv_obj_set_style_pad_all(container, 0, LV_PART_MAIN); |
|||
lv_table_set_col_cnt(container,user->max_cols); |
|||
lv_table_set_row_cnt(container,user->total_rows); |
|||
|
|||
// 填充表格数据
|
|||
for (int i = 0; i < user->total_rows; i++) { |
|||
for (int j = 0; j < user->max_cols; j++) { |
|||
const char *val = csv_get_cell(user, i, j); |
|||
lv_table_set_cell_value(container, i, j, val ? val : ""); |
|||
} |
|||
} |
|||
|
|||
// 释放内存
|
|||
rt_memheap_free(user); |
|||
|
|||
return 0; |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
/*
|
|||
* Copyright (c) 2006-2021, RT-Thread Development Team |
|||
* |
|||
* SPDX-License-Identifier: Apache-2.0 |
|||
* |
|||
* Change Logs: |
|||
* Date Author Notes |
|||
* 2026-02-18 24018 the first version |
|||
*/ |
|||
#ifndef APPLICATIONS_LVGL_UI_DATA_CSV_H_ |
|||
#define APPLICATIONS_LVGL_UI_DATA_CSV_H_ |
|||
|
|||
int parse_csv_to_table(lv_obj_t *container, const char *csv_data); |
|||
|
|||
#endif /* APPLICATIONS_LVGL_UI_DATA_CSV_H_ */ |
|||
@ -0,0 +1,20 @@ |
|||
cd /d D:\RT-ThreadStudio\workspace\828F |
|||
set RTT_ROOT= |
|||
set ENV_ROOT=D:/RT-ThreadStudio/platform/env_released/env |
|||
set RTT_EXEC_PATH=D:/RT-ThreadStudio/repo/Extract/ToolChain_Support_Packages/ARM/GNU_Tools_for_ARM_Embedded_Processors/13.3/bin |
|||
set KCONF_EXEC_PATH=%ENV_ROOT%\tools\exec |
|||
set RTT_CC=gcc |
|||
set RTTS_PLATFORM=STUDIO |
|||
set SCONS=%ENV_ROOT%\tools\Python27\Scripts |
|||
set PKGS_ROOT=%ENV_ROOT%\packages |
|||
set PATH=%ENV_ROOT%\tools\MinGit-2.25.1-32-bit\cmd;%PATH% |
|||
set PATH=%ENV_ROOT%\tools\Python27;%PATH% |
|||
set PATH=%ENV_ROOT%\tools\Python27\Scripts;%PATH% |
|||
set PATH=%ENV_ROOT%\tools\bin;%PATH% |
|||
set PATH=%RTT_EXEC_PATH%;%PATH% |
|||
set PATH=%KCONF_EXEC_PATH%;%PATH% |
|||
set PATH=%ENV_ROOT%\tools\scripts\pkgs;%PATH% |
|||
set PATH=%ENV_ROOT%\tools\qemu\qemu32;%PATH% |
|||
set PYTHONPATH=%ENV_ROOT%\tools\Python27; |
|||
set PATH=%PATH%; |
|||
scons --target=eclipse --project-name=828F |
|||
Loading…
Reference in new issue