《lvgl基础学习 —— 分层架构》

1.为什么一定要分层

  如果这样写代码:

static void slider_cb(lv_event_t *e)
{
    int val = lv_slider_get_value(slider);
    ioctl(fd, ISP_SET_EXPOSURE, val);   //
}

短期没问题,长期会变成:

  • UI 改 → 硬件逻辑跟着改

  • 没法单元测试

  • 没法做 PC 仿真

  • 换平台(RK → Ambarella)几乎重写

  这就是“UI 直接操硬件”的灾难

 

2.正确的三层架构

┌──────────────┐
│     UI       │  ← LVGL(button / slider / switch)
│  只关心交互   │
└──────▲───────┘
       │ 消息 / 调用
┌──────┴───────┐
│   Service    │  ← 业务逻辑(状态 / 策略 / 校验)
│  不碰 LVGL   │
└──────▲───────┘
       │ 抽象接口
┌──────┴───────┐
│   Driver     │  ← ioctl / sysfs / i2c / spi
│  不知道 UI   │
└──────────────┘

总之就是:

  UI不知道硬件

  Driver不知道UI

  Service做中间人

 

3.每一层”只干什么,不干什么“

1️⃣ UI 层(LVGL)

✔ 可以做

  • 创建控件

  • 响应点击 / 拖动

  • 显示状态

❌ 绝对不做

  • ioctl

  • open("/dev/xxx")

  • sleep

  • 复杂逻辑

📌 UI = 纯交互层


2️⃣ Service 层(业务层,最重要)

✔ 可以做

  • 参数合法性判断

  • 状态保存

  • 模式切换

  • 异步处理

❌ 不做

  • 直接操作 LVGL

  • 直接画 UI

📌 Service = 大脑


3️⃣ Driver 层(驱动 / 设备访问)

✔ 只做

  • 和设备打交道

  • 提供最底层接口

int driver_set_exposure(int val);

❌ 不做

  • 判断 UI 状态

  • 知道按钮 / slider

📌 Driver = 手脚

 

4.数据流是怎么走的?

用户拖动 Slider 的完整链路:

用户拖 slider
   ↓
UI slider_cb()
   ↓
service_set_exposure(val)
   ↓
driver_set_exposure(val)
   ↓
硬件

反方向(硬件状态变化)

硬件变化
   ↓
driver_get_exposure()
   ↓
service_update_state()
   ↓
UI 刷新 label

 

demo:Slider 调节“亮度”,Label 显示当前值, UI 不知道硬件,Driver 不知道 LVGL

Driver 层(driver_brightness.c)

// driver_brightness.c
#include <stdio.h>

static int g_brightness = 50;

int driver_set_brightness(int val)
{
    if(val < 0 || val > 100)
        return -1;

    g_brightness = val;
    printf("[DRIVER] brightness = %d\n", g_brightness);
    return 0;
}

int driver_get_brightness(void)
{
    return g_brightness;
}

Service 层(service_brightness.c)

 

posted @ 2025-12-19 18:11  一个不知道干嘛的小萌新  阅读(0)  评论(0)    收藏  举报