一:项目介绍
该项目最终实现的功能很简单,手指在触摸屏左滑(下一张图片),右滑(上一张图片)
1.1软硬件资源
硬件:pc机,ARM Cortex-A9开发板
软件:linux 操作系统
1.3项目流程
本项目主要分为三大模块:
一:LCD驱动编写
二:I2C驱动编写
三:使用I2C读取触摸屏上的数据,判断是向左或者向右,再控制lcd进行图片的显示
大体流程图如下所示:
二:项目环境搭建
2.1安装交叉环境编译器 4.5.1,dnw软件
2.2烧写uboot
三:LCD裸板驱动的编写
在编写lcd驱动前先看一下电路图:
可以观察到 LCD1由45根线来控制,主要配置的寄存器是24根RGB以及TOU1 EINT10 以及VDEN VYNC HSYNC VCLK驱动;
在核心板中找到网标,找出相应的寄存器;
编写lcd可大致分为如下几步:
第一步:配置 OUT1 EINT10 以及24根RGB
第二步:看时序图配置相关寄存器
第三步:配置窗口寄存器
3.1 lcd控制器
Exynos4412的LCD控制器可以通过编程支持不同LCD屏的要求,例如行和列像素数,数据总线宽度,接口时序和刷新频率等。
LCD控制器的主要作用,是将定位在系统存储器中的显示缓冲区中的LCD图像数据传送到外部LCD驱动器,并产生必要的控制信号,
例如RGB_VSYNC,RGB_HSYNC, RGB_VCLK等
由上图可知:LCD控制器的构成主要由VSFR,VDMA,VPRCS , VTIME和视频时钟产生器几个模块组成;
(1)VSFR由121个可编程控制器组,一套gammaLUT寄存器组(包括64个寄存器),一套i80命令寄存器组(包括12个寄存器)和5块256*32调色板存储器组成,主要用于对lcd控制器进行配置。
(2)VDMA是LCD专用的DMA传输通道,可以自动从系统总线上获取视频数据传送到VPRCS,无需CPU干涉。
(3)VPRCS收到数据后组成特定的格式(如16bpp或24bpp),然后通过数据接口(RGB_VD, VEN_VD, V656_VD or SYS_VD)传送到外部LCD屏上。
(4)VTIME模块由可编程逻辑组成,负责不同lcd驱动器的接口时序控制需求。VTIME模块产生 RGB_VSYNC, RGB_HSYNC, RGB_VCLK, RGB_VDEN,VEN_VSYNC等信号。
3.2 lcd接口信号
其中主要的RGB接口信号:
(1)LCD_HSYNC:行同步信号,表示一行数据的开始,LCD控制器在整个水平线(整行)数据移入LCD驱动器后,插入一个LCD_HSYNC信号;
(2)LCD_VSYNC: 帧同步信号,表示一帧数据的开始,LCD控制器在一个完整帧显示完成后立即插入一个LCD_VSYNC信号,开始新一帧的显示;VSYNC信号出现的频率表示一秒钟内能显示多少帧图像,称为“显示器的频率”
(3)LCD_VCLK:像素时钟信号,表示正在传输一个像素的数据;
(4)LCD_VDEN:数据使能信号;
(5) LCD_VD[23:0]: LCD像素数据输出端口
3.3、RGB信号的时序
(1)、相关参数说明
VBPD(vertical back porch):表示在一帧图像开始时,垂直同步信号以后的无效的行数。
VFBD(vertical front porch):表示在一帧图像结束后,垂直同步信号以前的无效的行数。
VSPW(vertical sync pulse width):表示垂直同步脉冲的宽度,用行数计算。
HBPD(horizontal back porch):表示从水平同步信号开始到一行的有效数据开始之间的VCLK的个数。
HFPD(horizontal front porth):表示一行的有效数据结束到下一个水平同步信号开始之间的VCLK的个数。
HSPW(horizontal sync pulse width):表示水平同步信号的宽度,用VCLK计算。
(2)、帧的传输过程
VSYNC信号有效时,表示一帧数据的开始,信号宽度为(VSPW +1)个HSYNC信号周期,即(VSPW +1)个无效行;
VSYNC信号脉冲之后,总共还要经过(VBPD+ 1)个HSYNC信号周期,有效的行数据才出现; 所以,在VSYNC信号有效之后,还要经过(VSPW +1 + VBPD + 1)个无效的行;
随即发出(LINEVAL+ 1)行的有效数据;
最后是(VFPD + 1)个无效的行。
(3)、行中像素数据的传输过程
HSYNC信号有效时,表示一行数据的开始,信号宽度为(HSPW+ 1)个VCLK信号周期,即(HSPW +1)个无效像素;
HSYNC信号脉冲之后,还要经过(HBPD +1)个VCLK信号周期,有效的像素数据才出现;
随后发出(HOZVAL+1)个像素的有效数据;
最后是(HFPD +1)个无效的像素。
(4)、将VSYNC、HSYNC、VCLK等信号的时间参数设置好之后,并将帧内存的地址告诉LCD控制器,它即可自动地发起DMA传输从帧内存中得到图像数据,最终在上述信号的控制下RGB数据出现在数据总线VD[23:0]上。用户只需要把要显示的图像数据写入帧内存中。
3.4、lcd相关寄存器设置说明
(1)设置LCD的RGB接口,只需要将其设置为2即可。同时将其IO口设置成为内部上拉,且将其驱动能力设置为最强代码如下:
GPF0CON = 0x22222222;
GPF1CON = 0x22222222;
GPF2CON = 0x22222222;
GPF3CON &= ~(0xffff);
GPF3CON |= 0x2222;
/*max driver strength*/
GPF0DRV = 0xfffffff;
GPF1DRV = 0xfffffff;
GPF2DRV = 0xfffffff;
GPF3DRV &= ~0xff;
GPF3DRV |= 0xff;
(2)设置LCD相关时钟寄存器
这一步主要设置选择LCD时钟输入源为MPLL,且不对其进行分频,同时设置LCDBLK_CFG使其使用FIMD接口,且设置LCDBLK_CFG2使其PWM输出使能;
(4)设置VIDCONx,设置接口类型,时钟分频,极性以及使能LCD控制器等
VIDCON0:这一个寄存器主要设置接口类型和时钟分频,这里仅仅设置了其时钟分频值,由于我们的MPLL为800MHZ,所以这里设置值,根据手册进行计算,要得到33.3MHZ左右的像素时钟;
VIDCON0 = (1 << 17)|(23 <<6)|3;
VIDCON1:主要设置时钟信号,需不需要翻转,以及触发方式;
VIDTCONx:用来设置时序和长宽等参数,这里就主要设置VBPD(vertical back porch)、 VFBD(vertical frontporch)、VSPW(vertical sync pulse width)、HBPD(horizontal backporch)、 HFPD(horizontal sync pulse width)等参数
VIDTCON0取值过程,VIDTCON0设置帧同步时序。
VIDTCON0 = (22 << 16) | (21 << 8) | (0);
VIDTCON1取值过程,VIDTCON1设置像素同步时序。
VIDTCON1 = (35 << 16) | (209 << 8) | (9);
VIDTCON2
VIDTCON2 = (479 << 11) | 799;
(5)设置WINCON0寄存器,即设置数据格式。
Exynos4412的LCD控制器有overlay功能,它支持5个window。这里只使用window0,设置其代码RGB模式为24bit(A888)且使能window0;
WINCON0 = (1 << 22) | (1 << 15) | (11 << 2) | 1;
(6)设置VID0SD0A/B/C,即设置Window0的坐标系
配置VIDW00ADD0B0和VIDW00ADD1B0,设置framebuffer的地址;
(7)配置SHADOWCON和WINCHMAP2、选择使能DMA通道0。由于我们使用的是Window0,所以需要使能DMA通道0;
(8)最后设置VIDCON0低两位使能LCD
VIDCON0 |= 1 | (1 << 1);
下面是Tiny4412 LCD裸板驱动具体代码:
1 #define LCD_BASE 0x11C00000 2 3 #define VIDCON0 (*(volatile unsigned int *)(LCD_BASE + 0x0000)) 4 #define VIDCON1 (*(volatile unsigned int *)(LCD_BASE + 0x0004)) 5 #define VIDCON2 (*(volatile unsigned int *)(LCD_BASE + 0x0008)) 6 #define VIDCON3 (*(volatile unsigned int *)(LCD_BASE + 0x000C)) 7 #define VIDTCON0 (*(volatile unsigned int *)(LCD_BASE + 0x0010)) 8 #define VIDTCON1 (*(volatile unsigned int *)(LCD_BASE + 0x0014)) 9 #define VIDTCON2 (*(volatile unsigned int *)(LCD_BASE + 0x0018)) 10 #define VIDTCON3 (*(volatile unsigned int *)(LCD_BASE + 0x001C)) 11 #define WINCON0 (*(volatile unsigned int *)(LCD_BASE + 0x0020)) 12 #define WINCON1 (*(volatile unsigned int *)(LCD_BASE + 0x0024)) 13 #define WINCON2 (*(volatile unsigned int *)(LCD_BASE + 0x0028)) 14 #define WINCON3 (*(volatile unsigned int *)(LCD_BASE + 0x002C)) 15 #define WINCON4 (*(volatile unsigned int *)(LCD_BASE + 0x0030)) 16 #define SHADOWCON (*(volatile unsigned int *)(LCD_BASE + 0x0034)) 17 #define WINCHMAP2 (*(volatile unsigned int *)(LCD_BASE + 0x003C)) 18 #define VIDOSD0A (*(volatile unsigned int *)(LCD_BASE + 0x0040)) 19 #define VIDOSD0B (*(volatile unsigned int *)(LCD_BASE + 0x0044)) 20 #define VIDOSD0C (*(volatile unsigned int *)(LCD_BASE + 0x0048)) 21 #define VIDOSD1A (*(volatile unsigned int *)(LCD_BASE + 0x0050)) 22 #define VIDOSD1B (*(volatile unsigned int *)(LCD_BASE + 0x0054)) 23 #define VIDOSD1C (*(volatile unsigned int *)(LCD_BASE + 0x0058)) 24 #define VIDOSD1D (*(volatile unsigned int *)(LCD_BASE + 0x005C)) 25 #define VIDOSD2A (*(volatile unsigned int *)(LCD_BASE + 0x0060)) 26 #define VIDOSD2B (*(volatile unsigned int *)(LCD_BASE + 0x0064)) 27 #define VIDOSD2C (*(volatile unsigned int *)(LCD_BASE + 0x0068)) 28 #define VIDOSD2D (*(volatile unsigned int *)(LCD_BASE + 0x006C)) 29 #define VIDOSD3A (*(volatile unsigned int *)(LCD_BASE + 0x0070)) 30 #define VIDOSD3B (*(volatile unsigned int *)(LCD_BASE + 0x0074)) 31 #define VIDOSD3C (*(volatile unsigned int *)(LCD_BASE + 0x0078)) 32 #define VIDOSD4A (*(volatile unsigned int *)(LCD_BASE + 0x0080)) 33 #define VIDOSD4B (*(volatile unsigned int *)(LCD_BASE + 0x0084)) 34 #define VIDOSD4C (*(volatile unsigned int *)(LCD_BASE + 0x0088)) 35 #define VIDW00ADD0B0 (*(volatile unsigned int *)(LCD_BASE + 0x00A0)) 36 #define VIDW00ADD0B1 (*(volatile unsigned int *)(LCD_BASE + 0x00A4)) 37 #define VIDW00ADD0B2 (*(volatile unsigned int *)(LCD_BASE + 0x20A0)) 38 #define VIDW01ADD0B0 (*(volatile unsigned int *)(LCD_BASE + 0x00A8)) 39 #define VIDW01ADD0B1 (*(volatile unsigned int *)(LCD_BASE + 0x00AC)) 40 #define VIDW01ADD0B2 (*(volatile unsigned int *)(LCD_BASE + 0x20A8)) 41 #define VIDW02ADD0B0 (*(volatile unsigned int *)(LCD_BASE + 0x00B0)) 42 #define VIDW02ADD0B1 (*(volatile unsigned int *)(LCD_BASE + 0x00B4)) 43 #define VIDW02ADD0B2 (*(volatile unsigned int *)(LCD_BASE + 0x20B0)) 44 #define VIDW03ADD0B0 (*(volatile unsigned int *)(LCD_BASE + 0x00B8)) 45 #define VIDW03ADD0B1 (*(volatile unsigned int *)(LCD_BASE + 0x00BC)) 46 #define VIDW03ADD0B2 (*(volatile unsigned int *)(LCD_BASE + 0x20B8)) 47 #define VIDW04ADD0B0 (*(volatile unsigned int *)(LCD_BASE + 0x00C0)) 48 #define VIDW04ADD0B1 (*(volatile unsigned int *)(LCD_BASE + 0x00C4)) 49 #define VIDW04ADD0B2 (*(volatile unsigned int *)(LCD_BASE + 0x20C0)) 50 #define VIDW00ADD1B0 (*(volatile unsigned int *)(LCD_BASE + 0x00D0)) 51 #define VIDW00ADD1B1 (*(volatile unsigned int *)(LCD_BASE + 0x00D4)) 52 #define VIDW00ADD1B2 (*(volatile unsigned int *)(LCD_BASE + 0x20D0)) 53 #define VIDW01ADD1B0 (*(volatile unsigned int *)(LCD_BASE + 0x00D8)) 54 #define VIDW01ADD1B1 (*(volatile unsigned int *)(LCD_BASE + 0x00DC)) 55 #define VIDW01ADD1B2 (*(volatile unsigned int *)(LCD_BASE + 0x20D8)) 56 #define VIDW02ADD1B0 (*(volatile unsigned int *)(LCD_BASE + 0x00E0)) 57 #define VIDW02ADD1B1 (*(volatile unsigned int *)(LCD_BASE + 0x00E4)) 58 #define VIDW02ADD1B2 (*(volatile unsigned int *)(LCD_BASE + 0x20E0)) 59 #define VIDW03ADD1B0 (*(volatile unsigned int *)(LCD_BASE + 0x00E8)) 60 #define VIDW03ADD1B1 (*(volatile unsigned int *)(LCD_BASE + 0x00EC)) 61 #define VIDW03ADD1B2 (*(volatile unsigned int *)(LCD_BASE + 0x20E8)) 62 #define VIDW04ADD1B0 (*(volatile unsigned int *)(LCD_BASE + 0x00F0)) 63 #define VIDW04ADD1B1 (*(volatile unsigned int *)(LCD_BASE + 0x00F4)) 64 #define VIDW04ADD1B2 (*(volatile unsigned int *)(LCD_BASE + 0x20F0)) 65 #define VIDW00ADD2 (*(volatile unsigned int *)(LCD_BASE + 0x0100)) 66 #define VIDW01ADD2 (*(volatile unsigned int *)(LCD_BASE + 0x0104)) 67 #define VIDW02ADD2 (*(volatile unsigned int *)(LCD_BASE + 0x0108)) 68 #define VIDW03ADD2 (*(volatile unsigned int *)(LCD_BASE + 0x010C)) 69 #define VIDW04ADD2 (*(volatile unsigned int *)(LCD_BASE + 0x0110)) 70 #define VIDINTCON0 (*(volatile unsigned int *)(LCD_BASE + 0x0130)) 71 #define VIDINTCON1 (*(volatile unsigned int *)(LCD_BASE + 0x0134)) 72 #define W1KEYCON0 (*(volatile unsigned int *)(LCD_BASE + 0x0140)) 73 #define VIDW0ALPHA0 (*(volatile unsigned int *)(LCD_BASE + 0x021C)) 74 #define VIDW0ALPHA1 (*(volatile unsigned int *)(LCD_BASE + 0x0220)) 75 #define VIDW1ALPHA0 (*(volatile unsigned int *)(LCD_BASE + 0x0224)) 76 #define VIDW1ALPHA1 (*(volatile unsigned int *)(LCD_BASE + 0x0228)) 77 #define VIDW2ALPHA0 (*(volatile unsigned int *)(LCD_BASE + 0x022C)) 78 #define VIDW2ALPHA1 (*(volatile unsigned int *)(LCD_BASE + 0x0230)) 79 #define VIDW3ALPHA0 (*(volatile unsigned int *)(LCD_BASE + 0x0234)) 80 #define VIDW3ALPHA1 (*(volatile unsigned int *)(LCD_BASE + 0x0238)) 81 #define VIDW4ALPHA0 (*(volatile unsigned int *)(LCD_BASE + 0x023C)) 82 #define VIDW4ALPHA1 (*(volatile unsigned int *)(LCD_BASE + 0x0240)) 83 84 #endif