打印

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

[复制链接]
楼主: milkyway1888
手机看帖
扫描二维码
随时随地手机跟帖
21
VIP4会员| | 2011-5-25 09:03 | 只看该作者 回帖奖励 |倒序浏览
void DrawPixel(int iScrX, int iScrY, uint uiColor) 里面的:
pucColorTemp = (uchar *)&uiColor;不对吧。uiColor可以为寄存器变量,不能用指针。

使用特权

评论回复
22
milkyway1888|  楼主 | 2011-5-25 15:10 | 只看该作者
我定义了一个全局大数组:
          uchar EG_lcd_pucCurrentDispMem[153600];
在液晶初始化函数里进行了初始化:
        for(i=0;i<153600;i++)
        EG_lcd_pucCurrentDispMem[i]=0xFF;
效果还是一样啊。终止在刷一部分屏幕上。

使用特权

评论回复
23
milkyway1888|  楼主 | 2011-5-25 15:10 | 只看该作者
本帖最后由 milkyway1888 于 2011-5-25 15:20 编辑

把我的代码贴出来,兄弟们帮我分析一下,看看问题究竟出在哪里:

main.c
----------------------------------------
int main(ulong arc,void *argv)
{
char x=0;
// uint uiColor;
// uint i;
/* DevHandle hRS232Handle;
EA_ucOpenDevice("COM", EM_io_PORT1, &hRS232Handle);
EA_ucInitRS232(hRS232Handle, EM_232_115200BPS, EM_232_NOPAR, EM_232_8DBS);
EA_ucWriteDevice(hRS232Handle, 9, 1, "case RED\r\n");
EA_ucWriteDevice(hRS232Handle, 9, 1, "case YEL\r\n");
    while(1)
{  
  EA_ucWriteDevice(hRS232Handle, 13, 1, "Set To High\r\n");
  rPDATB|=(1<<10);
    for(i=0; i<0xFFFFF; i++);
  EA_ucWriteDevice(hRS232Handle, 13, 1, "Set To low \r\n");
       rPDATB&=~(1<<10);
    for(i=0; i<0xFFFFF; i++);
}
*/
EI_lcd_vInit0();
  while(1)
{
  switch(x)
  {
      case 0: Clear(RED); break;
   case 1: Clear(BLUE); break;
   case 2: Clear(YELLOW); break;
   case 3: Clear(GRAY); break;

   case 5: DrawHorizonLine(0,0x0001,0x00EF,0x0001, BLUE); break; //程序就卡死在这个位置
   case 6: DrawHorizonLine(0,0x0002,0x00EF,0x0002, BLUE); break;

   case 9: GLCD_Test();break;
  }         
     x++;
  if(x==10) x=0;
  Delayms(2000);
}

return 0;
}


/****************************************************************************
* 函数名称:Delayms(uint nCount)
* 功    能:实现毫秒级的延时操作,精度为10ms
* 入口参数:nCount-毫秒数
* 出口参数:无
****************************************************************************/
void Delayms(uint nCount)
{
volatile uint i;   
    for (i = 0; i < 5000*nCount; i++);
}
/*******************************************************************************
* 函数名称: DrawHorizonLine
*   
* 功能描述: 画横线
*
* 输入参数: uiBeginX    - 起始点横坐标(0~239)
*           uiBeginY    - 起始点纵坐标(0~319)
*           uiEndX      - 终止点横坐标(0~239)
*           uiEndY      - 终止点纵坐标(0~319)
*
*******************************************************************************/
void DrawHorizonLine(int iBeginX, int iBeginY,int iEndX,int iEndY, ushort uiColor)
{
    int curx,cury;  
    curx = (int)iBeginX;
    cury = (int)iBeginY;
uiColor&=0xFFFF;
EI_lcd_vDrawPixel0(curx,cury,uiColor);
    while(curx!=iEndX )
    {
        curx += 1;
  EI_lcd_vDrawPixel0(curx,cury,uiColor);      
    }
   
    // 更新显示
    EI_lcd_vUpdateDisplay();
}

---------------------------------------
调用lcd.c
----------------------------------------
/****************************************************************************
* 函数名称:Clear(ushort Color)
* 功    能: 直接清屏函数,不使用缓冲区
***************************************************************************/
void Clear(ushort Color)
{
uint index;
SetWindows(0x0000,0x0000,0x00EF,0x013F);
SetCursor(0x0000,0x0000);   
  WRITE_INDEX(0x22);
for(index=0;index<76800;index++)
{
  WRITE_DATA(Color);
}
}  

/**********************************************************************
* 函数名称: EI_lcd_vDrawPixel0
*   
* 功能描述: 将液晶上坐标点(iScrX,iScrY)的象素用uiColor填充
*   
***********************************************************************/
void EI_lcd_vDrawPixel0(int iScrX, int iScrY, ushort uiColor)
{
      if (iScrX >= EG_lcd_tViewPort.lLeft && iScrX <= EG_lcd_tViewPort.lRight &&
        iScrY >= EG_lcd_tViewPort.lTop  && iScrY <= EG_lcd_tViewPort.lBottom)
    {   
  EG_lcd_pucCurrentDispMem[(iScrY * EM_lcd_DotsPerLine + iScrX) * EM_lcd_BytePerPixel] = (uchar)(uiColor>>8);
  EG_lcd_pucCurrentDispMem[(iScrY * EM_lcd_DotsPerLine + iScrX) * EM_lcd_BytePerPixel + 1] = (uchar)(uiColor&0xff);
       }
}


/*******************************************************************************
* 函数名称: EI_lcd_vUpdateDisplay
*   
* 功能描述: 刷新显示
*
*******************************************************************************/
void EI_lcd_vUpdateDisplay(void)
{
    DevHandle hRS232Handle;
//输出串口调试信息
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);

//连续写入SPI
LCD_RESET;
EI_spi_vSendByte(DATA_WRITE);
for (j=0; j <76800; j++)
{
    EI_spi_vSendByte(EG_lcd_pucCurrentDispMem[j*2]);
    EI_spi_vSendByte(EG_lcd_pucCurrentDispMem[j*2+1]);
}

LCD_SET;

EA_ucWriteDevice(hRS232Handle, 16, 1, "LCD Update end!\r\n");
EA_ucCloseDevice(&hRS232Handle);
}

使用特权

评论回复
24
wangkj| | 2011-5-25 15:47 | 只看该作者
for(i=0;i<153600;i++)
        EG_lcd_pucCurrentDispMem[i]=(i%9)+' ';

for (j=0; j <76800; j++)
{
    EI_spi_vSendByte(EG_lcd_pucCurrentDispMem[j*2]);
    put_ch_serial(EG_lcd_pucCurrentDispMem[j*2]);
    EI_spi_vSendByte(EG_lcd_pucCurrentDispMem[j*2+1]);
    put_ch_serial(EG_lcd_pucCurrentDispMem[j*2+1]);}
}

还有,你的spi原型呢?或许是spi子函数出问题了呢。

使用特权

评论回复
25
milkyway1888|  楼主 | 2011-5-25 17:17 | 只看该作者
本帖最后由 milkyway1888 于 2011-5-25 17:32 编辑

谢谢wangkj! 根据你的建议,我修改了大数组的初始化以及在SPI循环里加了调试信息,还是无法刷全屏。

以下我的SPI写数据函数:
void EI_spi_vSendByte(uchar ucData)
{
    rSIODAT = ucData;
    rSIOCON |= (1 << 3);
    while((rINTPND & BIT_SIO) == 0);
    rI_ISPC = BIT_SIO;
}


另外,上面的EI_lcd_vUpdateDisplay(void)函数里给LCD_SPI写入数据的方式是把LCD_CS置低,把所有数据一次性写入SPI,然后再把CS置高。
如果在写数据中间加调试信息,不是把时序搞乱了吗?

使用特权

评论回复
26
wangkj| | 2011-5-25 17:21 | 只看该作者
没关系啊。

使用特权

评论回复
27
wangkj| | 2011-5-25 17:22 | 只看该作者
cs 和串口没关系。

使用特权

评论回复
28
wangkj| | 2011-5-25 17:22 | 只看该作者
while((rINTPND & BIT_SIO) == 0); 没准就是这句出错了

使用特权

评论回复
29
wangkj| | 2011-5-25 17:22 | 只看该作者
价格超时退出吧。

使用特权

评论回复
30
wangkj| | 2011-5-25 17:23 | 只看该作者
你没调试器啊?用调试器单步跟踪啊。

使用特权

评论回复
31
milkyway1888|  楼主 | 2011-5-25 17:35 | 只看该作者
我又用另一种方式实现SPI写数据(每次写16位):

void R61580_WRITE_DATA(ushort dat)
{
        ushort data = dat;
        R61580_LCD_RESET;  //片选 低有效
        EI_spi_vSendByte(R61580_DATA_WRITE);
        EI_spi_vSendByte((uchar)(data>>8)); //先写高8位再写低8位
        EI_spi_vSendByte((uchar)(data&0xff));
        R61580_LCD_SET;
}

然后把刷新函数EI_lcd_vUpdateDisplay(void)里头也改了:

        for (j=0; j <76800; j++)
        {
                datatemp=(ushort)(EG_lcd_pucCurrentDispMem[j*2]>>8) + (ushort)(EG_lcd_pucCurrentDispMem[j*2+1]); //8bit--->16bit
                R61580_WRITE_DATA(datatemp);
                EA_vUartPrintf("DrawPixel:%x\r\n",datatemp);

        }

但还是一样不能刷全屏。

使用特权

评论回复
32
wangkj| | 2011-5-25 20:05 | 只看该作者
28楼注意看。

使用特权

评论回复
33
delin17| | 2011-5-26 09:29 | 只看该作者
pucCurrentDispMem = &EG_lcd_pucCurrentDispMem[(iScrY * EM_lcd_DotsPerLine + iScrX)*EM_lcd_BytePerPixel];
     
  pucCurrentDispMem[0] = pucColorTemp[0];   
  pucCurrentDispMem[1] = pucColorTemp[1];

这个为什么搞这么复杂呢,直接用U16不行嘛?

使用特权

评论回复
34
milkyway1888|  楼主 | 2011-5-26 11:08 | 只看该作者
28# wangkj

这句意图是:等待数据发送结束。

#define rINTPND     (*(volatile ulong *)0x1e00004)
#define BIT_SIO      (ulong)(0x10)

使用特权

评论回复
35
milkyway1888|  楼主 | 2011-5-26 11:10 | 只看该作者
33# delin17
因为一次SPI操作是8位的数据。

使用特权

评论回复
36
wangkj| | 2011-5-26 12:22 | 只看该作者
我 知道,有可能会出错。就是一直没结束的意思。就死机了。

使用特权

评论回复
37
milkyway1888|  楼主 | 2011-5-26 13:47 | 只看该作者
36# wangkj

那怎么改比较好?

使用特权

评论回复
38
wangkj| | 2011-5-26 13:49 | 只看该作者
用软件模拟spi先,搞定了再改成硬件的。
你这种写法,软件模拟的没准更快。

使用特权

评论回复
39
milkyway1888|  楼主 | 2011-5-26 13:59 | 只看该作者
本帖最后由 milkyway1888 于 2011-5-26 14:21 编辑

硬件上改成GPIO模拟SPI不好动啊,我的液晶屏和硬件平台之间改连接线比较麻烦。

使用特权

评论回复
40
英雄无敌六| | 2011-5-26 16:14 | 只看该作者
给你一个例子

初始化SPI:
        rGPGDAT |= (1<<3);                //CS
        rGPGCON |= (0x01<<6);
                       
        //打开SPI1为主机查询模式
        rSPCON1 = (0x0<<5) | (1<<4) | (1<<3) | (0<<2) | (0<<1);
        rSPPRE1 = PLL_GetPClk() / (1000*2);                //2M
        rGPGCON |= (0x3<<10) | (0x3<<12) | (0x3<<14);        //SCK1, MOSI1, MISO1


发送数据:
        rGPGDAT &= ~(1<<3);        //CS=0

        rSPTDAT1 = data;
        while( !(rSPSTA1 & (1<<0)) );

        rGPGDAT |= (1<<3);                //CS=1

使用特权

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

本版积分规则