代码改变世界

进阶新的阶段--LCD

2015-09-20 11:40  1784717631  阅读(271)  评论(0编辑  收藏  举报

  lcd终于可以装上逼格满满的屏幕,满心欢喜,结果开始就大面积黑屏,原来是部分新的板子烧写了旧的superboot,重新烧写新的之后问题解决。

  lcd的显示原理是由点到线,线到面不断扫描的原理,具体设计到的上下左右边距的时序相关资料有,这里就不再赘述了。这里要说的是相关配置的思路,

  首先要使寄存器工作,当然是看lcd与芯片的硬件接口了,配置相关的引脚,

  其次,lcd通过接口与芯片相连之后,当然是要配置lcd的控制器寄存器、时序的控制寄存器、窗口的控制寄存器,一定要区分这三者的区别,区分好之后只要一步步配置就会发现让lcd简单的工作起来并不似那么复杂

  最后,配置窗口的上下左右边距和图片的尺寸大小,还有要指明图片缓存去的地址,这个是指定的,最后 使能channel 0传输数据

   相关代码如下,相关寄存器就不贴出来了,芯片手册很容易找到,这里只放重点

void  lcd_init(void)
{
// 配置引脚用于LCD功能
GPF0CON = 0x22222222; //4 //4--7
GPF1CON = 0x22222222; // 0 --7
GPF2CON = 0x22222222; // 0--7
GPF3CON = 0x22222222; //0--3

// 打开背光
GPD0CON &= ~(0xf<<4);
GPD0CON |= (1<<4); //输出模式??? (1<<5)

GPD0DAT |= (1<<1); //????输出高电平,打开背光

// 10: RGB=FIMD I80=FIMD ITU=FIMD 设置数据输出路径
DISPLAY_CONTROL = 2<<0;

// bit[26~28]:使用RGB接口 000
// bit[18]:RGB 并行 0
// bit[2]:选择时钟源为HCLK_DSYS=166MHz 0
VIDCON0 &= ~( (3<<26)|(1<<18)|(1<<2) );

// bit[1]:使能lcd控制器
// bit[0]:当前帧结束后使能lcd控制器
VIDCON0 |= ( (1<<0)|(1<<1) );

// bit[4]:选择需要分频
// bit[6~13]:分频系数为15 ???,即VCLK = 166M/(14+1) = 11M
VIDCON0 |= 5<<6 | 1<<4;


// H43-HSD043I9W1.pdf(p13) 时序图:VSYNC和HSYNC都是低脉冲
// s5pv210芯片手册(p1207) 时序图:VSYNC和HSYNC都是高脉冲有效,所以需要反转
VIDCON1 |= 1<<5 | 1<<6;

// 设置时序p1207 p13
VIDTCON0 = VBPD<<16 | VFPD<<8 | VSPW<<0;
VIDTCON1 = HBPD<<16 | HFPD<<8 | HSPW<<0;
// 设置长宽
VIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0);

// 设置windows 0
// bit[0]:使能 1
// bit[2~5]:24bpp 1011
WINCON0 |= 1<<0;
WINCON0 &= ~(0xf << 2); //清2--5
WINCON0 |= (0xB<<2) | (1<<15); // 24 位

#define LeftTopX 0
#define LeftTopY 0
#define RightBotX 799
#define RightBotY 479

// 设置windows1的上下左右
VIDOSD0A = (LeftTopX<<11) | (LeftTopY << 0);
VIDOSD0B = (RightBotX<<11) | (RightBotY << 0);
//the Window Size
VIDOSD0C = (LINEVAL + 1) * (HOZVAL + 1);


// 设置fb的地址
VIDW00ADD0B0 = FB_ADDR;
VIDW00ADD1B0 = (((HOZVAL + 1)*4 + 0) * (LINEVAL + 1)) & (0xffffff);//长度

// 使能channel 0传输数据
SHADOWCON = 0x1;
}

 

lcd配置完成就可以开始工作了,然后就可以优雅的画图了哈哈

// 画图
void lcd_draw_bmp(const unsigned char gImage_bmp[])
{
  int i, j;
  unsigned char *p = (unsigned char *)gImage_bmp;
  int blue, green, red;
  int color;
  // 图片大小480x270像素
  for (i = 0; i < 480; i++)
  for (j = 0; j < 800; j++)
  {
    blue = *p++;
    green = *p++;
    red = *p++;

    color = red << 16 | green << 8 | blue << 0;
    lcd_draw_pixel(i, j, color);
  }
}

// 清屏 清屏会产生黑屏(0x0),所以后面做打地鼠的时候把清屏关掉
void lcd_clear_screen(int color)
{
  int i, j;

  for (i = 0; i < ROW; i++)
    for (j = 0; j < COL; j++)
      lcd_draw_pixel(i, j, color);

}

下面相关形状的画法

 

// 描点
void lcd_draw_pixel(int row, int col, int color)
{
  unsigned long * pixel = (unsigned long *)FB_ADDR;

  *(pixel + row * COL + col) = color;

}

 

// 划横线
void lcd_draw_hline(int row, int col1, int col2, int color)
{
  int j;

  // 描第row行,第j列
  for (j = col1; j <= col2; j++)
  lcd_draw_pixel(row, j, color);

}

 

// 划竖线
void lcd_draw_vline(int col, int row1, int row2, int color)
{
  int i;
  // 描第i行,第col列
  for (i = row1; i <= row2; i++)
  lcd_draw_pixel(i, col, color);

}

 

// 划十字
void lcd_draw_cross(int row, int col, int halflen, int color)
{
  lcd_draw_hline(row, col-halflen, col+halflen, color);
  lcd_draw_vline(col, row-halflen, row+halflen, color);
}

 

 

// 画字符
void lcd_draw_char(unsigned char c)
{
  // 必须是静态变量
  static int x = 0; // 第几列
  static int y = 0; // 第几行

  int i,j;
  unsigned char line_dots;

  // 获得字模
  unsigned char *char_dots = (unsigned char *) (fontdata_8x16 + c * 16);


  // 是否需要回车换行
  if (c == '\n')
  {
    y += 16;
    if (y > ROW)
    y = 0;
    return ;
  }
  else if (c == '\r')
  {
    x = 0;
    return;
  }

  for (i = 0; i < 16; i++)
  {
    line_dots = char_dots[i];
    for (j = 0; j < 8; j++)
    {
      // 为1,则描蓝点
      if (line_dots & (0x80 >> j))
      {
        lcd_draw_pixel(y+i, x+j, 0xff);
      }  
  }
}

// 光标移动到下一个8*16的位置
x += 8;
if (x > COL)
{
  x = 0;
  y += 16;
  if (y > ROW)
  y = 0;
}
}