s3c2440 LCD及触摸屏的学习笔记(1)

所用的LCD为TopPoly-TD035STED4(TFT)型号,240*320的

其VCLK为6.39MHz。 根据s3c2440手册s3c2440处理LCD的时钟源是HCLK,通过寄存器LCDCON1中的CLKVAL可以调整VCLK频率大小,它的公式为:VCLK=HCLK÷[(CLKVAL+1)×2],程序的内部分频为FCLK=400MHz、HCLK=100MHz、PCLK=50MHz(MPLLCON=(92<<12)|(1<<4)|1;),因此得到CLKVAL取整为6。

注:(LCD一般需要三个时序信号:VSYNC、HSYNC和VCLK。VSYNC是垂直同步信号,在每进行一个帧(即一个屏)的扫描之前,该信号就有效一次,由该信号可以确定LCD的场频,即每秒屏幕刷新的次数(单位Hz)。HSYNC是水平同步信号,在每进行一行的扫描之前,该信号就有效一次,由该信号可以确定LCD的行频,即每秒屏幕从左到右扫描一行的次数(单位Hz)。VCLK是像素时钟信号。

其中VSYNC是帧同步信号,VSYNC每发出1个脉冲,都意味着新的1屏视频资料开始发送。而HSYNC为行同步 信号,每个HSYNC脉冲都表明新的1行视频资料开始发送。而VDEN则用来标明视频资料的有效,VCLK是用来锁存视频资料的像数时钟。网上搜到的资料来解释这几个时序信号。

可以查看s3c2440手册‘Figure 15-6. TFT LCD Timing Example’图)

 通过上图可以得到:

代码
#define  LCD_WIDTH   240               // 屏幕的宽
#define  LCD_HEIGHT  320               // 屏幕的高
 
// 垂直同步信号的脉宽、后肩和前肩-----这些值是根据TopPoly-TD035STED4.pdf文件中的13页的表
#define  VSPW      1  // (3-1)
#define  VBPD      1  // (15-1)
#define  VFPD      1  // (12-1)

// 水平同步信号的脉宽、后肩和前肩-----这些值是根据TopPoly-TD035STED4.pdf文件中的13页的表
#define  HSPW       (10-1)
#define  HBPD       (20-1)
#define  HFPD        (10-1)

// 显示尺寸
#define  LINEVAL  (LCD_HEIGHT-1)
#define  HOZVAL   (LCD_WIDTH-1)

注:(对于一个已知尺寸的LCD屏,只要确定了VCLK值,行频和场频就应该知道了。但这样还不行的,因为在每一帧时钟信号中,还会有一些与屏显示无关的时钟出现,这就给确定行频和场频带来了一定的复杂性。如在HSYNC信号先后会有水平同步信号前肩(HFPD)和水平同步信号后肩(HBPD)出现,在VSYNC信号先后会有垂直同步信号前肩(VFPD)和垂直同步信号后肩(VBPD)出现,在这些信号时序内,不会有有效像素信号出现,另外HSYNC和VSYNC信号有效时,其电平要保持一定的时间,它们分别叫做水平同步信号脉宽HSPW和垂直同步信号脉宽VSPW,这段时间也不能有像素信号。因此计算行频和场频时,一定要包括这些信号。HBPD、HFPD和HSPW的单位是一个VCLK的时间,而VSPW、VFPD和VBPD的单位是扫描一行所用的时间。也是网上搜的。)

 这些信号(VSPW、VFPD、VBPD、LINEVAL、HBPD、HFPD、HSPW和HOZVAL)是通过寄存器LCDCON2、LCDCON3和LCDCON4来配置的,具体查看s3c2440的手册。

LCDCON1寄存器:

               LINECNT   :当前行扫描计数器值,标明当前扫描到了多少行。
               CLKVAL :决定VCLK的分频 比(上面已经提到过)。LCD控制器输出的VCLK是直接由系统总线(AHB)
                             的工作频率HCLK(一般为100MHZ)直接分频得到的。做为240*320的TFT屏,应保证得
                             出的VCLK在5~10MHz之间。
                MMODE :VM信号的触发模式(仅对STN屏有效,对TFT屏无意义。)PNRMODE :选择当前的显示模式,
                              对于TFT屏而言,应选择[11],即TFT LCD panel。

                BPPMODE :选择色彩模式,对于真彩显示而言,选择16bpp(64K色)即可满足要求。

                ENVID  : 使能LCD信号输出

 LCDCON5寄存器:

                 VSTATUS :当前VSYNC信号扫描状态,指明当前VSYNC同步信号处于何种扫描阶段。

                  HSTATUS  : 当前HSYNC信号扫描状态,指明当前HSYNC同步信号处于何种扫描阶段。
                 BPP24BL  : 设定24bpp显示模式时,视频资料在显示缓冲区中的排列顺序(即低位有效还是高位有效)。
                                  对于16bpp的 64K色显示模式,该设置位无意义。
                 FRM565  : 对于16bpp显示模式,有2中形式,一种是RGB=5:5:5:1,另一种是5:6:5。后一 种模式最为
                                 常用,它的含义是表示64K种色彩的16bit RGB资料中,红色(R)占了5bit,绿色(G)占了
                                 6bit,兰色(B)占了5bit。
                 INVVCLK 、INVLINE 、INVFRAME 、INVVD :通过前面提到的‘Figure 15-6’的时序图,我们知
                                 道,CPU的LCD控制器输 出的时序默认是正脉冲,而LCD需要VSYNC(VFRAME)、
                                 VLINE(HSYNC)均为负脉冲,因此 INVLINE 和 INVFRAME 必须设为“1 ”,即选择反相输
                                  出。 INVVDEN , INVPWREN , INVLEND 的功能同前面的类似。
                 PWREN  : LCD电源使能控制。在CPU LCD控制器的输出信号中,有一个电源使能管脚LCD_PWREN,用
                                来做为LCD屏电源的开关信号。
                 ENLEND  : 对普通的TFT屏无效,可以不考虑。

                 INVVDEN、INVPWREN、INVLEND:是否翻转这些信号,一般为正常,不需要翻转。

                  BSWP 、HWSWP : 为字节(Byte)或半字(Half-Word)交换使能。由于不同的GUI对
                                             FrameBuffer(显示缓冲区)的管理不同,必要时需要通过调整 BSWP 和 HWSWP
                                             来适应GUI。
因此:

代码
// for LCDCON1
#define  CLKVAL_TFT          4             // 设置时钟信号
#define  MVAL_USED          0             //
#define  PNRMODE_TFT      3             // TFT型LCD
#define  BPPMODE_TFT      13            // 24位TFT型LCD

// for LCDCON5  
#define  BPP24BL        0        // 32位数据表示24位颜色值时,低位数据有效,高8位无效
#define  INVVCLK        0        // 像素值在VCLK下降沿有效
#define  INVVLINE       1        // 翻转HSYNC信号
#define  INVVFRAME      1        // 翻转VSYNC信号
#define  INVVD          0        // 正常VD信号极性
#define  INVVDEN        0        // 正常VDEN信号极性
#define  PWREN          1        // 使能PWREN信号
#define  BSWP           0        // 颜色数据字节不交换
#define  HWSWP          0        // 颜色数据半字不交换

rLCDCON1 = (CLKVAL_TFT << 8 ) | (MVAL_USED << 7 ) | (PNRMODE_TFT << 5 ) | (BPPMODE_TFT << 1 ) | 0 ;
rLCDCON2 = (VBPD << 24 ) | (LINEVAL << 14 ) | (VFPD << 6 ) | (VSPW);
rLCDCON3 = (HBPD << 19 ) | (HOZVAL << 8 ) | (HFPD);
rLCDCON4 = (HSPW); //

rLCDCON5  =  (BPP24BL << 12 )  |  (INVVCLK << 10 )  |  (INVVLINE << 9 )  |  (INVVFRAME << 8 )  |  ( 0 << 7 )  |  (INVVDEN << 6 )  |  (PWREN << 3 )   | (BSWP << 1 )  |  (HWSWP);

LCDSADDR1和LCDSADDR2:
              LCDBASEL=LCDBASEU+(PAGEWITH+OFFSIZE)×(LINEVAL+1)
LCDSADDR3寄存器:
                  OFFSIZE:用于虚拟屏幕的偏移长度,如果我们不使用虚拟屏幕,就把它置为0 。
                   PAGEWIDTH:定义了视口的宽,单位是半字,如在上面的例子中,PAGEWIDTH应该为320×32÷16。

代码
#define  M5D(n)  ((n) & 0x1fffff)      // 用于设置显示缓存区时,取低21位地址
// 定义显示缓存区
volatile  U32 LCD_BUFFER[LCD_HEIGHT][LCD_WIDTH];
rLCDSADDR1 = (((U32)LCD_BUFFER >> 22 ) << 21 ) | M5D((U32)LCD_BUFFER >> 1 );
rLCDSADDR2 = M5D((M5D((U32)LCD_BUFFER >> 1 ) + ((LCD_WIDTH * 32 / 16 + 0 ) * 320 )));
rLCDSADDR3 = (LCD_WIDTH * 32 / 16 ) & 0x7ff ; // 参考s3c2440的手册

简单程序实现:

代码
// ***************************************************
#include  " def.h "
#include  " option.h "
#include  " 2440addr.h "      
#include  " 2440lib.h "
#include  " 2440slib.h "       
// ================================

#define  M5D(n)  ((n) & 0x1fffff)      // 用于设置显示缓存区时,取低21位地址

#define  LCD_WIDTH   240               // 屏幕的宽
#define  LCD_HEIGHT  320               // 屏幕的高
 
// 垂直同步信号的脉宽、后肩和前肩-----这些值是根据TopPoly-TD035STED4.pdf文件中的13页的表
#define  VSPW      1  // (3-1)
#define  VBPD      1  // (15-1)
#define  VFPD      1  // (12-1)

// 水平同步信号的脉宽、后肩和前肩-----这些值是根据TopPoly-TD035STED4.pdf文件中的13页的表
#define  HSPW       (10-1)
#define  HBPD       (20-1)
#define  HFPD        (10-1)

// 显示尺寸
#define  LINEVAL  (LCD_HEIGHT-1)
#define  HOZVAL   (LCD_WIDTH-1)

// for LCDCON1
#define  CLKVAL_TFT          4             // 设置时钟信号
#define  MVAL_USED          0             //
#define  PNRMODE_TFT      3             // TFT型LCD
#define  BPPMODE_TFT      13            // 24位TFT型LCD

// for LCDCON5  
#define  BPP24BL        0        // 32位数据表示24位颜色值时,低位数据有效,高8位无效
#define  INVVCLK        0        // 像素值在VCLK下降沿有效
#define  INVVLINE       1        // 翻转HSYNC信号
#define  INVVFRAME      1        // 翻转VSYNC信号
#define  INVVD          0        // 正常VD信号极性
#define  INVVDEN        0        // 正常VDEN信号极性
#define  PWREN          1        // 使能PWREN信号
#define  BSWP           0        // 颜色数据字节不交换
#define  HWSWP          0        // 颜色数据半字不交换

// 定义显示缓存区
volatile  U32 LCD_BUFFER[LCD_HEIGHT][LCD_WIDTH];
// **********************************************************

// 延时程序
void  delay( int  a)
{
        int  k;
        for (k = 0 ;k < a;k ++ )              ;
}
   
// 绘制屏幕背景颜色,颜色为c
void  Brush_Background( U32 c)
{
    int  x,y ;
     for ( y  =   0  ; y  <  LCD_HEIGHT ; y ++  )
    {
         for ( x  =   0  ; x  <  LCD_WIDTH ; x ++  )
        {
            LCD_BUFFER[y][x]  =  c ;
        }
    }
}

  void  init_port_lcd()
 {
    rGPCCON  =   0xaaaaaaaa ;       
        rGPCUP   =   0xffff ;      //  The pull up function is disabled GPC[15:0] 

         // *** PORT D GROUP
         // Ports  : GPD15 GPD14 GPD13 GPD12 GPD11 GPD10 GPD9 GPD8 GPD7 GPD6 GPD5 GPD4 GPD3 GPD2 GPD1 GPD0
         // Signal : VD23  VD22  VD21  VD20  VD19  VD18  VD17 VD16 VD15 VD14 VD13 VD12 VD11 VD10 VD9  VD8
         // Binary : 10    10  , 10    10  , 10    10  , 10   10 , 10   10 , 10   10 , 10   10 ,10   10
        rGPDCON  =   0xaaaaaaaa ;       
        rGPDUP   =   0xffff ; 

    rLCDCON1 = (CLKVAL_TFT << 8 ) | (MVAL_USED << 7 ) | (PNRMODE_TFT << 5 ) | (BPPMODE_TFT << 1 ) | 0 ;
    rLCDCON2 = (VBPD << 24 ) | (LINEVAL << 14 ) | (VFPD << 6 ) | (VSPW);
    rLCDCON3 = (HBPD << 19 ) | (HOZVAL << 8 ) | (HFPD);
    rLCDCON4 = (HSPW);
     // rLCDCON4 =  (5<< 0);
    rLCDCON5  =  (BPP24BL << 12 )  |  (INVVCLK << 10 )  |  (INVVLINE << 9 )  |  (INVVFRAME << 8 )  |  ( 0 << 7 )  |  (INVVDEN << 6 )  |  (PWREN << 3 )   | (BSWP << 1 )  |  (HWSWP);

    rLCDSADDR1 = (((U32)LCD_BUFFER >> 22 ) << 21 ) | M5D((U32)LCD_BUFFER >> 1 );
    rLCDSADDR2 = M5D( (M5D((U32)LCD_BUFFER >> 1 ) + ((LCD_WIDTH * 32 / 16 + 0 ) * 320 ))  ); // LCD_WIDTH*LCD_HEIGHT*4
    rLCDSADDR3 = (LCD_WIDTH * 32 / 16 ) & 0x7ff ; // 参考s3c2440的手册
    rLCDINTMSK |= ( 3 );       //  屏蔽LCD中断
     // rTCONSEL = 0;             // 无效LPC3480
        rTCONSEL    &=  ( ~ 7 );
 

        rTPAL      =   0x0 ;
        rTCONSEL  &=   ~ (( 1 << 4 )  |   1 );

    rGPGUP = rGPGUP & ( ~ ( 1 << 4 )) | ( 1 << 4 );       // GPG4上拉电阻无效
    rGPGCON = rGPGCON & ( ~ ( 3 << 8 )) | ( 3 << 8 );  // 设置GPG4为LCD_PWREN
    rGPGDAT  =  rGPGDAT  |  ( 1 << 4 ) ;                // GPG4置1

    rLCDCON5 = rLCDCON5 & ( ~ ( 1 << 3 )) | ( 1 << 3 );    // 有效PWREN信号
    rLCDCON5 = rLCDCON5 & ( ~ ( 1 << 5 )) | ( 0 << 5 );    // PWREN信号极性不翻转

    rLCDCON1 |= 1 ;                    // LCD开启
 }


int  Main( int  argc,  char   ** argv)
{
     int  i;
    U8 key;
    U32 mpll_val = 0 ;
     int  data;
  
    mpll_val  =  ( 92 << 12 ) | ( 1 << 4 ) | ( 1 );
    
     // init FCLK=400M, so change MPLL first
    ChangeMPllValue((mpll_val >> 12 ) & 0xff , (mpll_val >> 4 ) & 0x3f , mpll_val & 3 );
    ChangeClockDivider(key,  12 );    

     // ChangeClockDivider(1,1);     //  1:2:4    FCLK:HCLK:PCLK
         //  rCLKDIVN=0x4;     //   1:4:4
         // ChangeMPllValue(82,2,1);      // FCLK=135.0Mhz     
     // ChangeMPllValue(82,1,1);      // FCLK=180.0Mhz     
         // ChangeMPllValue(161,3,1);     // FCLK=202.8Mhz 
         // ChangeMPllValue(117,1,1);     // FCLK=250.0Mhz 
         // ChangeMPllValue(122,1,1);     // FCLK=260.0Mhz 
         // ChangeMPllValue(125,1,1);     // FCLK=266.0Mhz 
         // ChangeMPllValue(127,1,1);     // FCLK=270.0Mhz  
    
         // MMU_EnableICache();
         // MMU_EnableDCache();
    
        MMU_DisableICache();
        MMU_DisableDCache();

    init_port_lcd();
     while ( 1 )
    {
         // 黑色背景
        Brush_Background( 0x0000 );
        delay( 5000000 );
         // 白色背景
        Brush_Background( 0xffffff );
        delay( 5000000 );
         // 蓝色背景
        Brush_Background( 0x00ff );
        delay( 5000000 );
         // 绿色背景
        Brush_Background( 0xff00 );
        delay( 5000000 );
         // 黄色背景
        Brush_Background( 0xffff00 );
        delay( 5000000 );
    }
    return   0 ;
}

该程序说明: 该程序为W35(320*240)LCD显示显示+触摸屏驱动程序+UART0通信 显示文字取模软件使用说明: 该显示程序用到的取模方式为:阴码、列行式、逆向、十六进制。在软件菜单选项中设定。 该程序可以在LCD显示数字、字母、汉字,显示的汉字要先用取模软件进行取模后,才能用。 触摸屏可以识别了,做了个小实例,按左边黄色的矩形框,显示“你好”,按右边的框,显示“LOVE” UART0串口通信 接收上位机发送命令,采用中断方式完成。(1、2、3) 接收为正确指令,发送相应回答。 接收为不正确指令,发送“please input 1/2/3” int main(void) { int i; U8 key; U32 mpll_val = 0 ; Port_Init(); Isr_Init(); i = 2 ; //hzh, don&#39;t use 100M! //boot_params.cpu_clk.val = 3; switch ( i ) { case 0: //200 key = 12; mpll_val = (92<<12)|(4<<4)|(1); break; case 1: //300 key = 13; mpll_val = (67<<12)|(1<<4)|(1); break; case 2: //400 key = 14; mpll_val = (92<<12)|(1<<4)|(1); break; case 3: //440!!! key = 14; mpll_val = (102<<12)|(1<<4)|(1); break; default: key = 14; mpll_val = (92<<12)|(1<>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3); ChangeClockDivider(key, 12); cal_cpu_bus_clk(); consoleNum = 0; // Uart 0 select for debug. Uart_Init( 0,115200 ); //串口初始化 Uart_Select( consoleNum ); uart0_int(); //串口中断初始化 #if 0 UsbdMain(); MMU_Init(); //MMU should be reconfigured or turned off for the debugger, #else MMU_Init(); //hzh #ifdef DEBUG_VERSION #endif #endif Uart_Printf("please input 1/2/3 \n"); uarttem=0; while(1) { switch(uarttem) { case &#39;1&#39;: Uart_Printf("我是小丑!\n"); uarttem=0; break; case &#39;2&#39;: Uart_Printf("但我很自信!\n"); uarttem=0; break; case &#39;3&#39;: Uart_Printf("我也有梦想!\n"); uarttem=0; break; default: break; } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值