最近研究了s3c2410下LCD控制器的相关知识,主要的参考资料就是 三星s3c2410数据手册(arm920T),英文版,看的不是非常明白,后来参考了WinCE下的部分代码,似有所领悟。于是写了此程序,用以在LCD上显示图片。 本程序可以在LCD上居中显示小于800×480的任意大小的图片。用到的辅助工具就是上篇文章中的RGB分量提取器. 关键模块如下: 0、全局变量的定义: #define DMA_BUFFER_BASE 0xAC000000 #define DMA_PHYSICAL_BASE 0x35000000 // S3C2410X01 0x30000000 #define FRAMEBUF_BASE (DMA_BUFFER_BASE + 0x00100000) #define FRAMEBUF_DMA_BASE (DMA_PHYSICAL_BASE + 0x00000000)//0x00100000 #define IOP_BASE 0x56000000 // 0x56000000 typedef struct { unsigned int GPACON; // 00 unsigned int GPADAT; unsigned int PAD1[2]; ................... }IOPreg; // Define LCD type of S3C2400X01 #define TFT24BPP 3 #define LCDTYPE TFT24BPP // define LCD type as upper definition. // // Registers : LCD Controller // #define LCD_BASE 0x4D000000 // 0x4D000000 typedef struct { unsigned int LCDCON1; // 00 unsigned int LCDCON2; // 04 unsigned int LCDCON3; // 08 ..................... }LCDreg ; // LCD register value #define MODE_TFT_24BIT (224) #define LCD_XSIZE_TFT (800) #define LCD_YSIZE_TFT (480) #define ARRAY_SIZE_TFT_24BIT (SCR_XSIZE*4*SCR_YSIZE) #define HOZVAL_TFT (LCD_XSIZE_TFT-1) #define LINEVAL_TFT (LCD_YSIZE_TFT-1) #define MVAL (13) #define MVAL_USED (0) #define VBPD ((32-1)&0xff) #define VFPD ((11-1)&0xff) #define VSPW ((2-1) &0x3f) #define HBPD ((88-1)&0x7f) #define HFPD ((40-1)&0xff) #define HSPW ((128-1)&0xff) #define CLKVAL_TFT (1) #define M5D(n) ((n) & 0x1fffff) U32* pLCDBuffer24=(U32*)FRAMEBUF_DMA_BASE; U32* picData; volatile LCDreg *s2410LCD = (LCDreg *)LCD_BASE; volatile IOPreg *s2410IOP= (IOPreg *)IOP_BASE; int nCol = 800;//象素列数 int nRow = 480;//象素行数 U32* picDataT=NULL; 1、入口函数,其中包括了相应端口、寄存器初始化的入口,aa,bb,cc,dd,ee是可选择的5幅预定义图片的GRB码数组,具体代码如下 void lcd_Main(void) { char sel; Uart_Printf("Lcd_Driver "); lcd_port_init(); lcd_regs_init(); Uart_Printf("select one Picture to show(1 2 3 4 5 0) "); while((sel = Uart_Getch()) != 'e') { Uart_Printf("%c ",sel); switch(sel) { case '1': picData = (U32*)aa;break; case '2': picData =(U32*)bb;break; case '3': picData = (U32*)cc;break; case '4': picData = (U32*)dd; break; case '5': picData = (U32*)ee;break; default: Uart_Printf("Input 1 2 3 4 5 0 "); } lcd_display(); Uart_Printf("select one Picture to show(1 2 3 4 5 0) "); } Uart_Printf("Exit"); //lcd_close(); } 2、相应端口设置,包括GPC,GPD,GPG的相应位的设置: void lcd_port_init(void) { // LCD port initialize. s2410IOP->GPCUP = 0xFFFFFFFF; s2410IOP->GPCCON = 0xAAAAAAAA; s2410IOP->GPDUP = 0xFFFFFFFF; s2410IOP->GPDCON = 0xAAAAAAAA; s2410IOP->GPGCON &= ~(3 << 8); /**//* Set LCD_PWREN as output */ s2410IOP->GPGCON |= (1 << 8); s2410IOP->GPGDAT |= (1 << 4); //* Backlight ON,关键,不然lcd不亮 } 3、控制寄存器设置: void lcd_regs_init(void) { #ifdef MODE_TFT_24BIT s2410LCD->LCDCON1 = (1 << 8) | //* VCLK = HCLK / ((CLKVAL + 1) * 2) -> About 7 Mhz (MVAL_USED << 7) | //* 0 : Each Frame (3 << 5) | // TFT LCD Pannel (13 << 1) | //Y: // 24bpp Mode (0 << 0) ; // Disable LCD Output s2410LCD->LCDCON2 = (VBPD << 24) | //* VBPD : ((32-1)&0xff) (LINEVAL_TFT << 14) | //* LINEVAL_TFT : 480 - 1 (VFPD << 6) | //* VFPD : ((11-1)&0xff) (VSPW << 0) ; //* VSPW : ((2-1) &0x3f) s2410LCD->LCDCON3 = (HBPD << 19) | //* HBPD : ((88-1)&0x7f) (HOZVAL_TFT << 8) | //* HOZVAL_TFT : 800 - 1 (HFPD << 0) ; //* HFPD : ((40-1)&0xff) s2410LCD->LCDCON4 = (MVAL << 8) | //* MVAL : 13 (HSPW << 0) ; //* HSPW : ((128-1)&0xff) s2410LCD->LCDCON5 = 0x00000000; /**//* s2410LCD->LCDCON5 = (0 << 12) | // BPP24BL : LSB valid (0 << 11) | // FRM565 MODE : 5:5:5:1 Format (0 << 10) | // INVVCLK : VCLK Falling Edge (0 << 9) | // INVVLINE : Inverted Polarity (0 << 8) | // INVVFRAME : Inverted Polarity (0 << 7) | // INVVD : Normal (0 << 6) | // INVVDEN : Normal (0 << 5) | // INVPWREN : Normal (0 << 4) | // INVENDLINE : Normal (0 << 3) | // PWREN : Disable PWREN (0 << 2) | // ENLEND : Disable LEND signal (0 << 1) | // BSWP : Swap Disable (0 << 0) ; // HWSWP : Swap Enable */ s2410LCD->LCDSADDR1 = ((FRAMEBUF_DMA_BASE >> 22) << 21) | ((M5D(FRAMEBUF_DMA_BASE >> 1)) << 0); //LCDBANK = ((FRAMEBUF_DMA_BASE >> 22) << 21) //LCDBASEU = ((M5D(FRAMEBUF_DMA_BASE) >> 1) << 0) s2410LCD->LCDSADDR2 = (M5D(FRAMEBUF_DMA_BASE) >> 1) + ( (LCD_XSIZE_TFT*2) + 0 )*(LINEVAL_TFT+1); //LCDBASEL = s2410LCD->LCDSADDR2 s2410LCD->LCDSADDR3 = (((LCD_XSIZE_TFT - LCD_XSIZE_TFT) / 1) << 11) | (LCD_XSIZE_TFT); //OFFSIZE = (((LCD_XSIZE_TFT - LCD_XSIZE_TFT) / 1) << 11) == 0 //PAGEWIDTH = (LCD_XSIZE_TFT) s2410LCD->TPAL = 0x0; s2410LCD->LCDCON1 |= 1; #endif }
4、居中显示图片:
void lcd_display(void) { int y; int pw, ph; int sw=800, sh=480; U32* pdata; U32* pBt=NULL; lcd_clear(); get_XY();//获得图片的宽与高,以保存在RGB数组的头两个字节。 pw = nCol, ph = nRow; pBt = pLCDBuffer24 + sw*(sh/2-ph/2) + (sw/2-pw/2);//定位图片显示的起始位置 pdata = (U32*)picDataT; for(y=0; y<nRow; ++y) ...{ memcpy((pBt+800*y),(char*)pdata,nCol*4);//一行一行显示 pdata = (U32*)(pdata+nCol); } s2410LCD->LCDCON1 |= 0; } 5、每次显示都要获得图片的宽度和高度,并且清除前面的屏幕,所谓清屏就是显示背景图片(蓝色):
void lcd_clear() { int y=0; U32* pdata = (U32*)(bgData+2); for(y=0; y<480; ++y) { memcpy((pLCDBuffer24+800*y),(char*)pdata,800*4); pdata = (U32*)(pdata+800); } } void get_XY(void) { nCol = picData[0]; nRow = picData[1]; picDataT =(U32*) (picData + 2); }
|