lvgl的时基函数是不是就相当于一个计时器每记一代表1ms过去,而这个函数可以自己做一个定时器接口回传数字也可以直接用freertos的时基回传函数作为时钟计数,如果我的时基回传的不是1ms增一的时基
一、核心结论
您的理解完全正确,LVGL的时基函数本质是一个虚拟时间计数器,其核心逻辑如下:
1. 默认单位假设:LVGL认为每次调用`lv_tick_inc(1)`对应1ms物理时间,但实际时间关联完全由开发者控制。
2. 时基来源无关性:无论使用硬件定时器、FreeRTOS时基或其他方式,只要保证计数器增量与物理时间成正比即可。
3. 延时误差根源:若时基增量非1ms(如10ms/次),则LVGL的`lv_task_handler`、动画等所有依赖时间的模块均会按比例拉长或缩短时间感知。
二、关键机制解析
1. 时基实现方案对比
| 方案类型 | 典型场景 | 适配方法 | 风险点
| 1ms硬件定时器 | STM32 SysTick中断 | 直接调用`lv_tick_inc(1)` | 中断负载过高
| FreeRTOS时基| (10ms/tick| 需换算`lv_tick_inc(portTICK_PERIOD_MS)` | 时间分辨率低
| 混合模式 | 高精度传感器同步 | 自定义`lv_tick_get()`函数,从RTC或高精度时钟获取时间 | 需处理多线程同步 |
LVGL时基函数可以用lv_tick_inc(1)也可以用lv_tick_get()区别在于前者是自己计算,也就是说跟外界无关,而后者依赖外部提取的时基,比如用rtos的时间片,lv_tick_get()会返回一个数值作为时基
全部流程:首先LV_TICK_CUSTOM=0就是用lv_tick_get(),LV_TICK_CUSTOM=1就是用lv_tick_get()作为时·基,如果选择LV_TICK_CUSTOM=0就需要自己去配置我们只讲LV_TICK_CUSTOM=1
LV_TICK_CUSTOM=1后,
首先引用了rtos的头文件以方便引用rtos的时基函数,LV_TICK_CUSTOM_SYS_TIME_EXPR是用在下面lv_tick_get()作时基源,而xTaskGetTickCount()是会返回rtos的当前时间片计数值,其实现:xtickscount是rtos自己的时间片全局变量,在内部是systick中断的作用在freertos里实现加加
TickType_t xTaskGetTickCount( void )
{
TickType_t xTicks;
/* Critical section required if running on a 16 bit processor. */
portTICK_TYPE_ENTER_CRITICAL();
{
xTicks = xTickCount;
}
portTICK_TYPE_EXIT_CRITICAL();
return xTicks;
}
2. 时基错误的影响
- 动画系统:原1秒动画若时基为10ms,实际耗时10秒(比例`1:10`)。
- 输入事件:触摸采样间隔放大,导致操作响应迟滞。
- 定时任务:自动刷新、数据保存等周期性任务触发间隔异常。
3. 验证与调试方法
- 代码验证:通过物理时间与计数器比对:
uint32_t t1 = lv_tick_get();
HAL_Delay(1000); // 已知准确的1秒延时
assert((lv_tick_get() - t1) >= 990 && (lv_tick_get() - t1) <= 1010);
- 硬件验证:使用示波器监测GPIO引脚翻转,验证时基中断的实际周期。
三、FreeRTOS时基适配指南
1. 配置要点
- 配置`configTICK_RATE_HZ`:
- 若设为`1000`,可直接使用`xTaskGetTickCount()`作为1ms时基。
- 若设为`100`(默认10ms/tick),需在调用`lv_tick_inc()`时传入参数`10`。
2. 代码示例
// FreeRTOS任务中周期调用
void vTaskGUI(void *pvParameters) {
TickType_t xLastWakeTime = xTaskGetTickCount();
while(1) {
lv_task_handler();
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(5)); // 5ms周期
lv_tick_inc(5); // 手动补偿时基
}
}
3. 性能权衡
| Tick频率(Hz) | 时基精度 | CPU负载 | 适用场景 |
|---------------|----------|---------|------------------------|
| 1000 | 1ms | 高 | 高刷新率UI(60fps+) |
| 100 | 10ms | 低 | 简单界面(仪表盘等) |
| 自定义 | 动态调整 | 中 | 混合关键任务系统 |
---
四、深度优化建议
1. 动态时基补偿
// 在时基误差超过阈值时自动修正
void lv_tick_compensate() {
static uint32_t last_real_time = 0;
uint32_t real_time = get_hardware_millis(); // 从RTC或高精度时钟获取
uint32_t lv_time = lv_tick_get();
if(abs(real_time - lv_time) > 50) { // 允许50ms误差
lv_tick_set(real_time); // 强制同步
}
}
2. 多级时基架构
- 高精度层:1ms硬件定时器驱动LVGL核心动画。
- 低精度层:FreeRTOS时基处理后台任务(如网络通信)。
- 动态切换:根据系统负载自动调整时基分辨率。
---
五、设计哲学总结
1. 抽象与实现的解耦:LVGL通过虚拟时基实现跨平台,开发者需在物理层保证时间精度。
2. 误差容忍与补偿:通过软件算法弥补硬件时基缺陷,平衡性能与精度。
3. 系统级时间观:GUI时基需与系统其他模块(如传感器、通信协议栈)的时间参考系对齐,避免全局时序混乱。
操作建议:在嵌入式项目中优先采用独立硬件定时器生成1ms时基,若资源受限,需在FreeRTOS配置中明确标注时间换算关系,并在关键功能(如动画)中增加时间校准逻辑。