0、引子
近日在論壇看到有人說屏幕閃爍,問道怎么解決。在嵌入式gui使用方面,屏幕閃爍一般多出現在多個窗口層疊、多圖層層疊、更新圖層時。受限於接口速度,即使屏幕有很高的刷新率,也做不到無閃爍,所以要從減少數據傳送上下功夫,比如使用內存設備處理好數據再整體搬到LCD上,還有就是使用局部刷新較少刷新的數據量,同時還要注意圖層順序的問題。
1、內存設備避免閃爍原理
當在液晶屏上繪制一些文字疊加在圖片上的效果時,通常是先在液晶屏上繪制底層的圖片,然后再在圖片上疊加上文字,多次刷新會出現閃爍。
存儲設備可在各種情況下使用,主要用於防止在繪制重疊項目時出現顯示器閃爍。其基本思想很簡單,不使用存儲設備時,繪制操作直接寫入顯示器,屏幕在執行繪制操作時隨時更新,從而在進行各種更新時使屏幕閃爍。例如,如果要在背景中繪制一個位圖,在前景中繪制一些透明文本,應首先繪制位圖,然后繪制文本。效果將是文本出現閃爍。但是,如果在此過程中使用存儲設備,則所有繪制操作都在存儲器中執行。僅在所有操作都完成后才將最終結果顯示在屏幕上,實現一次性從內存到LCD繪制,其優點是沒有閃爍。
下圖形象的解釋了內存設備避免閃爍的原理。
2、emWin使用內存設備
emWin使用內存設備需要先打開配置:
#define GUI_SUPPORT_MEMDEV (1) // Memory devices available
測試例子:
void MainTask(void) { GUI_Init(); // // Check if recommended memory for the sample is available // if (GUI_ALLOC_GetNumFreeBytes() < RECOMMENDED_MEMORY) { GUI_ErrorOut("Not enough memory available."); return; } GUI_SetColor(GUI_LIGHTGRAY); GUI_RECT rect = { 0, 0, LCD_GetXSize(), 49 }; GUI_FillRectEx(&rect); char title[] = "Draw direct And Use Memory device"; GUI_SetFont(GUI_FONT_24_ASCII); GUI_SetColor(GUI_RED); GUI_SetTextMode(GUI_TEXTMODE_TRANS); GUI_DispStringInRect(title, &rect, GUI_TA_HCENTER | GUI_TA_VCENTER); GUI_DispStringAt("Direct Draw", 70, 200); GUI_DispStringAt("Use Memory", 300, 200); GUI_MEMDEV_Handle hMem = GUI_MEMDEV_Create(280, 50, 150, 150); int i = 0; while (1) { GUI_Delay(5); Draw(50, 50, 200, 200, i); // 直接在LCD繪制 GUI_MEMDEV_Select(hMem); //選擇內存設備 Draw(280, 50, 430, 200, i); // 在內存中繪制 GUI_MEMDEV_Select(0); // 恢復LCD設備 GUI_MEMDEV_CopyToLCDAt(hMem, 280, 50); i++; if (i >= 1000) i = 0; } while(1); } void Draw(int x0, int y0, int x1, int y1, int i) { char buf[10] = { 0 }; GUI_SetColor(GUI_BLUE); GUI_FillRect(x0, y0, x1, y1); GUI_SetFont(GUI_FONT_D64); GUI_SetTextMode(GUI_TEXTMODE_XOR); sprintf(buf, "%d", i); GUI_DispStringHCenterAt(buf, x0 + (x1 - x0) / 2, y0 + (y1 - y0) / 2 - 32); }
3、測試效果
測試截圖如下:
動態效果可以看到,左側直接繪制有閃爍,尤其是百位數字即使沒有更新時候也會閃爍一次。右側是先在內存中繪制,然后從內存設備拷貝到界面上,只需要更新一次,沒有閃爍。
4、參考文獻
1、《emWin用戶參考手冊》
2、野火《emWin應用開發實戰指南》