Mini2440裸机液晶屏TD35驱动

我把地址定义都加到.h文件中,使用时只需包含lcd_td35.h即可。

能简单实现画点,画线,画矩形,显示图片,显示字符和字符串,显示数字功能。

// lcd_td35.h
// 2015.12.16

#ifndef __LCD_TD35_H__
#define __LCD_TD35_H__

#define U32 unsigned int
#define U16 unsigned short
#define S32 int
#define S16 short int
#define U8  unsigned char
#define    S8  char

#define    BYTE    char
#define    WORD     short
#define    DWORD    int
#define    UINT    U32
#define    LPSTR    U8 *        

#define TRUE     1   
#define FALSE     0
#define OK        1
#define FAIL    0

// S3C2440地址宏定义
//=====================================================================
// I/O PORT 
#define rGPACON    (*(volatile unsigned *)0x56000000)    //Port A control
#define rGPADAT    (*(volatile unsigned *)0x56000004)    //Port A data

#define rGPBCON    (*(volatile unsigned *)0x56000010)    //Port B control
#define rGPBDAT    (*(volatile unsigned *)0x56000014)    //Port B data
#define rGPBUP     (*(volatile unsigned *)0x56000018)    //Pull-up control B

#define rGPCCON    (*(volatile unsigned *)0x56000020)    //Port C control
#define rGPCDAT    (*(volatile unsigned *)0x56000024)    //Port C data
#define rGPCUP     (*(volatile unsigned *)0x56000028)    //Pull-up control C

#define rGPDCON    (*(volatile unsigned *)0x56000030)    //Port D control
#define rGPDDAT    (*(volatile unsigned *)0x56000034)    //Port D data
#define rGPDUP     (*(volatile unsigned *)0x56000038)    //Pull-up control D

#define rGPECON    (*(volatile unsigned *)0x56000040)    //Port E control
#define rGPEDAT    (*(volatile unsigned *)0x56000044)    //Port E data
#define rGPEUP     (*(volatile unsigned *)0x56000048)    //Pull-up control E

#define rGPFCON    (*(volatile unsigned *)0x56000050)    //Port F control
#define rGPFDAT    (*(volatile unsigned *)0x56000054)    //Port F data
#define rGPFUP     (*(volatile unsigned *)0x56000058)    //Pull-up control F

#define rGPGCON    (*(volatile unsigned *)0x56000060)    //Port G control
#define rGPGDAT    (*(volatile unsigned *)0x56000064)    //Port G data
#define rGPGUP     (*(volatile unsigned *)0x56000068)    //Pull-up control G

#define rGPHCON    (*(volatile unsigned *)0x56000070)    //Port H control
#define rGPHDAT    (*(volatile unsigned *)0x56000074)    //Port H data
#define rGPHUP     (*(volatile unsigned *)0x56000078)    //Pull-up control H

#define rGPJCON    (*(volatile unsigned *)0x560000d0)    //Port J control
#define rGPJDAT    (*(volatile unsigned *)0x560000d4)    //Port J data
#define rGPJUP     (*(volatile unsigned *)0x560000d8)    //Pull-up control J

// PWM TIMER 1
#define rTCFG0  (*(volatile unsigned *)0x51000000)    //Timer 0 configuration
#define rTCFG1  (*(volatile unsigned *)0x51000004)    //Timer 1 configuration
#define rTCON   (*(volatile unsigned *)0x51000008)    //Timer control
#define rTCNTB1 (*(volatile unsigned *)0x51000018)    //Timer count buffer 1
#define rTCMPB1 (*(volatile unsigned *)0x5100001c)    //Timer compare buffer 1
#define rTCNTO1 (*(volatile unsigned *)0x51000020)    //Timer count observation 1
// TIMER 3
#define rTCNTB3 (*(volatile unsigned *)0x51000030)    //Timer count buffer 3
#define rTCMPB3 (*(volatile unsigned *)0x51000034)    //Timer compare buffer 3
#define rTCNTO3 (*(volatile unsigned *)0x51000038)    //Timer count observation 3

// LCD CONTROLLER
#define rLCDCON1    (*(volatile unsigned *)0x4d000000)    //LCD control 1
#define rLCDCON2    (*(volatile unsigned *)0x4d000004)    //LCD control 2
#define rLCDCON3    (*(volatile unsigned *)0x4d000008)    //LCD control 3
#define rLCDCON4    (*(volatile unsigned *)0x4d00000c)    //LCD control 4
#define rLCDCON5    (*(volatile unsigned *)0x4d000010)    //LCD control 5
#define rLCDSADDR1  (*(volatile unsigned *)0x4d000014)    //STN/TFT Frame buffer start address 1
#define rLCDSADDR2  (*(volatile unsigned *)0x4d000018)    //STN/TFT Frame buffer start address 2
#define rLCDSADDR3  (*(volatile unsigned *)0x4d00001c)    //STN/TFT Virtual screen address set
#define rREDLUT     (*(volatile unsigned *)0x4d000020)    //STN Red lookup table
#define rGREENLUT   (*(volatile unsigned *)0x4d000024)    //STN Green lookup table 
#define rBLUELUT    (*(volatile unsigned *)0x4d000028)    //STN Blue lookup table
#define rDITHMODE   (*(volatile unsigned *)0x4d00004c)    //STN Dithering mode
#define rTPAL       (*(volatile unsigned *)0x4d000050)    //TFT Temporary palette
#define rLCDINTPND  (*(volatile unsigned *)0x4d000054)    //LCD Interrupt pending
#define rLCDSRCPND  (*(volatile unsigned *)0x4d000058)    //LCD Interrupt source
#define rLCDINTMSK  (*(volatile unsigned *)0x4d00005c)    //LCD Interrupt mask
#define rTCONSEL     (*(volatile unsigned *)0x4d000060)    //LPC3600 Control --- edited by junon
#define PALETTE     0x4d000400                        //Palette start address
//=================================================================================

// LCD_TD35
#define LCD_TD35
#define LCD_WIDTH 240
#define LCD_HEIGHT 320

#define LCD_PIXCLOCK 4

#define LCD_RIGHT_MARGIN 100
#define LCD_LEFT_MARGIN 0
#define LCD_HSYNC_LEN 4

#define LCD_UPPER_MARGIN 0
#define LCD_LOWER_MARGIN 0
#define LCD_VSYNC_LEN 9

// 延时Ms
void Lcd_Delay_Ms(int time);
// LCD背光
void LcdBkLtSet(U32 HiRatio);

// 初始化用于LCD的引脚
void Lcd_Port_Init(void);

// MODE_16BIT_240320
void Lcd_Init(void);

/*
 * 设置是否输出LCD电源开关信号LCD_PWREN
 * 输入参数:
 *     invpwren: 0 - LCD_PWREN有效时为正常极性
 *               1 - LCD_PWREN有效时为反转极性
 *     pwren:    0 - LCD_PWREN输出有效
 *               1 - LCD_PWREN输出无效
 */
void Lcd_PowerEnable(int invpwren, int pwren);
// LCD控制器是否输出信号
void Lcd_EnvidOnOff(int onoff);
// 完成所有初始化
void Lcd_TD35_Init(void);
// 画像素点
void PutPixel(U32 x,U32 y,U16 c);
// 用单颜色清屏(5:6:5 RGB)
void Lcd_ClearScr(U16 c);
// 画线
void Draw_Line(int x1,int y1,int x2,int y2, U16 color);
// 画矩形
void Draw_Rectangle(int x1,int y1,int x2,int y2, U16 color);
// 显示图片(240x320)
void Draw_Bmp(int x0,int y0,int h,int l,const unsigned char *bmp);
// 显示ASCII 字符
// x,y:起始坐标
// color:颜色
// size:字体大小 12/16/24
// mode:当前背景(1)自定义白色背景(0)
// ch:要显示的字符:" "--->"~"
void Draw_Char(U16 x, U16 y, U16 color, U8 size, U8 mode, U8 ch);
// 显示字符串
// x,y:起点坐标
// width,height:区域大小  
// color:颜色
// size:字体大小 12/16/24
// mode:当前背景(1)自定义白色背景(0)
// *p:字符串起始地址 
void Draw_String(U16 x, U16 y, U16 width, U16 height, U16 color, U8 size, U8 mode, U8 p[]);  
// m^n次方
U32 Lcd_Pow(U8 m,U8 n);
// 显示数字
// x,y:起点坐标
// color:颜色
// size:字体大小 12/16/24
// mode:当前背景(1)自定义白色背景(0)
// num:  
// len:显示位数
// 超过前面是否补0,是(1)
void Draw_Num(U16 x,U16 y,U16 color,U8 size,U8 mode,U32 num,U8 len,U8 show0);


// 测试用
void Lcd_TD35_Test(void);

#endif
// lcd_td35.c
// 2015.12.16

#include "lcd_td35.h"
#include "lcd_font.h"
#include "scene1_240x320.h" // 包含图片数据

#define GPB1_TO_OUT()       (rGPBUP &= 0xfffd, rGPBCON &= 0xfffffff3, rGPBCON |= 0x00000004)
#define GPB1_TO_1()         (rGPBDAT |= 0x0002)
#define GPB1_TO_0()         (rGPBDAT &= 0xfffd)


#define LCD_XSIZE  LCD_WIDTH    // 240
#define LCD_YSIZE  LCD_HEIGHT   // 320
#define SCR_XSIZE  LCD_WIDTH
#define SCR_YSIZE  LCD_HEIGHT   

volatile static unsigned short LCD_BUFFER[SCR_YSIZE][SCR_XSIZE];


void Lcd_Delay_Ms(int time)
{
    // PCLK=50MHz
    //U32 val = (PCLK>>3)/1000-1;
    U32 val = (50000000>>3)/1000-1; // 6250-1=6249

    rTCFG0 &= ~(0xff<<8);
    rTCFG0 |= 3<<8;         //prescaler = 3+1
    rTCFG1 &= ~(0xf<<12);
    rTCFG1 |= 0<<12;        //mux = 1/2

    rTCNTB3 = val;          //1000Hz   freq=50M/4/2/6249
    rTCMPB3 = val>>1;       // 50%
    rTCON &= ~(0xf<<16);
    rTCON |= 0xb<<16;       //interval, inv-off, update TCNTB3&TCMPB3, start timer 3
    rTCON &= ~(2<<16);      //clear manual update bit
    while(time--) {
        while(rTCNTO3>=val>>1);
        while(rTCNTO3<val>>1);
    };
}

void LcdBkLtSet(U32 HiRatio)
{
#define FREQ_PWM1       1000

    if(!HiRatio)
    {
        rGPBCON  = rGPBCON & (~(3<<2)) | (1<<2);
        rGPBDAT &= ~(1<<1);
        return;
    }
    rGPBCON = rGPBCON & (~(3<<2)) | (2<<2);
    
    if( HiRatio > 100 )
        HiRatio = 100 ; 
    
    rTCON = rTCON & (~(0xf<<8)) ;           // clear manual update bit, stop Timer1

    rTCFG0  &= 0xffffff00;                  // set Timer 0&1 prescaler 0
    rTCFG0 |= 15;                           //prescaler = 15+1

    rTCFG1  &= 0xffffff0f;                  // set Timer 1 MUX 1/16
    rTCFG1  |= 0x00000030;                  // set Timer 1 MUX 1/16

    rTCNTB1  = ( 100000000>>8 )/FREQ_PWM1;      //if set inverter off, when TCNT2<=TCMP2, TOUT is high, TCNT2>TCMP2, TOUT is low
    rTCMPB1  = ( rTCNTB1*(100-HiRatio))/100 ;   //if set inverter on,  when TCNT2<=TCMP2, TOUT is low,  TCNT2>TCMP2, TOUT is high

    rTCON = rTCON & (~(0xf<<8)) | (0x0e<<8) ;
    rTCON = rTCON & (~(0xf<<8)) | (0x0d<<8) ;
}

void Lcd_Port_Init(void)
{
    GPB1_TO_OUT();
    GPB1_TO_1();

    rGPCUP=0xffffffff; // Disable Pull-up register
    rGPCCON=0xaaaa02a8; //Initialize VD[7:0],VM,VFRAME,VLINE,VCLK

    rGPDUP=0xffffffff; // Disable Pull-up register
    rGPDCON=0xaaaaaaaa; //Initialize VD[15:8]
}

void Lcd_Init(void)
{
#define M5D(n)  ((n)&0x1fffff)
#define LCD_ADDR ((U32)LCD_BUFFER)

    rLCDCON1 = (LCD_PIXCLOCK << 8) | (3 <<  5) | (12 << 1);
    rLCDCON2 = (LCD_UPPER_MARGIN << 24) | ((LCD_HEIGHT - 1) << 14) | (LCD_LOWER_MARGIN << 6) | (LCD_VSYNC_LEN << 0);
    rLCDCON3 = (LCD_RIGHT_MARGIN << 19) | ((LCD_WIDTH  - 1) <<  8) | (LCD_LEFT_MARGIN << 0);
    rLCDCON4 = (13 <<  8) | (LCD_HSYNC_LEN << 0);
    //rLCDCON5 = (1<<11) | (1 << 9) | (1 << 8) | (1 << 3) | (1 << 0);
    rLCDCON5 = (1<<11) | (1<<10) | (1<<8) | (1<<9) | (1<<0);

    rLCDSADDR1 = ((LCD_ADDR >> 22) << 21) | ((M5D(LCD_ADDR >> 1)) <<  0);
    rLCDSADDR2 = M5D((LCD_ADDR + LCD_WIDTH * LCD_HEIGHT * 2) >> 1);
    rLCDSADDR3 = LCD_WIDTH;        

    rLCDINTMSK |= 3;
    rTCONSEL &= (~7);
 
    rTPAL = 0x0;
    rTCONSEL &= ~((1<<4) | 1);  
}

void Lcd_PowerEnable(int invpwren,int pwren)
{
    //GPG4 is setted as LCD_PWREN
    rGPGUP = rGPGUP|(1<<4); // Pull-up disable
    rGPGCON = rGPGCON|(3<<8); //GPG4=LCD_PWREN
    
    //Enable LCD POWER ENABLE Function
    rLCDCON5 = rLCDCON5&(~(1<<3))|(pwren<<3);   // PWREN
    rLCDCON5 = rLCDCON5&(~(1<<5))|(invpwren<<5);   // INVPWREN
}

void Lcd_EnvidOnOff(int onoff)
{
    if(onoff==1)
    rLCDCON1|=1; // ENVID=ON
    else
    rLCDCON1 =rLCDCON1 & 0x3fffe; // ENVID Off
}

void Lcd_TD35_Init(void)
{
    Lcd_Init();
    //LcdBkLtSet(70);
    Lcd_PowerEnable(0, 1);
    Lcd_EnvidOnOff(1); 
    // RGB=5:6:5
    Lcd_ClearScr( (0x00<<11) | (0x00<<5) | (0x00) );  
}

void PutPixel(U32 x,U32 y,U16 c)
{
    if(x<SCR_XSIZE && y<SCR_YSIZE)
        LCD_BUFFER[(y)][(x)] = c;
}

// 5:6:5 RGB
void Lcd_ClearScr(U16 c)
{
    unsigned int x,y ;
        
    for( y = 0 ; y < SCR_YSIZE ; y++ )
    {
        for( x = 0 ; x < SCR_XSIZE ; x++ )
        {
            LCD_BUFFER[y][x] = c ;
        }
    }
}

void Draw_Line(int x1,int y1,int x2,int y2, U16 color)
{
    int dx,dy,e;
    dx=x2-x1; 
    dy=y2-y1;
    
    if(dx>=0)
    {
        if(dy >= 0) // dy>=0
        {
            if(dx>=dy) // 1/8 octant
            {
                e=dy-dx/2;
                while(x1<=x2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){y1+=1;e-=dx;}   
                    x1+=1;
                    e+=dy;
                }
            }
            else        // 2/8 octant
            {
                e=dx-dy/2;
                while(y1<=y2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){x1+=1;e-=dy;}   
                    y1+=1;
                    e+=dx;
                }
            }
        }
        else           // dy<0
        {
            dy=-dy;   // dy=abs(dy)

            if(dx>=dy) // 8/8 octant
            {
                e=dy-dx/2;
                while(x1<=x2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){y1-=1;e-=dx;}   
                    x1+=1;
                    e+=dy;
                }
            }
            else        // 7/8 octant
            {
                e=dx-dy/2;
                while(y1>=y2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){x1+=1;e-=dy;}   
                    y1-=1;
                    e+=dx;
                }
            }
        }   
    }
    else //dx<0
    {
        dx=-dx;     //dx=abs(dx)
        if(dy >= 0) // dy>=0
        {
            if(dx>=dy) // 4/8 octant
            {
                e=dy-dx/2;
                while(x1>=x2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){y1+=1;e-=dx;}   
                    x1-=1;
                    e+=dy;
                }
            }
            else        // 3/8 octant
            {
                e=dx-dy/2;
                while(y1<=y2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){x1-=1;e-=dy;}   
                    y1+=1;
                    e+=dx;
                }
            }
        }
        else           // dy<0
        {
            dy=-dy;   // dy=abs(dy)

            if(dx>=dy) // 5/8 octant
            {
                e=dy-dx/2;
                while(x1>=x2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){y1-=1;e-=dx;}   
                    x1-=1;
                    e+=dy;
                }
            }
            else        // 6/8 octant
            {
                e=dx-dy/2;
                while(y1>=y2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){x1-=1;e-=dy;}   
                    y1-=1;
                    e+=dx;
                }
            }
        }   
    }
}

void Draw_Rectangle(int x1,int y1,int x2,int y2, U16 color)
{
    int i;

    for(i=y1;i<=y2;i++)
        Draw_Line(x1,i,x2,i,color);
}

// full screen, x0=y0=0,h=240,l=320
void Draw_Bmp(int x0,int y0,int h,int l,const unsigned char *bmp)
{
    int x,y;
    U32 c;
    int p = 0;
    
    for( y = 0 ; y < l ; y++ )
    {
        for( x = 0 ; x < h ; x++ )
        {
            c = bmp[p+1] | (bmp[p]<<8) ;

            if ( ( (x0+x) < SCR_XSIZE) && ( (y0+y) < SCR_YSIZE) )
                LCD_BUFFER[y0+y][x0+x] = c ;

            p = p + 2 ;
        }
    }
}

void Draw_Char(U16 x, U16 y, U16 color, U8 size, U8 mode, U8 ch)
{                             
    U8 temp,t1,t;
    U16 y0=y;
    // 计算字体大小
    U8 csize=(size / 8 + ((size % 8)?1:0))*(size/2);              
    ch = ch - ' ';
    for(t=0;t<csize;t++)
    {   
        if(size==12)
            temp=ASCII_1206[ch][t];
        else if(size==16)
            temp=ASCII_1608[ch][t];
        else if(size==24)
            temp=ASCII_2412[ch][t];
        else 
            return; 
        for(t1=0;t1<8;t1++)
        {               
            if(temp & 0x80)
                PutPixel(x,y,color);
            else if(mode==0)
                PutPixel(x,y,0xffff);
                //PutPixel(x,y,color);
            temp<<=1;
            y++;
            if(x>=LCD_WIDTH)
                return;
            if((y-y0)==12)
            {
                y=y0;
                x++;
                if(x>=LCD_WIDTH)
                    return;  
                break;
            }
        }    
    }   
}   
    
void Draw_String(U16 x, U16 y, U16 width, U16 height, U16 color, U8 size, U8 mode, U8 p[])
{         
    U8 x0 = x;
    width += x;
    height += y;
    while((*p<='~')&&(*p>=' '))
    {       
        if(x>=width){x=x0;y+=size;}
        if(y>=height)break;
        Draw_Char(x,y,color,size,mode,*p);
        x+=size/2;
        p++;
    }  
}

U32 Lcd_Pow(U8 m,U8 n)
{
    U32 result=1;    
    while(n--)result*=m;    
    return result;
}   

//
void Draw_Num(U16 x,U16 y,U16 color,U8 size,U8 mode,U32 num,U8 len,U8 show0)
{  
    U8 t,temp;
    U8 enshow=0;                           
    for(t=0;t<len;t++)
    {
        temp=(num/Lcd_Pow(10,len-t-1))%10;
        if(enshow==0&&t<(len-1))
        {
            if(temp==0)
            {
                if(show0)
                    Draw_Char(x+(size/2)*t,y,color,size,mode,'0');  
                else 
                    Draw_Char(x+(size/2)*t,y,color,size,mode,' ');  
                continue;
            }
            else 
                enshow=1; 
             
        }
        Draw_Char(x+(size/2)*t,y,color,size,mode,temp+'0');
    }
} 

void Lcd_TD35_Test(void)
{
    Lcd_ClearScr(0);
    //Lcd_Delay_Ms(1000);

/*    Lcd_ClearScr(0);
    #define LCD_BLANK       30
    #define C_UP        ( LCD_XSIZE - LCD_BLANK*2 )
    #define C_RIGHT     ( LCD_XSIZE - LCD_BLANK*2 )
    #define V_BLACK     ( ( LCD_YSIZE - LCD_BLANK*4 ) / 6 )
    Draw_Rectangle( LCD_BLANK, LCD_BLANK, ( LCD_XSIZE - LCD_BLANK ), ( LCD_YSIZE - LCD_BLANK ),0x0000);       //fill a Rectangle with some color
    Draw_Rectangle( (LCD_BLANK*2), (LCD_BLANK*2 + V_BLACK*0), (C_RIGHT), (LCD_BLANK*2 + V_BLACK*1),0x001f);       //fill a Rectangle with some color
    Draw_Rectangle( (LCD_BLANK*2), (LCD_BLANK*2 + V_BLACK*1), (C_RIGHT), (LCD_BLANK*2 + V_BLACK*2),0x07e0);       //fill a Rectangle with some color
    Draw_Rectangle( (LCD_BLANK*2), (LCD_BLANK*2 + V_BLACK*2), (C_RIGHT), (LCD_BLANK*2 + V_BLACK*3),0xf800);       //fill a Rectangle with some color
    Draw_Rectangle( (LCD_BLANK*2), (LCD_BLANK*2 + V_BLACK*3), (C_RIGHT), (LCD_BLANK*2 + V_BLACK*4),0xffe0);       //fill a Rectangle with some color
    Draw_Rectangle( (LCD_BLANK*2), (LCD_BLANK*2 + V_BLACK*4), (C_RIGHT), (LCD_BLANK*2 + V_BLACK*5),0xf81f);       //fill a Rectangle with some color
    Draw_Rectangle( (LCD_BLANK*2), (LCD_BLANK*2 + V_BLACK*5), (C_RIGHT), (LCD_BLANK*2 + V_BLACK*6),0x07ff);       //fill a Rectangle with some color
    Lcd_Delay_Ms(1000);

    Lcd_ClearScr(0);
    Draw_Bmp(0, 0, 240, 320, scene1_240x320);
    Lcd_Delay_Ms(1000);*/

    Draw_Char(0, 0, 0xffff, 12, 1, 'A');
    Draw_Char(50, 0, 0xffff, 16, 1, 'A');
    Draw_Char(150, 0, 0xffff, 24, 1, 'A');

    Draw_String(0, 100, 100, 100, 0x001f, 12, 1, "Hello World ! Hello World ! Hello World !");
    Draw_String(120, 100, 100, 100, 0x001f, 16, 1, "Hello World !");

    Draw_Num(0,200,0xffff,16,1,1234,3,0);
    Draw_Num(50,200,0xffff,16,1,1234,6,0);
    Draw_Num(100,200,0xffff,16,1,1234,6,1);

}

 

posted @ 2015-12-18 18:47  ht-beyond  阅读(1134)  评论(0编辑  收藏  举报