17.ARM裸板实现LCD显示--面向对象的编程思路

目录

1.程序框架:

 2.LCD管理层和控制器相关层的代码分析

3.LCD管理层和LCD屏幕相关层

4.LCD的初始化

5.测试LCD

源代码: 


前言

在实现LCD的程序下实现面向对象的一种编程思路

1.程序框架:

程序的框架大致如上所述:

问题1:LCD控制管理层(④层)如何去管理下面不同LCD控制器的代码呢?

答:提取出不同lcd控制器共同的特点(比如:控制器的名字、控制器初始化、控制器使能和失能),然后把其写成一个结构体封装起来,供给下一层调用(第⑤层),在(第⑤层)中也需要去分别实现(自己的控制器初始化、控制器使能和失能,例如说:s3c2440控制器、TI控制器),然后在本层(第④层)也有初始化函数,当需要使用s3c2440的控制器的时候,就把这个结构变量指向s3c2440,如果使用的Ti控制器就执行TI,这样一来,我们就可以忽略底层硬件的差异,当使用特定控制器的时候把指针变量指向特定的控制器就OK了。

在管理层(④层)的结构体如下:

在LCD控制器相关层(⑤层)生成一个结构体变量,然后实现结构体里面的函数(其实这里只有一个s3c2440的控制器)

问题2:LCD控制器管理层(第④)和LCD控制器相关层(第⑤)如何通信?

答:在第④层中创建一个结构体数组A,A数组就保存了已经就绪的LCD控制器,在第④层中提供一个注册函数,给第⑤层调用,在第⑤层中某个lcd控制器注册了以后,就会把这些控制器的信息保存在A数组中,从而实现不同层之间的通信。

在管理层中(第④)创建一个存储已经注册的LCD控制器的数组:

在管理层中(第④)也会提供一个函数供给下一层(第⑤)调用用于注册LCD控制器 

在LCD控制器相关层(第⑤)把自己注册到数组里面,以便可以被调用

通过问题1和问题2就可以很清楚的知道如何通过lcd_controller.c文件是如何去管理下面的控制器了。


 2.LCD管理层和控制器相关层的代码分析

使用代码更详细的说明:

在LCD控制器相关层(第⑤层)中有以下的函数:

如果还有其他的控制器的话比如:ti的lcd控制器,函数结构应该是类似的。

解析:在这一层中主要是涉及到寄存器的操作,需要初始化使用到的引脚,通过接受p_lcd_params类型变量的参数来初始化LCD显示相关的寄存器,也有LCD的使能失能函数,同时比较重要的是最后一个函数,注册函数,只有调用了注册函数,对于管理层来说这个控制器才是可见状态。

  • 如果这时还有一个TI的LCD控制器的话,此时应该新建一个 ti_lcd_controller.c和ti_lcd_controller.h文件,其中里面的函数结构大致如下:

当你注册完了之后,这个LCD控制器的信息就会保存在结构体数组里面,如果你想使用哪个控制器的话可以直接使用名字来找到这个结构体:

在lcd_controller.c中这样子做:

解释:外部调用的时候,这个程序就会在已经注册的数组里面通过 name这个结构体变量去找到被选择的这个lcd控制器的信息,如果找到匹配的就把这个控制器的信息保存全局变量中,

例如:调用函数select_lcd_controller("s3c2440");的就是选择s3c2440这个控制器

那么它所调用的初始化函数就自然是s3c2440的初始化函数了,因为此时这个指针变量就指向s3c2440。

  • 在lcd_controller中(第④层)有哪些函数?

其中lcd_controller.c的代码如下:

#include "lcd.h"
#include "lcd_controller.h"
#include "s3c2440_lcd_controller.h"
#include "../string_utils.h"

/*这个文件的功能用于管理不同的lcd控制器*/

//定义lcd控制器的个数,最大为5个
#define LCD_CONTROLLER_NUM 5 
//保存已经注册的LCD控制器的信息
static p_lcd_controller p_array_lcd_controller[LCD_CONTROLLER_NUM];
//保存选中的lcd控制器信息的数组 
static p_lcd_controller p_beselected_lcdcontroller;




//注册某款lcd控制器:供给下层的程序调用:例如2440或者 ti控制器

int register_lcd_controller(p_lcd_controller plcdcontroller)
{
	/*放置到数组的哪一项呢?
	 *从数组的头开始扫描,如果发现哪一项是空的就直接放进去 
	*/
	int i;
	for (i=0;i<LCD_CONTROLLER_NUM;i++)
	{
		if(!p_array_lcd_controller[i])  /*此项没有数据*/
		{
			//存放
			p_array_lcd_controller[i] = plcdcontroller;
			return i;
		}
	
	}
	return -1;  //失败
}

//选择某一款LCD:
/*根据控制器的名字,在已经注册的控制器数组(LCD_CONTROLLER_NUM)
  找出和所选中的控制器名字一样的具体lcd控制器的的参数。
  如果在已注册的数组未找到,说明没有这款控制器
 */
int select_lcd_controller(char *name)
{
	int i;
	for (i=0;i<LCD_CONTROLLER_NUM;i++)
	{
		/*从头开始扫描数组,如果这个数组项不为空,而且控制器
          的名字和我们选择的是一致的话:找到相对应的具体某款lcd控制器
	     */
		if(p_array_lcd_controller[i] && !strcmp(p_array_lcd_controller[i]->name,name) );	
		{
			//找到了这个控制器的信息,存取全局变量中,以便使用
			p_beselected_lcdcontroller = p_array_lcd_controller[i];
		}
	
	}
	return -1;	//失败

	
}

/*向上:接收不同LCD的参数:
 例如:引脚的极性,时序,数据格式bpp,
      分辨率和frambuffer的地址
  向下:使用这些参数设置对应的LCD控制器
  例如:s3c2440_lcd_controller
 
 */
int lcd_controller_init(p_lcd_params plcd_params)
{
	/*调用被选中的LCD控制器初始化函数*/
	if(p_beselected_lcdcontroller)  //变量非空,确保已经有选中的lcd控制器才调用
	{
		p_beselected_lcdcontroller ->init(plcd_params);
		return 0;
	}
	return -1;
}

/*lcd控制器使能*/
void lcd_controller_enable(void)
{
	if(p_beselected_lcdcontroller)	//变量非空,确保已经有选中的lcd控制器才调用
	{
		p_beselected_lcdcontroller->enable();
		
	}


	
}
/*lcd控制器使能*/
void lcd_controller_disable(void)
{
	if(p_beselected_lcdcontroller)	//变量非空,确保已经有选中的lcd控制器才调用
	{
		p_beselected_lcdcontroller->disable();
		
	}

}

/*lcd控制器注册函数
  注意:这里注册的是:s3c2440的控制器,如果需要
       调用别的控制器在这里直接修改就OK*/
void lcd_controller_add(void)
{
	s3c2440_lcd_controller_add2array();

}

备注:如果此时你想使用某款LCD控制器的话,通过函数的封装,就可以只调用两个函数:

在管理层的用户就可以


3.LCD管理层和LCD屏幕相关层

他们直接的联系和上面的逻辑是一样了,lcd.c同样忽略了不同尺寸LCD的差异,在这里使用了4.2寸的LCD屏幕。

  • 提取处不同LCD共同的特点

其实不同LCD区别,无非就是引脚极性,分辨率,bpp等的不同,frambuffer地址。

因此在lcd.h中新建一个结构体用于保存LCD详细的参数。

如下:

/*建立一个枚举类型,用于极性的判断*/
enum {
	/* NORMAL : 正常极性:通过原理图才可知正常极性
	 * INVERT : 反转极性
	 */
	NORMAL = 0,
	INVERT = 1,
};

/*创建一个结构体用于定义LCD的极性*/
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;

/*LCD时序结构体*/
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;

/*LCD参数,包括极性,时序,分辨率,bpp,frambuffer地址
 *         这些参数是我们需要告诉LCD控制器的参数,用一个
 *         结构体把他们保存起来。
 */
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;

同样在LCD管理层中也会提供注册函数,给下一层去注册不同尺寸的LCD,同时也有选中函数,根据lcd屏幕的名字来选择不同尺寸的LCD:

在lcd中有以下函数:


  • 在LCD屏幕相关层去定义一个结构体变量,设置4.3寸LCD屏幕特有的性质:

因此在lcd_4.3.c中也会提供一个注册函数,把自己注册到LCD列表里面:

调用的是上一层管理层所提供的注册函数


4.LCD的初始化

在lcd.c提供了一个初始化函数

如下:

可以直接在测试函数中去调用这个函数就能直接初始化LCD了。


5.测试LCD

步骤:

1.初始化

2.使能


/*LCD测试函数*/
void lcd_test(void)
{
	unsigned int fb_base;
	int xres, yres, bpp;
	int x, y;
	unsigned short *p;

	/*初始化LCD*/
	lcd_init();
	/*使能LCD*/
	lcd_enable();
	/*获得参数*/
	  //这个函数获取得到的数值是在lcd_test里面使用的
	get_lcd_params(&fb_base,&xres,&yres,&bpp);
	  //这个函数中获取的值是在画点函数中用的,
	  //fb_get_lcd_params();
	/*获得字体需要用的LCD参数*/
	//font_init();
	/*判断bpp的数值*/
	if (bpp == 16)
	{
		/* 让LCD输出整屏的红色 */

		/* 565: 0xf800 */

		p = (unsigned short *)fb_base;
		for (x = 0; x < xres; x++)
			for (y = 0; y < yres; y++)
				*p++ = 0xf800;

		/* green */
		p = (unsigned short *)fb_base;
		for (x = 0; x < xres; x++)
			for (y = 0; y < yres; y++)
				*p++ = 0x7e0;

		/* blue */
		p = (unsigned short *)fb_base;
		for (x = 0; x < xres; x++)
			for (y = 0; y < yres; y++)
				*p++ = 0x1f;

		/* black */
		p = (unsigned short *)fb_base;
		for (x = 0; x < xres; x++)
			for (y = 0; y < yres; y++)
				*p++ = 0;
			
	}
	

	
}

源代码: https://download.csdn.net/download/qq_36243942/11110048

发布了91 篇原创文章 · 获赞 247 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/qq_36243942/article/details/89039634
今日推荐