嵌入式学习-uboot-lesson14-LCD相关
2016-07-12 09:27
274 查看
关于LCD的相关知识在这里就不再说了,下面就直接开始对LCD进行编程分析。
根据上面两幅图可以得知,
1.LCD的VD[0:23]一共24个引脚,接在GPI[0:15],GPJ[0:7] 这24个IO口上,
2.GPJ[8:11]分别接LCD的:
GPJ8—-HSYNC:行(水平方向)同步信号
GPJ9—-VSYNC:场(垂直方向)同步信号
GPJ10—VDEN:video data enable 视频输入使能端
GPJ11—VCLK :像素之间时钟信号
因此需要对这些引脚进行配置,使之满足我们的需求。
第二步和第三步的全部过程在上面两幅图中全部标了出来,下面我们只需根据上面的步骤进行编程即可
根据上图需要将GPI寄存器的所有引脚配置为0b10模式
即:
根据上面两幅图,可知需要将GPJ[0:15] 和GPJ[16:23]都设置为ob10
即:
其中时钟源选择HCLK为133MHZ
VCLK=视频时钟源/(CLKVAL+1) 其中。根据4.3寸屏的手册,VCLK的典型值为9MHZ,经过计算,得CLKVAL大约等于14
根据上面的几幅图,可以得出时序图:
5.4 VFPD
vfpd+1=tvf=2 vfpd=1
综合上面,即:
VIDOSD0A:窗口 0 位置控制 A 寄存器
左上角X,Y坐标
VIDOSD0B:窗口 0 位置控制 B 寄存器
右下角XY坐标
VIDOSD0C:窗口 0 位置控制 C 寄存器
行数列数(1个像素24位,但是占据32位,即4个字节)
同时,单位为word 所以为272*480
VIDW00ADD0B0 窗口 0 的缓冲区开始地址控制寄存器,缓冲区 0
存放FRAME_BUFFER的基地址
VIDW00ADD0B1 窗口 0 的缓冲区开始地址控制寄存器,缓冲区 1
VBASEL=VBASEU+(PAGEWIDTH+OFFSIZE)*(LINEVAL+1)=0+(480*4+0)*272
OFFSIZE:偏移值 从0开始
通过以上步骤即可实现了LCD的初始化,下面将对其进行测试,观察是否出现正确的图像。
在显示图片之前,需要先将屏幕清一下(可不做)
然后可以在屏幕上进行划线,或者将某个区域填充为纯色,具体代码如下
随后,便可以将图片显示在LCD上
贴上图片:
稍后
贴上主要代码:
菜鸟一枚,如有错误,多多指教。。。
一、硬件结构
根据上面两幅图可以得知,
1.LCD的VD[0:23]一共24个引脚,接在GPI[0:15],GPJ[0:7] 这24个IO口上,
2.GPJ[8:11]分别接LCD的:
GPJ8—-HSYNC:行(水平方向)同步信号
GPJ9—-VSYNC:场(垂直方向)同步信号
GPJ10—VDEN:video data enable 视频输入使能端
GPJ11—VCLK :像素之间时钟信号
因此需要对这些引脚进行配置,使之满足我们的需求。
二、编程流程
根据第一步,我们首先需要做的工作是:1).配置引脚
同时,我们还需要对LCD的时序进行配置2).设置LCD时序值
同时,还需要对在内存中专门开辟出来的framebuffer,进行初始化3).帧缓存初始化
第二步和第三步的全部过程在上面两幅图中全部标了出来,下面我们只需根据上面的步骤进行编程即可
三、编程实现
1).配置引脚
根据上图需要将GPI寄存器的所有引脚配置为0b10模式
即:
#define GPICON (*((volatile unsigned long*)0x7F008100)) //端口I 配置寄存器 GPICON = 0xaaaaaaaa; //16个引脚都配置为0b10
根据上面两幅图,可知需要将GPJ[0:15] 和GPJ[16:23]都设置为ob10
即:
#define GPJCON (*((volatile unsigned long*)0x7F008120)) //端口J 配置寄存器 GPJCON = 0xaaaaaa;
2).设置LCD时序值和帧缓存初始化
1.MIFPCON 的第三位SEL_BYPASS为0(正常模式)
根据前面的步骤流程图可知,需要将其第三位设为0即可#define MOFPCON (*((volatile unsigned long*)0x7410800C)) //调制解调器接口控制寄存器 MOFPCON = 0<<3;
2.SPCON的LCD_SEL[1:0]位设置为01,表示使用 RGB I/F 类型
根据上面的步骤流程图,需要将SPCON的[1:0]位设置为0b01即可#define SPCON (*((volatile unsigned long*)0x7F0081A0)) //特殊端口控制寄存器 SPCON &= ~(0x3); SPCON |= 0x01;
3.VIDCON0:配置视频输出格式和显示使能/禁止
#define VIDCON0 (*((volatile unsigned long*)0x77100000)) //视频控制0 寄存器 VIDCON0 &= ~((0x3<<26)| (0x3<<17) | (0x1<<16) | (0x3<<2)|(0<<5));
其中时钟源选择HCLK为133MHZ
VCLK=视频时钟源/(CLKVAL+1) 其中。根据4.3寸屏的手册,VCLK的典型值为9MHZ,经过计算,得CLKVAL大约等于14
VIDCON0 |= ((14<<6) | (1<<4)|(3<<0));
4VIDCON1 RGB控制信号
根据时序图,在VCLK的下降沿得到数据#define VIDCON1 (*((volatile unsigned long*)0x77100004)) //视频控制1 寄存器 VIDCON1 &= ~(1<<7); VIDCON1 |= ((1<<6) | (1<<5));
5VIDTCONx视频时序控制寄存器
根据上面的几幅图,可以得出时序图:
5.1 VSPW
vspw+1=tvp=10 vspw=9#define VSPW 9
5.2 VBPD
vbpd+1=tvb=2 vbpd=1#define VBPD 1
5.3 LINEVAL
一共有272行,272-1=271#define LINEVAL 272-1
5.4 VFPD
vfpd+1=tvf=2 vfpd=1
#define VFPD 1
5.5 HSPW
hspw+1=thp=41 hspw=40#define HSPW 40
5.6 HBPD
hbpd+1=thb=2 hbpd=1#define HBPD 1
5.7 HOZVAL
480-1=479#define HOZVAL 480-1
5.8 HFPD
hfpd+1=thf=2 hfpd=1#define HFPD 1
综合上面,即:
#define VSPW 9 #define VBPD 1 #define LINEVAL 272-1 #define VFPD 1 #define HSPW 40 #define HBPD 1 #define HOZVAL 480-1 #define HFPD 1 #define VIDTCON0 (*((volatile unsigned long*)0x77100010)) //视频时序控制0寄存器 #define VIDTCON1 (*((volatile unsigned long*)0x77100014)) //视频时序控制1寄存器 #define VIDTCON2 (*((volatile unsigned long*)0x77100018)) //视频时序控制2寄存器 VIDTCON0 = (VBPD << 16) | (VFPD << 8) | (VSPW << 0); VIDTCON1 = (HBPD << 16) | (HFPD << 8) | (HSPW << 0); VIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0);
6WINCON0 窗口0控制寄存器
#define WINCON0 (*((volatile unsigned long*)0x77100020)) //窗口0 控制寄存器 WINCON0 &= ~(0xf << 2); WINCON0 |= (0xb<<2); WINCON0 = (1<<16)|(0xb<<2)|(1<<0);
7
VIDOSD0A:窗口 0 位置控制 A 寄存器
左上角X,Y坐标
VIDOSD0B:窗口 0 位置控制 B 寄存器
右下角XY坐标
VIDOSD0C:窗口 0 位置控制 C 寄存器
行数列数(1个像素24位,但是占据32位,即4个字节)
同时,单位为word 所以为272*480
#define VIDOSD0A (*((volatile unsigned long*)0x77100040)) //视频窗口0 的位置控制寄存器 #define VIDOSD0B (*((volatile unsigned long*)0x77100044)) //视频窗口0 的位置控制寄存器 #define VIDOSD0C (*((volatile unsigned long*)0x77100048)) //视频窗口0 的位置控制寄存器 #define LeftTopX 0 #define LeftTopY 0 #define RightBotX 479 #define RigntBotY 271 VIDOSD0A = (LeftTopX<<11) |(LeftTopY<<0); VIDOSD0B = (RightBotX<<11)|(RigntBotY<<0); VIDOSD0C = (LINEVAL+1)*(HOZVAL+1);
8
VIDW00ADD0B0 窗口 0 的缓冲区开始地址控制寄存器,缓冲区 0
存放FRAME_BUFFER的基地址
VIDW00ADD0B1 窗口 0 的缓冲区开始地址控制寄存器,缓冲区 1
VBASEL=VBASEU+(PAGEWIDTH+OFFSIZE)*(LINEVAL+1)=0+(480*4+0)*272
OFFSIZE:偏移值 从0开始
#define FRAME_BUFFER 0x54000000 #define VIDW00ADD0B0 (*((volatile unsigned long*)0x771000A0)) //窗口 0 的缓冲区开始地址控制寄存器,缓冲区 0 #define VIDW00ADD1B0 (*((volatile unsigned long*)0x771000D0)) //窗口 0 的缓冲区开始地址控制寄存器,缓冲区 1 VIDW00ADD0B0 = FRAME_BUFFER; VIDW00ADD1B0 = (FRAME_BUFFER+((HOZVAL+1)*4+0)*(LINEVAL+1))&(0xffffff);
通过以上步骤即可实现了LCD的初始化,下面将对其进行测试,观察是否出现正确的图像。
四、测试
这次主要的测试是通过在显示屏上显示一副图片来完成的,在显示图片之前,需要先将屏幕清一下(可不做)
void lcd_clear() { int x,y,color; for(x=0;x<272;x++) for(y=0;y<480;y++) point(x,y,0xFFFfff); //WIN0MAP = (1<<24)|(color&0xffffff); }
然后可以在屏幕上进行划线,或者将某个区域填充为纯色,具体代码如下
//划横线 -> 描第201行,第y列 for(y=100;y<380;y++) point(210,y,0xFF0000);
随后,便可以将图片显示在LCD上
//x0,y0,x(高度),y(宽度) 272*480 Paint_Bmp(0,0,272,480,bmp); void Paint_Bmp(U16 x0,U16 y0,U16 x,U16 y,const unsigned char gImage_bmp[]) { int i, j; unsigned char *p = (unsigned char *)gImage_bmp; int blue, green, red; int color; // 图片大小200x200像素 for (i = x0 ; i < x0 +x; i++) for (j = y0; j < y0 + y; j++) { blue = *p++; green = *p++; red = *p++; // D[23:16] = Red data, D[15:8] = Green data,D[7:0] = Blue data color = (red << 16)| (green << 8)|( blue << 0); point(i, j, color); } }
贴上图片:
稍后
贴上主要代码:
/******************************************** *file name: lcd.c *author : stone *date : 2016.7.11 *function : lcd的初始化及测试 *********************************************/ #define GPICON (*((volatile unsigned long*)0x7F008100)) //端口I 配置寄存器 #define GPJCON (*((volatile unsigned long*)0x7F008120)) //端口J 配置寄存器 #define MOFPCON (*((volatile unsigned long*)0x7410800C)) //调制解调器接口控制寄存器 #define SPCON (*((volatile unsigned long*)0x7F0081A0)) //特殊端口控制寄存器 #define VIDCON0 (*((volatile unsigned long*)0x77100000)) //视频控制0寄存器 #define VIDCON1 (*((volatile unsigned long*)0x77100004)) //视频控制1寄存器 #define VIDTCON0 (*((volatile unsigned long*)0x77100010)) //视频时序控制0寄存器 #define VIDTCON1 (*((volatile unsigned long*)0x77100014)) //视频时序控制1寄存器 #define VIDTCON2 (*((volatile unsigned long*)0x77100018)) //视频时序控制2寄存器 #define WINCON0 (*((volatile unsigned long*)0x77100020)) //窗口0 控制寄存器 #define VIDOSD0A (*((volatile unsigned long*)0x77100040)) //视频窗口0 的位置控制寄存器 #define VIDOSD0B (*((volatile unsigned long*)0x77100044)) //视频窗口0 的位置控制寄存器 #define VIDOSD0C (*((volatile unsigned long*)0x77100048)) //视频窗口0 的位置控制寄存器 #define VIDW00ADD0B0 (*((volatile unsigned long*)0x771000A0)) //窗口 0 的缓冲区开始地址控制寄存器,缓冲区 0 #define VIDW00ADD1B0 (*((volatile unsigned long*)0x771000D0)) //窗口 0 的缓冲区开始地址控制寄存器,缓冲区 1 #define WIN0MAP (*((volatile unsigned long*)0x77100180)) #define VSPW 9 #define VBPD 1 #define LINEVAL 272-1 #define VFPD 1 #define HSPW 40 #define HBPD 1 #define HOZVAL 480-1 #define HFPD 1 #define LeftTopX 0 #define LeftTopY 0 #define RightBotX 479 #define RigntBotY 271 #define FRAME_BUFFER 0x54000000 extern unsigned char bmp[391680]; typedef unsigned short U16; void lcd_port_init() { GPICON = 0xaaaaaaaa; //16个引脚都配置为0b10 GPJCON = 0xaaaaaa; } void lcd_config_init() { MOFPCON = 0<<3; SPCON &= ~(0x3); SPCON |= 0x01; VIDCON0 &= ~((0x3<<26)| (0x3<<17) | (0x1<<16) | (0x3<<2)|(0<<5)); VIDCON0 |= ((14<<6) | (1<<4)|(3<<0)); VIDCON1 &= ~(1<<7); VIDCON1 |= ((1<<6) | (1<<5)); VIDTCON0 = (VBPD << 16) | (VFPD << 8) | (VSPW << 0); VIDTCON1 = (HBPD << 16) | (HFPD << 8) | (HSPW << 0); VIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0); WINCON0 &= ~(0xf << 2); WINCON0 |= (0xb<<2); WINCON0 = (1<<16)|(0xb<<2)|(1<<0); VIDOSD0A = (LeftTopX<<11) |(LeftTopY<<0); VIDOSD0B = (RightBotX<<11)|(RigntBotY<<0); VIDOSD0C = (LINEVAL+1)*(HOZVAL+1); VIDW00ADD0B0 = FRAME_BUFFER; VIDW00ADD1B0 = (FRAME_BUFFER+((HOZVAL+1)*4+0)*(LINEVAL+1))&(0xffffff); } void point(int row, int col, int color) { unsigned long *point = (unsigned long*)FRAME_BUFFER; *(point + row*480 + col) = color; } void lcd_clear() { int x,y,color; for(x=0;x<272;x++) for(y=0;y<480;y++) point(x,y,0xFFFfff); //WIN0MAP = (1<<24)|(color&0xffffff); } void Paint_Bmp(U16 x0,U16 y0,U16 x,U16 y,const unsigned char gImage_bmp[]) { int i, j; unsigned char *p = (unsigned char *)gImage_bmp; int blue, green, red; int color; // 图片大小200x200像素 for (i = x0 ; i < x0 +x; i++) for (j = y0; j < y0 + y; j++) { blue = *p++; green = *p++; red = *p++; // D[23:16] = Red data, D[15:8] = Green data,D[7:0] = Blue data color = (red << 16)| (green << 8)|( blue << 0); point(i, j, color); } } /*void Paint_txt(U16 x0,U16 y0,U16 x,U16 y,const unsigned char gImage_bmp[]) { int i, j; unsigned char *p = (unsigned char *)gImage_bmp; int blue, green, red; int color; // 图片大小200x200像素 for (i = x0 ; i < x0 +x; i++) for (j = y0; j < y0 + y; j++) { //blue = *p++; //green = *p++; //red = *p++; // D[23:16] = Red data, D[15:8] = Green data,D[7:0] = Blue data //color = (red << 16)| (green << 8)|( blue << 0); color = *p; point(i, j, color); } }*/ void lcd_init() { lcd_port_init(); lcd_config_init(); } void lcd_test() { int y; lcd_clear(); //划横线 -> 描第150行,第y列 for(y=100;y<380;y++) point(210,y,0xFF0000); //x0,y0,x(高度),y(宽度) 272*480 Paint_Bmp(0,0,272,480,bmp); //Paint_txt(0,0,224,56,zi); }
菜鸟一枚,如有错误,多多指教。。。
相关文章推荐
- 新手上路 腾云驾雾
- PHP 判断数组是否为空的几种方法
- Python如何调用新浪api接口的问题
- uiUIlabel 自适应宽度和高度
- 链表排序
- Active Shape Models with Stasm 接口使用
- 不要在功能上竞争
- 状态码
- ratingbar设置不可调节星星数量
- 从0开始学习ssh之日志工具与配置log4j
- mysql 主主复制(双主复制)报错Last_SQL_Errno: 1146
- require.js配合插件text.js实现最简单的单页应用程序
- Java Web开发问题
- 事务中的锁,行锁与表锁
- 前端入门
- SAP复制会计年度
- Mybatis分页
- IDEA 滚动条跳动问题
- AtomicInteger类保证线程安全的用法
- IOS Dev Intro - ARC Memory Leak