ARM裸机程序设计—LCD程序设计

来源:互联网 发布:新疆七五事件真相知乎 编辑:程序博客网 时间:2024/06/07 02:41

LCD裸机驱动程序总结:

LCD裸机驱动程序流程:
一、LCD初始化:
   1、端口初始化:设置GPC和GPD为LCD输出端口模式
   2、显示模式初始化:
       LCDCON1:选择BBP(位每像素)模式、选择显示模式、决定VLCK频率
       LCDCON2:bit[31:24](1:VPBD)、bit[23:14](320-1:行数)、bit[13:6](5:VFPD)、bit[5:0](1:VSPW)
       LCDCON3:bit[25:19](36:HBPD);bit[18:8](240-1:列数);bit[7:0](19:HFPD)
       LCDCON4:bit[15:8](13:MVAL,只有当LCDCON1 bit[7]MMODE=1才有效);bit[7:0](5:HSPW)
       LCDCON5:bit[11](5:6:5 Format)
   3、帧缓初始化:设置帧缓冲器的起始地址、结束地址、虚拟屏
   4、LCD其他杂项设置:屏蔽中断、调色板、禁止LPC3600/LCC3600模式
   5、LCD开启和关闭:LCDCON1的第0位置1即可开启LCD
二、LCD显示:由于一帧中有240*320个像素点,每个像素点都有一个值(0-255),那么把每个像素点的值送到帧缓冲器中,即可实现显示功能。 如果想显示图片的话,需要把一张图片转化成数据,然后在程序中把每一个像素点送到帧缓冲器即可。

源程序:

//Main.c

/*************************************************
实验环境:mini2440开发板
完成时间:2011,4,15
作者:阿龍
实现功能:在LCD上进行显示
遇到的问题:
**************************************************/
#define GLOBAL_CLK  1
#include <stdlib.h>
#include <string.h>
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "mmu.h"
#include "profile.h"
#include "memtest.h"

#define CLKVAL 4
#define LCD_LONG 320
#define LCD_WIDTH 240

#define LINEVAL LCD_LONG-1
#define LCD_YSIZE LCD_LONG
#define LCD_XSIZE LCD_WIDTH

#define LCD_UPPER_MARGIN 1
#define LCD_LOWER_MARGIN 5
#define LCD_VSYNC_LEN 1

#define LCD_RIGHT_MARGIN 39
#define LCD_LEFT_MARGIN 16
#define LCD_HSYNC_LEN 5

#define SCR_XSIZE LCD_XSIZE
#define SCR_YSIZE LCD_YSIZE
volatile static unsigned short LCD_BUFFER[SCR_YSIZE][SCR_XSIZE];

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

#define PAGEWIDE LCD_WIDTH
#define OFFSIZE 0

#define LCD_RIGHT_MARGIN 39
#define LCD_LEFT_MARGIN 16
#define LCD_HSYNC_LEN 5
#define ADC_FREQ 2500000
extern unsigned char sunflower_240x320[];
/**************************************************
函数声明
***************************************************/
void delay(int times);
void LCD_init(void);
void LCD_port_init(void);
void DisM_init(void);
void FraBuf_init(void);
void MASK(void);
static void Lcd_EnvidOnOff(int num);
void TFT_LCD_Show(void);
static void Lcd_ClearScr(U16 c);
static void Pait_Bmp(int x0,int y0,int h,int l,const unsigned char *bmp);
void Set_Clk(void);
static void cal_cpu_bus_clk(void);
/**************************************************
主函数
***************************************************/
void Main(void)
{
 /*时钟初始化*/
 Set_Clk();
 //MMU_Init();  //不能用MMU_Init()
 /*LCD初始化*/
 LCD_init();
 /*LCD显示*/
 TFT_LCD_Show();
 }
void delay(int times)
{
 int x,y;
 for(x=times;x>0;x--)
  for(y=400;y>0;y--);
}
/*********************************************************
LCD初始化
**********************************************************/
void LCD_init(void)
{
 /*LCD端口初始化*/
 LCD_port_init();
 /*显示模式初始化*/
 DisM_init();
 /*LCD帧缓冲初始化*/
 FraBuf_init();
 /*LCD其他杂项屏蔽和处理*/ 
 MASK();
 /*LCD开启和关闭*/
 Lcd_EnvidOnOff(1); 
}
/**************************************************
LCD端口初始化
***************************************************/
void LCD_port_init(void)
{
 rGPCCON = 0xaaaa02a8;  //设置GPC为LCD模式
 rGPCUP = 0xffffffff;
 rGPDCON =0xaaaaaaa;
 rGPCUP =0xffffffff;
}
/*********************************************************
LCD显示模式初始化
**********************************************************/
void DisM_init(void)
{
 /*bit[17:8](4:CLKVAL);bit[6:5](11:TFT LCD panel);bit[4:1](1100:16 bpp for TFT)*/
 rLCDCON1 = (12<<1)|(3<<5)|(CLKVAL<<8);   //选择BBP(位每像素)模式、选择显示模式、决定VCLK频率
 /*bit[31:24](1:VBPD);bit[23:14](320-1:行数);bit[13:6](5:VFPD);bit[5:0](1:VSPW)*/
 rLCDCON2 = (LCD_UPPER_MARGIN<<24)|((LCD_YSIZE-1)<<14)|(LCD_LOWER_MARGIN<<6)|(LCD_VSYNC_LEN<<0);
 /*bit[25:19](36:HBPD);bit[18:8](240-1:列数);bit[7:0](19:HFPD)*/
 rLCDCON3 = (LCD_RIGHT_MARGIN <<19)|((LCD_XSIZE-1)<<8)|(LCD_LEFT_MARGIN<<0);
 /*bit[15:8](13:MVAL,只有当LCDCON1 bit[7]MMODE=1才有效);bit[7:0](5:HSPW)*/
 rLCDCON4 = (13<<8)|(LCD_HSYNC_LEN<<0);
 /*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)*/
 rLCDCON5 = (1<<0)|(1<<3)|(1<<8)|(1<<9)|(1<<11); 
}
/*********************************************************
LCD帧缓存寄存器初始化
**********************************************************/
void FraBuf_init(void)
{
 /* LCDBANK: 视频帧缓冲区内存地址30-22位。     LCDBASEU: 视频帧缓冲区的开始地址21-1位

LCDBASEL: 视频帧缓冲区的结束地址21-1位*/
 /*bit[29:21]:LCDBANK,bit[20:0]:LCDBASEU*/
 rLCDSADDR1 = ((LCD_ADDR>>22)<<21)|((M5D(LCD_ADDR>>1))<<0);
 /*bit[20:0]:LCDBASEL*/
 rLCDSADDR2 = M5D((LCD_ADDR+LCD_WIDTH * LCD_LONG * 2)>>1);
 /*PAGEWIDTH:虚拟屏幕一行的字节数,如果不使用虚拟屏幕,设置为实际屏幕的行字节数
   OFFSIZE:虚拟屏幕左侧偏移的字节数,如果不使用虚拟屏幕,设置为*/
 /*bit[21:11]:OFFSIZE; bit[10:0]:PAGEWIDTH*/
 rLCDSADDR3 = LCD_WIDTH;
}
/*********************************************************
对LCD其他的一些屏蔽和处理
**********************************************************/
void MASK(void)
{
 /*屏蔽中断*/
 rLCDINTMSK |= 3;
 rTCONSEL   &= (~7);
 
 /*disable调色板*/
 rTPAL = 0x0;
    
 /*禁止LPC3600/LCC3600模式*/
 rTCONSEL &= ~((1<<4) | 1);  
}
/*********************************************************
LCD的开启与关闭函数
**********************************************************/
static void Lcd_EnvidOnOff(int onoff)
{
 if(onoff==1)
    rLCDCON1|=1; // ENVID=ON
 else
    rLCDCON1 =rLCDCON1 & 0x3fffe; // ENVID Off
}
/*********************************************************
LCD显示函数
**********************************************************/
void TFT_LCD_Show(void)

    /*红(255:0:0);绿(0:255:0);蓝(0:0:255);黑(0:0:0);白(255,255,255)*/
     /*在屏幕上显示三基色*/
    Lcd_ClearScr( (0x00<<11) | (0x00<<5) | (0x00)  )  ;  //clear screen black
    delay(10000);
    Lcd_ClearScr((0x1f<<11) | (0x00<<5) | (0x00));   //red
    delay(10000);
     Lcd_ClearScr((0x00<<11) | (0x3f<<5) | (0x00));   //green
    delay(10000);
    Lcd_ClearScr((0x00<<11) | (0x00<<5) | (0x1f));   //blue
    delay(10000);

    Lcd_ClearScr( (0x1f<<11) | (0x3f<<5) | (0x1f)  )  ;  //clear screen white
    delay(10000);
    /*显示一副图片在屏幕上*/
    Pait_Bmp(0, 0, 240, 320, sunflower_240x320);
}
/*********************************************************
LCD全屏填充颜色函数
**********************************************************/
static 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;    //把得到的值送到缓冲器中即可显示颜色
  }
}
/*在屏幕上显示图片*/
static void Pait_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 Set_Clk(void)
{
 int i;
 U8 key;
 U32 mpll_val = 0 ;
 i = 2 ;              //don'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<<4)|(1);
  break;
 }
  //init FCLK=400M, so change MPLL first
 ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);   //set the register--rMPLLCON
 ChangeClockDivider(key, 12);    //the result of rCLKDIVN [0:1:0:1] 3-0 bit
 cal_cpu_bus_clk();    //HCLK=100M   PCLK=50M
}
/*************************************************
**************************************************/
static void cal_cpu_bus_clk(void)
{
 static U32 cpu_freq;
    static U32 UPLL;
  U32 val;
 U8 m, p, s;
  val = rMPLLCON;
 m = (val>>12)&0xff;
 p = (val>>4)&0x3f;
 s = val&3;

 //(m+8)*FIN*2 不要超出32位数!
 FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;     //FCLK=400M  FIN=12000000
 val = rCLKDIVN;
 m = (val>>1)&3;
 p = val&1; 
 val = rCAMDIVN;
 s = val>>8;
  switch (m) {
 case 0:
  HCLK = FCLK;
  break;
 case 1:
  HCLK = FCLK>>1;
  break;
 case 2:
  if(s&2)
   HCLK = FCLK>>3;
  else
   HCLK = FCLK>>2;
  break;
 case 3:
  if(s&1)
   HCLK = FCLK/6;
  else
   HCLK = FCLK/3;
  break;
 }
  if(p)
  PCLK = HCLK>>1;
 else
  PCLK = HCLK;
 if(s&0x10)
  cpu_freq = HCLK;
 else
  cpu_freq = FCLK;
 val = rUPLLCON;
 m = (val>>12)&0xff;
 p = (val>>4)&0x3f;
 s = val&3;
 UPLL = ((m+8)*FIN)/((p+2)*(1<<s));
 UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;
}