使用共享数据池框架,解耦传感器与LVGL

📅 2026/7/29 14:16:18
使用共享数据池框架,解耦传感器与LVGL
HWInterface共享数据池(统一入口)。所有传感器任务往里写所有 UI 定时器回调从里读两边通过它解耦。接口结构体设计每个外设一个 Interfacetypedef struct { HW_RTC_InterfaceTypeDef RealTimeClock; // { GetTimeDate, SetDate, SetTime, CalculateWeekday } HW_BLE_InterfaceTypeDef BLE; // { Init, Enable, Disable } HW_Power_InterfaceTypeDef Power; // { power_remain, Init, Shutdown, BatCalculate } HW_LCD_InterfaceTypeDef LCD; // { SetLight } HW_IMU_InterfaceTypeDef IMU; // { Steps, wrist_state, Init, WristEnable, GetSteps, SetSteps } HW_AHT21_InterfaceTypeDef AHT21; // { temperature, humidity, Init, GetHumiTemp } HW_Barometer_InterfaceTypeDef Barometer; // { altitude, Init } HW_Ecompass_InterfaceTypeDef Ecompass; // { direction, Init, Sleep } HW_HRmeter_InterfaceTypeDef HR_meter; // { HrRate, SPO2, Init, Sleep } } HW_InterfaceTypeDef; //存放所有外设的结构体 // 全局单例应用层统一访问入口 extern HW_InterfaceTypeDef HWInterface;数据流全景传感器 → HWInterface → LVGL 刷新整个机制由三条并行的 FreeRTOS 任务和 LVGL 自身的定时器/刷新管线协同完成。下面是完整的路径1. 传感器任务写数据到HWInterface任务SensorDataUpdateTask[user_SensUpdateTask.c](/OV_Watch/User/Tasks/Src/user_SensUpdateTask.c)通过HomeUpdata_MessageQueue消息队列触发每 500ms 执行一次收到 HomeUpdata 消息 → HWInterface.Power.power_remain BatCalculate() → HWInterface.IMU.Steps GetSteps() → HWInterface.AHT21.temperature/humidity GetHumiTemp() → HWInterface.Ecompass.direction Azimuth_Calculate() → HWInterface.Barometer.altitude Altitude_Calculate()其他传感器页面如指南针、环境温湿度、心率在对应页面激活时也会在同一个任务的不同if/else分支里实时更新HWInterface的对应字段。2. LVGL 定时器从HWInterface读取并更新控件主页的刷新不依赖消息队列而是靠LVGL 定时器。在ui_HomePage_screen_init()中创建ui_HomePageTimer lv_timer_create(HomePage_timer_cb, 500, NULL);HomePage_timer_cb每 500ms 执行一次核心逻辑是比较-更新模式[ui_HomePage.c](/OV_Watch/User/GUI_App/Screens/Src/ui_HomePage.c)// 读 HWInterface 中的传感器数据 HWInterface.RealTimeClock.GetTimeDate(DateTime); HWInterface.Power.power_remain; HWInterface.IMU.Steps; HWInterface.AHT21.temperature; HWInterface.AHT21.humidity; // 与本地缓存值比较有变化才调用 LVGL API if(ui_BatArcValue ! HWInterface.Power.power_remain) { ui_BatArcValue HWInterface.Power.power_remain; lv_arc_set_value(ui_BatArc, ui_BatArcValue); // ← 标记 arc 为脏 lv_label_set_text(ui_BatNumLabel, value_strbuf); // ← 标记 label 为脏 } // 温度、湿度、步数同理...每次调用lv_label_set_text()、lv_arc_set_value()等 API 时LVGL 内部会标记对应控件为脏 (invalidated)等待下次刷新周期重绘。3. LVGL 核心任务驱动刷新管线LvHandlerTask[user_TasksInit.c](/OV_Watch/User/Tasks/Src/user_TasksInit.c)是一个独立的 FreeRTOS 任务优先级最低osPriorityLowvoid LvHandlerTask(void *argument) { while (1) { uint32_t wait lv_task_handler(); // ← 核心处理所有定时器 重绘脏区域 if (wait 1U) wait 1U; if (wait 30U) wait 30U; osDelay(wait); } }lv_task_handler()做两件事执行所有到期的 LVGL 定时器→ 触发HomePage_timer_cb进而更新控件遍历所有脏对象调用 flush 回调→ 将更新后的画面刷到物理屏幕同时TaskTickHook()在 FreeRTOS 的 tick hook 中每 tick 调用一次lv_tick_inc(1)为 LVGL 提供时间基准。这套架构的优点接口规整所有硬件操作入口集中代码可读性高分层解耦业务层隔离底层驱动方便移植硬件状态集中管理每个外设的运行状态温度、步数、心率封装在各自接口内统一规范新增传感器时只需要新增结构体成员上层调用风格保持一致。