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应用开发实战指南》