嵌入式LCD闪烁–emWin使用内存设备避免闪烁

  • 2020 年 3 月 27 日
  • 筆記

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