打印

44b0平台驱动TFT液晶,写显示缓冲区时遇到问题

[复制链接]
5444|50
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
milkyway1888|  楼主 | 2011-5-7 17:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
所用液晶:240*320 TFT彩屏
  处理器: S3C44B0
  液晶和处理器传输数据的接口为SPI,液晶初始化和直接写GRAM刷全屏没问题了。但是我想通过开缓冲区的方式写屏却有问题,一直找不到原因,请各位帮忙分析一下。
  我的思路是调用一个描点函数DrawPixel和一个刷新函数UpdateDisplay 在屏上画线来验证这两个函数的正确性。
  现象:执行了刷白屏后,屏幕右上角局部显示朱红色(与LCD初始化函数memset设置的颜色0xF8一致),然后设备就死机了。
  我在刷新函数中添加串口调试信息,串口只输出了一次:LCD Update set! 难道刷新函数运行至“// 在变化区域写入显示数据”之前的位置就卡死了?是不是我刷新函数的代码有问题?

  下面是我写的描点函数和刷新函数的代码:
   /**********************************************************************
* 函数名称: DrawPixel0
*   
* 功能描述: 将液晶上坐标点(iScrX,iScrY)的象素用uiColor填充
*
* 输入参数: iScrX - 横坐标值
* iScrY - 纵坐标值
* uiColor - 要填充的颜色
***********************************************************************/
void DrawPixel(int iScrX, int iScrY, uint uiColor)
{

uchar *pucCurrentDispMem, *pucColorTemp;
uiColor&=0xFFFF;
  if (iScrX >= EG_lcd_tViewPort.lLeft && iScrX <= EG_lcd_tViewPort.lRight &&
  iScrY >= EG_lcd_tViewPort.lTop && iScrY <= EG_lcd_tViewPort.lBottom)
  {

  pucColorTemp = (uchar *)&uiColor;
  pucCurrentDispMem = &EG_lcd_pucCurrentDispMem[(iScrY * EM_lcd_DotsPerLine + iScrX)*EM_lcd_BytePerPixel];
     
  pucCurrentDispMem[0] = pucColorTemp[0];   
  pucCurrentDispMem[1] = pucColorTemp[1];
     
  }
}

/*******************************************************************************
* 函数名称: UpdateDisplay
*   
* 功能描述: 刷新显示
*   
*******************************************************************************/

void UpdateDisplay(void)
{  
  uchar *pucCurrentDispMem;
  ushort datatemp;
  uint j;

  pucCurrentDispMem = EG_lcd_pucCurrentDispMem;

  WriteRS232(hRS232Handle, 16, 1, "LCD Update set!\r\n"); // 串口调试信息输出
  SetWindows(0x0000,0x0000,0x00EF,0x013F);
  SetCursor(0x0000,0x0000);   

  // 在变化区域写入显示数据   
  WRITE_INDEX(0x22);
  for (j=0; j <76800; j++)
  {
  // 写数据
datatemp=((ushort)(*pucCurrentDispMem++)) + (((ushort)(*pucCurrentDispMem++))<<8);
WRITE_DATA(datatemp);
     
  }

}
 

相关帖子

沙发
huanben| | 2011-5-7 22:47 | 只看该作者
你好 你的屏是什么驱动的?

使用特权

评论回复
板凳
milkyway1888|  楼主 | 2011-5-8 09:45 | 只看该作者
44B0的SPI接到液晶控制器的SPI接口来驱动

使用特权

评论回复
地板
milkyway1888|  楼主 | 2011-5-15 14:06 | 只看该作者
没有人做过类似的开发吗?
目前我定位了程序卡死在刷新函数的FOR循环内部。但还没有找到原因。

void UpdateDisplay(void)
{
  DevHandle hRS232Handle;
uchar *pucCurrentDispMem;
ushort datatemp;
  uint j;

  pucCurrentDispMem = EG_lcd_pucCurrentDispMem;

//输出串口调试信息
EA_ucOpenDevice("COM", EM_io_PORT1, &hRS232Handle);
EA_ucInitRS232(hRS232Handle, EM_232_115200BPS, EM_232_NOPAR, EM_232_8DBS);
EA_ucWriteDevice(hRS232Handle, 16, 1, "LCD Update set!\r\n");

SetWindows(0x0000,0x0000,0x00EF,0x013F);
SetCursor(0x0000,0x0000);  
WRITE_INDEX(0x22);
  for (j=0; j <76800; j++)
  {  
  datatemp=((ushort)(*pucCurrentDispMem++)) + (((ushort)(*pucCurrentDispMem))<<8); //2个8bit--->16bit
pucCurrentDispMem++;
WRITE_DATA(datatemp);  
EA_ucWriteDevice(hRS232Handle, 7, 1, "Update\r\n"); // 程序卡死在此位置
}
EA_ucWriteDevice(hRS232Handle, 16, 1, "LCD Update end!\r\n");
EA_ucCloseDevice(&hRS232Handle);
}

程序卡死在 for 循环从显示缓存把数据刷新到LCD屏的过程中,实验时发现下面这句的标红色字体部分如果长度不同,卡死的位置也有所差异。但程序一定卡死在这个for循环内部。
EA_ucWriteDevice(hRS232Handle, 7, 1, "???\r\n");

使用特权

评论回复
5
milkyway1888|  楼主 | 2011-5-18 10:00 | 只看该作者
在for 循环里面delay一毫秒,程序是可以正常运行的,但是这样的话,刷新整个LCD需要76.8秒,根本无法满足应用要求。
  还尝试过把for 循环的次数减小(如720次),不用加延时,程序也可以正常运行的, 但循环次数达不到76800次,就无法刷新整个屏幕。
  for (j=0; j <720; j++)
  {   
  datatemp=((ushort)(*pucCurrentDispMem++)) + (((ushort)(*pucCurrentDispMem))<<8);   
  pucCurrentDispMem++;
  WRITE_DATA(datatemp);   
  }
   
  但一旦把for循环的次数增加,程序就会死在循环里,LCD卡死在刷新一部分屏幕,示波器也没有数据输出。

使用特权

评论回复
6
huanben| | 2011-5-18 14:17 | 只看该作者
你好 你的驱动是什么?有用过IO驱动吗 或者直接总线驱动?

使用特权

评论回复
7
milkyway1888|  楼主 | 2011-5-18 16:40 | 只看该作者
CPU的SPI接到LCD的SPI上驱动

使用特权

评论回复
8
milkyway1888|  楼主 | 2011-5-20 15:22 | 只看该作者
坛子里有没有用44B0挂SPI玩过彩屏的兄弟啊?出来吼一声

使用特权

评论回复
9
wangkj| | 2011-5-21 08:06 | 只看该作者
1:估计是屏的spi硬件问题,spi被干扰没对齐。一位错全错。然后内部逻辑整个乱掉了。
原来我做的那个屏也有这个问题,后来,我在硬件逻辑上加了矫正才解决的。

2 也可能是软件问题,检测这个办法很简单,连续输入同样的数据,别用内存。如果这个没问题,说明你的内存管理那块问题。如果有问题,换算法但最好换屏,有硬件缺陷就是陷阱。

3 spi的屏,硬件逻辑做不好,很不好玩。

使用特权

评论回复
10
milkyway1888|  楼主 | 2011-5-23 09:54 | 只看该作者
1. 我不使用缓存,直接把数据写到LCD的GRAAM的方式(直接给0x22写数据),是可以刷整个屏幕的。这是否说明SPI的时序和硬件没问题?
2. wangkj你说的内存管理那块问题是指什么?我在液晶初始化函数里开辟的显示缓存大小为EG_lcd_uiMemerySize = 76800*2 字节,缓存大小应该足够大了吧?相关代码如下:
--------------------------------------------------------
// 设置当前显示缓冲
  EG_lcd_uiMemerySize = (EM_lcd_XSIZE0 * EM_lcd_YSIZE0 * EM_lcd_PIXELSIZE0) >> 3;
  EG_lcd_pucCurrentDispMem = (uchar *)EA_pvMalloc(EG_lcd_uiMemerySize);   
  EG_lcd_pucHalMem = (uchar *)EA_pvMalloc(EG_lcd_uiMemerySize);  
// 缓存初始化,在于能够首次全屏刷新
  memset(EG_lcd_pucCurrentDispMem, 0xF8, EG_lcd_uiMemerySize);
  memset(EG_lcd_pucHalMem, 0xFF, EG_lcd_uiMemerySize);

3.. 我用示波器看液晶的 CS\SDI\SCL 信号都是正确的。这是否也可以证明SPI硬件和时序正确?

4. 我现在的问题就卡在一旦想通过“写缓冲区DrawPixel+刷新UpdateDisplay”的方式写屏,就会卡死在刷新的for循环函数里。是说我那两个函数对缓存的操作有什么问题么?

一直找不到问题的根源,还请各位大侠不吝指教。谢谢!

使用特权

评论回复
11
wangkj| | 2011-5-23 22:28 | 只看该作者
弄个大数组,别用mem管理,有时候,系统的mem管理会出问题。

使用特权

评论回复
12
wangkj| | 2011-5-23 22:29 | 只看该作者
严重怀疑内存管理问题。大数组弄个全局的。

使用特权

评论回复
13
wangkj| | 2011-5-23 22:30 | 只看该作者
先试试看。

使用特权

评论回复
14
milkyway1888|  楼主 | 2011-5-24 09:31 | 只看该作者
本帖最后由 milkyway1888 于 2011-5-24 09:38 编辑

谢谢wangkj!
我在lcd.c 的开头定义了缓冲区数组:
uchar EG_lcd_pucCurrentDispMem[153600]; //当前显示缓存

但程序还是卡死在UpdateDisplay(void) 的for里头。
我如果把for 循环的次数减小(如1200次),程序运行正常。和使用malloc的现象相同。

使用特权

评论回复
15
wangkj| | 2011-5-24 13:22 | 只看该作者
再数组中,写入数据,从0到长度。
然后向lcd发送,死机后,用示波器看。
如果示波器上spck和数据线正常,说明lcd有问题。

如果没数据,说明是arm的软件或者硬件问题。
还有就是降低发送速度,用软件模拟spi试试,这样能控制发送速度。

现在的问题是:lcd问题,arm软件问题,arm硬件问题。通过上面的3中办法,就能分清到底是那个问题。

使用特权

评论回复
16
milkyway1888|  楼主 | 2011-5-24 13:43 | 只看该作者
死机的表现是:LCD刷了最上面的几行屏,示波器没数据了。
SPI的速度我调高或者调低影响不大,速度高时死机时刷新的屏会多几行。
搞得我把那两个设计缓存操作的函数看了又看,不知道是不是C语言功力太差,哪儿搞错了。实在郁闷。

使用特权

评论回复
17
wangkj| | 2011-5-24 14:13 | 只看该作者
那肯定是单片机死机了,如果有调试器,看看死哪里了。

如果没调试器,只能打printf了。

别用指针,反复刷大数组中的数据出去。
就做一个循环。越简单越好。

使用特权

评论回复
18
milkyway1888|  楼主 | 2011-5-24 15:09 | 只看该作者
我在刷新函数的for循环中加入串口调试(输出4字节):         
EA_ucWriteDevice(hRS232Handle, 4, 1, "Upd\r\n");
数了数串口输出的数据个数,卡死在第55804次。

当然,如果我加入的串口调试信息不是输出4字节,比如改为12个字节的调试信息:
EA_ucWriteDevice(hRS232Handle, 12, 1, "LCD Update+\r\n");
卡死在第4205次。

这是何解?

使用特权

评论回复
19
wangkj| | 2011-5-25 08:41 | 只看该作者
循环直接输出字符数组中的数据到屏就行。看看效果

使用特权

评论回复
20
wangkj| | 2011-5-25 08:42 | 只看该作者
算法别搞那么多,越简单越好。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

28

帖子

0

粉丝