进阶新的阶段--LCD
2015-09-20 11:40 1784717631 阅读(272) 评论(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;
}
}