在这里首先感谢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 */14 15 __forceinline void LCD_SetCursor(U16 x, U16 y)16 {17 int xPhys;18 int yPhys;19 /* Convert logical into physical coordinates (Dep. on LCDConf.h) */20 #if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y21 xPhys = LOG2PHYS_X(x, y);22 yPhys = LOG2PHYS_Y(x, y);23 #else24 xPhys = x;25 yPhys = y;26 #endif27 28 LCD->LCD_REG = 0x004F;29 LCD->LCD_RAM = 319 - xPhys;30 LCD->LCD_REG = 0x004E;31 LCD->LCD_RAM = yPhys; 32 }33 34 /*********************************************************************35 *36 * 当前坐标读一个像素37 */38 __forceinline U16 LCD_GetPoint()39 {40 LCD->LCD_REG = 0x22;41 LCD->LCD_RAM > 0; //等待数据稳定42 return LCD->LCD_RAM;43 }44 45 /*********************************************************************46 *47 * 当前坐标写一个像素48 */49 50 __forceinline void LCD_SetPoint(U16 point)51 {52 LCD->LCD_REG = 0x22;53 LCD->LCD_RAM = point;54 }55 56 /*********************************************************************57 *58 * 当前坐标开始画一条水平线59 * xEnd:结束坐标60 */61 __forceinline void LCD_DrawHLineExt(int x, int xEnd, U16 point)62 {63 LCD->LCD_REG = 0x22;64 while (x++ <= xEnd)65 LCD->LCD_RAM = point;66 }
这些基本函数 要根据各自的lcd屏驱动所定的。
在原先的移植上 做如下修改:
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_Y10 xPhys = LOG2PHYS_X(x, y);11 yPhys = LOG2PHYS_Y(x, y);12 #else13 xPhys = x;14 yPhys = y;15 #endif16 /* 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 26 GUI_USE_PARA(x);27 GUI_USE_PARA(y);28 /* Convert logical into physical coordinates (Dep. on LCDConf.h) */29 #if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y30 xPhys = LOG2PHYS_X(x, y);31 yPhys = LOG2PHYS_Y(x, y);32 #else33 xPhys = x;34 yPhys = y;35 #endif36 /* Read from hardware ... Adapt to your system */37 {38 PixelIndex = ili9320_GetPoint(xPhys, yPhys);/* ... */39 }40 return PixelIndex;41 }42 43 44 45 修改后46 void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex) {47 GUI_USE_PARA(x);48 GUI_USE_PARA(y);49 GUI_USE_PARA(PixelIndex);50 51 LCD_SetCursor(x, y);52 LCD_SetPoint(PixelIndex);53 }54 unsigned int LCD_L0_GetPixelIndex(int x, int y) {55 GUI_USE_PARA(x);56 GUI_USE_PARA(y);57 58 LCD_SetCursor(x, y);59 return LCD_GetPoint();60 }
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 15 16 修改后17 void LCD_L0_DrawHLine (int x0, int y, int x1) {18 if (GUI_Context.DrawMode & LCD_DRAWMODE_XOR) {19 while(x0++ <= x1)20 LCD_L0_XorPixel(x0, y);21 } else {22 LCD_SetCursor(x0, y);23 LCD_DrawHLineExt(x0, x1, LCD_COLORINDEX);24 }25 }
细节观察,这个函数只是把写坐标分离出来了。
关键的修改,大部分刷屏程序都用到LCD_L0_DrawHLine函数,所以优化他对你的程序提速起了决定性的改变。
原理很简单,只要画水平线时,每写一个像素,坐标会自动后移一位。所以没必要每次都指定坐标,把设置坐标的时间给节约出来。
最后就是画图函数了,我的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 35 修改后如下36 static void DrawBitLine16BPP(int x, int y, U16 const GUI_UNI_PTR * p, int xsize, const LCD_PIXELINDEX * pTrans) {37 LCD_PIXELINDEX pixel;38 39 LCD_SetCursor(x, y);40 if ((GUI_Context.DrawMode & LCD_DRAWMODE_TRANS) == 0) {41 if (pTrans) {42 for (; xsize > 0; xsize--, x++, p++) {43 pixel = *p;44 LCD_SetPoint(*(pTrans + pixel));45 }46 } else {47 for (;xsize > 0; xsize--, x++, p++) {48 LCD_SetPoint(*p);49 }50 }51 } else {52 if (pTrans) {53 for (; xsize > 0; xsize--, x++, p++) {54 pixel = *p;55 if (pixel) {56 LCD_SetPoint(*(pTrans + pixel));57 }58 }59 } else {60 for (; xsize > 0; xsize--, x++, p++) {61 pixel = *p;62 if (pixel) {63 LCD_SetPoint(pixel);64 }65 }66 }67 }68 }
好了,修改完了,可以进行测试了。
这里附上我的测试工程:
视频预览。
#