基於嵌入式Linux的LCD液晶點陣顯示的基本實現

本文以嵌入式Linux爲板載系統。寫一個測試LCD液晶點陣的小例子,在這個小例子當中主要實現液晶點陣的中文和英文實現。


一、前期準備工作

1、基本開發環境

PC機 : Ubuntu9.10

gcc版本 : gcc version 4.3.2

板載系統 :Linux(kernel version Linux-3.4.10)

2、字體文件的準備

因爲本測試程序要實現液晶點陣的中英文兩種實現方式,所以需要兩種點陣字體。

英文字體來自Linux內核中的drivers/video/console/font_8X16.c的fontdata_8X16這個數組當中。

中文字體來自於網絡下載的字體文件HZK16,可以從這個地址下載得到。

二、打開LCD驅動設備文件和HZK16點陣字體文件

在打開設備文件之前,定義一些全局變量方便測試程序的編寫,具體如下:

/* 一些全局變量的定義 */
int fd_fb;							// LCD設備驅動的文件句柄
struct fb_var_screeninfo var;		// 定義LCD的可變參數
struct fb_fix_screeninfo fix; 		// 定義LCD的固定參數
int screen_size;					// 表示整個屏幕所佔顯存的大小
int line_width;						// 表示屏幕每一行所佔顯存的大小
int pixel_width;					// 表示每個像素點所佔顯存的大小
char *fbmem;						// 表示顯存的起始地址

int fd_hzk16;						// HZK16漢字庫的文件句柄
struct stat hzk16_stat;				// 描述HZK16這個文件的狀態信息
char *hzk16mem;						// HZK16這個漢字庫映射到內存的起始地址

1、打開LCD驅動設備文件

打開LCD設備驅動來獲取液晶的可變參數,固定參數,以及將液晶顯存映射到用戶空間,具體實現如下所示:

/* 以可讀可寫方式打開LCD液晶驅動 */
	fd_fb = open("/dev/fb0", O_RDWR);
	if(fd_fb == -1)
	{
		printf("can't open /dev/fb0!\n");
		return -1;
	}

	/* 獲取LCD液晶的可變參數 */
	ret = ioctl(fd_fb, FBIOGET_VSCREENINFO, &var);
	if(ret == -1)
	{
		printf("can't ioctl for /dev/fb0!\n");
		return -1;
	}

	/* 獲取LCD液晶的固定參數 */
	ret = ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix);
	if(ret == -1)
	{
		printf("can't ioctl for /dev/fb0!\n");
		return -1;
	}

	/* 獲取液晶顯存,每一行顯存,每一個像素顯存的大小 */
	screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
	line_width  = var.xres * var.bits_per_pixel / 8;
	pixel_width = var.bits_per_pixel / 8;

	/* 將液晶顯存映射到用戶空間 */
	fbmem = mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
	if(fbmem == (char *)-1)
	{
		printf("mmap for /dev/fb0 error!\n");
		return -1;
	}

2、打開HZK16點陣字體文件

打開HZK16文件來將HZK16字庫的內容映射到程序的用戶空間,方便對字體文件的操作,具體實現如下:

/* 以只讀方式打開漢子庫HZK16這個文件 */
	fd_hzk16 = open("HZK16", O_RDONLY);
	if(fd_hzk16 == -1)
	{
		printf("can't open HZK16!\n");
		return -1;
	}

	/* 獲取HZk16這個漢字庫的文件信息 */
	ret = fstat(fd_hzk16, &hzk16_stat);
	if(ret == -1)
	{
		printf("fstat for HZK16 is error!\n");
		return -1;
	}

	/* 將漢子庫HZK16文件中的內容映射到用戶空間 */
	hzk16mem = mmap(NULL, hzk16_stat.st_size, PROT_READ, MAP_SHARED, fd_hzk16, 0);
	if(hzk16mem == (char *)-1)
	{
		printf("mmap for HZK16 error!\n");
		return -1;
	}

三、液晶點陣的基本操作的實現

1、LCD液晶顯示英文字符串

這個函數的具體實現如下:

/*	LCD顯示英文字符串		
 *		x : 表示x軸座標
 *		y : 表示y軸座標
 *		str : 表示顯示的字符串的首地址
 */
void lcd_show_string(int x, int y, char* str)
{
	int i = 0;

	for(i = 0; str[i] != '\0'; i++)		// 判斷是否顯示完畢
	{
		if((x + 8) > var.xres)
		{
			x = 0;
			y = y + 16;
			if(y > var.yres)
				y = 0;
		}

		lcd_show_char(x, y, str[i]);
		x = x + 8;
	}
}
它的內部調用的lcd_show_char()這個顯示單個英文字符的函數,它的具體實現如下:
/*	LCD顯示字符函數
 *		x : 表示要顯示的字符的x座標
 *		y : 表示要顯示的字符的y座標
 *		c : 表示要顯示的字符
 */
void lcd_show_char(int x, int y, char c)
{
	/* 獲取字符在字符數組中的起始位置 */
	unsigned char *buffer = (unsigned char *)&yl_lcd_font_8x16[c * 16];
	unsigned char data;
	int i, j;

	/* 循環操作將整個字符寫入到顯存指定位置中,達到在指定位置顯示字符 */
	for(i = 0; i < 16; i++)
	{
		data = buffer[i];
		for(j = 0; j < 8; j++)
		{
			if(data & 0x80)
			{
				lcd_put_pixel(x + j, y + i, WHITE);  /*白色*/
			}
			else
			{
				lcd_put_pixel(x + j, y + i, BLACK);  /*黑色*/
			}
			data = data << 1;
		}
	}
}
在這個函數的內部它有調用的lcd_put_pixel()這個函數來吧點陣寫到LCD的framebuffer中,它的具體實現如下:

/*	LCD像素點顯示
 *		x : 表示x軸的座標
 *		y : 表示y軸的座標
 *		color : 表示像素點要顯示的顏色
 */
void lcd_put_pixel(int x, int y, int color)
{
	unsigned char *pen8 = fbmem + y * line_width + x * pixel_width;
	unsigned short *pen16 = (unsigned short *)pen8;
	unsigned int *pen32 = (unsigned int *)pen32;

	int red, green, blue;

	/* 判斷像素點的大小 */
	switch(var.bits_per_pixel)
	{
		case 16:	/* 16 bit */
			{
				red   = (color >> 16) & 0xff;
				green = (color >> 8) & 0xff;
				blue  = color & 0xff;

				*pen16 = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
				
				break;	
			}
		case 32:	/* 32 bit */
			{
				*pen32 = color;
				break;
			}
		default :
			{
				printf("Don't support this size of pixel : %d\n", var.bits_per_pixel);
				break;
			}
	}
}
從上面可以看出不管是中文顯示還是英文顯示最終調用的都是lcd_put_pixel()這個函數來進行點陣顯示。

2、LCD液晶顯示中文字符串

LCD顯示中文字符串的具體實現如下:

/*	LCD顯示中文字符串
 *		x : 表示x軸座標
 *		y : 表示y軸座標
 *		str : 表示要顯示的漢子字符編碼的首地址
 */
void lcd_show_chinese(int x, int y, char* str)
{
	int i = 0;
	for(i = 0; str[i] != '\0'; i = i + 2)	// 判斷是否顯示完畢
	{
		if((x + 16) > var.xres)
		{
			x = 0;
			y = y + 16;
			if(y > var.yres)
				y = 0;
		}
		lcd_show_single_chinese(x, y, &str[i]);
		x = x + 16;
	}
}
在這個函數內部調用了lcd_show_single_chinese()這個顯示單個漢子的函數,它的具體實現如下:
/*	LCD液晶顯示單個漢子
 *		x : 表示x軸的座標
 *		y : 表示y軸的座標
 *		str : 表示要顯示的漢子的字符編碼
 */
void lcd_show_single_chinese(int x, int y, char* str)
{
	/* 確定漢子在字符中的位置 */
	int area = str[0] - 0xa1;
	int where = str[1] - 0xa1;
	unsigned char* buffer = (unsigned char *)(hzk16mem + (area * 94 + where) * 32);
	unsigned short data;
	int i, j;

	/* 循環的將漢子的點陣寫入到LCD液晶屏的顯存當中 */
	for(i = 0; i < 16; i++)
	{
		data = (buffer[i * 2] << 8) | buffer[i * 2 + 1];
		for(j = 0; j < 16; j++)
		{
			if(data & 0x8000)
			{
				lcd_put_pixel(x + j, y + i, WHITE);  /*白色*/
			}
			else
			{
				lcd_put_pixel(x + j, y + i, BLACK);  /*黑色*/
			}
			data = data << 1;
		}
	}
}

3、LCD液晶進行中英文混合顯示

這個函數的具體實現如下:

/*	LCD中英文混合顯示函數
 *		 x : 表示x軸座標
 *		 y : 表示y軸座標
 *		 str : 表示要顯示的字符串的首地址
 */
void lcd_show_str_chn(int x, int y, char *str)
{
	int i = 0;
	for(i = 0; str[i] != '\0'; )	// 判斷是否顯示完
	{
		if(str[i] < 128)	// 表示是英文字符
		{
			if((x + 8) > var.xres)
			{
				x = 0;
				y = y + 16;
				if(y > var.yres)
					y = 0;
			}
			lcd_show_char(x, y, str[i]);
			x = x + 8;
			i = i + 1;
		}
		else 		// 表示是中文字符
		{
			if((x + 16) > var.xres)
			{
				x = 0;
				y = y + 16;
				if(y > var.yres)
					y = 0;
			}
			lcd_show_single_chinese(x, y, &str[i]);
			x = x + 16;
			i = i + 2;
		}
	}
}

4、LCD液晶的清屏函數

這個函數的主要功能是清除整個屏幕爲指定的顏色,它的實現如下:

/*	LCD液晶清屏
 *		color : 表示要將屏幕成的顏色
 */
void lcd_clear_screen(int color)
{
	memset(fbmem, color, screen_size);
}

四、測試

對上面實現的基本函數進行測試,看看能不能正常進行中文顯示,英文顯示以及中英文混合顯示,具體實現如下:

/* 將整個液晶屏清屏爲黑色 */
	lcd_clear_screen(BLACK);

	/* 在液晶屏上進行中英文的顯示操作 */
	lcd_show_string(100, 100, "Hello world!");
	lcd_show_string(100, 120, "Welcome to Embedded world!");
	lcd_show_chinese(100, 140, "學習嵌入式開發");
	lcd_show_str_chn(100, 160, "**農業大學, www.syau.edu.cn");
通過編譯並執行可以得出相應的結果。


附錄:完整的程序代碼所在的位置。

http://download.csdn.net/download/tech_pro/9871728


發佈了83 篇原創文章 · 獲贊 75 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章