实验(12)LCD实验
(1)head.S程序如下:
@**
@ File: head.S
@功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
@**
.extern main
.text
.global _start
_start:
@**
@中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用
@**
b Reset
@ 0x04:未定义指令中止模式的向量地址
HandleUndef:
b HandleUndef
@ 0x08:管理模式的向量地址,通过SWI指令进入此模式
HandleSWI:
b HandleSWI
@ 0x0c:指令预取终止导致的异常的向量地址
HandlePrefetchAbort:
b HandlePrefetchAbort
@ 0x10:数据访问终止导致的异常的向量地址
HandleDataAbort:
b HandleDataAbort
@ 0x14:保留
HandleNotUsed:
b HandleNotUsed
@ 0x18:中断模式的向量地址
b HandleIRQ
@ 0x1c:快中断模式的向量地址
HandleFIQ:
b HandleFIQ
Reset:
ldr sp, =4096 @设置栈指针,以下都是C函数,调用前需要设好栈
bl disable_watch_dog @关闭WATCHDOG,否则CPU会不断重启
bl clock_init @设置MPLL,改变FCLK、HCLK、PCLK
bl memsetup @设置存储控制器以使用SDRAM
bl nand_init @初始化NAND Flash
@复制代码到SDRAM中
ldr r0, =0x30000000 @ 1.目标地址= 0x30000000,这是SDRAM的起始地址
mov r1, #4096 @ 2.源地址= 4096,在SDRAM中运行的代码保存在NF该址开始处
mov r2, #16*1024 @ 3.复制长度= 16K,对于本实验,这是足够了
bl CopyCode2SDRAM @调用C函数CopyCode2SDRAM
@将NAND Flash中地址4096开始的2048字节代码(main.c编译得到)复制到SDRAM中
bl RdNF2SDRAM @调用C函数RdNF2SDRAM
bl clean_bss @清除bss段,未初始化或初值为0的全局/静态变量保存在bss段
msr cpsr_c, #0xd2 @进入中断模式
ldr sp, =0x31000000 @设置中断模式栈指针
msr cpsr_c, #0xdf @进入系统模式
ldr sp, =0x34000000 @设置系统模式栈指针
ldr lr, =ret_initirq @设置返回地址
ldr pc, =init_irq @调用中断初始化函数
ret_initirq:
msr cpsr_c, #0x5f @设置I-bit=0,开IRQ中断
ldr lr, =halt_loop @设置返回地址
ldr pc, =main @调用main函数
halt_loop:
b halt_loop
HandleIRQ:
sub lr, lr, #4 @计算返回地址
stmdb sp!,{ r0-r12,lr } @保存使用到的寄存器
@注意,此时的sp是中断模式的sp
@初始值是上面设置的4096
ldr lr, =int_return @设置调用IRQ_Handle函数后的返回地址
ldr pc, =IRQ_Handle @调用中断分发函数,在interrupt.c中
int_return:
ldmia sp!,{ r0-r12,pc }^ @中断返回, ^表示将spsr的值复制到cpsr
(2)init.c程序如下:
/*
- init.c:进行一些初始化
*/
include "s3c24xx.h"
void disable_watch_dog(void);
void clock_init(void);
void memsetup(void);
void copy_steppingstone_to_sdram(void);
void clean_bss(void);
/*
*关闭WATCHDOG,否则CPU会不断重启
*/
void disable_watch_dog(void)
{
WTCON = 0; //关闭WATCHDOG很简单,往这个寄存器写0即可
}
define FCLK 200000000
define HCLK 100000000
define PCLK 50000000
define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))
define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
/*
*对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV
*有如下计算公式:
S3C2410: MPLL(FCLK) = (m Fin)/(p 2^s)
S3C2410: MPLL(FCLK) = (2 m Fin)/(p * 2^s)
*其中: m = MDIV + 8, p = PDIV + 2, s = SDIV
*对于本开发板,Fin = 12MHz
*设置CLKDIVN,令分频比为:FCLK:HCLK:PCLK=1:2:4,
- FCLK=200MHz,HCLK=100MHz,PCLK=50MHz
*/
void clock_init(void)
{
// LOCKTIME = 0x00ffffff; //使用默认值即可
CLKDIVN = 0x03; // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
/ HDIVN非0,CPU的总线模式应变为“asynchronous bus mode”/
asm(
"mrc p15, 0, r1, c1, c0, 0\n" /读出控制寄存器/
"orr r1, r1, #0xc0000000\n" /设置为“asynchronous bus mode”/
"mcr p15, 0, r1, c1, c0, 0\n" /写入控制寄存器/
);
/判断是S3C2410还是S3C2440 /
if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
{
MPLLCON = S3C2410_MPLL_200MHZ; /现在FCLK=200M,HCLK=100M,PCLK=50M/
}
else
{
MPLLCON = S3C2440_MPLL_200MHZ; /现在FCLK=200M,HCLK=100M,PCLK=50M/
}
}
/*
*设置存储控制器以使用SDRAM
*/
void memsetup(void)
{
volatile unsigned long p = (volatile unsigned long )MEM_CTL_BASE;
/*这个函数之所以这样赋值,而不是像前面的实验(比如mmu实验)那样将配置值
*写在数组中,是因为要生成”位置无关的代码”,使得这个函数可以在被复制到
- SDRAM之前就可以在steppingstone中运行
*/
/存储控制器13个寄存器的值/
p[0] = 0x22011110; //BWSCON
p[1] = 0x00000700; //BANKCON0
p[2] = 0x00000700; //BANKCON1
p[3] = 0x00000700; //BANKCON2
p[4] = 0x00000700; //BANKCON3
p[5] = 0x00000700; //BANKCON4
p[6] = 0x00000700; //BANKCON5
p[7] = 0x00018005; //BANKCON6
p[8] = 0x00018005; //BANKCON7
/* REFRESH,
HCLK=12MHz: 0x008C07A3,
HCLK=100MHz: 0x008C04F4
*/
p[9] = 0x008C04F4;
p[10] = 0x000000B1; //BANKSIZE
p[11] = 0x00000030; //MRSRB6
p[12] = 0x00000030; //MRSRB7
}
void copy_steppingstone_to_sdram(void)
{
unsigned int pdwSrc = (unsigned int )0;
unsigned int pdwDest = (unsigned int )0x30000000;
while (pdwSrc < (unsigned int *)4096)
{
pdwDest = pdwSrc;
pdwDest++;
pdwSrc++;
}
}
void clean_bss(void)
{
extern int bss_start, bss_end;
int *p = &__bss_start;
for (; p <&__bss_end; p++)
*p = 0;
}
(3)interrupt.c程序如下:
include "s3c24xx.h"
//extern void I2CIntHandle(void);
void (*isr_handle_array[50])(void);
void Dummy_isr(void)
{
while(1);
}
void init_irq(void)
{
int i = 0;
for (i = 0; i < sizeof(isr_handle_array) / sizeof(isr_handle_array[0]); i++)
{
isr_handle_array[i] = Dummy_isr;
}
INTMOD = 0x0; //所有中断都设为IRQ模式
INTMSK = BIT_ALLMSK; //先屏蔽所有中断
// isr_handle_array[ISR_IIC_OFT] = I2CIntHandle;
}
void IRQ_Handle(void)
{
unsigned long oft = INTOFFSET;
//清中断
if (oft == 4)
EINTPEND = 1<<7; //EINT4-7合用IRQ4,注意EINTPEND[3:0]保留未用,向这些位写入1可能导致未知结果
SRCPND = 1<<oft;
INTPND = INTPND;
/调用中断服务程序/
isr_handle_arrayoft;
}
(3_2)interrupt.h程序如下:
void EINT_Handle();
(4)main.c程序如下:
include
include "serial.h"
include "lcdlib.h"
include "s3c24xx.h"
int main()
{
char c;
uart0_init(); //波特率115200,8N1(8个数据位,无校验位,1个停止位)
while (1)
{
printf("\r\n##### Test TFT LCD #####\r\n");
printf("[1] TFT240320 8Bit\n\r");
printf("[2] TFT240320 16Bit\n\r");
printf("[3] TFT640480 8Bit\n\r");
printf("[4] TFT640480 16Bit\n\r");
printf("Enter your selection: ");
c = getc();
printf("%c\n\r", c);
switch (c)
{
case '1':
{
Test_Lcd_Tft_8Bit_240320();
break;
}
case '2':
{
Test_Lcd_Tft_16Bit_240320();
break;
}
case '3':
{
Test_Lcd_Tft_8Bit_640480();
break;
}
case '4':
{
Test_Lcd_Tft_16Bit_640480();
break;
}
default:
break;
}
}
return 0;
}
(5)lcdlib.c程序如下:
/*
- FILE: lcdlib.c——实现TFT LCD的测试函数
*/
include
include "lcddrv.h"
include "framebuffer.h"
/*
*以240x320,8bpp的显示模式测试TFT LCD
*/
void Test_Lcd_Tft_8Bit_240320(void)
{
Lcd_Port_Init(); //设置LCD引脚
Tft_Lcd_Init(MODE_TFT_8BIT_240320); //初始化LCD控制器
Lcd_PowerEnable(0, 1); //设置LCD_PWREN有效,它用于打开LCD的电源
Lcd_EnvidOnOff(1); //使能LCD控制器输出信号
Lcd_Palette8Bit_Init(); //初始化调色板
ClearScr(0x0); //清屏
printf("[TFT 64K COLOR(16bpp) LCD TEST]\n");
printf("1. Press any key to draw line\n");
getc();
DrawLine(0 , 0 , 239, 0 , 0); //颜色为DEMO256pal[0]
DrawLine(0 , 0 , 0 , 319, 1); //颜色为DEMO256pal[1]
DrawLine(239, 0 , 239, 319, 2); // ……
DrawLine(0 , 319, 239, 319, 4);
DrawLine(0 , 0 , 239, 319, 8);
DrawLine(239, 0 , 0 , 319, 16);
DrawLine(120, 0 , 120, 319, 32);
DrawLine(0 , 160, 239, 160, 64);
printf("2. Press any key to draw circles\n");
getc();
Mire();
printf("3. Press any key to fill the screem with one color\n");
getc();
ClearScr(128); //输出单色图像,颜色为DEMO256pal[128]
printf("4. Press any key to fill the screem by temporary palette\n");
getc();
ClearScrWithTmpPlt(0x0000ff); //输出单色图像,颜色为蓝色
printf("5. Press any key to fill the screem by palette\n");
getc();
DisableTmpPlt(); //关闭临时调色板寄存器
ChangePalette(0xffff00); //改变整个调色板为黄色,输出单色图像
printf("6. Press any key stop the testing\n");
getc();
Lcd_EnvidOnOff(0);
}
/*
*以240x320,16bpp的显示模式测试TFT LCD
*/
void Test_Lcd_Tft_16Bit_240320(void)
{
Lcd_Port_Init();//设置LCD引脚
Tft_Lcd_Init(MODE_TFT_16BIT_240320); //初始化LCD控制器
Lcd_PowerEnable(0, 1); //设置LCD_PWREN有效,它用于打开LCD的电源
Lcd_EnvidOnOff(1); //使能LCD控制器输出信号
ClearScr(0x0); //清屏,黑色
printf("[TFT 64K COLOR(16bpp) LCD TEST]\n");
printf("1. Press any key to draw line\n");
getc();
DrawLine(0 , 0 , 239, 0 , 0xff0000); //红色
DrawLine(0 , 0 , 0 , 319, 0x00ff00); //绿色
DrawLine(239, 0 , 239, 319, 0x0000ff); //蓝色
DrawLine(0 , 319, 239, 319, 0xffffff); //白色
DrawLine(0 , 0 , 239, 319, 0xffff00); //黄色
DrawLine(239, 0 , 0 , 319, 0x8000ff); //紫色
DrawLine(120, 0 , 120, 319, 0xe6e8fa); //银色
DrawLine(0 , 160, 239, 160, 0xcd7f32); //金色
printf("2. Press any key to draw circles\n");
getc();
Mire();
printf("3. Press any key to fill the screem with one color\n");
getc();
ClearScr(0xff0000); //红色
printf("4. Press any key to fill the screem by temporary palette\n");
getc();
ClearScrWithTmpPlt(0x0000ff); //蓝色
printf("5. Press any key stop the testing\n");
getc();
Lcd_EnvidOnOff(0);
}
/*
*以640x480,8bpp的显示模式测试TFT LCD
*/
void Test_Lcd_Tft_8Bit_640480(void)
{
Lcd_Port_Init(); //设置LCD引脚
Tft_Lcd_Init(MODE_TFT_8BIT_640480); //初始化LCD控制器
Lcd_PowerEnable(0, 1); //设置LCD_PWREN有效,它用于打开LCD的电源
Lcd_EnvidOnOff(1); //使能LCD控制器输出信号
Lcd_Palette8Bit_Init(); //初始化调色板
ClearScr(0x0); //清屏,黑色
printf("[TFT 64K COLOR(16bpp) LCD TEST]\n");
printf("1. Press any key to draw line\n");
getc();
DrawLine(0 , 0 , 639, 0 , 0); //颜色为DEMO256pal[0]
DrawLine(0 , 0 , 0 , 479, 1); //颜色为DEMO256pal[1]
DrawLine(639, 0 , 639, 479, 2); // ……
DrawLine(0 , 479, 639, 479, 4);
DrawLine(0 , 0 , 639, 479, 8);
DrawLine(639, 0 , 0 , 479, 16);
DrawLine(320, 0 , 320, 479, 32);
DrawLine(0 , 240, 639, 240, 64);
printf("2. Press any key to draw circles\n");
getc();
Mire();
printf("3. Press any key to fill the screem with one color\n");
getc();
ClearScr(128); //输出单色图像,颜色为DEMO256pal[128]
printf("4. Press any key to fill the screem by temporary palette\n");
getc();
ClearScrWithTmpPlt(0x0000ff); //输出单色图像,颜色为蓝色
printf("5. Press any key to fill the screem by palette\n");
getc();
DisableTmpPlt(); //关闭临时调色板寄存器
ChangePalette(0xffff00); //改变整个调色板为黄色,输出单色图像
printf("6. Press any key stop the testing\n");
getc();
Lcd_EnvidOnOff(0);
}
/*
*以640x480,16bpp的显示模式测试TFT LCD
*/
void Test_Lcd_Tft_16Bit_640480(void)
{
Lcd_Port_Init(); //设置LCD引脚
Tft_Lcd_Init(MODE_TFT_16BIT_640480); //初始化LCD控制器
Lcd_PowerEnable(0, 1); //设置LCD_PWREN有效,它用于打开LCD的电源
Lcd_EnvidOnOff(1); //使能LCD控制器输出信号
ClearScr(0x0); //清屏,黑色
printf("[TFT 64K COLOR(16bpp) LCD TEST]\n");
printf("1. Press any key to draw line\n");
getc();
DrawLine(0 , 0 , 639, 0 , 0xff0000); //红色
DrawLine(0 , 0 , 0 , 479, 0x00ff00); //绿色
DrawLine(639, 0 , 639, 479, 0x0000ff); //蓝色
DrawLine(0 , 479, 639, 479, 0xffffff); //白色
DrawLine(0 , 0 , 639, 479, 0xffff00); //黄色
DrawLine(639, 0 , 0 , 479, 0x8000ff); //紫色
DrawLine(320, 0 , 320, 479, 0xe6e8fa); //银色
DrawLine(0 , 240, 639, 240, 0xcd7f32); //金色
printf("2. Press any key to draw circles\n");
getc();
Mire();
printf("3. Press any key to fill the screem with one color\n");
getc();
ClearScr(0xff0000); //红色
printf("4. Press any key to fill the screem by temporary palette\n");
getc();
ClearScrWithTmpPlt(0x0000ff); //蓝色
printf("5. Press any key stop the testing\n");
getc();
Lcd_EnvidOnOff(0);
}
(5)lcddrv.c程序如下:
/*
- FILE: lcddrv.c
*提供操作LCD控制器、调色板等的底层函数
*/
include
include "s3c24xx.h"
include "lcddrv.h"
unsigned int fb_base_addr;
unsigned int bpp;
unsigned int xsize;
unsigned int ysize;
static const unsigned short DEMO256pal[]={
0x0b5e,0xce9a,0xffd9,0x9d99,0xb63a,0xae7c,0xdd71,0x6c57,0xfd4d,0x00ae,0x9c4d,0xb5f8,0xad96,0x0131,0x0176,0xefff,0xcedd,0x9556,0xe4bf,0x00b6,0x22b7,0x002b,0x89de,0x002c,0x57df,0xab5f,0x3031,0x14bf,0x797e,0x5391,0x93ab,0x7239,0x7453,0xafdf,0x71b9,0x8c92,0x014d,0x302e,0x5175,0x0029,0x0969,0x004e,0x2a6d,0x0021,0x3155,0x4b6e,0xd677,0xf6b6,0x9b5f,0x4bb5,0xffd5,0x0027,0xdfdf,0x74d8,0x1256,0x6bcd,0x9b08,0x2ab2,0xbd72,0x84b5,0xfe52,0xd4ad,0x00ad,0xfffc,0x422b,0x73b0,0x0024,0x5246,0x8e5e,0x28b3,0x0050,0x3b52,0x2a4a,0x3a74,0x8559,0x3356,0x1251,0x9abf,0x4034,0x40b1,
0x8cb9,0x00b3,0x5c55,0xdf3d,0x61b7,0x1f5f,0x00d9,0x4c59,0x0926,0xac3f,0x925f,0x85bc,0x29d2,0xc73f,0xef5c,0xcb9f,0x827b,0x5279,0x4af5,0x01b9,0x4290,0xf718,0x126d,0x21a6,0x515e,0xefbd,0xd75e,0x42ab,0x00aa,0x10b3,0x7349,0x63b5,0x61a3,0xaadf,0xcb27,0x87df,0x6359,0xc7df,0x4876,0xb5bc,0x4114,0xfe2e,0xef5e,0x65be,0x43b9,0xe5df,0x21c9,0x7d16,0x6abb,0x5c11,0x49f7,0xbc0b,0x9e1a,0x3b0f,0x202b,0xff12,0x821b,0x842f,0xbccf,0xdefb,0x8a3e,0x68fa,0xa4f1,0x38ae,0x28b7,0x21ad,0x31d7,0x0073,0x182b,0x1831,0x3415,0xbdf6,0x2dbf,0x0a5d,0xc73d,0x182c,0x293e,0x7b3d,0x643d,0x3cbd,
0x92dd,0x09d4,0x1029,0x7cdd,0x6239,0x182e,0x5aea,0x11eb,0x8abc,0x7bfa,0x00a7,0x2153,0x1853,0x1318,0x0109,0x54fa,0x72a7,0x89e3,0x01cf,0x3a07,0x7b17,0x1a14,0x2150,0x23dc,0x4142,0x1b33,0x00a4,0xf6df,0x08fc,0x18ae,0x3a7e,0x18d1,0xa51c,0xff5a,0x1a0f,0x28fa,0xdfbe,0x82de,0x60d7,0x1027,0x48fa,0x5150,0x6213,0x89d6,0x110d,0x9bbb,0xbedd,0x28e1,0x1925,0xf449,0xaa79,0xd5f4,0x693c,0x110a,0x2889,0x08a2,0x923d,0x10a6,0xd9bc,0x5b2e,0x32ec,0xcf7f,0x1025,0x2148,0x74b4,0x6d59,0x9d14,0x0132,0x00f0,0x56bf,0x00f1,0xffff,0x0173,0x0133,0x00b0,0x00b1,0xf7ff,0x08b1,0xfffe,0x08b0,
0x0171,0xf7bf,0x10f3,0xf7fe,0x08ef,0x1192,0xefbe,0x1131,0x2177,0xff9f,0x1116,0xffbc,0x5914,0x22ef,0xb285,0xa6df,
};
/*
*初始化用于LCD的引脚
*/
void Lcd_Port_Init(void)
{
GPCUP = 0xffffffff; //禁止内部上拉
GPCCON =0xaaaaaaaa; // GPC用于D[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND
GPDUP = 0xffffffff; //禁止内部上拉
GPDCON = 0xaaaaaaaa; // GPD用于VD[23:8]
printf("Initializing GPIO ports..........\n");
}
/*
*初始化LCD控制器
*输入参数:
type:显示模式
MODE_TFT_8BIT_240320 : 240*320 8bpp的TFT LCD
MODE_TFT_16BIT_240320 : 240*320 16bpp的TFT LCD
MODE_TFT_8BIT_640480 : 640*480 8bpp的TFT LCD
MODE_TFT_16BIT_640480 : 640*480 16bpp的TFT LCD
*/
void Tft_Lcd_Init(int type)
{
switch(type)
{
case MODE_TFT_8BIT_240320:
/*
*设置LCD控制器的控制寄存器LCDCON1~5
- LCDCON1:
*设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
*选择LCD类型: TFT LCD
*设置显示模式: 8BPP
*先禁止LCD信号输出
- LCDCON2/3/4:
*设置控制信号的时间参数
*设置分辨率,即行数及列数
*现在,可以根据公式计算出显示器的频率:
*当HCLK=100MHz时,
Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
{(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
{2x(CLKVAL+1)/(HCLK)}]
= 60Hz
- LCDCON5:
*设置显示模式为8BPP时,调色板中的数据格式: 5:6:5
*设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号):反转
*字节交换使能
*/
LCDCON1 = (CLKVAL_TFT_240320<<8) | (LCDTYPE_TFT<<5) | \
(BPPMODE_8BPP<<1) | (ENVID_DISABLE<<0);
LCDCON2 = (VBPD_240320<<24) | (LINEVAL_TFT_240320<<14) | \
(VFPD_240320<<6) | (VSPW_240320);
LCDCON3 = (HBPD_240320<<19) | (HOZVAL_TFT_240320<<8) | (HFPD_240320);
LCDCON4 = HSPW_240320;
LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
(BSWP<<1);
/*
*设置LCD控制器的地址寄存器LCDSADDR1~3
*帧内存与视口(view point)完全吻合,
*图像数据格式如下(8BPP时,帧缓冲区中的数据为调色板中的索引值):
|----PAGEWIDTH----|
y/x 0 1 2 239
0 idx idx idx ... idx
1 idx idx idx ... idx
- LCDSADDR1:
*设置LCDBANK、LCDBASEU
- LCDSADDR2:
*设置LCDBASEL:帧缓冲区的结束地址A[21:1]
- LCDSADDR3:
OFFSIZE等于0,PAGEWIDTH等于(240/2)
*/
LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) |
LOWER21BITS(LCDFRAMEBUFFER>>1);
LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
(LINEVAL_TFT_240320+1)(HOZVAL_TFT_240320+1)1)>>1);
LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_240320/2);
/禁止临时调色板寄存器/
TPAL = 0;
fb_base_addr = LCDFRAMEBUFFER;
bpp = 8;
xsize = 240;
ysize = 320;
break;
case MODE_TFT_16BIT_240320:
/*
*设置LCD控制器的控制寄存器LCDCON1~5
- LCDCON1:
*设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
*选择LCD类型: TFT LCD
*设置显示模式: 16BPP
*先禁止LCD信号输出
- LCDCON2/3/4:
*设置控制信号的时间参数
*设置分辨率,即行数及列数
*现在,可以根据公式计算出显示器的频率:
*当HCLK=100MHz时,
Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
{(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
{2x(CLKVAL+1)/(HCLK)}]
= 60Hz
- LCDCON5:
*设置显示模式为16BPP时的数据格式: 5:6:5
*设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号):反转
*半字(2字节)交换使能
*/
LCDCON1 = (CLKVAL_TFT_240320<<8) | (LCDTYPE_TFT<<5) | \
(BPPMODE_16BPP<<1) | (ENVID_DISABLE<<0);
LCDCON2 = (VBPD_240320<<24) | (LINEVAL_TFT_240320<<14) | \
(VFPD_240320<<6) | (VSPW_240320);
LCDCON3 = (HBPD_240320<<19) | (HOZVAL_TFT_240320<<8) | (HFPD_240320);
LCDCON4 = HSPW_240320;
LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
(HWSWP<<1);
/*
*设置LCD控制器的地址寄存器LCDSADDR1~3
*帧内存与视口(view point)完全吻合,
*图像数据格式如下:
|----PAGEWIDTH----|
y/x 0 1 2 239
0 rgb rgb rgb ... rgb
1 rgb rgb rgb ... rgb
- LCDSADDR1:
*设置LCDBANK、LCDBASEU
- LCDSADDR2:
*设置LCDBASEL:帧缓冲区的结束地址A[21:1]
- LCDSADDR3:
OFFSIZE等于0,PAGEWIDTH等于(240*2/2)
*/
LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) |
LOWER21BITS(LCDFRAMEBUFFER>>1);
LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
(LINEVAL_TFT_240320+1)(HOZVAL_TFT_240320+1)2)>>1);
LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_240320*2/2);
/禁止临时调色板寄存器/
TPAL = 0;
fb_base_addr = LCDFRAMEBUFFER;
bpp = 16;
xsize = 240;
ysize = 320;
break;
case MODE_TFT_8BIT_640480:
/*
*设置LCD控制器的控制寄存器LCDCON1~5
- LCDCON1:
*设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
*选择LCD类型: TFT LCD
*设置显示模式: 8BPP
*先禁止LCD信号输出
- LCDCON2/3/4:
*设置控制信号的时间参数
*设置分辨率,即行数及列数
*现在,可以根据公式计算出显示器的频率:
*当HCLK=100MHz时,
Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
{(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
{2x(CLKVAL+1)/(HCLK)}]
= 60Hz
- LCDCON5:
*设置显示模式为8BPP时,调色板中的数据格式: 5:6:5
*设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号):反转
*字节交换使能
*/
LCDCON1 = (CLKVAL_TFT_640480<<8) | (LCDTYPE_TFT<<5) | \
(BPPMODE_8BPP<<1) | (ENVID_DISABLE<<0);
LCDCON2 = (VBPD_640480<<24) | (LINEVAL_TFT_640480<<14) | \
(VFPD_640480<<6) | (VSPW_640480);
LCDCON3 = (HBPD_640480<<19) | (HOZVAL_TFT_640480<<8) | (HFPD_640480);
LCDCON4 = HSPW_640480;
LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
(BSWP<<1);
/*
*设置LCD控制器的地址寄存器LCDSADDR1~3
*帧内存与视口(view point)完全吻合,
*图像数据格式如下(8BPP时,帧缓冲区中的数据为调色板中的索引值):
|----PAGEWIDTH----|
y/x 0 1 2 639
0 idx idx idx ... idx
1 idx idx idx ... idx
- LCDSADDR1:
*设置LCDBANK、LCDBASEU
- LCDSADDR2:
*设置LCDBASEL:帧缓冲区的结束地址A[21:1]
- LCDSADDR3:
OFFSIZE等于0,PAGEWIDTH等于(640/2)
*/
LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) |
LOWER21BITS(LCDFRAMEBUFFER>>1);
LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
(LINEVAL_TFT_640480+1)(HOZVAL_TFT_640480+1)1)>>1);
LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_640480/2);
/禁止临时调色板寄存器/
TPAL = 0;
fb_base_addr = LCDFRAMEBUFFER;
bpp = 8;
xsize = 640;
ysize = 480;
break;
case MODE_TFT_16BIT_640480:
/*
*设置LCD控制器的控制寄存器LCDCON1~5
- LCDCON1:
*设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
*选择LCD类型: TFT LCD
*设置显示模式: 16BPP
*先禁止LCD信号输出
- LCDCON2/3/4:
*设置控制信号的时间参数
*设置分辨率,即行数及列数
*现在,可以根据公式计算出显示器的频率:
*当HCLK=100MHz时,
Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
{(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
{2x(CLKVAL+1)/(HCLK)}]
= 60Hz
- LCDCON5:
*设置显示模式为16BPP时的数据格式: 5:6:5
*设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号):反转
*半字(2字节)交换使能
*/
LCDCON1 = (CLKVAL_TFT_640480<<8) | (LCDTYPE_TFT<<5) | \
(BPPMODE_16BPP<<1) | (ENVID_DISABLE<<0);
LCDCON2 = (VBPD_640480<<24) | (LINEVAL_TFT_640480<<14) | \
(VFPD_640480<<6) | (VSPW_640480);
LCDCON3 = (HBPD_640480<<19) | (HOZVAL_TFT_640480<<8) | (HFPD_640480);
LCDCON4 = HSPW_640480;
LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
(HWSWP<<1);
/*
*设置LCD控制器的地址寄存器LCDSADDR1~3
*帧内存与视口(view point)完全吻合,
*图像数据格式如下:
|----PAGEWIDTH----|
y/x 0 1 2 639
0 rgb rgb rgb ... rgb
1 rgb rgb rgb ... rgb
- LCDSADDR1:
*设置LCDBANK、LCDBASEU
- LCDSADDR2:
*设置LCDBASEL:帧缓冲区的结束地址A[21:1]
- LCDSADDR3:
OFFSIZE等于0,PAGEWIDTH等于(640*2/2)
*/
LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) |
LOWER21BITS(LCDFRAMEBUFFER>>1);
LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
(LINEVAL_TFT_640480+1)(HOZVAL_TFT_640480+1)2)>>1);
LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_640480*2/2);
/禁止临时调色板寄存器/
TPAL = 0;
fb_base_addr = LCDFRAMEBUFFER;
bpp = 16;
xsize = 640;
ysize = 480;
break;
default:
break;
}
}
/*
*设置调色板
*/
void Lcd_Palette8Bit_Init(void)
{
int i;
volatile unsigned int *palette;
LCDCON5 |= (FORMAT8BPP_565<<11); //设置调色板中数据格式为5:6:5
palette = (volatile unsigned int *)PALETTE;
for (i = 0; i < 256; i++)
*palette++ = DEMO256pal[i];
}
/*
*改变调色板为一种颜色
*输入参数:
- color:颜色值,格式为0xRRGGBB
*/
void ChangePalette(UINT32 color)
{
int i;
unsigned char red, green, blue;
UINT32 *palette;
palette=(UINT32 *)PALETTE;
for (i = 0; i < 256; i++)
{
red = (color >> 19) & 0xff;
green = (color >> 10) & 0xff;
blue = (color >> 3) & 0xff;
color = (red << 11) | (green << 5) | blue; //格式5:6:5
while ((LCDCON5>>16) == 2); //等待直到VSTATUS不为”有效”
*palette++ = color;
}
}
/*
*设置是否输出LCD电源开关信号LCD_PWREN
*输入参数:
invpwren: 0 - LCD_PWREN有效时为正常极性
1 - LCD_PWREN有效时为反转极性
pwren: 0 - LCD_PWREN输出有效
1 - LCD_PWREN输出无效
*/
void Lcd_PowerEnable(int invpwren, int pwren)
{
GPGCON = (GPGCON & (~(3<<8))) | (3<<8); // GPG4用作LCD_PWREN
GPGUP = (GPGUP & (~(1<<4))) | (1<<4); //禁止内部上拉
LCDCON5 = (LCDCON5 & (~(1<<5))) | (invpwren<<5); //设置LCD_PWREN的极性:正常/反转
LCDCON5 = (LCDCON5 & (~(1<<3))) | (pwren<<3); //设置是否输出LCD_PWREN
}
/*
*设置LCD控制器是否输出信号
*输入参数:
- onoff:
*0 :关闭
- 1 :打开
*/
void Lcd_EnvidOnOff(int onoff)
{
if (onoff == 1)
LCDCON1 |= 1; // ENVID ON
else
LCDCON1 &= 0x3fffe; // ENVID Off
}
/*
*使用临时调色板寄存器输出单色图像
*输入参数:
- color:颜色值,格式为0xRRGGBB
*/
void ClearScrWithTmpPlt(UINT32 color)
{
TPAL = (1<<24)|((color & 0xffffff)<<0);
}
/*
*停止使用临时调色板寄存器
*/
void DisableTmpPlt(void)
{
TPAL = 0;
}
(5)lcddrv.h程序如下:
/*
- FILE: lcddrv.h
*操作LCD控制器、调色板等的底层函数接口
*/
ifndef LCDDRV_H
define LCDDRV_H
include
define LOWER21BITS(n) ((n) & 0x1fffff)
define BPPMODE_1BPP 0x8
define BPPMODE_2BPP 0x9
define BPPMODE_4BPP 0xA
define BPPMODE_8BPP 0xB
define BPPMODE_16BPP 0xC
define BPPMODE_24BPP 0xD
define LCDTYPE_TFT 0x3
define ENVID_DISABLE 0
define ENVID_ENABLE 1
define FORMAT8BPP_5551 0
define FORMAT8BPP_565 1
define HSYNC_NORM 0
define HSYNC_INV 1
define VSYNC_NORM 0
define VSYNC_INV 1
define BSWP 1
define HWSWP 1
//TFT LCD Panel(240*320)
define MODE_TFT_1BIT_240320 (0x4101)
define MODE_TFT_8BIT_240320 (0x4102)
define MODE_TFT_16BIT_240320 (0x4104)
define MODE_TFT_24BIT_240320 (0x4108)
//TFT 240320
define LCD_XSIZE_TFT_240320 (240)
define LCD_YSIZE_TFT_240320 (320)
//TFT 240320
define HOZVAL_TFT_240320 (LCD_XSIZE_TFT_240320-1)
define LINEVAL_TFT_240320 (LCD_YSIZE_TFT_240320-1)
define CLKVAL_TFT_240320 (4)
// 60hz @133Mhz
// (9) 60hz @100Mhz
//Timing parameter for LTS350Q1(SAMSUNG)
define VBPD_240320 ((2-1)&0xff)
define VFPD_240320 ((6-1)&0xff)
define VSPW_240320 ((2-1) &0x3f)
define HBPD_240320 ((37-1)&0x7f)
define HFPD_240320 ((20-1)&0xff)
define HSPW_240320 ((6-1)&0xff)
//TFT LCD Panel(640*480)
define MODE_TFT_1BIT_640480 (0x4201)
define MODE_TFT_8BIT_640480 (0x4202)
define MODE_TFT_16BIT_640480 (0x4204)
define MODE_TFT_24BIT_640480 (0x4208)
//TFT 640480
define LCD_XSIZE_TFT_640480 (640)
define LCD_YSIZE_TFT_640480 (480)
//TFT640480
define HOZVAL_TFT_640480 (LCD_XSIZE_TFT_640480-1)
define LINEVAL_TFT_640480 (LCD_YSIZE_TFT_640480-1)
//Timing parameter for V16C6448AB(PRIME VIEW)
define VBPD_640480 ((33-1)&0xff)
define VFPD_640480 ((10-1)&0xff)
define VSPW_640480 ((2-1) &0x3f)
define HBPD_640480 ((48-1)&0x7f)
define HFPD_640480 ((16-1)&0xff)
define HSPW_640480 ((96-1)&0xff)
define CLKVAL_TFT_640480 (1)
//53.5hz @90Mhz
//VSYNC,HSYNC should be inverted
//HBPD=47VCLK,HFPD=15VCLK,HSPW=95VCLK
//VBPD=32HSYNC,VFPD=9HSYNC,VSPW=1HSYNC
define LCDFRAMEBUFFER 0x30400000
/*
*初始化用于LCD的引脚
*/
void Lcd_Port_Init(void);
/*
*初始化LCD控制器
*输入参数:
type:显示模式
MODE_TFT_8BIT_640480 : 640*640 8bpp的TFT LCD
MODE_TFT_16BIT_640480 : 640*640 16bpp的TFT LCD
*/
void Tft_Lcd_Init(int type);
/*
*设置调色板
*/
void Lcd_Palette8Bit_Init(void);
/*
*设置LCD控制器是否输出信号
*输入参数:
onoff:
0 :关闭
1 :打开
*/
void Lcd_EnvidOnOff(int onoff);
/*
*设置是否输出LCD电源开关信号LCD_PWREN
*输入参数:
invpwren: 0 - LCD_PWREN有效时为正常极性
1 - LCD_PWREN有效时为反转极性
pwren: 0 - LCD_PWREN输出有效
1 - LCD_PWREN输出无效
*/
void Lcd_PowerEnable(int invpwren, int pwren);
/*
*使用临时调色板寄存器输出单色图像
*输入参数:
- color:颜色值,格式为0xRRGGBB
*/
void ClearScrWithTmpPlt(UINT32 color);
/*
*停止使用临时调色板寄存器
*/
void DisableTmpPlt(void);
/*
*改变调色板为一种颜色
*输入参数:
- color:颜色值,格式为0xRRGGBB
*/
void ChangePalette(UINT32 color);
endif /LCDDRV_H/
(5)s3c24xx.h程序如下:
/ WOTCH DOG register /
define WTCON ((volatile unsigned long )0x53000000)
/ SDRAM regisers /
define MEM_CTL_BASE 0x48000000
define SDRAM_BASE 0x30000000
/ NAND Flash registers /
define NFCONF ((volatile unsigned int )0x4e000000)
define NFCMD ((volatile unsigned char )0x4e000004)
define NFADDR ((volatile unsigned char )0x4e000008)
define NFDATA ((volatile unsigned char )0x4e00000c)
define NFSTAT ((volatile unsigned char )0x4e000010)
/GPIO registers/
define GPBCON ((volatile unsigned long )0x56000010)
define GPBDAT ((volatile unsigned long )0x56000014)
define GPFCON ((volatile unsigned long )0x56000050)
define GPFDAT ((volatile unsigned long )0x56000054)
define GPFUP ((volatile unsigned long )0x56000058)
define GPGCON ((volatile unsigned long )0x56000060)
define GPGDAT ((volatile unsigned long )0x56000064)
define GPGUP ((volatile unsigned long )0x56000068)
define GPHCON ((volatile unsigned long )0x56000070)
define GPHDAT ((volatile unsigned long )0x56000074)
define GPHUP ((volatile unsigned long )0x56000078)
/UART registers/
define ULCON0 ((volatile unsigned long )0x50000000)
define UCON0 ((volatile unsigned long )0x50000004)
define UFCON0 ((volatile unsigned long )0x50000008)
define UMCON0 ((volatile unsigned long )0x5000000c)
define UTRSTAT0 ((volatile unsigned long )0x50000010)
define UTXH0 ((volatile unsigned char )0x50000020)
define URXH0 ((volatile unsigned char )0x50000024)
define UBRDIV0 ((volatile unsigned long )0x50000028)
/interrupt registes/
define SRCPND ((volatile unsigned long )0x4A000000)
define INTMOD ((volatile unsigned long )0x4A000004)
define INTMSK ((volatile unsigned long )0x4A000008)
define PRIORITY ((volatile unsigned long )0x4A00000c)
define INTPND ((volatile unsigned long )0x4A000010)
define INTOFFSET ((volatile unsigned long )0x4A000014)
define SUBSRCPND ((volatile unsigned long )0x4A000018)
define INTSUBMSK ((volatile unsigned long )0x4A00001c)
/external interrupt registers/
define EINTMASK ((volatile unsigned long )0x560000a4)
define EINTPEND ((volatile unsigned long )0x560000a8)
(6)Makefile程序如下:
objs := head.o init.o interrupt.o main.o
int.bin: $(objs)
arm-linux-ld -Ttext 0x00000000 -o int_elf $^
arm-linux-objcopy -O binary -S int_elf $@
arm-linux-objdump -D -m arm int_elf > int.dis
%.o:%.c
arm-linux-gcc -nostdlib -Wall -O2 -c -o $@ $<
%.o:%.S
arm-linux-gcc -nostdlib -Wall -O2 -c -o $@ $<
clean:
rm -f int.bin int_elf int.dis *.o