关于基于lvgl库做的注册登录功能的代码步骤:
mlittle-endian -marm -mcpu=arm926ej-s 适配GEC6818架构(若为A53,可将 arm926ej-s 改为 cortex-a53)。4. LVGL库路径:-L/path/to/your/lvgl/build/lib 替换为LVGL库编译后的输出目录(包含 liblvgl.a 或 liblvgl.so)。3. LVGL头文件路径:-I/path/to/your/
以下是完整的文件拆分和代码存放说明,按功能模块化划分,方便工程管理:
一、需要创建的文件清单
文件名 作用 类型
main.c 程序入口,初始化硬件和LVGL 源文件
ui.h 声明界面相关函数 头文件
ui.c 实现登录、注册、主页面的UI 源文件
user_data.h 声明用户数据处理函数 头文件
user_data.c 实现注册/登录的文件读写逻辑 源文件
二、各文件代码及存放位置
1. main.c(工程入口)存放内容:主函数,初始化硬件、LVGL,启动界面
#include "lvgl/lvgl.h"
#include "ui.h" // 包含界面函数声明
#include "user_data.h" // 包含用户数据处理声明
// 硬件初始化(需根据GEC6818实际驱动实现)
static void hardware_init(void) {
// 此处添加LCD屏幕、触摸驱动的初始化代码
// 例如:打开LCD设备、设置分辨率、初始化触摸输入等
}
int main(void) {
// 1. 初始化硬件
hardware_init();
// 2. 初始化LVGL
lv_init();
lv_port_disp_init(); // 显示接口初始化(适配GEC6818 LCD)
lv_port_indev_init(); // 输入设备初始化(适配触摸)
// 3. 初始化用户数据(如检查存储文件是否存在)
// (可选,user_data.c中若有初始化逻辑可在此调用)
// 4. 显示初始界面(登录页)
create_login_ui();
// 5. LVGL主循环
while (1) {
lv_task_handler(); // 处理LVGL任务
usleep(5000); // 5ms延迟
}
return 0;
}
2. ui.h(界面函数声明)存放内容:声明所有界面创建和回调函数
#ifndef UI_H
#define UI_H
#include "lvgl/lvgl.h"
// 登录界面
void create_login_ui(void);
// 注册界面
void create_reg_ui(void);
// 主页面(登录成功后显示)
void switch_to_main_page(lv_timer_t *t);
// 注册成功后返回登录页
void back_to_login(lv_timer_t *t);
#endif // UI_H
3. ui.c(界面实现)存放内容:登录/注册/主页面的LVGL组件创建,按钮回调逻辑
#include "ui.h"
#include "user_data.h" // 调用注册/登录函数
// 登录界面输入缓存
static char username[32] = "";
static char password[32] = "";
// 注册界面输入缓存
static char reg_username[32] = "";
static char reg_password[32] = "";
// 登录界面创建
void create_login_ui(void) {
// 清空当前界面
lv_obj_clean(lv_scr_act());
// 1. 创建主页面容器
lv_obj_t *page = lv_obj_create(lv_scr_act());
lv_obj_set_size(page, LV_HOR_RES, LV_VER_RES);
// 2. 账号输入框
lv_obj_t *user_label = lv_label_create(page);
lv_label_set_text(user_label, "账号:");
lv_obj_align(user_label, LV_ALIGN_TOP_LEFT, 50, 100);
lv_obj_t *user_ta = lv_textarea_create(page);
lv_textarea_set_placeholder_text(user_ta, "请输入账号");
lv_textarea_set_max_length(user_ta, 31);
lv_obj_set_size(user_ta, 200, 50);
lv_obj_align_to(user_ta, user_label, LV_ALIGN_OUT_RIGHT_MID, 20, 0);
lv_textarea_set_text(user_ta, username);
// 3. 密码输入框
lv_obj_t *pwd_label = lv_label_create(page);
lv_label_set_text(pwd_label, "密码:");
lv_obj_align(pwd_label, LV_ALIGN_TOP_LEFT, 50, 180);
lv_obj_t *pwd_ta = lv_textarea_create(page);
lv_textarea_set_placeholder_text(pwd_ta, "请输入密码");
lv_textarea_set_password_mode(pwd_ta, true);
lv_textarea_set_max_length(pwd_ta, 31);
lv_obj_set_size(pwd_ta, 200, 50);
lv_obj_align_to(pwd_ta, pwd_label, LV_ALIGN_OUT_RIGHT_MID, 20, 0);
lv_textarea_set_text(pwd_ta, password);
// 4. 登录按钮及回调
lv_obj_t *login_btn = lv_btn_create(page);
lv_obj_set_size(login_btn, 100, 40);
lv_obj_align(login_btn, LV_ALIGN_TOP_MID, -60, 280);
lv_obj_t *login_btn_label = lv_label_create(login_btn);
lv_label_set_text(login_btn_label, "登录");
lv_obj_add_event_cb(login_btn, login_btn_cb, LV_EVENT_CLICKED, NULL);
// 5. 注册按钮(跳转到注册界面)
lv_obj_t *to_reg_btn = lv_btn_create(page);
lv_obj_set_size(to_reg_btn, 100, 40);
lv_obj_align(to_reg_btn, LV_ALIGN_TOP_MID, 60, 280);
lv_obj_t *to_reg_label = lv_label_create(to_reg_btn);
lv_label_set_text(to_reg_label, "注册");
lv_obj_add_event_cb(to_reg_btn, to_reg_cb, LV_EVENT_CLICKED, NULL);
}
// 注册界面创建
void create_reg_ui(void) {
lv_obj_clean(lv_scr_act()); // 清空当前界面
// 1. 标题
lv_obj_t *title = lv_label_create(lv_scr_act());
lv_label_set_text(title, "用户注册");
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 50);
// 2. 注册账号输入框
lv_obj_t *reg_user_label = lv_label_create(lv_scr_act());
lv_label_set_text(reg_user_label, "新账号:");
lv_obj_align(reg_user_label, LV_ALIGN_TOP_LEFT, 50, 100);
lv_obj_t *reg_user_ta = lv_textarea_create(lv_scr_act());
lv_textarea_set_placeholder_text(reg_user_ta, "请设置账号");
lv_textarea_set_max_length(reg_user_ta, 31);
lv_obj_set_size(reg_user_ta, 200, 50);
lv_obj_align_to(reg_user_ta, reg_user_label, LV_ALIGN_OUT_RIGHT_MID, 20, 0);
lv_textarea_set_text(reg_user_ta, reg_username);
// 3. 注册密码输入框
lv_obj_t *reg_pwd_label = lv_label_create(lv_scr_act());
lv_label_set_text(reg_pwd_label, "新密码:");
lv_obj_align(reg_pwd_label, LV_ALIGN_TOP_LEFT, 50, 180);
lv_obj_t *reg_pwd_ta = lv_textarea_create(lv_scr_act());
lv_textarea_set_placeholder_text(reg_pwd_ta, "请设置密码");
lv_textarea_set_password_mode(reg_pwd_ta, true);
lv_textarea_set_max_length(reg_pwd_ta, 31);
lv_obj_set_size(reg_pwd_ta, 200, 50);
lv_obj_align_to(reg_pwd_ta, reg_pwd_label, LV_ALIGN_OUT_RIGHT_MID, 20, 0);
lv_textarea_set_text(reg_pwd_ta, reg_password);
// 4. 注册按钮及回调
lv_obj_t *reg_btn = lv_btn_create(lv_scr_act());
lv_obj_set_size(reg_btn, 100, 40);
lv_obj_align(reg_btn, LV_ALIGN_TOP_MID, -60, 280);
lv_obj_t *reg_btn_label = lv_label_create(reg_btn);
lv_label_set_text(reg_btn_label, "注册");
lv_obj_add_event_cb(reg_btn, reg_btn_cb, LV_EVENT_CLICKED, NULL);
// 5. 返回登录按钮
lv_obj_t *back_btn = lv_btn_create(lv_scr_act());
lv_obj_set_size(back_btn, 100, 40);
lv_obj_align(back_btn, LV_ALIGN_TOP_MID, 60, 280);
lv_obj_t *back_btn_label = lv_label_create(back_btn);
lv_label_set_text(back_btn_label, "返回登录");
lv_obj_add_event_cb(back_btn, back_to_login_cb, LV_EVENT_CLICKED, NULL);
}
// 登录按钮回调
static void login_btn_cb(lv_event_t *e) {
// 获取输入框内容
lv_obj_t *user_ta = lv_obj_get_child(lv_scr_act(), 1); // 账号输入框
lv_obj_t *pwd_ta = lv_obj_get_child(lv_scr_act(), 3); // 密码输入框
const char *user = lv_textarea_get_text(user_ta);
const char *pwd = lv_textarea_get_text(pwd_ta);
// 调用登录验证函数(来自user_data.c)
int ret = login_user(user, pwd);
lv_obj_t *msg;
if (ret == 0) {
msg = lv_msgbox_create(NULL, "提示", "登录成功!", NULL, false);
lv_timer_create(switch_to_main_page, 1500, NULL); // 跳转主页面
} else if (ret == -1) {
msg = lv_msgbox_create(NULL, "提示", "暂无注册用户,请先注册", NULL, false);
} else {
msg = lv_msgbox_create(NULL, "提示", "账号或密码错误", NULL, false);
}
lv_obj_center(msg);
}
// 注册按钮回调
static void reg_btn_cb(lv_event_t *e) {
// 获取注册输入框内容
lv_obj_t *reg_user_ta = lv_obj_get_child(lv_scr_act(), 1); // 新账号输入框
lv_obj_t *reg_pwd_ta = lv_obj_get_child(lv_scr_act(), 3); // 新密码输入框
const char *user = lv_textarea_get_text(reg_user_ta);
const char *pwd = lv_textarea_get_text(reg_pwd_ta);
// 调用注册函数(来自user_data.c)
int ret = register_user(user, pwd);
lv_obj_t *msg;
if (ret == 0) {
msg = lv_msgbox_create(NULL, "提示", "注册成功!", NULL, false);
lv_timer_create(back_to_login, 1500, NULL); // 返回登录页
} else if (ret == -1) {
msg = lv_msgbox_create(NULL, "提示", "账号或密码不能为空", NULL, false);
} else if (ret == -2) {
msg = lv_msgbox_create(NULL, "提示", "账号已存在", NULL, false);
} else {
msg = lv_msgbox_create(NULL, "提示", "注册失败", NULL, false);
}
lv_obj_center(msg);
}
// 跳转到注册界面的回调
static void to_reg_cb(lv_event_t *e) {
create_reg_ui();
}
// 返回登录界面的回调
static void back_to_login_cb(lv_event_t *e) {
create_login_ui();
}
// 登录成功后跳转主页面
void switch_to_main_page(lv_timer_t *t) {
lv_obj_clean(lv_scr_act());
lv_obj_t *main_label = lv_label_create(lv_scr_act());
lv_label_set_text(main_label, "欢迎进入主页面!");
lv_obj_center(main_label);
}
// 注册成功后返回登录页
void back_to_login(lv_timer_t *t) {
create_login_ui();
}
4. user_data.h(用户数据函数声明)存放内容:声明注册、登录、账号检查等函数
#ifndef USER_DATA_H
#define USER_DATA_H
#include <stdio.h>
// 注册用户(返回0成功,-1空输入,-2账号已存在,-3文件错误)
int register_user(const char *username, const char *password);
// 登录验证(返回0成功,-1无注册用户,-2账号密码错误)
int login_user(const char *username, const char *password);
#endif // USER_DATA_H
5. user_data.c(用户数据处理)存放内容:文件读写逻辑,实现注册和登录的核心验证
#include "user_data.h"
#include <string.h>
// 存储用户信息的文件路径
#define USER_FILE "users.txt"
// 检查账号是否已存在
static int is_username_exist(const char *username) {
FILE *fp = fopen(USER_FILE, "r");
if (!fp) return 0; // 文件不存在,无重复
char line[128], u[32];
while (fgets(line, sizeof(line), fp)) {
if (sscanf(line, "%31[^:]", u) == 1 && strcmp(u, username) == 0) {
fclose(fp);
return 1; // 账号已存在
}
}
fclose(fp);
return 0;
}
// 注册函数:写入文件
int register_user(const char *username, const char *password) {
// 检查输入合法性
if (strlen(username) == 0 || strlen(password) == 0) return -1;
if (is_username_exist(username)) return -2;
// 写入文件(追加模式)
FILE *fp = fopen(USER_FILE, "a");
if (!fp) return -3;
fprintf(fp, "%s:%s\n", username, password); // 实际需加密存储
fclose(fp);
return 0;
}
// 登录函数:读取文件比对
int login_user(const char *username, const char *password) {
FILE *fp = fopen(USER_FILE, "r");
if (!fp) return -1; // 无注册用户
char line[128], u[32], p[32];
while (fgets(line, sizeof(line), fp)) {
if (sscanf(line, "%31[^:]:%31s", u, p) == 2) {
if (strcmp(u, username) == 0 && strcmp(p, password) == 0) {
fclose(fp);
return 0; // 登录成功
}
}
}
fclose(fp);
return -2; // 账号或密码错误
}
三、工程文件结构
project/
├── main.c # 主程序入口
├── ui.h # 界面函数声明
├── ui.c # 登录/注册界面实现
├── user_data.h # 数据处理函数声明
├── user_data.c # 注册/登录文件读写逻辑
└── Makefile # 编译配置(需自行编写,链接LVGL库)
四、编译说明
• 编译时需链接LVGL库(-llvgl),确保GEC6818的交叉编译环境正确配置。
• 运行后会在程序目录自动生成users.txt文件,存储注册的账号密码。
按此结构存放代码,可实现模块化管理,方便后续修改界面或数据存储逻辑。
如果你的交叉编译工具链是 arm-linux-gcc(而非 arm-linux-gnueabihf-gcc),只需调整 Makefile 中的工具链和编译选项即可。以下是适配 arm-linux-gcc 的版本,可直接使用:适配 arm-linux-gcc 的 Makefile
# 交叉编译工具链(使用arm-linux-gcc)
CC = arm-linux-gcc
# LVGL库路径(替换为你的LVGL实际路径)
LVGL_DIR = /path/to/your/lvgl
# 源文件列表
SRCS = main.c ui.c user_data.c
# 目标文件
OBJS = $(SRCS:.c=.o)
# 生成的可执行文件名
TARGET = login_demo
# 编译选项(适配arm-linux-gcc,无需硬浮点参数)
CFLAGS = -I. \
-I$(LVGL_DIR) \
-I$(LVGL_DIR)/src \
-I$(LVGL_DIR)/src/core \
-I$(LVGL_DIR)/src/hal \
-I$(LVGL_DIR)/src/widgets \
-O2 -Wall -Wextra \
-mlittle-endian \
-marm \
-mcpu=arm926ej-s # GEC6818若基于ARM9架构,用此参数;若为A53,可保留-mcpu=cortex-a53
# 链接选项(链接LVGL库和系统库)
LDFLAGS = -L$(LVGL_DIR)/build/lib \ # LVGL库的编译输出路径
-llvgl \ # 链接LVGL库
-lm -lpthread -ldl # 系统库(数学库、线程库等)
# 默认目标:编译生成可执行文件
all: $(TARGET)
# 链接目标文件
$(TARGET): $(OBJS)
$(CC) $(OBJS) -o $@ $(LDFLAGS)
@echo "编译完成:生成可执行文件 $(TARGET)"
# 编译.c文件为.o文件
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# 清理编译产物
clean:
rm -f $(OBJS) $(TARGET)
@echo "清理完成"
.PHONY: all clean
关键调整说明
1. 工具链修改:将 CC 改为 arm-linux-gcc,匹配你的工具链。
2. 架构参数:
◦ 若GEC6818基于 ARM9 架构(部分版本),使用 -mcpu=arm926ej-s。
◦ 若基于 Cortex-A53 架构,保留 -mcpu=cortex-a53 即可。
3. 去除硬浮点参数:arm-linux-gcc 通常不默认支持 neon-vfpv4 等硬浮点选项,因此删除 -mfpu=neon-vfpv4 和 -mfloat-abi=hard。
使用方法
1. 替换 LVGL_DIR 为你的LVGL库实际路径(例如 ~/lvgl)。
2. 终端进入工程目录,执行 make 编译,生成 login_demo。
3. 传输到开发板后,执行 chmod +x login_demo 赋予权限,再运行 ./login_demo。
如果编译时出现架构不匹配的错误,可尝试删除 -mcpu=xxx 选项,或根据开发板CPU型号调整。
如果直接用 arm-linux-gcc 命令编译(不通过 Makefile),可以执行以下完整命令(需根据你的实际路径调整):
arm-linux-gcc main.c ui.c user_data.c -o login_demo \
-I/path/to/your/lvgl \
-I/path/to/your/lvgl/src \
-I/path/to/your/lvgl/src/core \
-I/path/to/your/lvgl/src/hal \
-I/path/to/your/lvgl/src/widgets \
-L/path/to/your/lvgl/build/lib \
-llvgl -lm -lpthread -ldl \
-O2 -Wall -mlittle-endian -marm -mcpu=arm926ej-s
命令说明(按顺序):
1. 编译源文件:main.c ui.c user_data.c 是工程的所有源文件。
2. 指定输出文件名:-o login_demo 表示生成名为 login_demo 的可执行文件。
3. LVGL头文件路径:-I/path/to/your/lvgl 及后续 -I 选项,替换为你的LVGL库实际路径(需包含所有LVGL的头文件目录)。
4. LVGL库路径:-L/path/to/your/lvgl/build/lib 替换为LVGL库编译后的输出目录(包含 liblvgl.a 或 liblvgl.so)。
5. 链接库:-llvgl 链接LVGL库;-lm -lpthread -ldl 链接系统必要的数学库、线程库等。
6. 编译选项:-O2 优化编译;-Wall 显示警告;-mlittle-endian -marm -mcpu=arm926ej-s 适配GEC6818架构(若为A53,可将 arm926ej-s 改为 cortex-a53)。
使用步骤:
1. 打开终端,进入存放 main.c、ui.c、user_data.c 的工程目录。
2. 将上述命令中的 /path/to/your/lvgl 替换为你的LVGL库实际路径(例如 ~/lvgl-8.3)。
3. 粘贴并执行命令,编译成功后会生成 login_demo 文件。
4. 传输到GEC6818开发板,执行 chmod +x login_demo 后,运行 ./login_demo 即可。
如果编译报错“找不到头文件”或“找不到库”,检查路径是否正确;若报架构错误,调整 -mcpu 参数即可。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)