欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MINI2440裸机实验之LCD

程序员文章站 2022-07-14 09:38:50
...

s3c2440的LCD控制器

有关LCD的刷新控制方式及s3c2440的LCD控制器的介绍可参考以下两篇文章:

mini2440硬件篇之LCD

六、2440裸机开发 lcd操作

以上文章对液晶显示器时序图中各时间段具体作用做了比较通俗易懂的讲解。

硬件部分

上诉文章中使用的LCD都是常规液晶显示器,但在查看原理图及液晶数据手册时发现我使用的MINI2440开发板上自带的液晶跟文中的液晶并不一致,区别主要体现在只有DE、CLK和RGB引脚,该液晶型号为TD35-TD035STEB2,其时序图如下。

MINI2440裸机实验之LCD

MINI2440裸机实验之LCD


从时序图中可以看出,DE为该液晶屏的主要控制引脚,通过控制DE引脚的下拉就可以控制液晶屏的刷新,但有一个问题就是如何使用s3c2440的LCD控制器来控制该液晶屏呢?

这里我进行了这样的尝试,认为上图中的Tvdisp = LINEVAL +1 ;Tvblank = VSPW+1+VBPD+1;VFPD+1 = 0;Thdisp = HOZVAL+1;

Thblank = HSPW+1 + HBPD+1;HFPD+1 = 0;

其他部分参考了mini2440硬件篇之LCD并对本液晶的特点进行了相应的修改,最终的程序共包含3个文件:

lcd.c

/* lcd.c */
#define rLCDCON1 (*(volatile unsigned int *)0x4D000000)
#define rLCDCON2 (*(volatile unsigned int *)0x4D000004)
#define rLCDCON3 (*(volatile unsigned int *)0x4D000008)
#define rLCDCON4 (*(volatile unsigned int *)0x4D00000C)
#define rLCDCON5 (*(volatile unsigned int *)0x4D000010)
#define rLCDSADDR1 (*(volatile unsigned int *)0x4D000014)
#define rLCDSADDR2 (*(volatile unsigned int *)0x4D000018)
#define rLCDSADDR3 (*(volatile unsigned int *)0x4D00001C)
#define rGPCCON (*(volatile unsigned int *)0x56000020)
#define rGPCUP (*(volatile unsigned int *)0x56000028)
#define rGPDUP (*(volatile unsigned int *)0x56000038)
#define rGPDCON (*(volatile unsigned int *)0x56000030)

#define LCD_WIDTH 240
#define LCD_HEIGHT 320

#define M5D( n ) ( ( n ) & 0x1fffff )

volatile static unsigned short LCD_BUFFER[LCD_HEIGHT][LCD_WIDTH];

#define LCD_ADDR ( (unsigned long)LCD_BUFFER ) 

void delay(volatile unsigned long count)
{
    while(count--);
}

void LCDInit(void)
{
	rGPCUP = 0xffffffff;//Disable Pull-up register  
    	rGPCCON = 0xaaaa02a8;//设置GPC各引脚对应引脚功能为 VD[7...0],VM,VFRAME,VLINE,VCLK  
      
    	rGPDUP = 0xffffffff;//Disable Pull-up register  
    	rGPDCON = 0xaaaaaaaa;//设置VD[15:8] 
	
	rLCDCON1 = (6 << 8) | (3 << 5) | (0x0C << 1);
	rLCDCON2 = (2 << 24) | ((320 - 1) << 14) | (9 << 0);
	rLCDCON3 = (8 << 19) | ((240 - 1) << 8);
	rLCDCON4 = (70 << 0);
	rLCDCON5 = (1 << 11) | (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; 
}

void LCDClearScreen( unsigned short usColor)  
{  
    unsigned int x,y ;  
          
    for( y = 0 ; y < LCD_HEIGHT ; y++ )  
    {  
        for( x = 0 ; x < LCD_WIDTH ; x++ )  
        {  
            LCD_BUFFER[y][x] = usColor ;  
        }  
    }  
}

void main(void)
{
	unsigned int x,y,z=0x0000;
	LCDInit();
	for(x=0;x<320;x++)
	{
		for(y=0;y<240;y++)
		{
			LCD_BUFFER[x][y] = z++;
		}
	}
	rLCDCON1 |= 1;
	while(1)
	{
	}
}

start.S

.text
.global _start
_start:

	ldr r0,=0x53000000
	mov r1,#0x00
	str r1,[r0]    /* disable the watchdog timer */
	
   	ldr sp,=0x34000000    /* set stack pointer */

	b  main

Makefile

objs := start.o lcd.o

lcd.bin:$(objs)
	arm-linux-ld -Ttext 0x30000000 -o lcd_elf $^
	arm-linux-objcopy -O binary -S lcd_elf aaa@qq.com
	arm-linux-objdump -D -m arm lcd_elf > lcd.dis
%.o:%.c
	arm-linux-gcc -c -o aaa@qq.com $<
%.o:%.S
	arm-linux-gcc -c -o aaa@qq.com $<
clean:
	rm -f lcd_elf *.o

这里要说明的是,这个程序编译完成之后将不在使用JLINK进行下载,而使用友善之臂提供的工具MINITools来直接下载至SDRAM来之前,这个可以从Makefile中的链接地址以及start.S的文件内容看出来,之前不使用该方法下载的原因是为了熟悉及实践SDRAM的操作。

该程序最终的显示效果如下图所示

MINI2440裸机实验之LCD