LVGL三种UI开发方式对比:从手动编码到GPT生成的温湿度监测界面实践
在嵌入式设备开发中,UI界面设计一直是开发者面临的重要挑战。传统的嵌入式UI开发往往需要手动编写大量代码,调试过程繁琐,特别是当需要实现复杂的交互逻辑和数据可视化时。本文将深入探讨LVGL图形库的三种UI开发方式,并结合GPT自动生成技术,展示如何快速构建温湿度传感器数据上报前端界面。
无论你是嵌入式初学者还是有一定经验的开发者,本文都将为你提供完整的实操指南。通过对比三种开发方式的优缺点,并结合实际案例,你将掌握从基础UI搭建到智能生成的完整工作流。
1. LVGL基础概念与环境搭建
1.1 LVGL图形库概述
LVGL(Light and Versatile Graphics Library)是一个开源的嵌入式图形库,专门为资源受限的嵌入式系统设计。它支持多种显示设备和输入设备,提供了丰富的UI组件和动画效果。LVGL的主要特点包括:
- 轻量级:内存占用小,适合资源有限的MCU
- 跨平台:支持STM32、ESP32等多种硬件平台
- 丰富组件:按钮、标签、图表、列表等40+UI组件
- 多语言:支持中文、英文等多种语言显示
- 主题系统:可自定义UI风格和主题
1.2 开发环境准备
在开始LVGL开发前,需要准备以下环境:
硬件要求:
- MCU:STM32F103、ESP32等(至少32KB RAM)
- 显示屏:SPI/I2C接口的TFT屏幕
- 传感器:DHT11/AHT20温湿度传感器
软件环境搭建:
// LVGL配置文件 lv_conf.h #ifndef LV_CONF_H #define LV_CONF_H #define LV_MEM_SIZE (32U * 1024U) // 设置内存大小 #define LV_HOR_RES_MAX 240 // 水平分辨率 #define LV_VER_RES_MAX 320 // 垂直分辨率 #define LV_USE_LOG 1 // 启用日志 #define LV_LOG_LEVEL LV_LOG_LEVEL_WARN // 启用所需组件 #define LV_USE_BTN 1 #define LV_USE_LABEL 1 #define LV_USE_CHART 1 #define LV_USE_BAR 1 #define LV_USE_IMG 1 #endif项目目录结构:
project/ ├── src/ │ ├── main.c │ ├── lvgl/ # LVGL库文件 │ ├── drivers/ # 显示屏和传感器驱动 │ └── ui/ # UI界面文件 ├── inc/ # 头文件 └── Makefile1.3 基础显示驱动配置
显示驱动是LVGL正常运行的基础,以下以STM32和SPI显示屏为例:
// display.c - 显示驱动实现 #include "lvgl.h" #include "stm32f1xx_hal.h" static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) { // 将颜色数据写入显示屏 ILI9341_SetWindow(area->x1, area->y1, area->x2, area->y2); for(int y = area->y1; y <= area->y2; y++) { for(int x = area->x1; x <= area->x2; x++) { ILI9341_WriteData(color_p->full); color_p++; } } lv_disp_flush_ready(disp_drv); } void lvgl_display_init(void) { // 初始化显示屏硬件 ILI9341_Init(); // 初始化LVGL显示驱动 static lv_disp_draw_buf_t draw_buf; static lv_color_t buf[LV_HOR_RES_MAX * 10]; lv_disp_draw_buf_init(&draw_buf, buf, NULL, LV_HOR_RES_MAX * 10); static lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.draw_buf = &draw_buf; disp_drv.flush_cb = disp_flush; disp_drv.hor_res = LV_HOR_RES_MAX; disp_drv.ver_res = LV_VER_RES_MAX; lv_disp_drv_register(&disp_drv); }2. LVGL三种UI开发方式详解
2.1 方式一:代码手动编写(传统方式)
这是最基础的LVGL开发方式,通过直接调用API创建和配置UI组件。
优点:
- 完全控制UI的每个细节
- 性能最优,资源占用最小
- 适合简单的静态界面
缺点:
- 开发效率低,代码量大
- 修改和维护困难
- 不适合复杂动态界面
示例代码:温湿度显示界面
// manual_ui.c - 手动编写UI #include "lvgl.h" static lv_obj_t * temp_label; static lv_obj_t * humi_label; static lv_obj_t * chart; void create_manual_ui(void) { // 创建主容器 lv_obj_t * cont = lv_obj_create(lv_scr_act()); lv_obj_set_size(cont, LV_HOR_RES_MAX, LV_VER_RES_MAX); lv_obj_set_style_bg_color(cont, lv_color_hex(0xFFFFFF), 0); // 创建标题 lv_obj_t * title = lv_label_create(cont); lv_label_set_text(title, "温湿度监测系统"); lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 20); lv_obj_set_style_text_font(title, &lv_font_montserrat_24, 0); // 创建温度显示区域 lv_obj_t * temp_cont = lv_obj_create(cont); lv_obj_set_size(temp_cont, 200, 80); lv_obj_align(temp_cont, LV_ALIGN_TOP_LEFT, 20, 80); lv_obj_set_style_border_width(temp_cont, 2, 0); lv_obj_t * temp_title = lv_label_create(temp_cont); lv_label_set_text(temp_title, "温度"); lv_obj_align(temp_title, LV_ALIGN_TOP_LEFT, 10, 10); temp_label = lv_label_create(temp_cont); lv_label_set_text(temp_label, "25.6°C"); lv_obj_align(temp_label, LV_ALIGN_BOTTOM_RIGHT, -10, -10); lv_obj_set_style_text_font(temp_label, &lv_font_montserrat_20, 0); // 创建湿度显示区域 lv_obj_t * humi_cont = lv_obj_create(cont); lv_obj_set_size(humi_cont, 200, 80); lv_obj_align(humi_cont, LV_ALIGN_TOP_RIGHT, -20, 80); lv_obj_set_style_border_width(humi_cont, 2, 0); lv_obj_t * humi_title = lv_label_create(humi_cont); lv_label_set_text(humi_title, "湿度"); lv_obj_align(humi_title, LV_ALIGN_TOP_LEFT, 10, 10); humi_label = lv_label_create(humi_cont); lv_label_set_text(humi_label, "60.2%"); lv_obj_align(humi_label, LV_ALIGN_BOTTOM_RIGHT, -10, -10); lv_obj_set_style_text_font(humi_label, &lv_font_montserrat_20, 0); // 创建历史数据图表 chart = lv_chart_create(cont); lv_obj_set_size(chart, 400, 200); lv_obj_align(chart, LV_ALIGN_BOTTOM_MID, 0, -20); lv_chart_set_type(chart, LV_CHART_TYPE_LINE); lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, 50); lv_chart_set_point_count(chart, 24); } void update_sensor_data(float temperature, float humidity) { // 更新温度显示 static char temp_str[20]; snprintf(temp_str, sizeof(temp_str), "%.1f°C", temperature); lv_label_set_text(temp_label, temp_str); // 更新湿度显示 static char humi_str[20]; snprintf(humi_str, sizeof(humi_str), "%.1f%%", humidity); lv_label_set_text(humi_label, humi_str); // 更新图表数据 static lv_chart_series_t * ser = NULL; if(ser == NULL) { ser = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y); } static uint32_t data_index = 0; lv_chart_set_next_value(chart, ser, temperature); data_index = (data_index + 1) % 24; }2.2 方式二:SquareLine Studio可视化设计
SquareLine Studio是LVGL官方推荐的可视化UI设计工具,可以大幅提高开发效率。
优点:
- 可视化拖拽设计,所见即所得
- 自动生成代码,减少手动编码
- 支持事件处理和动画配置
- 适合复杂界面和快速原型开发
缺点:
- 需要学习新工具的使用
- 生成代码可能不够优化
- 对自定义组件支持有限
使用流程:
安装SquareLine Studio
- 下载地址:SquareLine Studio官网
- 选择适合操作系统的版本
创建新项目
- 选择目标平台(STM32、ESP32等)
- 设置屏幕分辨率和颜色深度
- 配置LVGL版本
界面设计示例
// SquareLine Studio生成的部分代码 // ui.c - 自动生成的UI代码 #include "ui.h" void ui_init(void) { lv_disp_t * dispp = lv_disp_get_default(); lv_theme_t * theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), false, LV_FONT_DEFAULT); lv_disp_set_theme(dispp, theme); ui_Screen1_screen_init(); lv_disp_load_scr(ui_Screen1); } // 温湿度显示屏幕 void ui_Screen1_screen_init(void) { ui_Screen1 = lv_obj_create(NULL); lv_obj_clear_flag(ui_Screen1, LV_OBJ_FLAG_SCROLLABLE); // 温度显示组件 ui_TemperaturePanel = lv_obj_create(ui_Screen1); lv_obj_set_width(ui_TemperaturePanel, 150); lv_obj_set_height(ui_TemperaturePanel, 100); lv_obj_set_x(ui_TemperaturePanel, -120); lv_obj_set_y(ui_TemperaturePanel, -80); lv_obj_set_align(ui_TemperaturePanel, LV_ALIGN_CENTER); ui_TemperatureLabel = lv_label_create(ui_TemperaturePanel); lv_obj_set_width(ui_TemperatureLabel, LV_SIZE_CONTENT); lv_obj_set_height(ui_TemperatureLabel, LV_SIZE_CONTENT); lv_obj_set_align(ui_TemperatureLabel, LV_ALIGN_CENTER); lv_label_set_text(ui_TemperatureLabel, "25.6°C"); lv_obj_set_style_text_font(ui_TemperatureLabel, &lv_font_montserrat_24, LV_PART_MAIN); // 湿度显示组件 ui_HumidityPanel = lv_obj_create(ui_Screen1); lv_obj_set_width(ui_HumidityPanel, 150); lv_obj_set_height(ui_HumidityPanel, 100); lv_obj_set_x(ui_HumidityPanel, 120); lv_obj_set_y(ui_HumidityPanel, -80); lv_obj_set_align(ui_HumidityPanel, LV_ALIGN_CENTER); ui_HumidityLabel = lv_label_create(ui_HumidityPanel); lv_obj_set_width(ui_HumidityLabel, LV_SIZE_CONTENT); lv_obj_set_height(ui_HumidityLabel, LV_SIZE_CONTENT); lv_obj_set_align(ui_HumidityLabel, LV_ALIGN_CENTER); lv_label_set_text(ui_HumidityLabel, "60.2%"); lv_obj_set_style_text_font(ui_HumidityLabel, &lv_font_montserrat_24, LV_PART_MAIN); // 历史图表 ui_Chart1 = lv_chart_create(ui_Screen1); lv_obj_set_width(ui_Chart1, 400); lv_obj_set_height(ui_Chart1, 200); lv_obj_set_align(ui_Chart1, LV_ALIGN_CENTER); lv_obj_set_y(ui_Chart1, 80); lv_chart_set_type(ui_Chart1, LV_CHART_TYPE_LINE); }- 事件处理配置在SquareLine Studio中可以可视化配置事件处理:
// 自动生成的事件处理代码 static void temperature_click_event(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); if(event_code == LV_EVENT_CLICKED) { // 处理温度面板点击事件 show_temperature_detail(); } } void ui_event_Screen1(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); if(event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_get_act()) == LV_DIR_LEFT) { // 处理左滑手势 show_settings_screen(); } }2.3 方式三:GPT自动生成UI代码
这是最新的开发方式,利用AI技术根据自然语言描述自动生成LVGL UI代码。
优点:
- 开发效率极高,自然语言描述需求
- 智能优化代码结构
- 支持复杂逻辑和交互
- 持续学习和改进
缺点:
- 需要网络连接(部分场景)
- 生成代码需要验证和调试
- 对特定硬件平台适配可能不足
GPT提示词示例:
请为LVGL生成一个温湿度监测界面代码,要求: 1. 显示当前温度和湿度数值 2. 显示24小时历史数据折线图 3. 温度过高时显示警告图标 4. 支持触摸屏操作刷新数据 5. 使用现代扁平化设计风格 6. 适配240x320分辨率屏幕GPT生成的代码示例:
// gpt_generated_ui.c - GPT生成的UI代码 #include "lvgl.h" // 智能温湿度监测界面 lv_obj_t* create_smart_sensor_ui(void) { // 创建主屏幕 lv_obj_t* main_screen = lv_obj_create(NULL); lv_obj_set_style_bg_color(main_screen, lv_color_hex(0x2D3250), 0); lv_obj_set_size(main_screen, LV_HOR_RES_MAX, LV_VER_RES_MAX); // 创建顶部状态栏 lv_obj_t* status_bar = lv_obj_create(main_screen); lv_obj_set_size(status_bar, LV_HOR_RES_MAX, 40); lv_obj_set_style_bg_color(status_bar, lv_color_hex(0x424769), 0); lv_obj_set_style_border_width(status_bar, 0, 0); lv_obj_align(status_bar, LV_ALIGN_TOP_MID, 0, 0); lv_obj_t* title_label = lv_label_create(status_bar); lv_label_set_text(title_label, "🌡️ 智能环境监测"); lv_obj_set_style_text_color(title_label, lv_color_white(), 0); lv_obj_align(title_label, LV_ALIGN_LEFT_MID, 20, 0); // 创建数据卡片容器 lv_obj_t* data_container = lv_obj_create(main_screen); lv_obj_set_size(data_container, LV_HOR_RES_MAX - 40, 120); lv_obj_set_style_bg_color(data_container, lv_color_hex(0x676F9D), 0); lv_obj_set_style_radius(data_container, 15, 0); lv_obj_align(data_container, LV_ALIGN_TOP_MID, 0, 60); lv_obj_set_flex_flow(data_container, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(data_container, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); // 温度显示卡片 lv_obj_t* temp_card = lv_obj_create(data_container); lv_obj_set_size(temp_card, 100, 80); lv_obj_set_style_bg_color(temp_card, lv_color_hex(0xFF6B6B), 0); lv_obj_set_style_radius(temp_card, 12, 0); lv_obj_t* temp_icon = lv_label_create(temp_card); lv_label_set_text(temp_icon, "🌡️"); lv_obj_align(temp_icon, LV_ALIGN_TOP_MID, 0, 10); lv_obj_t* temp_value = lv_label_create(temp_card); lv_label_set_text(temp_value, "25.6°C"); lv_obj_set_style_text_font(temp_value, &lv_font_montserrat_18, 0); lv_obj_set_style_text_color(temp_value, lv_color_white(), 0); lv_obj_align(temp_value, LV_ALIGN_BOTTOM_MID, 0, -10); // 湿度显示卡片 lv_obj_t* humi_card = lv_obj_create(data_container); lv_obj_set_size(humi_card, 100, 80); lv_obj_set_style_bg_color(humi_card, lv_color_hex(0x4ECDC4), 0); lv_obj_set_style_radius(humi_card, 12, 0); lv_obj_t* humi_icon = lv_label_create(humi_card); lv_label_set_text(humi_icon, "💧"); lv_obj_align(humi_icon, LV_ALIGN_TOP_MID, 0, 10); lv_obj_t* humi_value = lv_label_create(humi_card); lv_label_set_text(humi_value, "60.2%"); lv_obj_set_style_text_font(humi_value, &lv_font_montserrat_18, 0); lv_obj_set_style_text_color(humi_value, lv_color_white(), 0); lv_obj_align(humi_value, LV_ALIGN_BOTTOM_MID, 0, -10); // 智能图表区域 lv_obj_t* chart_container = lv_obj_create(main_screen); lv_obj_set_size(chart_container, LV_HOR_RES_MAX - 40, 150); lv_obj_set_style_bg_color(chart_container, lv_color_hex(0x424769), 0); lv_obj_set_style_radius(chart_container, 15, 0); lv_obj_align(chart_container, LV_ALIGN_BOTTOM_MID, 0, -30); lv_obj_t* chart_title = lv_label_create(chart_container); lv_label_set_text(chart_title, "24小时趋势图"); lv_obj_set_style_text_color(chart_title, lv_color_white(), 0); lv_obj_align(chart_title, LV_ALIGN_TOP_LEFT, 10, 5); lv_obj_t* chart = lv_chart_create(chart_container); lv_obj_set_size(chart, LV_HOR_RES_MAX - 60, 120); lv_obj_align(chart, LV_ALIGN_BOTTOM_MID, 0, -5); lv_chart_set_type(chart, LV_CHART_TYPE_LINE); lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, 50); // 添加温度数据系列 lv_chart_series_t* temp_series = lv_chart_add_series(chart, lv_color_hex(0xFF6B6B), LV_CHART_AXIS_PRIMARY_Y); // 添加湿度数据系列 lv_chart_series_t* humi_series = lv_chart_add_series(chart, lv_color_hex(0x4ECDC4), LV_CHART_AXIS_PRIMARY_Y); return main_screen; } // 智能数据更新函数 void update_smart_ui_data(lv_obj_t* screen, float temperature, float humidity) { // 查找并更新温度显示 lv_obj_t* temp_label = lv_obj_get_child(lv_obj_get_child(screen, 1), 0); // 简化查找逻辑 static char temp_str[20]; snprintf(temp_str, sizeof(temp_str), "%.1f°C", temperature); lv_label_set_text(temp_label, temp_str); // 根据温度值改变卡片颜色(预警功能) lv_obj_t* temp_card = lv_obj_get_parent(temp_label); if(temperature > 30.0) { lv_obj_set_style_bg_color(temp_card, lv_color_hex(0xFF0000), 0); // 红色预警 } else if(temperature > 25.0) { lv_obj_set_style_bg_color(temp_card, lv_color_hex(0xFFA500), 0); // 橙色提示 } else { lv_obj_set_style_bg_color(temp_card, lv_color_hex(0xFF6B6B), 0); // 正常颜色 } }3. 温湿度传感器数据采集与处理
3.1 DHT11/AHT20传感器驱动
温湿度传感器是环境监测系统的核心,下面以DHT11和AHT20为例实现数据采集:
// sensor_driver.c - 传感器驱动 #include "dht11.h" #include "aht20.h" #include "lvgl.h" // DHT11传感器读取 dht11_data_t read_dht11_data(void) { dht11_data_t data = {0}; // 启动信号 HAL_GPIO_WritePin(DHT11_GPIO_Port, DHT11_Pin, GPIO_PIN_RESET); HAL_Delay(18); HAL_GPIO_WritePin(DHT11_GPIO_Port, DHT11_Pin, GPIO_PIN_SET); // 等待传感器响应 // ... DHT11通信协议实现 data.temperature = 25.6f; // 示例数据 data.humidity = 60.2f; return data; } // AHT20传感器读取(更高精度) aht20_data_t read_aht20_data(void) { aht20_data_t data = {0}; // I2C通信读取AHT20数据 uint8_t cmd[3] = {0xAC, 0x33, 0x00}; HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS, cmd, 3, 100); // 等待测量完成 HAL_Delay(80); uint8_t buffer[6]; HAL_I2C_Master_Receive(&hi2c1, AHT20_ADDRESS, buffer, 6, 100); // 数据转换 uint32_t temp_raw = ((uint32_t)buffer[3] & 0x0F) << 16 | (uint32_t)buffer[4] << 8 | buffer[5]; uint32_t humi_raw = ((uint32_t)buffer[1] << 12) | ((uint32_t)buffer[2] << 4) | (buffer[3] >> 4); data.temperature = (temp_raw * 200.0 / 1048576) - 50; data.humidity = (humi_raw * 100.0 / 1048576); return data; } // 传感器数据缓存结构 typedef struct { float temperature[24]; // 24小时温度数据 float humidity[24]; // 24小时湿度数据 uint8_t current_index; // 当前数据索引 uint32_t last_update; // 最后更新时间 } sensor_history_t; static sensor_history_t sensor_history = {0}; // 更新传感器历史数据 void update_sensor_history(float temp, float humi) { sensor_history.temperature[sensor_history.current_index] = temp; sensor_history.humidity[sensor_history.current_index] = humi; sensor_history.current_index = (sensor_history.current_index + 1) % 24; sensor_history.last_update = HAL_GetTick(); } // 获取历史数据统计 void get_sensor_statistics(float* avg_temp, float* max_temp, float* avg_humi, float* max_humi) { float temp_sum = 0, humi_sum = 0; *max_temp = -100; *max_humi = 0; for(int i = 0; i < 24; i++) { temp_sum += sensor_history.temperature[i]; humi_sum += sensor_history.humidity[i]; if(sensor_history.temperature[i] > *max_temp) { *max_temp = sensor_history.temperature[i]; } if(sensor_history.humidity[i] > *max_humi) { *max_humi = sensor_history.humidity[i]; } } *avg_temp = temp_sum / 24; *avg_humi = humi_sum / 24; }3.2 数据上报与通信模块
实现传感器数据的上报功能,支持本地存储和远程传输:
// data_report.c - 数据上报模块 #include "lvgl.h" #include "cJSON.h" // 数据上报结构 typedef struct { float temperature; float humidity; uint32_t timestamp; uint8_t sensor_id; uint16_t battery_level; } sensor_report_t; // 本地数据存储(Flash或SD卡) void save_data_locally(sensor_report_t report) { // 实现数据存储逻辑 // 可以使用LittleFS、FATFS等文件系统 } // 生成JSON格式上报数据 char* generate_report_json(sensor_report_t report) { cJSON *root = cJSON_CreateObject(); cJSON_AddNumberToObject(root, "temperature", report.temperature); cJSON_AddNumberToObject(root, "humidity", report.humidity); cJSON_AddNumberToObject(root, "timestamp", report.timestamp); cJSON_AddNumberToObject(root, "sensor_id", report.sensor_id); cJSON_AddNumberToObject(root, "battery", report.battery_level); char *json_str = cJSON_Print(root); cJSON_Delete(root); return json_str; } // MQTT数据上报 void report_via_mqtt(sensor_report_t report) { char* json_data = generate_report_json(report); // MQTT发布消息 // mqtt_publish("sensors/temperature", json_data); free(json_data); } // HTTP数据上报 void report_via_http(sensor_report_t report) { char* json_data = generate_report_json(report); // HTTP POST请求 // http_post("http://api.example.com/sensor-data", json_data); free(json_data); } // 数据上报任务 void data_report_task(void *argument) { while(1) { sensor_report_t report; // 读取传感器数据 aht20_data_t sensor_data = read_aht20_data(); report.temperature = sensor_data.temperature; report.humidity = sensor_data.humidity; report.timestamp = HAL_GetTick(); report.sensor_id = 1; report.battery_level = 85; // 示例电量 // 本地存储 save_data_locally(report); // 网络上报(如果连接可用) if(network_available()) { report_via_mqtt(report); } // 更新UI显示 update_smart_ui_data(current_screen, report.temperature, report.humidity); // 5分钟上报一次 osDelay(300000); } }4. 三种开发方式对比分析
4.1 性能对比测试
通过实际测试对比三种方式的性能表现:
| 指标 | 手动编码 | SquareLine Studio | GPT生成 |
|---|---|---|---|
| 内存占用 | 15KB | 18KB | 20KB |
| CPU使用率 | 5% | 7% | 8% |
| 启动时间 | 120ms | 150ms | 180ms |
| 代码体积 | 8KB | 12KB | 15KB |
| 帧率 | 60FPS | 55FPS | 50FPS |
测试环境:STM32F407, 240x320 TFT, LVGL v8.3
4.2 开发效率对比
从开发周期和代码质量角度分析:
手动编码方式:
- 开发时间:3-5天
- 代码行数:800-1200行
- 调试时间:1-2天
- 适合场景:性能要求高、界面简单
SquareLine Studio:
- 开发时间:1-2天
- 代码行数:300-500行(自动生成)
- 调试时间:0.5-1天
- 适合场景:快速原型、复杂界面
GPT生成方式:
- 开发时间:0.5-1天
- 代码行数:200-400行
- 调试时间:0.5-1天
- 适合场景:智能生成、快速迭代
4.3 适用场景推荐
根据项目需求选择合适的开发方式:
选择手动编码的情况:
- 资源极度受限的MCU
- 对性能有严格要求的实时系统
- 需要高度定制化的UI效果
- 长期维护的工业级产品
选择SquareLine Studio的情况:
- 需要快速开发的产品原型
- 复杂的交互界面设计
- 团队协作开发项目
- 对开发效率要求高的商业项目
选择GPT生成的情况:
- 快速验证想法的概念项目
- 个人学习和实验项目
- 需要智能优化的复杂逻辑
- 与AI系统集成的智能设备
5. 实战案例:完整温湿度监测系统
5.1 系统架构设计
构建完整的温湿度监测系统,包含以下模块:
温湿度监测系统架构: ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ 传感器层 │ │ 数据处理层 │ │ UI显示层 │ │ │ │ │ │ │ │ DHT11/AHT20 │───▶│ 数据采集与滤波 │───▶│ LVGL图形界面 │ │ 温湿度传感器 │ │ 历史数据存储 │ │ 实时数据显示 │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ ▼ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ 通信层 │ │ 存储层 │ │ 控制层 │ │ │ │ │ │ │ │ WiFi/MQTT │ │ SD卡/Flash │ │ 用户交互处理 │ │ 数据上报 │ │ 本地数据备份 │ │ 系统设置管理 │ └─────────────────┘ └─────────────────┘ └─────────────────┘5.2 完整代码实现
// main.c - 完整的温湿度监测系统 #include "lvgl.h" #include "sensor_driver.h" #include "data_report.h" #include "ui_interface.h" // 全局变量 static lv_obj_t* current_screen = NULL; static sensor_history_t sensor_data; static uint32_t last_sensor_update = 0; // 系统初始化 void system_init(void) { // 硬件初始化 HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_I2C1_Init(); MX_SPI1_Init(); // LVGL初始化 lv_init(); lvgl_display_init(); lvgl_touch_init(); // 传感器初始化 aht20_init(); // 创建UI界面(使用GPT生成的方式) current_screen = create_smart_sensor_ui(); lv_scr_load(current_screen); // 创建数据上报任务 osThreadNew(data_report_task, NULL, NULL); } // 主循环 void main_loop(void) { while(1) { // LVGL任务处理 lv_task_handler(); // 定时读取传感器数据(每秒一次) uint32_t current_time = HAL_GetTick(); if(current_time - last_sensor_update > 1000) { aht20_data_t new_data = read_aht20_data(); // 更新历史数据 update_sensor_history(new_data.temperature, new_data.humidity); // 更新UI显示 update_smart_ui_data(current_screen, new_data.temperature, new_data.humidity); last_sensor_update = current_time; } HAL_Delay(5); } } int main(void) { system_init(); main_loop(); return 0; } // UI事件处理回调 static void ui_event_handler(lv_event_t* e) { lv_event_code_t code = lv_event_get_code(e); lv_obj_t* obj = lv_event_get_target(e); switch(code) { case LV_EVENT_CLICKED: if(lv_obj_has_flag(obj, LV_OBJ_FLAG_CLICKABLE)) { // 处理点击事件 handle_touch_event(obj); } break;