S3C2440之LCD

来源:互联网 发布:java学完可以做什么 编辑:程序博客网 时间:2024/05/21 12:42

s3c2440具有LCD控制器,可以很方便驱动各种LCD.下面以TFT型LCD为例,讲一讲LCD控制器的用法:

LCD控制器方框图:


可以看到s3c2440中LCD控制器的外部接口信号有33个,包括24个数据位和9个控制位。

那么这些数据位控制位有什么作用呢,首先那看看TFT屏的工作时序:


VSYNC为帧同步信号,每发出一个脉冲表示新的一屏图像数据开始传输。计算方法:VSFHSF÷[(VSPW1)(VBPD1)(VFPD1)(LINEVAL1)]

HSYNC为行同步信号,每发出一个脉冲表示新的一行图像数据开始传输。计算方法:HSFVCLK÷[(HSPW1)(HSPD1)(HFPD1)(HOZVAL1)]

VCLK为像素同步信号,每发出一个脉冲表示新的一个点图像数据开始传输。计算方法:VCLKHCLK÷[(CLKVAL1)×2]

LCD显示是一帧一帧(一个画面)的,每一帧里显示又是从上到下一行一行的,每一行显示又是从左到右一个点一个点的。

而VSYNC,HSYNC,VCLK这些决定了他们的显示速度。

图中的VSPW,HSPW等决定相应脉冲的宽度,VBPD,HBPD决定了延时时间。

这些参数的设置都是由LCDCONn决定的。

具体功能可以参见数据手册。

来看具体的编程流程:

需要设置的寄存器:

           LCDCON1:LCD控制寄存器1

           LCDCON2:LCD控制寄存器2

           LCDCON3:LCD控制寄存器3

           LCDCON4:LCD控制寄存器4

           LCDCON5:LCD控制寄存器5

           LCDSADDR1:帧缓冲器开始地址1寄存器

           LCDSADDR2:帧缓冲器开始地址2寄存器

           LCDSADDR3:帧缓冲器开始地址3寄存器

一,初始化。

初始化包括端口初始化,显示模式初始化,帧缓冲初始化。

1,端口初始化:

主要是初始化相应端口为第二功能,这些脚将会与LCD连接。

[html] view plaincopy
  1. rGPCUP=0xffffffff; // Disable Pull-up register  
  2. rGPCCON=0xaaaa02a8; //Initialize VD[7:0],VM,VFRAME,VLINE,VCLK  
  3. rGPDUP=0xffffffff; // Disable Pull-up register  
  4. rGPDCON=0xaaaaaaaa; //Initialize VD[15:8]  

2,显示模式初始化:

主要是设置显示的相关参数,通过LCDCON1~LCDCON5来完成。

具体功能可以参见数据手册:

[html] view plaincopy
  1. #define LCD_WIDTH 240  
  2. #define LCD_HEIGHT 320  
  3. #define LCD_PIXCLOCK 4  
  4. #define LCD_RIGHT_MARGIN 39  
  5. #define LCD_LEFT_MARGIN 16  
  6. #define LCD_HSYNC_LEN 5  
  7. #define LCD_UPPER_MARGIN 1  
  8. #define LCD_LOWER_MARGIN 5  
  9. #define LCD_VSYNC_LEN 1  
[html] view plaincopy
  1. #define LCD_XSIZE  LCD_WIDTH  
  2. #define LCD_YSIZE  LCD_HEIGHT  
  3. #define SCR_XSIZE  LCD_WIDTH  
  4. #define SCR_YSIZE  LCD_HEIGHT  

用到的寄存器及设置的说明:

LCDCON1:bit[17:8](4:CLKVAL);bit[6:5](11:TFT LCD panel);bit[4:1](1100:16 bpp for TFT)

[html] view plaincopy
  1. rLCDCON1 = (LCD_PIXCLOCK << 8) | (3 <<  5) | (12 << 1);  

LCDCON2:bit[31:24](1:VBPD);bit[23:14](320-1:行数);bit[13:6](5:VFPD);bit[5:0](1:VSPW)

[html] view plaincopy
  1. rLCDCON2 = (LCD_UPPER_MARGIN << 24) | ((LCD_HEIGHT - 1) << 14) | (LCD_LOWER_MARGIN << 6) | (LCD_VSYNC_LEN << 0);  
LCDCON3:bit[25:19](36:HBPD);bit[18:8](240-1:列数);bit[7:0](19:HFPD)

[html] view plaincopy
  1. rLCDCON3 = (LCD_RIGHT_MARGIN << 19) | ((LCD_WIDTH  - 1) <<  8) | (LCD_LEFT_MARGIN << 0);  
LCDCON4:bit[15:8](13:MVAL,只有当LCDCON1 bit[7]MMODE=1才有效);bit[7:0](5:HSPW)

[html] view plaincopy
  1. rLCDCON4 = (13 <<  8) | (LCD_HSYNC_LEN << 0);  
LCDCON5:bit[11](5:6:5 Format);bit[9](VLINE/HSYNC polarity inverted);bit[8](VFRAME/VSYNC inverted)bit[3](Enalbe PWERN signal),bit[1](half-word swap control bit)

[html] view plaincopy
  1. rLCDCON5   =  (1<<11) | (1 << 9) | (1 << 8) | (1 << 3) | (1 << 0);  

3,帧缓冲初始化:

LCDSADDR1~3来告诉LCD控制器要从从显示缓存的那个地址开始取数据,要去多少数据等。

LCDBANK: 视频帧缓冲区内存地址30-22位
LCDBASEU: 视频帧缓冲区的开始地址21-1位
LCDBASEL: 视频帧缓冲区的结束地址21-1位

PAGEWIDTH:虚拟屏幕一行的字节数,如果不使用虚拟屏幕,设置为实际屏幕的行字节数

OFFSIZE:虚拟屏幕左侧偏移的字节数,如果不使用虚拟屏幕,设置为0

[html] view plaincopy
  1.      
  2. /*bit[29:21]:LCDBANK,bit[20:0]:LCDBASEU*/  
  3.     rLCDSADDR1 = ((LCD_ADDR >> 22) << 21) | ((M5D(LCD_ADDR >> 1)) <<  0);      
  4.     /*bit[20:0]:LCDBASEL*/  
  5.     rLCDSADDR2 = M5D((LCD_ADDR + LCD_WIDTH * LCD_HEIGHT * 2) >> 1);   
  6.     /*bit[21:11]:OFFSIZE; bit[10:0]:PAGEWIDTH*/  
  7.     rLCDSADDR3 = LCD_WIDTH;  
二,初始化好了以后,就可以向LCD缓冲区里面写数据了。

LCD控制器就会不断地自动从你设定的缓冲区地址以设定的方式读取数据并显示在LCD上了。

[html] view plaincopy
  1. /*显示一副图片在屏幕上*/  
  2. Pait_Bmp(0, 0, 240, 320, sunflower_240x320);  

[html] view plaincopy
  1. /*在屏幕上画图*/  
  2. static void Pait_Bmp(int x0,int y0,int h,int l,const unsigned char *bmp)  
  3. {  
  4.     int x,y;  
  5.     U32 c;  
  6.     int p = 0;  
  7.       
  8.     for( y = 0 ; y < l ; y++ )  
  9.     {  
  10.         for( x = 0 ; x < h ; x++ )  
  11.         {  
  12.             c = bmp[p+1] | (bmp[p]<<8) ;  
  13.   
  14.         if ( ( (x0+x) < SCR_XSIZE) && ( (y0+y) < SCR_YSIZE) )  
  15.             LCD_BUFFER[y0+y][x0+x] = c ;  
  16.   
  17.             p = p + 2 ;  
  18.         }  
  19.     }  
  20. }  
LCD.c源代码:实现在MINI2440上测试三原色和显示图片

[html] view plaincopy
  1. #define LCD_N35 //NEC 256K色240*320/3.5英寸TFT真彩液晶屏,每一条水平线上包含240个像素点,共有320条这样的线  
  2.   
  3. #if defined(LCD_N35)  
  4.   
  5. #define LCD_WIDTH 240  
  6. #define LCD_HEIGHT 320  
  7. #define LCD_PIXCLOCK 4  
  8.   
  9. #define LCD_RIGHT_MARGIN 39  
  10. #define LCD_LEFT_MARGIN 16  
  11. #define LCD_HSYNC_LEN 5  
  12.   
  13. #define LCD_UPPER_MARGIN 1  
  14. #define LCD_LOWER_MARGIN 5  
  15. #define LCD_VSYNC_LEN 1  
  16.   
  17. #endif  
  18.   
  19. void TFT_LCD_Test(void);  
  20.   
  21. #define LCD_XSIZE  LCD_WIDTH  
  22. #define LCD_YSIZE  LCD_HEIGHT  
  23. #define SCR_XSIZE  LCD_WIDTH  
  24. #define SCR_YSIZE  LCD_HEIGHT  
  25.   
  26. volatile static unsigned short LCD_BUFFER[SCR_YSIZE][SCR_XSIZE];  //定义320行,240列的数组,用于存放显示数据  
  27.   
  28. extern unsigned char sunflower_240x320[];  
  29.   
  30. #define M5D(n)  ((n)&0x1fffff)  
  31. #define LCD_ADDR ((U32)LCD_BUFFER)  
  32.   
  33. #define ADC_FREQ 2500000  
  34.   
  35. volatile U32 preScaler;  
  36.   
  37. static void cal_cpu_bus_clk(void);  
  38. void Set_Clk(void);  
  39.   
  40. /*演示函数*/  
  41. void delay(int times)  
  42. {  
  43.     int i,j;  
  44.     for(i=0;i<times;i++)  
  45.        for(j=0;j<400;j++);  
  46. }  
  47.   
  48. /*在屏幕上画图*/  
  49. static void Pait_Bmp(int x0,int y0,int h,int l,const unsigned char *bmp)  
  50. {  
  51.     int x,y;  
  52.     U32 c;  
  53.     int p = 0;  
  54.       
  55.     for( y = 0 ; y < l ; y++ )  
  56.     {  
  57.         for( x = 0 ; x < h ; x++ )  
  58.         {  
  59.             c = bmp[p+1] | (bmp[p]<<8) ;  
  60.   
  61.         if ( ( (x0+x) < SCR_XSIZE) && ( (y0+y) < SCR_YSIZE) )  
  62.             LCD_BUFFER[y0+y][x0+x] = c ;  
  63.   
  64.             p = p + 2 ;  
  65.         }  
  66.     }  
  67. }  
  68.   
  69.   
  70. /*填充全屏为某一颜色*/  
  71. static void Lcd_ClearScr( U16 c)  
  72. {  
  73.     unsigned int x,y ;  
  74.           
  75.     for( y = 0 ; y < SCR_YSIZE ; y++ )  
  76.     {  
  77.         for( x = 0 ; x < SCR_XSIZE ; x++ )  
  78.         {  
  79.         LCD_BUFFER[y][x] = c ;  
  80.         }  
  81.     }  
  82. }  
  83.   
  84.   
  85. /*LCD开关*/  
  86. static void Lcd_EnvidOnOff(int onoff)  
  87. {  
  88.     if(onoff==1)  
  89.     rLCDCON1|=1; // ENVID=ON  
  90.     else  
  91.     rLCDCON1 =rLCDCON1 & 0x3fffe; // ENVID Off  
  92. }  
  93.   
  94.   
  95. /*端口初始化*/  
  96. static void Lcd_Port_Init( void )  
  97. {  
  98.     rGPCUP=0xffffffff; // Disable Pull-up register  
  99.     rGPCCON=0xaaaa02a8; //Initialize VD[7:0],VM,VFRAME,VLINE,VCLK  
  100.   
  101.     rGPDUP=0xffffffff; // Disable Pull-up register  
  102.     rGPDCON=0xaaaaaaaa; //Initialize VD[15:8]  
  103. }  
  104.   
  105. /*LCD初始化*/  
  106. static void LCD_Init(void)  
  107. {  
  108.     Lcd_Port_Init();  
  109.   
  110.     /*显示模式初始化*/  
  111.     /*bit[17:8](4:CLKVAL);bit[6:5](11:TFT LCD panel);bit[4:1](1100:16 bpp for TFT)*/  
  112.     rLCDCON1 = (LCD_PIXCLOCK << 8) | (3 <<  5) | (12 << 1);  
  113.       
  114.     /*bit[31:24](1:VBPD);bit[23:14](320-1:行数);bit[13:6](5:VFPD);bit[5:0](1:VSPW)*/  
  115.     rLCDCON2 = (LCD_UPPER_MARGIN << 24) | ((LCD_HEIGHT - 1) << 14) | (LCD_LOWER_MARGIN << 6) | (LCD_VSYNC_LEN << 0);  
  116.       
  117.     /*bit[25:19](36:HBPD);bit[18:8](240-1:列数);bit[7:0](19:HFPD)*/  
  118.     rLCDCON3 = (LCD_RIGHT_MARGIN << 19) | ((LCD_WIDTH  - 1) <<  8) | (LCD_LEFT_MARGIN << 0);  
  119.       
  120.     /*bit[15:8](13:MVAL,只有当LCDCON1 bit[7]MMODE=1才有效);bit[7:0](5:HSPW)*/  
  121.     rLCDCON4 = (13 <<  8) | (LCD_HSYNC_LEN << 0);  
  122.       
  123.     /*bit[11](5:6:5 Format);bit[9](VLINE/HSYNC polarity inverted);bit[8](VFRAME/VSYNC inverted)  
  124.       bit[3](Enalbe PWERN signal),bit[1](half-word swap control bit)*/  
  125.     rLCDCON5   =  (1<<11) | (1 << 9) | (1 << 8) | (1 << 3) | (1 << 0);  
  126.       
  127.       
  128.       
  129.   
  130.         /*帧缓冲地址初始化*/  
  131.     /*  
  132.     LCDBANK: 视频帧缓冲区内存地址30-22位  
  133.     LCDBASEU: 视频帧缓冲区的开始地址21-1位  
  134.     LCDBASEL: 视频帧缓冲区的结束地址21-1位  
  135.     */  
  136.     /*bit[29:21]:LCDBANK,bit[20:0]:LCDBASEU*/  
  137.         rLCDSADDR1 = ((LCD_ADDR >> 22) << 21) | ((M5D(LCD_ADDR >> 1)) <<  0);  
  138.       
  139.         /*bit[20:0]:LCDBASEL*/  
  140.         rLCDSADDR2 = M5D((LCD_ADDR + LCD_WIDTH * LCD_HEIGHT * 2) >> 1);  
  141.       
  142.       
  143.         /*PAGEWIDTH:虚拟屏幕一行的字节数,如果不使用虚拟屏幕,设置为实际屏幕的行字节数  
  144.       OFFSIZE:虚拟屏幕左侧偏移的字节数,如果不使用虚拟屏幕,设置为0  
  145.     */  
  146.     /*bit[21:11]:OFFSIZE; bit[10:0]:PAGEWIDTH*/  
  147.         rLCDSADDR3 = LCD_WIDTH;          
  148.   
  149.     /*屏蔽中断*/  
  150.         rLCDINTMSK |= 3;  
  151.     rTCONSEL   &= (~7);  
  152.    
  153.     /*disable调色板*/  
  154.     rTPAL = 0x0;  
  155.       
  156.     /*禁止LPC3600/LCC3600模式*/  
  157.     rTCONSEL &= ~((1<<4) | 1);   
  158.       
  159.     /*打开LCD*/  
  160.     Lcd_EnvidOnOff(1);     
  161. }  
  162.   
  163.   
  164. void TFT_LCD_Show(void)  
  165. {     
  166.     /*红(255:0:0);绿(0:255:0);蓝(0:0:255);黑(0:0:0);白(255,255,255)*/  
  167.       
  168.     /*在屏幕上显示三基色*/  
  169.       
  170.     Lcd_ClearScr( (0x00<<11) | (0x00<<5) | (0x00)  )  ;     //clear screen black  
  171.     delay(10000);  
  172.           
  173.     Lcd_ClearScr((0x1f<<11) | (0x00<<5) | (0x00));          //red  
  174.     delay(10000);  
  175.           
  176.     Lcd_ClearScr((0x00<<11) | (0x3f<<5) | (0x00));          //green  
  177.     delay(10000);  
  178.       
  179.     Lcd_ClearScr((0x00<<11) | (0x00<<5) | (0x1f));          //blue  
  180.     delay(10000);  
  181.   
  182.     Lcd_ClearScr( (0x1f<<11) | (0x3f<<5) | (0x1f)  )  ;     //clear screen white  
  183.     delay(10000);  
  184.       
  185.     /*显示一副图片在屏幕上*/  
  186.     Pait_Bmp(0, 0, 240, 320, sunflower_240x320);  
  187. }  
0 0
原创粉丝点击