-
lv_timer_handler()
?是 LVGL 的“心臟”:這個函數會依次做以下事情:-
處理定時器(如動畫、延遲回調)。
-
讀取輸入設備(如觸摸屏、按鍵的狀態)。
-
刷新臟區域(僅重繪屏幕上發生變化的區域)。
-
執行用戶注冊的回調函數(如按鈕點擊事件)。
-
-
開發者需要手動調用它:通常在一個?
while(1)
?循環或 FreeRTOS 任務中定期調用,例如每 5~50ms 調用一次。例如:c
復制
while (1) {lv_timer_handler(); // 驅動 LVGL 的核心邏輯vTaskDelay(5); // FreeRTOS 中延時 5ms }
-
如果沒有調用?
lv_timer_handler()
:LVGL 的定時器不會觸發,輸入設備狀態不會被讀取,UI 也不會更新,導致“死機”。
2.?為什么 LVGL 不依賴硬件中斷?
-
跨平臺兼容性:LVGL 需要支持從低端單片機到 Linux 的各種平臺,硬件中斷機制差異較大,輪詢更通用。
-
可控性:輪詢允許開發者自由控制 LVGL 的調用頻率,避免中斷搶占導致實時系統的不確定性(尤其是在 FreeRTOS 中)。
-
資源效率:中斷處理需要上下文切換,頻繁的中斷可能占用過多 CPU 資源,而輪詢可以通過調整調用間隔平衡性能與功耗。
3.?LVGL 如何與 FreeRTOS 協同工作?
-
典型場景:在 FreeRTOS 中創建一個專用任務(如?
lvgl_task
),負責定期調用?lv_timer_handler()
。例如:c
復制
void lvgl_task(void *pvParameters) {while (1) {lv_timer_handler(); // 驅動 LVGLvTaskDelay(pdMS_TO_TICKS(5)); // 5ms 周期} }
-
輸入設備的讀取:觸摸屏或按鍵的狀態通常也需要通過輪詢或中斷獲取,但 LVGL 不強制要求使用中斷。例如:
-
輪詢方式:在?
lv_timer_handler()
?中調用?lv_indev_read()
。 -
中斷方式:在觸摸屏中斷中標記事件,然后在?
lv_timer_handler()
?中處理。
-
因為需要用到systicks作為lvgl時基函數的基本盤,所以你freertos配置systicks時最好為1ms也就是時間片長短哪里的配置綜合結果要為每1ms systicks觸發一次
4.?LVGL 的優化:減少輪詢開銷
-
臟區域機制(Dirty Area):LVGL 只會重繪屏幕上發生變化的區域,而不是全屏刷新,大幅降低 CPU 負載。
-
事件驅動回調:用戶可以為 UI 元素(如按鈕)注冊回調函數,僅在事件發生時觸發邏輯,避免不必要的輪詢計算。
-
定時器精度控制:通過調整?
lv_timer_handler()
?的調用頻率,平衡響應速度和 CPU 占用率。
5.?對比 FreeRTOS 的任務調度
-
FreeRTOS 的任務:基于優先級搶占,依賴調度器(如 PendSV 中斷)切換任務。
-
LVGL 的輪詢:依賴開發者主動調用?
lv_timer_handler()
,本質上是一個“協作式”任務。 -
關鍵區別:LVGL 不直接依賴硬件中斷,而是通過任務調度間接實現“偽實時性”。
6.?你的推測是否正確?
-
正確部分:
-
LVGL 確實依賴輪詢(
lv_timer_handler()
),而非硬件中斷。 -
不調用?
lv_timer_handler()
?會導致 LVGL 無法工作。
-
-
需要補充的細節:
-
LVGL 的輪詢是協作式的,需要開發者將?
lv_timer_handler()
?嵌入到主循環或任務中。 -
FreeRTOS 的任務調度和 LVGL 的輪詢是互補的,前者管理多任務,后者管理 UI 邏輯。
-
7.?實際項目中的建議
-
調用頻率:根據 UI 復雜度調整?
lv_timer_handler()
?的調用間隔(通常 5~50ms)。 -
任務優先級:在 FreeRTOS 中,為 LVGL 任務分配中低優先級,避免阻塞關鍵任務。
-
輸入設備優化:如果使用觸摸屏,可以在硬件中斷中標記觸摸事件,然后在?
lv_timer_handler()
?中批量處理,減少響應延遲。
1.?LVGL 的定時器機制
-
LVGL 內部有一個定時器系統,
lv_timer_handler()
?是這個系統的核心函數。它負責處理所有與時間相關的任務,比如動畫、屏幕刷新、輸入設備的狀態檢測等。 -
?
lv_timer_handler()
?函數必須定期調用,否則 LVGL 的定時器系統將無法正常工作,導致動畫停止、輸入設備無響應等問題。這是因為 LVGL 的定時器系統是基于輪詢的,而不是基于中斷的。 -
在 FreeRTOS 中,你可以在一個任務中定期調用?
lv_timer_handler()
,比如每隔幾毫秒調用一次。這個任務可以是一個低優先級的任務,確保它不會影響其他高優先級任務的執行。
2.?LVGL 的輸入設備處理
-
LVGL 通過?
lv_indev_read()
?函數來讀取輸入設備(如觸摸屏、按鍵等)的狀態。這個函數通常會在?lv_timer_handler()
?中被調用。 -
“持續監測觸摸屏有沒有被按下”實際上是通過定期調用?
lv_indev_read()
?來實現的。LVGL 并不會像 FreeRTOS 的任務調度那樣實時監測輸入設備,而是通過輪詢的方式來獲取輸入設備的狀態。 -
當?
lv_timer_handler()
?被調用時,它會檢查輸入設備的狀態,并根據這些狀態更新 UI。例如,如果檢測到觸摸屏被按下,LVGL 會更新相應的 UI 元素(如按鈕的狀態)。
3.?LVGL 與 FreeRTOS 的協同工作
-
FreeRTOS 的任務調度是基于優先級的,高優先級的任務會搶占低優先級的任務。LVGL 的?
lv_timer_handler()
?通常在一個低優先級的任務中運行,確保它不會影響其他高優先級任務的執行。 -
你提到的“類似 PendSV 的機制”在 LVGL 中并不存在。LVGL 的定時器系統和輸入設備處理是基于輪詢的,而不是基于中斷的。PendSV 是 FreeRTOS 用于任務切換的中斷,而 LVGL 的定時器系統是通過定期調用?
lv_timer_handler()
?來實現的。
4.?LVGL 的 UI 更新機制
-
當你添加 UI 部件(如按鈕、標簽等)時,LVGL 會將這些部件添加到顯示列表中。
lv_timer_handler()
?會定期檢查這些部件的狀態,并根據需要更新顯示。 -
如果觸摸屏被按下,LVGL 會檢測到這個事件,并更新相應的 UI 部件(如改變按鈕的顏色、觸發回調函數等)。這些更新操作通常是在?
lv_timer_handler()
?中完成的。
5.?總結
-
LVGL 的運行機制是基于輪詢的,而不是基于中斷的。它通過定期調用?
lv_timer_handler()
?來處理定時器、輸入設備和 UI 更新。 -
FreeRTOS 的任務調度機制與 LVGL 的定時器系統可以協同工作。你可以在 FreeRTOS 的一個任務中定期調用?
lv_timer_handler()
,確保 LVGL 的正常運行。 -
LVGL 并不會像 FreeRTOS 的任務調度那樣實時監測輸入設備,而是通過輪詢的方式來獲取輸入設備的狀態,并在?
lv_timer_handler()
?中處理這些狀態。