TFTLCD开窗口写数据问题

2019-08-23 15:34发布

原子哥,我遇到一个困惑,情况如下:
就是在TFTLCD开窗口显示数据时,我按照你的方式写的程序,要完成的功能是: 
1.在指定区域内填充指定颜 {MOD}
2.写字符
因为你说过开窗写数据可以提高写入速度,可是这样问题就来了。

问题一:在指定区域内填充指定颜 {MOD}时竖屏时一切正常,但是,横屏时就出问题了。(因为填充要么方向不对,要么坐标不对。。)
分析:我想了好久,也找了好久,还是没想出来,最后在论坛的http://www.openedv.com/posts/list/7477.htm#38275找到了答案,原来我的问题出在坐标设置上,分析如下


 








就改了我的程序如下:

/***********************************************************
* 函数名称:LCD_SetCursor
* 函数功能:LCD设置坐标函数
*           入口参数: x( 水平坐标 )、y( 垂直坐标 )    
*   出口参数:无
***********************************************************/ __inline void LCD_SetCursor( u16 x, u16 y )
{
#if USE_HORIZONTAL==1 // 使用横屏
 LCD_WriteREG(R32, y);   // 设置GRAM的x坐标
 LCD_WriteREG(R33, 319-x); // 设置GRAM的y坐标       
#else
 LCD_WriteREG( R32, x );   // 设置GRAM的x坐标
 LCD_WriteREG( R33, y );   // 设置GRAM的y坐标         
#endif
}

/**********************************************************
* 函数名称:LCD_SetWindowSize
* 函数功能:设置窗口大小(edx-stx)*(edy-sty)
*           入口参数: stx: 开始x坐标
*          edx: 结束x坐标
*                     sty: 开始y坐标
*       edy: 结束y坐标
*   出口参数:无
***********************************************************/ void LCD_SetWindowSize( u16 stx, u16 edx, u16 sty, u16 edy )
{
#if USE_HORIZONTAL==1  // 横屏
 LCD_WriteREG( R80, sty ); // LCD写寄存器函数
 LCD_WriteREG( R81, edy ); // LCD写寄存器函数
 LCD_WriteREG( R82, 319-edx ); // LCD写寄存器函数
 LCD_WriteREG( R83, 319-stx ); // LCD写寄存器函数
#else
 LCD_WriteREG( R80, stx ); // LCD写寄存器函数
 LCD_WriteREG( R81, edx ); // LCD写寄存器函数
 LCD_WriteREG( R82, sty ); // LCD写寄存器函数
 LCD_WriteREG( R83, edy ); // LCD写寄存器函数
#endif
}
/***********************************************************
* 函数名称:LCD_Fill
* 函数功能:在指定区域内填充指定颜 {MOD}
*           入口参数: 区域大小xend-xsta)*(yend-ysta)、c(颜 {MOD})    
*   出口参数:无
***********************************************************/ void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
{         
 u16 i,j;
 LCD_SetWindowSize(  xsta, xend, ysta, yend );// 设置窗口大小
    LCD_SetCursor(xsta,ysta); //设置光标位置
 LCD_WriteCom(R34);        //开始写入GRAM
#if USE_HORIZONTAL==1  // 使用横屏    
 for(i=0;i<(xend-xsta)+1;i++)
 {  
  for(j=0;j<(yend-ysta)+1;j++)LCD_WriteData(color);//填充颜 {MOD}   
 }
#else   
 for(i=0;i<(yend-ysta)+1;i++)
 {  
  for(j=0;j<(xend-xsta)+1;j++)LCD_WriteData(color);////填充颜 {MOD}    
 }
#endif
 LCD_SetWindowSize( 0x0000, LCD_W, 0x0000, LCD_H );//恢复窗体大小
}

把在指定区域内填充指定颜 {MOD}的问题解决。可是还有问题。

问题二: 开窗口 写字符时竖屏一切OK,问题还是出在横屏显示,横屏显示时叠加方式显示字符正常,可是不叠加方式就出问题了,
还是老办法去想、去找,最后还是没解决(不叠加方式显示要么是乱码、要么是显示字符方向不对),急啊!后来没办法只能重取模来解决。


就重取模:
// ------------------  常用ASCII表字模的数据表 ------------------ //
// 码表从0x20~0x7e 
// 取模软件:PCtoLCD2002                                          //
// 取模方式:阴码,逐列式,逆向,文字垂直翻转
// 大小:16*8
// -------------------------------------------------------------- //
。。。。。。。数据

改写程序如下:

/**********************************************************
* 函数名称:LCD_ShowChar
* 函数功能:在指定位置显示一个字符
*           入口参数:  x   : 0~234
*         y   : 0~308
*        Char: 要显示的字符:" "--->"~"
*         mode: 叠加方式(1)还是非叠加方式(0)
*                      c   : 字体颜 {MOD}
*   出口参数:无
***********************************************************/ void LCD_ShowChar(u16 x,u16 y,u8 Char,u8 mode, u16 c )
{    
    u8 temp;
    u8 pos,t;    
    if(x>MAX_CHAR_POSX||y>MAX_CHAR_POSY)return; 
    LCD_SetWindowSize( x, (x+LCD_FONT_W-1), y, (y+LCD_FONT_H-1) );// 开辟窗口写数据
    LCD_SetCursor(x,y); // 设置光标位置       
    LCD_WriteCom( R34 );// RAMdata 寄存器             
    Char=Char-' ';//得到偏移后的值
#if USE_HORIZONTAL==1 // 横屏
 if(!mode)//非叠加方式
 {
  for(pos=0;pos<(LCD_FONT_H);pos++)
  {
      temp=asc1_1608[Char][15-pos];    //调用1608字体
   for(t=0;t<(LCD_FONT_W);t++)
      {                
          if(temp&0x80)
    {
                    LCD_WriteData( c );
    }else LCD_WriteData( BACK_COLOR );        
          temp<<=1;
      }
  } 
 }
#else
 if(!mode)//非叠加方式
 {
  for(pos=0;pos<(LCD_FONT_H);pos++)
  {
   temp=asc2_1608[Char][pos];    //调用1608字体
   for(t=0;t<(LCD_FONT_W);t++)
      {                
          if(temp&0x01)
    {
                    LCD_WriteData( c );
    }else LCD_WriteData( BACK_COLOR );        
          temp>>=1;
      }
  }
 }
#endif
 else//叠加方式  叠加方式显示多用于在显示的图片上再显示字符
 {
  for(pos=0;pos<LCD_FONT_H;pos++)
  {
   temp=asc2_1608[Char][pos];   //调用1608字体
   for(t=0;t<LCD_FONT_W;t++)
      {                
          if(temp&0x01)LCD_DrawPoint(x+t,y+pos,c);//画一个点    
          temp>>=1;
      }
  }
 } 
 LCD_SetWindowSize( 0x0000, LCD_W, 0x0000, LCD_H );//恢复窗体大小    
}

上面在处理不叠加方式显示时横竖屏问题上用不同的取模数据和不同的扫描方式,但是叠加方式我还是没解决,只能共用一个取模数据和同种画点方法;

这样虽然解决了开窗显示字符问题,但是总感觉这样好浪费资源,不好,所以原子哥或者各位高手能给小弟指引一条明路,运用其他方法,在下不胜感激




友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
17条回答
正点原子
1楼-- · 2019-08-23 15:51
 精彩回答 2  元偷偷看……
etkl
2楼-- · 2019-08-23 18:37
给你2个我在用的函数,应对4个方向的
#define LCD_WIDTH    320
#define LCD_HEIGHT    240
void LCD_CreatWindows(u16 sx,u16 sy,u16 width,u16 height)
{
u16 ex = sx + width-1;
u16 ey = sy + height-1;

#ifdef vertical
    #ifdef __h1__
        LCD_WriteReg(R80,sx);
        LCD_WriteReg(R81,ex);
        LCD_WriteReg(R82,sy);
        LCD_WriteReg(R83,ey);
        LCD_WriteReg(R32,sx);
        LCD_WriteReg(R33,sy);
    #else
        LCD_WriteReg(R80,LCD_HEIGHT-1-ex);
        LCD_WriteReg(R81,LCD_HEIGHT-1-sx);
        LCD_WriteReg(R82,LCD_WIDTH-1-ey);
        LCD_WriteReg(R83,LCD_WIDTH-1-sy);
        LCD_WriteReg(R32,LCD_HEIGHT-1-sx);
        LCD_WriteReg(R33,LCD_WIDTH-1-sy);
    #endif
#else
    #ifdef __h1__
        LCD_WriteReg(R80,LCD_HEIGHT-1 - ey); //横屏也有2种方式,方式1
        LCD_WriteReg(R81,LCD_HEIGHT-1 - sy);
        LCD_WriteReg(R82,sx);
        LCD_WriteReg(R83,ex);
        LCD_WriteReg(R32,LCD_HEIGHT-1 - sy);
        LCD_WriteReg(R33,sx);
    #else
        LCD_WriteReg(R80,sy); //横屏也有2种方式,方式2,在方式1的基础上旋转180度
        LCD_WriteReg(R81,ey);
        LCD_WriteReg(R82,LCD_WIDTH-1-ex);
        LCD_WriteReg(R83,LCD_WIDTH-1-sx);
        LCD_WriteReg(R32,sy);
        LCD_WriteReg(R33,LCD_WIDTH-1-sx);
    #endif
#endif
    LCD_WR_REG(R34);//开始写入GRAM
}
在LCD初始化时,把寄存器3修改为这个,
#ifdef vertical
    #ifdef __h1__
        LCD_WriteReg(0x003,0x1030);
    #else
        LCD_WriteReg(0x003,0x1000);
    #endif
#else
    #ifdef __h1__
        LCD_WriteReg(0x003,0x10a8);    //控制扫描方向
    #else
        LCD_WriteReg(0x003,0x1098);    //控制扫描方向
    #endif
#endif

其他的就按照你之前写的来做就行了,希望能帮到你
JZHG1992
3楼-- · 2019-08-23 22:48
回复【3楼】etkl:
给你2个我在用的函数,应对4个方向的#define LCD_WIDTH    320#define LCD_HEIGHT    240void LCD_CreatWindows(u16 sx,u16 sy,u16 width,u16 height){u16 ex = sx + width-1;u16 ey = sy + height-1;#ifdef vertical    #ifdef __h1__        LCD_WriteReg(R80,sx);        LCD_WriteReg(R81,ex);        LCD_WriteReg(R82,sy);        LCD_WriteReg(R83,ey);        LCD_WriteReg(R32,sx);        LCD_WriteReg(R33,sy);    #else        LCD_Wri
......
---------------------------------
呵呵! 谢谢啊,原子哥说的对,没必要花时间去研究这个了~~
Stone_up
4楼-- · 2019-08-24 00:06
楼主你好。我最近也在搞TFTLCD开窗口显示。
我做出来的和你的效果一样。我也移植了你的代码。在指定的窗口显示指定的颜 {MOD},达不到效果。所以你的开窗口显示貌似也有问题。不知道你实际达到效果没有。
JZHG1992
5楼-- · 2019-08-24 00:46
回复【5楼】Stone_up:
---------------------------------
呵呵!我的是重新取模的,用了两种字模数据,一种是原子哥的方式,另一种是下面方式,扫描方式自己看看楼上吧。。

就重取模:
// ------------------  常用ASCII表字模的数据表 ------------------ //
// 码表从0x20~0x7e  
// 取模软件:PCtoLCD2002                                          //
// 取模方式:阴码,逐列式,逆向,文字垂直翻转
// 大小:16*8 
// -------------------------------------------------------------- //
。。。。。。。数据
lansing1648
6楼-- · 2019-08-24 04:17
 精彩回答 2  元偷偷看……

一周热门 更多>