[应用相关] uCGUI 驱动LCD提速 STM32F主芯

[复制链接]
 楼主| internally 发表于 2019-6-18 09:40 | 显示全部楼层 |阅读模式
在这里首先感谢wzt的**《ucgui液晶显示深度优化篇》写的很详细,运行很高效。
http://www.docin.com/p-453546222.html
         在这里我提出另一种方法,在完全不破坏原有的uCGUI接口功能上进行强力提速。当然速度方面要弱于wzt的速度,当然优点就在于不破坏所有接口功能,保留下了uCGUI的所有功能。例如两个图片交叉异或显示。
好了,下面开始改进。
         这里先提一下我用的LCD是3.2寸SSD1289屏,神舟三号开发板。 这里不管用什么屏,只要屏写像素点后如图所示移动就可以了。 从这里大家应该也看出来了, 我主要用到的方法就是在写连续像素时省去每次设置坐标点的问题。这就是我下面**思想的基础了。
我用的是LCDTemplate.c接口文件。直接在其上进行改进。
在文件最上方添加以下几个基本函数:
  1. typedef struct
  2. {
  3.   vu16 LCD_REG;
  4.   vu16 LCD_RAM;
  5. } LCD_TypeDef;
  6.       
  7. #define LCD_BASE    ((u32)(0x60000000 | 0x0C000000))
  8. static volatile LCD_TypeDef *LCD = ((volatile LCD_TypeDef *) LCD_BASE);

  9. /*********************************************************************
  10. *
  11. *       设定坐标
  12. */

  13. __forceinline void LCD_SetCursor(U16 x, U16 y)
  14. {
  15.     int xPhys;
  16.     int yPhys;
  17.     /* Convert logical into physical coordinates (Dep. on LCDConf.h) */
  18. #if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y
  19.       xPhys = LOG2PHYS_X(x, y);
  20.       yPhys = LOG2PHYS_Y(x, y);
  21. #else
  22.       xPhys = x;
  23.       yPhys = y;
  24. #endif

  25.     LCD->LCD_REG = 0x004F;
  26.     LCD->LCD_RAM = 319 - xPhys;
  27.     LCD->LCD_REG = 0x004E;
  28.     LCD->LCD_RAM = yPhys;   
  29. }

  30. /*********************************************************************
  31. *
  32. *       当前坐标读一个像素
  33. */
  34. __forceinline U16 LCD_GetPoint()
  35. {
  36.     LCD->LCD_REG = 0x22;
  37.     LCD->LCD_RAM > 0;       //等待数据稳定
  38.     return LCD->LCD_RAM;
  39. }

  40. /*********************************************************************
  41. *
  42. *       当前坐标写一个像素
  43. */

  44. __forceinline void LCD_SetPoint(U16 point)
  45. {
  46.     LCD->LCD_REG = 0x22;
  47.     LCD->LCD_RAM = point;
  48. }

  49. /*********************************************************************
  50. *
  51. *       当前坐标开始画一条水平线
  52. *       xEnd:结束坐标
  53. */
  54. __forceinline void LCD_DrawHLineExt(int x, int xEnd, U16 point)
  55. {
  56.     LCD->LCD_REG = 0x22;
  57.     while (x++ <= xEnd)
  58.         LCD->LCD_RAM = point;
  59. }
这些基本函数 要根据各自的lcd屏驱动所定的。

 楼主| internally 发表于 2019-6-18 09:41 | 显示全部楼层
在原先的移植上 做如下修改:
  1. 原函数
  2. void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex) {
  3.   int xPhys = 0;
  4.   int yPhys = 0;
  5.   GUI_USE_PARA(x);
  6.   GUI_USE_PARA(y);
  7.   GUI_USE_PARA(PixelIndex);
  8.   /* Convert logical into physical coordinates (Dep. on LCDConf.h) */
  9.   #if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y
  10.     xPhys = LOG2PHYS_X(x, y);
  11.     yPhys = LOG2PHYS_Y(x, y);
  12.   #else
  13.     xPhys = x;
  14.     yPhys = y;
  15.   #endif
  16.   /* Write into hardware ... Adapt to your system */
  17.   {
  18.     ili9320_SetPoint(xPhys, yPhys, PixelIndex);/* ... */
  19.   }
  20. }
  21. unsigned int LCD_L0_GetPixelIndex(int x, int y) {
  22.   int xPhys = 0;
  23.   int yPhys = 0;
  24.   LCD_PIXELINDEX PixelIndex;

  25.   GUI_USE_PARA(x);
  26.   GUI_USE_PARA(y);
  27.   /* Convert logical into physical coordinates (Dep. on LCDConf.h) */
  28.   #if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y
  29.     xPhys = LOG2PHYS_X(x, y);
  30.     yPhys = LOG2PHYS_Y(x, y);
  31.   #else
  32.     xPhys = x;
  33.     yPhys = y;
  34.   #endif
  35.   /* Read from hardware ... Adapt to your system */
  36.   {
  37.     PixelIndex = ili9320_GetPoint(xPhys, yPhys);/* ... */
  38.   }
  39.   return PixelIndex;
  40. }



  41. 修改后
  42. void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex) {
  43.   GUI_USE_PARA(x);
  44.   GUI_USE_PARA(y);
  45.   GUI_USE_PARA(PixelIndex);

  46.   LCD_SetCursor(x, y);
  47.   LCD_SetPoint(PixelIndex);
  48. }
  49. unsigned int LCD_L0_GetPixelIndex(int x, int y) {
  50.   GUI_USE_PARA(x);
  51.   GUI_USE_PARA(y);

  52.   LCD_SetCursor(x, y);
  53.   return LCD_GetPoint();
  54. }

  1. 原文件
  2. void LCD_L0_DrawHLine  (int x0, int y,  int x1) {
  3.   if (GUI_Context.DrawMode & LCD_DRAWMODE_XOR) {
  4.     for (; x0 <= x1; x0++) {
  5.       LCD_L0_XorPixel(x0, y);
  6.     }
  7.   } else {
  8.     for (; x0 <= x1; x0++) {
  9.       LCD_L0_SetPixelIndex(x0, y, LCD_COLORINDEX);
  10.     }
  11.   }
  12. }



  13. 修改后
  14. void LCD_L0_DrawHLine  (int x0, int y,  int x1) {
  15.   if (GUI_Context.DrawMode & LCD_DRAWMODE_XOR) {
  16.       while(x0++ <= x1)
  17.         LCD_L0_XorPixel(x0, y);
  18.   } else {
  19.     LCD_SetCursor(x0,  y);
  20.     LCD_DrawHLineExt(x0, x1, LCD_COLORINDEX);
  21.   }
  22. }


细节观察,这个函数只是把写坐标分离出来了。

关键的修改,大部分刷屏程序都用到LCD_L0_DrawHLine函数,所以优化他对你的程序提速起了决定性的改变。
 楼主| internally 发表于 2019-6-18 09:42 | 显示全部楼层
原理很简单,只要画水平线时,每写一个像素,坐标会自动后移一位。所以没必要每次都指定坐标,把设置坐标的时间给节约出来。

最后就是画图函数了,我的LCD是16位的,所以我只修改了DrawBitLine16BPP一个函数,如果你的是低于16位的,同理进行修改。

参考如下
  1. 原函数
  2. static void  DrawBitLine16BPP(int x, int y, U16 const GUI_UNI_PTR * p, int xsize, const LCD_PIXELINDEX * pTrans) {
  3.   LCD_PIXELINDEX pixel;
  4.   if ((GUI_Context.DrawMode & LCD_DRAWMODE_TRANS) == 0) {
  5.     if (pTrans) {
  6.       for (; xsize > 0; xsize--, x++, p++) {
  7.         pixel = *p;
  8.         LCD_L0_SetPixelIndex(x, y, *(pTrans + pixel));
  9.       }
  10.     } else {
  11.       for (;xsize > 0; xsize--, x++, p++) {
  12.         LCD_L0_SetPixelIndex(x, y, *p);
  13.       }
  14.     }
  15.   } else {
  16.     if (pTrans) {
  17.       for (; xsize > 0; xsize--, x++, p++) {
  18.         pixel = *p;
  19.         if (pixel) {
  20.           LCD_L0_SetPixelIndex(x, y, *(pTrans + pixel));
  21.         }
  22.       }
  23.     } else {
  24.       for (; xsize > 0; xsize--, x++, p++) {
  25.         pixel = *p;
  26.         if (pixel) {
  27.           LCD_L0_SetPixelIndex(x, y, pixel);
  28.         }
  29.       }
  30.     }
  31.   }
  32. }


  33. 修改后如下
  34. static void  DrawBitLine16BPP(int x, int y, U16 const GUI_UNI_PTR * p, int xsize, const LCD_PIXELINDEX * pTrans) {
  35.   LCD_PIXELINDEX pixel;
  36.   
  37.   LCD_SetCursor(x, y);
  38.   if ((GUI_Context.DrawMode & LCD_DRAWMODE_TRANS) == 0) {
  39.     if (pTrans) {
  40.       for (; xsize > 0; xsize--, x++, p++) {
  41.         pixel = *p;
  42.         LCD_SetPoint(*(pTrans + pixel));
  43.       }
  44.     } else {
  45.       for (;xsize > 0; xsize--, x++, p++) {
  46.         LCD_SetPoint(*p);
  47.       }
  48.     }
  49.   } else {
  50.     if (pTrans) {
  51.       for (; xsize > 0; xsize--, x++, p++) {
  52.         pixel = *p;
  53.         if (pixel) {
  54.           LCD_SetPoint(*(pTrans + pixel));
  55.         }
  56.       }
  57.     } else {
  58.       for (; xsize > 0; xsize--, x++, p++) {
  59.         pixel = *p;
  60.         if (pixel) {
  61.           LCD_SetPoint(pixel);
  62.         }
  63.       }
  64.     }
  65.   }
  66. }

好了,修改完了,可以进行测试了。
 楼主| internally 发表于 2019-6-18 09:42 | 显示全部楼层
这里附上我的测试工程:

http://pan.baidu.com/share/link?shareid=63325&uk=118334538

视频预览。

http://www.tudou.com/programs/view/sQexoNIhNR0/#
xiaoqizi 发表于 2019-7-8 09:32 | 显示全部楼层
非常感谢楼主分享
观海 发表于 2019-7-8 10:51 | 显示全部楼层
非常感谢楼主分享
guanjiaer 发表于 2019-7-8 10:58 | 显示全部楼层
非常感谢楼主分享
heimaojingzhang 发表于 2019-7-8 11:06 | 显示全部楼层
非常感谢楼主分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

315

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部

15

主题

315

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部