void Lcd_Init(void)
{
rGPCUP=0xffffffff; // Disable Pull-up register
rGPCCON=0xaaaa56a9; //Initialize VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND
rGPDUP=0xffffffff; // Disable Pull-up register
rGPDCON=0xaaaaaaaa; //Initialize VD[15:8]
//LCDCON1: TFT LCD panel,MMODE[7]=0,16bpp TFT,ENVID=off
rLCDCON1=(CLKVAL_TFT_320240<<8)|(MVAL_USED<<7)|(3<<5)|(12<<1)|0;
rLCDCON2=(VBPD_320240<<24)|(LINEVAL_TFT_320240<<14)|(VFPD_320240<<6)|(VSPW_320240);
rLCDCON3=(HBPD_320240<<19)|(HOZVAL_TFT_320240<<8)|(HFPD_320240);
rLCDCON4=(MVAL<<8)|(HSPW_320240);
rLCDCON5=(1<<11)|(1<<9)|(1<<8)|(1<<3)|(BSWP<<1)|(HWSWP);
//rLCDCON5=(1<<11)|(0<<9)|(0<<8)|(0<<6)|(BSWP<<1)|(HWSWP);
//FRM5:6:5,HSYNC and VSYNC are inverted
//LCDBANK[29:21] = (U32)LCD_BUFFER >> 22 : These bits indicate A[30:22] of the bank location for the video buffer in the system memory. LCDBANK value cannot be changed even when moving the view port. LCD frame buffer should be within aligned 4MB region, which ensures that LCDBANK value will not be changed when moving the view port. So, care should be taken to use the malloc() function.
//系统内存地址A[30:22]处的Bank位置为图像缓冲。LCDBANK的值在视图移动的值在视图移动时不能改变,LCD帧缓冲应该在4MB区域对齐,保证LCDBANK的值在移动视图时不会改变。
//LCDBASEU[20:0] = ((U32)LCD_BUFFER >> 1)&0x1fffff : For dual-scan LCD : These bits indicate A[21:1] of the start address of the upper address counter, which is for the upper frame memory of dual scan LCD or the frame memory of single scan LCD.
//For single-scan LCD : These bits indicate A[21:1] of the start address of the LCD frame buffer.
//双扫描:表明高地址计数器的起始地址A[21:1],用于LCD双扫描的上部帧内存或者单扫描的帧内存
//单扫描:表明LCD帧缓冲的起始地址A[21:1]
rLCDSADDR1=(((U32)LCD_BUFFER>>22)<<21)|M5D((U32)LCD_BUFFER>>1);
//LCDSADDR2 0x4d000018帧缓冲起始寄存器2:
//LCDBASEL[20:0] = ((LCD_ADDR + LCD_WIDTH * LCD_HEIGHT * 2) >> 1)& 0x1fffff = (LCD_ADDR >> 1 + LCD_WIDTH * LCD_HEIGHT)& 0x1fffff
//For dual-scan LCD: These bits indicate A[21:1] of the start address of the lower address counter, which is used for the lower frame memory of dual scan LCD.
//For single scan LCD: These bits indicate A[21:1] of the end address of the LCD frame buffer.
//LCDBASEL = ((the frame end address) >>1) + 1 = LCDBASEU + (PAGEWIDTH+OFFSIZE) x (LINEVAL+1)
//双扫描:表明低地址计数器的起始地址A[21:1],用于LCD双扫描的下部帧内存或者单扫描的帧内存
//单扫描:表明LCD帧缓冲的结束地址A[21:1]
rLCDSADDR2=M5D( ((U32)LCD_BUFFER+(SCR_XSIZE_TFT_320240*LCD_YSIZE_TFT_320240*2))>>1 );
//LCDSADDR3 0x4d00001c帧缓冲起始寄存器3:
//OFFSIZE = 0AGEWIDTH = 320 虚拟屏页宽(半字数量) 定义了帧中的视图域宽度
rLCDSADDR3=(((SCR_XSIZE_TFT_320240-LCD_XSIZE_TFT_320240)/1)<<11)|(LCD_XSIZE_TFT_320240/1);
rLCDINTMSK|=(3); // MASK LCD Sub Interrupt
//rTCONSEL|=((1<<4)|1); // Disable LCC3600, LPC3600
rTPAL=0; // Disable Temp Palette
}[url=][/url]
程序分析至此,大概已经清楚是如何通过LCD_BUFFER[(y)][(x)] = c来实现在LCD上显示单个像素了。就是在设置好各个LCD寄存器之后,通过将LCD_BUFFER地址与LCDBANK以及LCDBASEU、LCDBASEL对应之后,通过改变LCD_BUFFER里不同单元存储的值(即像素的颜色),即可在LCD相应位置上做出显示。
那么在应用不同LCD的时候,只需对LCDCONx以及LCDSADDRx做出相应的配置,再创建一个数组,做出上述的地址映射即可。
关于VCLK计算,由于配置的是TFT,可用到公式VCLK = HCLK / [(CLKVAL+1) * 2] ( CLKVAL>=0 ),设置的Fclk为400MHz,Hclk为100MHz(Fclk:Hclk=1:4),CLKVAL = 4,因此VLCK = 10MHz。
笔记:
首先说一下我们平时所说的多少位的LCD,有24位的,有16位的指的是LCD数据的位数,LCD的数据实际上是LCD要显示的颜色,24位的是红绿蓝各占8位,16位则是红绿蓝按照565分配的,其实24的也可以只接16位,每个颜色地位接地就可以,所以要给LCD的缓冲区一个数据才能在LCD上显示出来。那究竟是怎么显示的呢,那就得先说一下像素了,LCD的像素实际上就LCD屏幕有多少个点,LCD显示的东西都是一个一个点拼凑出来的,比如我用的是320*240的LCD,就是说LCD每一行有320个点,而每一列有240个点,所以总共有320*240个点,我们让适当的点显示适当的颜色就达到了我们的目的。
其实刚开始困扰我们的是LCD的初始化的问题,要设置的东西比较多,其实我们是记不住这些东西的,呵呵,作为入门我们可以参考别人的初始化程序,把里面的参数改成我们自己的LCD的参数就OK了。
那么我们到底是怎么把我们要显示的数据送给LCD控制起的呢?是这样的,我们可以定义一个二维数组,把我们要显示的数据存到里面,然后把这个数组的地址赋给LCD的相应的寄存器,这个寄存器是LCDSADDRn,具体的设置大家可以参考数据手册,我们可以把二维数组的坐标和LCD的坐标对应起来,那么我们就可以随意的让哪一个像素点显示什么颜色就显示什么颜色了。这就把数据送出的过程,也就是显示一个像素点的过程。
到现在我们已经知道如何显示一个像素了,那接下来就是LCD显示最基本的东西了----字符和图片。汉字和图片的显示都是基于像素点的显示的,我们把要显示的字符和图片转化成相应的数据,然后传递给LCD即可。我们可以专门的写一个显示字符的函数和一个显示图片的函数。显示字符的数据可以用取模软件生成,因为生成的字符数据是表示的每一个点要不要亮,亮的地方用1表示,不亮的地方用0表示,所以如果用LCD显示,我们还要告诉LCD显示什么颜色,这才是LCD需要的数据,比如说16*16的数据,有16行16列,我们将一行的数据,也就是16位数据的每一位都取出来,为1的地方,我们就给LCD一个16位的数据,为0的地方就不给数据,这样就能显示了,取模生成的数据都是按行来的。图片的显示直接就将16位的数据传递给LCD,这个图片数据的产生,我们可以用软件LCD彩色图片转换工具(BMP_to_H)生成C语言文件,我们只需对文件进行简单的修改就能加入到我们的程序中,修改方法在软件的说明中都有。
|