uCGUI 驱动LCD提速 STM32F主芯

来源:互联网 发布:js div的显示与隐藏 编辑:程序博客网 时间:2024/06/07 13:42

在这里首先感谢wzt的文章《ucgui液晶显示深度优化篇》写的很详细,运行很高效。

http://www.docin.com/p-453546222.html

         在这里我提出另一种方法,在完全不破坏原有的uCGUI接口功能上进行强力提速。当然速度方面要弱于wzt的速度,当然优点就在于不破坏所有接口功能,保留下了uCGUI的所有功能。例如两个图片交叉异或显示。

好了,下面开始改进。

         这里先提一下我用的LCD是3.2寸SSD1289屏,神舟三号开发板。 这里不管用什么屏,只要屏写像素点后如图所示移动就可以了。 从这里大家应该也看出来了, 我主要用到的方法就是在写连续像素时省去每次设置坐标点的问题。这就是我下面文章思想的基础了。

我用的是LCDTemplate.c接口文件。直接在其上进行改进。

在文件最上方添加以下几个基本函数:

typedef struct{  vu16 LCD_REG;  vu16 LCD_RAM;} LCD_TypeDef;       #define LCD_BASE    ((u32)(0x60000000 | 0x0C000000))static volatile LCD_TypeDef *LCD = ((volatile LCD_TypeDef *) LCD_BASE);/***********************************************************************       设定坐标*/__forceinline void LCD_SetCursor(U16 x, U16 y){    int xPhys;    int yPhys;    /* Convert logical into physical coordinates (Dep. on LCDConf.h) */#if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y      xPhys = LOG2PHYS_X(x, y);      yPhys = LOG2PHYS_Y(x, y);#else      xPhys = x;      yPhys = y;#endif    LCD->LCD_REG = 0x004F;    LCD->LCD_RAM = 319 - xPhys;    LCD->LCD_REG = 0x004E;    LCD->LCD_RAM = yPhys;    }/***********************************************************************       当前坐标读一个像素*/__forceinline U16 LCD_GetPoint(){    LCD->LCD_REG = 0x22;    LCD->LCD_RAM > 0;       //等待数据稳定    return LCD->LCD_RAM;}/***********************************************************************       当前坐标写一个像素*/__forceinline void LCD_SetPoint(U16 point){    LCD->LCD_REG = 0x22;    LCD->LCD_RAM = point;}/***********************************************************************       当前坐标开始画一条水平线*       xEnd:结束坐标*/__forceinline void LCD_DrawHLineExt(int x, int xEnd, U16 point){    LCD->LCD_REG = 0x22;    while (x++ <= xEnd)        LCD->LCD_RAM = point;}


 

这些基本函数 要根据各自的lcd屏驱动所定的。

在原先的移植上 做如下修改:

原函数void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex) {  int xPhys = 0;  int yPhys = 0;   GUI_USE_PARA(x);  GUI_USE_PARA(y);  GUI_USE_PARA(PixelIndex);  /* Convert logical into physical coordinates (Dep. on LCDConf.h) */  #if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y    xPhys = LOG2PHYS_X(x, y);    yPhys = LOG2PHYS_Y(x, y);  #else    xPhys = x;    yPhys = y;  #endif  /* Write into hardware ... Adapt to your system */  {    ili9320_SetPoint(xPhys, yPhys, PixelIndex);/* ... */  }}unsigned int LCD_L0_GetPixelIndex(int x, int y) {  int xPhys = 0;  int yPhys = 0;  LCD_PIXELINDEX PixelIndex;  GUI_USE_PARA(x);  GUI_USE_PARA(y);  /* Convert logical into physical coordinates (Dep. on LCDConf.h) */  #if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y    xPhys = LOG2PHYS_X(x, y);    yPhys = LOG2PHYS_Y(x, y);  #else    xPhys = x;    yPhys = y;  #endif  /* Read from hardware ... Adapt to your system */  {    PixelIndex = ili9320_GetPoint(xPhys, yPhys);/* ... */  }  return PixelIndex;}修改后void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex) {  GUI_USE_PARA(x);  GUI_USE_PARA(y);  GUI_USE_PARA(PixelIndex);  LCD_SetCursor(x, y);  LCD_SetPoint(PixelIndex);}unsigned int LCD_L0_GetPixelIndex(int x, int y) {  GUI_USE_PARA(x);  GUI_USE_PARA(y);  LCD_SetCursor(x, y);  return LCD_GetPoint();}


 

原文件void LCD_L0_DrawHLine  (int x0, int y,  int x1) {  if (GUI_Context.DrawMode & LCD_DRAWMODE_XOR) {    for (; x0 <= x1; x0++) {      LCD_L0_XorPixel(x0, y);    }  } else {    for (; x0 <= x1; x0++) {      LCD_L0_SetPixelIndex(x0, y, LCD_COLORINDEX);    }  }}修改后void LCD_L0_DrawHLine  (int x0, int y,  int x1) {  if (GUI_Context.DrawMode & LCD_DRAWMODE_XOR) {      while(x0++ <= x1)        LCD_L0_XorPixel(x0, y);  } else {    LCD_SetCursor(x0,  y);    LCD_DrawHLineExt(x0, x1, LCD_COLORINDEX);  }}


 

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

关键的修改,大部分刷屏程序都用到LCD_L0_DrawHLine函数,所以优化他对你的程序提速起了决定性的改变。

原理很简单,只要画水平线时,每写一个像素,坐标会自动后移一位。所以没必要每次都指定坐标,把设置坐标的时间给节约出来。

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

参考如下

原函数static void  DrawBitLine16BPP(int x, int y, U16 const GUI_UNI_PTR * p, int xsize, const LCD_PIXELINDEX * pTrans) {  LCD_PIXELINDEX pixel;  if ((GUI_Context.DrawMode & LCD_DRAWMODE_TRANS) == 0) {    if (pTrans) {      for (; xsize > 0; xsize--, x++, p++) {        pixel = *p;        LCD_L0_SetPixelIndex(x, y, *(pTrans + pixel));      }    } else {      for (;xsize > 0; xsize--, x++, p++) {        LCD_L0_SetPixelIndex(x, y, *p);      }    }  } else {    if (pTrans) {      for (; xsize > 0; xsize--, x++, p++) {        pixel = *p;        if (pixel) {          LCD_L0_SetPixelIndex(x, y, *(pTrans + pixel));        }      }    } else {      for (; xsize > 0; xsize--, x++, p++) {        pixel = *p;        if (pixel) {          LCD_L0_SetPixelIndex(x, y, pixel);        }      }    }  }}修改后如下static void  DrawBitLine16BPP(int x, int y, U16 const GUI_UNI_PTR * p, int xsize, const LCD_PIXELINDEX * pTrans) {  LCD_PIXELINDEX pixel;    LCD_SetCursor(x, y);  if ((GUI_Context.DrawMode & LCD_DRAWMODE_TRANS) == 0) {    if (pTrans) {      for (; xsize > 0; xsize--, x++, p++) {        pixel = *p;        LCD_SetPoint(*(pTrans + pixel));      }    } else {      for (;xsize > 0; xsize--, x++, p++) {        LCD_SetPoint(*p);      }    }  } else {    if (pTrans) {      for (; xsize > 0; xsize--, x++, p++) {        pixel = *p;        if (pixel) {          LCD_SetPoint(*(pTrans + pixel));        }      }    } else {      for (; xsize > 0; xsize--, x++, p++) {        pixel = *p;        if (pixel) {          LCD_SetPoint(pixel);        }      }    }  }}


 

好了,修改完了,可以进行测试了。

这里附上我的测试工程:

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

视频预览。

http://www.tudou.com/programs/view/sQexoNIhNR0/#

 

原创粉丝点击