0、引子測試
近日在論壇看到有人說屏幕閃爍,問道怎麼解決。在嵌入式gui使用方面,屏幕閃爍通常多出如今多個窗口層疊、多圖層層疊、更新圖層時。受限於接口速度,即便屏幕有很高的刷新率,也作不到無閃爍,因此要從減小數據傳送上下功夫,好比使用內存設備處理好數據再總體搬到LCD上,還有就是使用局部刷新較少刷新的數據量,同時還要注意圖層順序的問題。ui
一、內存設備避免閃爍原理spa
當在液晶屏上繪製一些文字疊加在圖片上的效果時,一般是先在液晶屏上繪製底層的圖片,而後再在圖片上疊加上文字,屢次刷新會出現閃爍。code
存儲設備可在各類狀況下使用,主要用於防止在繪製重疊項目時出現顯示器閃爍。其基本思想很簡單,不使用存儲設備時,繪製操做直接寫入顯示器,屏幕在執行繪製操做時隨時更新,從而在進行各類更新時使屏幕閃爍。例如,若是要在背景中繪製一個位圖,在前景中繪製一些透明文本,應首先繪製位圖,而後繪製文本。效果將是文本出現閃爍。可是,若是在此過程當中使用存儲設備,則全部繪製操做都在存儲器中執行。僅在全部操做都完成後纔將最終結果顯示在屏幕上,實現一次性從內存到LCD繪製,其優勢是沒有閃爍。blog
下圖形象的解釋了內存設備避免閃爍的原理。接口
二、emWin使用內存設備圖片
emWin使用內存設備須要先打開配置:內存
#define GUI_SUPPORT_MEMDEV (1) // Memory devices available開發
測試例子:it
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); }
三、測試效果
測試截圖以下:
動態效果能夠看到,左側直接繪製有閃爍,尤爲是百位數字即便沒有更新時候也會閃爍一次。右側是先在內存中繪製,而後從內存設備拷貝到界面上,只須要更新一次,沒有閃爍。
四、參考文獻
一、《emWin用戶參考手冊》
二、野火《emWin應用開發實戰指南》