LVGL的核心:lv_timer_handler

文章目錄

    • 🧠 一句話總結 LVGL 的運行核心:
    • 🔁 1. `while(1)` 主循環中的 `lv_task_handler()`
    • ?? 2. `lv_timer_handler()` 定時器調度核心
      • ? 并發控制
      • ? 關鍵行為流程:
      • 🌀 任務執行邏輯:
      • 🧮 計算下一次調用間隔
    • 📊 3. 額外性能監控與優化
    • 🎯 總結一張圖(邏輯關系)
    • 🧩 你需要做的最關鍵一件事
    • ? 總結重點


LVGL 的運行核心機制其實就圍繞兩個關鍵詞展開:定時器輪詢(Timer Loop)+ 任務處理器(Task Handler)。你貼的這段代碼正是 LVGL 運行機制的心臟,下面我會從宏觀和細節兩個層面幫你理解這套機制的運行流程。


🧠 一句話總結 LVGL 的運行核心:

LVGL 通過定時器輪詢機制(lv_timer_handler)周期性檢查并執行任務(動畫、事件、刷新等),由主循環中持續調用 lv_task_handler() 驅動系統更新。


🔁 1. while(1) 主循環中的 lv_task_handler()

while(1) {lv_task_handler();usleep(5000);  // 每 5ms 調用一次
}
  • 這是你在主線程、RTOS 任務或定時器中 周期性調用 的函數;
  • 實際內部會調用 lv_timer_handler(),這是 LVGL 所有內部“定時行為”的核心;
  • 例:刷新控件、執行動畫、檢測事件、處理輸入設備等,都是靠這里觸發。

?? 2. lv_timer_handler() 定時器調度核心

這是 LVGL 的任務調度中心,其關鍵職責如下:

? 并發控制

if(state_p->already_running) return 1;

防止多線程或中斷中重復進入,保護調度流程。


? 關鍵行為流程:

lv_timer_t * timer_active = lv_ll_get_head(timer_head);
  • LVGL 內部的“任務”是以 lv_timer_t 為單位組織的;
  • 每一個 lv_timer_t 都有周期(例如 30ms 執行一次);
  • 所有 timer 被鏈接在一個鏈表中,調度器依次遍歷并執行;

🌀 任務執行邏輯:

if(lv_timer_exec(timer_active)) {if(state_p->timer_created || state_p->timer_deleted) {break;}
}
  • 每次調度,調用 lv_timer_exec() 試圖執行任務;
  • 如果任務內部創建或刪除了其他 timer,則會中斷本次遍歷,從頭再來(保證鏈表安全);

🧮 計算下一次調用間隔

uint32_t delay = lv_timer_time_remaining(next);
  • 執行完任務后,計算距離下一次要執行的任務的最小延遲;
  • 這個值可用于指導下一輪 lv_task_handler() 的調用周期優化(例如設置精確定時器)。

📊 3. 額外性能監控與優化

state_p->idle_last = (state_p->busy_time * 100) / idle_period_time;
  • LVGL 會統計任務執行耗時,判斷 CPU 占用率;
  • 可用于分析系統是否卡頓,或優化任務調度頻率;

🎯 總結一張圖(邏輯關系)

主循環/RTOS任務↓
lv_task_handler()↓
lv_timer_handler()↓
遍歷 lv_timer 鏈表↓
執行注冊任務(動畫、屏幕刷新、事件分發等)↓
計算下次執行時間 & 性能分析

🧩 你需要做的最關鍵一件事

在你的系統中,確保 lv_task_handler() 每隔 5~10ms 被調用一次,即可激活 LVGL 的整個圖形與事件系統。


當然可以,以下是為 lv_timer_handler() 添加的詳細中文注釋版,注釋盡量保留原有邏輯結構,方便你后續閱讀和調試:


// LVGL 的定時器調度主函數,每次被調用會遍歷所有注冊的定時器并執行到期的任務
LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void)
{LV_TRACE_TIMER("begin");lv_timer_state_t * state_p = &state;// 避免定時器調度函數被重復進入(多線程或中斷中可能會并發調用)if(state_p->already_running) {LV_TRACE_TIMER("already running, concurrent calls are not allow, returning");return 1;}state_p->already_running = true;// 如果定時器已被暫停,直接返回if(state_p->lv_timer_run == false) {state_p->already_running = false; // 釋放“互斥鎖”return 1;}LV_PROFILER_BEGIN;lv_lock();  // 進入臨界區,保護鏈表等資源不被同時訪問// 獲取當前時間(單位 ms)uint32_t handler_start = lv_tick_get();// 檢查是否調用了 lv_tick_inc()(用于更新系統 tick)if(handler_start == 0) {state.run_cnt++;if(state.run_cnt > 100) {state.run_cnt = 0;LV_LOG_WARN("It seems lv_tick_inc() is not called.");}}/*************** 開始遍歷并執行定時器任務 ***************/lv_timer_t * next;lv_timer_t * timer_active;lv_ll_t * timer_head = timer_ll_p;  // 定時器鏈表頭指針do {// 每輪遍歷前先清空“狀態標志”state_p->timer_deleted = false;state_p->timer_created = false;// 獲取第一個定時器timer_active = lv_ll_get_head(timer_head);while(timer_active) {// 提前獲取下一個指針(因為本 timer 執行后可能會被刪除)next = lv_ll_get_next(timer_head, timer_active);// 如果當前定時器已經到期,則執行回調函數if(lv_timer_exec(timer_active)) {// 如果執行期間創建/刪除了定時器,鏈表結構可能被破壞,必須重新從頭遍歷if(state_p->timer_created || state_p->timer_deleted) {LV_TRACE_TIMER("Start from the first timer again because a timer was created or deleted");break;}}// 進入下一個定時器timer_active = next;}} while(timer_active);  // 如果因鏈表被修改跳出,則重新遍歷/*************** 計算下次定時器觸發時間 ***************/uint32_t time_until_next = LV_NO_TIMER_READY; // 默認無任務準備next = lv_ll_get_head(timer_head);while(next) {if(!next->paused) {// 獲取該定時器距離下一次觸發還需等待的時間uint32_t delay = lv_timer_time_remaining(next);if(delay < time_until_next)time_until_next = delay;  // 保留最短時間}next = lv_ll_get_next(timer_head, next);}/*************** 統計“空閑率”用于性能分析 ***************/state_p->busy_time += lv_tick_elaps(handler_start);  // 本輪花費時間uint32_t idle_period_time = lv_tick_elaps(state_p->idle_period_start);if(idle_period_time >= IDLE_MEAS_PERIOD) {// 計算過去一段時間內的 CPU 空閑率(100% - 忙碌率)state_p->idle_last = (state_p->busy_time * 100) / idle_period_time;state_p->idle_last = state_p->idle_last > 100 ? 0 : 100 - state_p->idle_last;// 重置統計值state_p->busy_time = 0;state_p->idle_period_start = lv_tick_get();}// 保存本次計算的“下次觸發間隔”state_p->timer_time_until_next = time_until_next;state_p->already_running = false;  // 解鎖,允許下次進入LV_TRACE_TIMER("finished (%" LV_PRIu32 " ms until the next timer call)", time_until_next);lv_unlock();  // 退出臨界區LV_PROFILER_END;return time_until_next;  // 返回最短等待時間,供外部調度參考
}

? 總結重點

  • 每次調用 lv_timer_handler()

    • 會遍歷所有活躍的定時器;
    • 執行到期的任務;
    • 動態應對中途創建/刪除定時器的情況;
    • 返回下次最早觸發的延時時間。
  • 所有動畫、控件刷新、事件分發等操作,最終都是通過定時器機制驅動。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/904771.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/904771.shtml
英文地址,請注明出處:http://en.pswp.cn/news/904771.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【數據機構】2. 線性表之“順序表”

- 第 96 篇 - Date: 2025 - 05 - 09 Author: 鄭龍浩/仟墨 【數據結構 2】 文章目錄 數據結構 - 2 -線性表之“順序表”1 基本概念2 順序表(一般為數組)① 基本介紹② 分類 (靜態與動態)③ 動態順序表的實現**test.c文件:****SeqList.h文件:****SeqList.c文件:** 數據結構 - 2 …

101 alpha——8 學習

alpha (-1 * rank(((sum(open, 5) * sum(returns, 5)) - delay((sum(open, 5) * sum(returns, 5)),這里我們操作符都明白&#xff0c;現在來看金融意義 金融意義 里層是這個 (sum(open, 5) * sum(returns, 5)) - delay((sum(open, 5) * sum(returns, 5)), 10 這里是兩個相減…

auto推導類型原則

auto 是 C11 引入的類型自動推導關鍵字&#xff0c;它允許編譯器根據表達式的類型來推導變量的確切類型。雖然使用 auto 可以讓代碼更簡潔&#xff0c;但理解它的類型推導規則非常關鍵&#xff0c;尤其是在涉及指針、引用、const、模板等場景時。 ? 一、基本推導原則 auto x …

使用智能表格做FMEDA

一、優點 使用智能表格替代excel做FMEDA具備以下優勢&#xff1a; 減少維護成本&#xff08;數據庫關聯&#xff0c;修改方便&#xff09;便于持續優化&#xff08;失效率分布&#xff0c;失效率模型可重復使用&#xff09;多人同步編寫&#xff08;同時操作&#xff0c;同步…

IP協議.

IP 協議是互聯網的核心協議&#xff0c;工作在網絡層。它給網絡中的設備分配唯一的 IP 地址&#xff0c;把上層數據封裝成數據包&#xff0c;然后根據目的 IP 地址通過路由器等設備進行轉發&#xff0c;實現數據在不同網絡間的傳輸。它還能在必要時對數據包進行分片和重組&…

archlinux 詳解系統層面

Arch Linux 深度解析&#xff1a;從設計哲學到系統架構 一、Arch Linux 概述&#xff1a;滾動發行的極客之選 Arch Linux 是一款以 滾動更新&#xff08;Rolling Release&#xff09; 為核心特性的 Linux 發行版&#xff0c;強調 輕量、靈活、高度可定制&#xff0c;旨在讓用…

HTML8:媒體元素

視頻和音頻 視頻元素 video 音頻 audio <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>媒體元素學習</title> </head> <body> <!--音頻和視頻 src:資源路徑 controls:控制條…

SpringBoot3集成Oauth2——1(/oauth2/token方法的升級踩坑)

備注&#xff1a;本文適用于你在SpringBoot2.7以前集成過oauth2&#xff0c;并且項目已經正式投入使用的情況&#xff0c;否則&#xff0c;我建議你直接學習或者找資料學習最新的oauth2集成&#xff0c;就不要糾結于老版本的oauth2。 原因&#xff1a;Spring Security 5.x和Sp…

筆記本電腦實現網線內網 + Wi-Fi外網同時使用的配置方案

1、同時連接兩個網絡? 插入網線連接內網&#xff0c;確保內網IP地址正常獲取&#xff08;如10.143.88.x&#xff09;&#xff1b;連接Wi-Fi接入外網&#xff0c;確認可正常訪問互聯網&#xff08;如網關為192.168.8.1&#xff09;。 2、 記錄關鍵網絡參數? 內網網關&#…

從韋斯利?卡普洛看北斗星咨詢公司的技術咨詢引領之路

在科技與商業深度交融的時代&#xff0c;技術咨詢公司扮演著舉足輕重的角色&#xff0c;它們宛如連接技術創新與企業實際需求的橋梁&#xff0c;助力企業在復雜多變的市場環境中找準技術發展方向&#xff0c;實現可持續增長。《對話 CTO&#xff0c;駕馭高科技浪潮》的第 5 章聚…

首版次軟件測試的內容有哪些?首版次軟件質量影響因素是什么?

首版次軟件測試不僅是簡單的“找錯”&#xff0c;更是系統地驗證和評估軟件各項功能和性能指標是否符合設計標準。 一、首版次軟件測試常見的測試內容   1.功能測試&#xff1a;對照需求文檔&#xff0c;確認功能模塊是否按預期實現&#xff0c;用戶操作流程是否順暢。   …

從零開始的python學習(六)P86+P87+P88

本文章記錄觀看B站python教程學習筆記和實踐感悟&#xff0c;視頻鏈接&#xff1a;【花了2萬多買的Python教程全套&#xff0c;現在分享給大家&#xff0c;入門到精通(Python全棧開發教程)】 https://www.bilibili.com/video/BV1wD4y1o7AS/?p6&share_sourcecopy_web&v…

從設計到開發,原型標注圖全流程標準化

一、原型標注圖是什么&#xff1f; 原型標注圖&#xff08;Annotated Prototype&#xff09;是設計原型&#xff08;Prototype&#xff09;的詳細說明書&#xff0c;通過圖文結合的方式&#xff0c;將設計稿中的視覺樣式、交互邏輯、適配規則等技術細節轉化為開發可理解的標準…

飛云分倉操盤副圖指標操作技術圖文分解

如上圖&#xff0c;副圖指標-飛云分倉操盤指標&#xff0c;指標三條線藍色“首峰線”&#xff0c;紅色“引力1”&#xff0c;青色“引力2”&#xff0c;多頭行情時“首峰線”和“引力1”之間顯示為紅色&#xff0c;“引力1”和“引力2”多頭是區間顏色顯示為紫色。 如上圖圖標信…

【LUT技術專題】ECLUT代碼解讀

目錄 原文概要 1. 訓練 2. 轉表 3. 測試 本文是對ECLUT技術的代碼解讀&#xff0c;原文解讀請看ECLUT。 原文概要 ECLUT通過EC模塊增大網絡感受野&#xff0c;提升超分效果&#xff0c;實現SRLUT的改進&#xff0c;主要是2個創新點&#xff1a; 提出了一個擴展卷積&…

動態規劃之背包問題:組合優化中的經典NP挑戰

背包問題概念&#xff1a; 背包問題是一種經典的組合優化的NP問題&#xff0c;在計算機科學、運籌學等領域有著廣泛的應用。 問題可以簡單的描述為&#xff1a; 假設有一個容量為C的背包和n個物品&#xff0c;每個物品i都有重量w[i]和價值v[i]。目標是選擇一些物品放入背包&…

vue3: pdf.js5.2.133 using typescript

npm install pdfjs-dist5.2.133 項目結構&#xff1a; <!--* creater: geovindu* since: 2025-05-09 21:56:20* LastAuthor: geovindu* lastTime: 2025-05-09 22:12:17* 文件相對于項目的路徑: \jsstudy\vuepdfpreview\comonents\pdfjs.vue* message: geovindu* IDE: vscod…

H2Database SQL 插入流程

H2Database SQL 插入流程 插入數據時會先進行 SQL 解析,然后找到插入表對應的 Primary Index 對應的 BTree,然后根據二分法定位到插入的葉子節點,將 key(主鍵) 和 value(Row) 插入到指定的葉子節點. 解析 SQL session 加鎖 創建 savepoint獲取or創建事務 設置 savepoint 執行…

虛擬機ubantu20.04系統橋接模式下無法ping通外網,但可以ping通本機的解決方案

1.出現的問題&#xff1a; 虛擬機ubantu20.04系統橋接模式下無法ping通外網,但可以ping通本機。 2.解決方案&#xff1a; 如果 DHCP 未分配 IP 地址&#xff0c;可以手動配置靜態 IP&#xff1a; 1.編輯網絡配置文件&#xff1a; sudo nano /etc/netplan/01-netcfg.yaml 修…

面對渠道競爭,品牌該如何應對?

無論是傳統零售渠道還是電商平臺的&#xff0c;渠道競爭仍舊是品牌維持和擴大影響力繞不開的一環。品牌想要保證自身的市場地位和盈利能力&#xff0c;就需要充分發揮各方面的優勢&#xff0c;來應對多變的市場環境。 一、改變產品定位 在存量市場上&#xff0c;消費者本身擁有…