第十七课(4)LCD编程

一、抽象出重要的结构体【led.h 、lcd_controlloer.h】

先完成:
【lcd_controller.c】<–【s3c244_lcd_controller.c】:
向上接收不同LCD的参数,向下使用这些参数设置对应的LCD控制器

因为要接收不同的LCD参数,所以我们需要把LCD的参数写成一个结构体:
lcd.h:

#ifndef _LCD_H
#define _LCD_H


enum {
	NORMAL = 0,
	INVERT = 1,
};

/* NORMAL : 正常极性
 * INVERT : 反转极性
 */
typedef struct pins_polarity {
	int vclk;  /* normal: 在下降沿获取数据 */
	int rgb;   /* normal: 高电平表示1 */
	int hsync; /* normal: 高脉冲 */
	int vsync; /* normal: 高脉冲 */
}pins_polarity, *p_pins_polarity;

typedef struct time_sequence {
	/* 垂直方向 */
	int tvp; /* vysnc脉冲宽度 */
	int tvb; /* 上边黑框, Vertical Back porch */
	int tvf; /* 下边黑框, Vertical Front porch */

	/* 水平方向 */
	int thp; /* hsync脉冲宽度 */
	int thb; /* 左边黑框, Horizontal Back porch */
	int thf; /* 右边黑框, Horizontal Front porch */

	int vclk;
}time_sequence, *p_time_sequence;


typedef struct lcd_params {
	char *name;
	/* 引脚极性 */
	pins_polarity pins_pol;
	
	/* 时序 */
	time_sequence time_seq;
	
	/* 分辨率, bpp */
	int xres;
	int yres;
	int bpp;
	
	/* framebuffer的地址 */
	unsigned int fb_base;
}lcd_params, *p_lcd_params;


#endif /* _LCD_H */

lcd_controlloer.h

#ifndef _LCD_CONTROLLER_H
#define _LCD_CONTROLLER_H

#include "lcd.h"

typedef struct lcd_controller {
	char *name;
	void (*init)(p_lcd_params plcdparams);
	void (*enable)(void);
	void (*disable)(void);
}lcd_controller, *p_lcd_controller;

#endif /* _LCD_CONTROLLER_H */

二、LCD控制器【s3c2440_lcd_controller.c】

1、初始化

(1) LCDCON1

LCDCON1val
CLKVAL [17:8]VCLK = HCLK / [(CLKVAL+1) x 2] ==>从LCD芯片手册看,将VCLK 取为9。100/(CLKVAL+1)x2则CLKVAL大约为5
PNRMODE [6:5]11 = TFT LCD panel
BPPMODE [4:1]1011 = 8 bpp for TFT; 1100 = 16 bpp for TFT; 1101 = 24 bpp for TFT

(2)LCDCON2 、LCDCON3、LCDCON4

在这里插入图片描述
将LCD手册上的时序图和s3c2440手册上的时序图,对比我们可以知道:
VSPW+1 = tVp
VBPD+1 = tVb
LINEVAL +1 = tVd
VFPD+1 = tVf

HSPW+1 = thp
HBPD+1 = thb
HOZVAL+1 = thd
HFPD+1= thf

就可以设置LCDCON2 和LCDCON3、LCDCON4。

(3)LCDCON5

LCDCON5val
FRM565 [11]1 = 5:6:5 Format
INVVCLK [10]0=clk下降沿得到数据
INVVLINE [9]HSYNC pulse polarity
INVVFRAME [8]VSYNC pulse polarity
INVVD [7]VD (video data) pulse polarity = RGB的脉冲极性
INVVDEN [6]
INVPWREN [5]
INVLEND [4]
ENLEND [2]
BSWP [1]数据存储P412
HWSWP [0]数据存储P412

这些引脚的极性是否要设置取决于原理图上是否有接:
在这里插入图片描述
疑惑:PWREN其实不明白这个引脚是怎么接的。

在LCD芯片手册搜索“DE”:34 DE I Data Enable 有这个引脚。

那么这两个引脚的极性如何呢?
我们需要参考s3c2440的时序图,可以看到VDEN在高电平时,VD(RGB)使能数据。
那么PWREN的极性呢?
我们可以在s3c2440芯片手册上再找找看:可以看出PWREN在高电平的时候,LCD引脚工作。
在这里插入图片描述

因此完善引脚极性的结构体:

/* NORMAL : 正常极性
 * INVERT : 反转极性
 */
typedef struct pins_polarity {
	int de;    /* normal: 高电平时可以传输数据 */
	int pwren; /* normal: 高电平有效 */
	int vclk;  /* normal: 在下降沿获取数据 */
	int rgb;   /* normal: 高电平表示1 */
	int hsync; /* normal: 高脉冲 */
	int vsync; /* normal: 高脉冲 */
}pins_polarity, *p_pins_polarity;

(4)LCDSADDR1

LCDSADDR1val
LCDBANK [29:21]A[30:22] 记得去掉最高位
LCDBASEU [20:0]A[21:1] 记得去掉最低位
LCDSADDR2val
LCDBASELLCDBASEL = ((the frame end address) >>1) + 1

the frame end address = fb_base + xresyresbpp/8 ;
the frame end address >>= 1;
the frame end address &= 0x1fffff;

2、引脚的配置

(1)背光驱动引脚

我们来看下 LED+和LED-引脚
在这里插入图片描述
在原理图里搜索“KEYBOARD”,GPB0控制LED背光驱动。
在这里插入图片描述

GPBCONval
GPB0 [1:0]01 = Output

(2)其他引脚的配置

3、senable diseable函数

从原理图上看需要将KEYBOARD引脚输出为高电平:
查阅背光驱动芯片的手册,所以是高电平输入:在这里插入图片描述
在这里插入图片描述
从MP3202DJ芯片手册看,en引脚高电平使能

GPBDATval
GPB0 [1:0]0关闭 1输出
LCDCON1val
ENVID [0]1 = Enable the video output and the LCD control signal.
LCDCON5val
PWREN [3]给LCD提供AVDD逻辑电源0 = Disable LEND signal 1 = Enable LEND signal

三、LCD的设置【lcd_3.4.h】

引脚极性的是normal还是invert去看LCD芯片的时序图
如:
.hsync = INVERT, /* normal: 高脉冲 /
.vsync = INVERT, /
normal: 高脉冲 */
要输出高脉冲之前是要先输出低脉冲,所以是 INVERT

引脚时序的要看LCD芯片的时序表
Horizontal signal=525(整个水平周期为525):
Note 1: thd=480CLK, thf= 2CLK, thp= 41CLK, thb= 2CLK
525CLK=480CLK + 2CLK + 41CLK + 2CLK

四、上层调用的文件

s3c2440_lcd_controller.c

void s3c2440_lcd_controller_add(void)
{	
	register_lcd_controller(&s3c2440_lcd_controller);
}

lcd_3_4.c

void lcd_3_4_add(void)
{	
	register_lcd(&lcd_4_3_params);
}

lcd.c

#define LCD_NUM 10

static p_lcd_params p_array_lcd[LCD_NUM];
static p_lcd_params g_p_lcd_selected;

int register_lcd(p_lcd_params plcd)
{
	int i;
	for (i = 0; i < LCD_NUM; i++)
	{
		if (!p_array_lcd[i])
		{
			p_array_lcd[i] = plcd;
			return i;
		}
	}
	return -1;		
}

int select_lcd(char *name)
{
	int i;
	for (i = 0; i < LCD_NUM; i++)
	{
		if (p_array_lcd[i] && !strcmp(p_array_lcd[i]->name, name))
		{
			g_p_lcd_selected = p_array_lcd[i];
			return i;
		}
	}
	return -1;		
}

int lcd_init(void)
{
	/* 注册LCD */
	lcd_4_3_add();

	/* 注册LCD控制器 */
	lcd_contoller_add();
	
	/* 选择某款LCD */
	select_lcd("lcd_4.3");

	/* 选择某款LCD控制器 */
	select_lcd_controller("s3c2440");

	/* 使用LCD的参数, 初始化LCD控制器 */
	lcd_controller_init(g_p_lcd_selected);
}

lcd.controller.c



#define LCD_CONTROLLER_NUM 10

static p_lcd_controller p_array_lcd_controller[LCD_CONTROLLER_NUM];
static p_lcd_controller g_p_lcd_controller_selected;

int register_lcd_controller(p_lcd_controller plcdcon)
{
	int i;
	for (i = 0; i < LCD_CONTROLLER_NUM; i++)
	{
		if (!p_array_lcd_controller[i])
		{
			p_array_lcd_controller[i] = plcdcon;
			return i;
		}
	}
	return -1;		
}

int select_lcd_controller(char *name)
{
	int i;
	for (i = 0; i < LCD_CONTROLLER_NUM; i++)
	{
		if (p_array_lcd_controller[i] && !strcmp(p_array_lcd_controller[i]->name, name))
		{
			g_p_lcd_controller_selected = p_array_lcd_controller[i];
			return i;
		}
	}
	return -1;		
}


/* 向上: 接收不同LCD的参数
 * 向下: 使用这些参数设置对应的LCD控制器
 */

int lcd_controller_init(p_lcd_params plcdparams)
{
	/* 调用所选择的LCD控制器的初始化函数 */
	if (g_p_lcd_controller_selected)
	{
		g_p_lcd_controller_selected->init(plcdparams);
		return 0;
	}
	return -1;
}

void lcd_contoller_add(void)
{
	s3c2440_lcd_contoller_add();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值