uCGUI 驱动LCD提速 STM32F主芯

转载 2013年12月04日 11:10:33

在这里首先感谢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/#

 

STM32F407vet6使用FSMC驱动LCD屏

我的方法也特别简单。高手勿喷。      首先,你得稍微了解一下FSMC的基本原理,就是说它是怎么用的,怎么配置,为什么能这么用。这个东西可以看看STM32F4的参考手册。这里不具体说了。(其实是因...
  • queryor
  • queryor
  • 2015年08月08日 00:00
  • 2402

STM32F4_LCD12864并行驱动

头文件: #ifndef   __12864LCD_H__ #define  __12864LCD_H__ #include "stm32f4xx.h" #include "stm32f4xx_g...

STM32F429 Discovery FMC驱动原子4.3寸LCD

本人手里有块STM32F429 Discovery板子,因为某种原因需要使用8080接口的LCD,而该块开发板自带的LCD接口采用LTDC驱动,所以就在正点原子这里买了一块4.3寸电容触摸屏,驱动IC...

ARM STM32F103VCT6驱动LCD屏12864实例

条件:ARM STM32F103VCT6芯片,开发平台keil5.20,ARM固件版本V3.50, LCD12864(ks0108) 并行通信。 第一步:端口初始化设置/**************...

stm32f4开发板驱动LCD液晶屏的个人总结

研究了几天的F4的FSMC方式驱动触摸屏,得到一些认识,现在列举如下,流水帐般没有组织的记录仅供自己以后参考 使用的是一款叫微雪电子的F407的开发板,但是他们的客服却不太愿解答用户提出的问...

stm32f103 nokia5110LCD驱动

  • 2016年01月10日 01:04
  • 2KB
  • 下载

STM32F4应用笔记(五)UCGUI+uC/OS-II+支持触摸屏

移植uC/OS-II 我们以上一篇工程为基础,进行移植。然后我们还需要用到正点原子F4【实验56 UCOSII实验1-任务调度】的代码,将实验56工程下的UCOSII文件夹直接复制到我们上一篇建立的...

stm32f407ZET驱动 1.8寸TFT_LCD

  • 2017年08月07日 10:18
  • 5.72MB
  • 下载

SPI LCD驱动(适用于STM32F030/031)

  • 2015年11月24日 19:05
  • 578KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:uCGUI 驱动LCD提速 STM32F主芯
举报原因:
原因补充:

(最多只允许输入30个字)