www.pudn.com > LCD-LGM.rar > LCD-LGM.c


/******************************************************* 
程序功能:LCD汉字及图形点阵显示 
作者:剑影 
厦门大学03级机电工程系 
email:gmdengxm@163.com 
QQ群:22086176 
 
********************************************************* 
接线说明: 
80C51  LGM12641BS1R 和 AMPIR 128 X 64 
P0.0~7 --- DB0~7 
P0.0~7接74ls373	D0~7 = Q0~7 
Q0---RW	 
Q1---DI(RS)	 
Q4 --- CS2( AMPIR 128 X 64)CS1( LGM12641BS1R) 
Q5--- CS1( AMPIR 128 X 64)	CS2( LGM12641BS1R) 
!(WR&RD) ---- E 
ALE ---LE(74ls373) 
 
********************************************************* 
AMPIR 128 X 64  命令说明 
 
DI	WR	D7	D6	D5	D4	D3	D2	D1	D0			 
 0	0	0	1	1	1	1	1	1	D	*D = 1时显示开 ×D = 0时显示关 
 0	0	1	1	A	A	A	A	A	A	* 设定显示开始行寄存器位置 
 0	0	1	0	1	1	1	A	A	A	*设定页地址 
 0	0	0	1	A	A	A	A	A	A	*设定列地址 
 1	0	D7	0	D5	D4	0	0	0	0	*D7为1表示LCD忙,D7=0可以读写操作,D5 = 1显示关状态,D5 = 0显示开状态, 
										*D4=1表示正在初始化,D4=0初始化完毕 
 
 0	1	D	D	D	D	D	D	D	D	*写入数据,列地址自动加1 
 1	1	D	D	D	D	D	D	D	D	*读取显示状态 
 
 
********************************************************/ 
 
 
 
 
 
#include  
#include  
 
typedef	unsigned char	uchar; 
typedef	unsigned int	uint; 
 
/****************LCD读写控制字*****************/ 
											//左半部 
#define		LLCD_CMD_WR 	PBYTE[0x10]     //写命令rs = 0 wr = 0 
#define		LLCD_CMD_RD		PBYTE[0x11]		//读命令rs = 0 wr = 1  
#define		LLCD_DATA_WR	PBYTE[0x12]		//写数据rs = 1 wr = 0 
#define		LLCD_DATA_RD	PBYTE[0x13]		//读数据rs = 1 wr = 1 
 
											//右半部 
#define		RLCD_CMD_WR		PBYTE[0x20]		//同上,为LCD右半部分的读写指令 
#define		RLCD_CMD_RD		PBYTE[0x21] 
#define		RLCD_DATA_WR	PBYTE[0x22] 
#define		RLCD_DATA_RD	PBYTE[0x23] 
 
#define		LCD_DOT_MAXX	128			//此LCD为128X64,分左右两部分,每部分64X64 
#define		LCD_DOT_MAXY	64	 
#define		LCD_MAXX		8			//以16为一个单位,行上最多可显示8个单位 
#define		LCD_MAXY		4			//列上可以显示4个单位,整个屏幕可显示8x4 =32个中文字符 
sbit		busy = P0^7; 
 
/***************数组定义***********************/ 
code uchar hanzi1[] = 
{ 
/*--  文字:  厦  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0x00,0x00,0xF0,0x10,0xF0,0xB0,0xB0,0xF0,0xB0,0xB0,0xF0,0xF0,0x10,0x00,0x00, 
0x00,0x10,0x0C,0x07,0x28,0x2B,0x1B,0x1F,0x1F,0x1F,0x17,0x33,0x33,0x30,0x30,0x00, 
 
/*--  文字:  门  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0x00,0x00,0xE0,0x80,0x10,0x30,0x20,0x20,0x30,0x20,0x20,0x20,0xE0,0x00,0x00, 
0x00,0x10,0x18,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00, 
 
/*--  文字:  大  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0x00,0x80,0xC0,0x80,0x80,0x80,0xF0,0xF0,0x80,0x80,0x80,0x80,0x00,0x00,0x00, 
0x00,0x10,0x18,0x18,0x18,0x0C,0x06,0x03,0x01,0x02,0x06,0x0C,0x18,0x38,0x10,0x00, 
 
/*--  文字:  学  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0x00,0xC0,0x40,0x70,0x40,0x40,0xF0,0x40,0x40,0x70,0x50,0x40,0xC0,0x00,0x00, 
0x00,0x0C,0x05,0x04,0x24,0x25,0x25,0x36,0x1F,0x0D,0x05,0x04,0x04,0x0D,0x0C,0x04, 
 
 
 
}; 
 
code uchar	hanzi2[] = 
{ 
/*--  文字:  机  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0x00,0x40,0x40,0xF0,0x40,0x40,0x00,0xE0,0x20,0x20,0xE0,0x20,0x00,0x00,0x00, 
0x00,0x04,0x06,0x03,0x3F,0x03,0x12,0x1C,0x0F,0x00,0x00,0x0F,0x18,0x18,0x18,0x08, 
 
/*--  文字:  电  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0x40,0xE0,0xA0,0xA0,0xA0,0xF0,0xB0,0xA0,0xA0,0xA0,0xE0,0x00,0x00,0x00,0x00, 
0x00,0x00,0x07,0x06,0x06,0x02,0x0F,0x1A,0x1A,0x32,0x36,0x33,0x30,0x30,0x18,0x00, 
 
/*--  文字:  工  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0x00,0x00,0x20,0x20,0x20,0x20,0xE0,0x60,0x20,0x20,0x20,0x20,0x00,0x00,0x00, 
0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x0F,0x08,0x08,0x08,0x18,0x18,0x18,0x18,0x00, 
 
/*--  文字:  程  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0xC0,0xA0,0xA0,0xE0,0x90,0x90,0xF0,0xF0,0xA0,0xA0,0xA0,0xF0,0x00,0x00,0x00, 
0x00,0x06,0x02,0x1F,0x3F,0x01,0x12,0x15,0x15,0x1F,0x1F,0x15,0x15,0x10,0x10,0x00, 
 
/*--  文字:  系  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0x00,0x20,0xA0,0xA0,0xE0,0xE0,0xA0,0xA0,0x50,0x50,0x10,0x10,0x00,0x00,0x00, 
0x00,0x10,0x10,0x18,0x1A,0x2F,0x23,0x3E,0x3E,0x03,0x05,0x09,0x1A,0x18,0x10,0x00, 
 
}; 
 
code uchar	hanzi3[] =  
{ 
/*--  文字:  0  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
 
/*--  文字:  3  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
 
/*--  文字:  机  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0x00,0x40,0x40,0xF0,0x40,0x40,0x00,0xE0,0x20,0x20,0xE0,0x20,0x00,0x00,0x00, 
0x00,0x04,0x06,0x03,0x3F,0x03,0x12,0x1C,0x0F,0x00,0x00,0x0F,0x18,0x18,0x18,0x08, 
 
/*--  文字:  械  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0x00,0x40,0xC0,0xF0,0x40,0x00,0x40,0xC0,0x40,0xF0,0x40,0xF0,0x40,0x00,0x00, 
0x04,0x04,0x02,0x01,0x3F,0x15,0x1A,0x07,0x02,0x1F,0x0F,0x0E,0x19,0x38,0x10,0x10, 
}; 
 
code uchar	hanzi4[] = 
{ 
/*--  文字:  剑  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x80,0x80,0xC0,0x40,0xA0,0xB0,0xB0,0xC0,0x40,0x00,0xC0,0x00,0x30,0xF0,0x00,0x00, 
0x00,0x10,0x18,0x1F,0x18,0x1E,0x08,0x0E,0x08,0x10,0x13,0x30,0x38,0x1F,0x00,0x00, 
 
/*--  文字:  影  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0x00,0x00,0x70,0x50,0xD0,0x50,0x70,0x70,0x80,0x40,0x20,0x30,0x90,0x00,0x00, 
0x01,0x01,0x11,0x1F,0x27,0x3E,0x07,0x0F,0x31,0x22,0x12,0x11,0x09,0x0C,0x06,0x00, 
 
/*--  文字:  制  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0x80,0x40,0x70,0x40,0xF0,0xD0,0xC0,0x40,0x00,0xE0,0x00,0x30,0xF0,0x00,0x00, 
0x01,0x01,0x11,0x1F,0x03,0x3F,0x03,0x06,0x1E,0x10,0x17,0x30,0x38,0x1F,0x00,0x00, 
 
/*--  文字:  作  --*/ 
/*--  隶书12;  此字体下对应的点阵为:宽x高=16x16   --*/ 
0x00,0x60,0x60,0xE0,0xE0,0x90,0x40,0x60,0x30,0xF0,0x60,0x60,0x60,0x40,0x40,0x00, 
0x00,0x00,0x00,0x1F,0x1F,0x00,0x00,0x00,0x00,0x3F,0x05,0x05,0x05,0x05,0x04,0x00, 
}; 
 
code uchar bmp[] = 
{ 
/*--  宽度x高度=32x32  --*/ 
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xE0,0xF0,0x30,0x18,0x04,0x02,0x00,0x00,0x00, 
0x00,0x00,0x00,0x00,0x80,0x80,0xC0,0xC0,0xE0,0xF0,0xF0,0xF0,0xF8,0xF8,0xFC,0xFC, 
0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0x1F,0x0F,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
0x00,0x70,0xFC,0xFE,0xFF,0x7F,0x3B,0x71,0x7B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 
0xE7,0x87,0x07,0x0F,0x0F,0x07,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
0x00,0x00,0x0F,0x0B,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x0E,0x18,0x01,0x03, 
0x07,0x0F,0x0F,0x1C,0x18,0x30,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
}; 
/***************变量定义***********************/ 
 
uchar	x,y; 
struct	cursortype 
{ 
	uchar	x,y,side; 
}cousor; 
 
 
/***************函数定义***********************/ 
void	lcd_cmd_wr(uchar cmdcode, uchar right);		//写命令 
void	lcd_data_wr(uchar ldata, uchar right);		//写数据 
void	lcd_busy_rd(uchar right);		//读状态 
void	chk_busy(uchar right); 
void	lcd_hanzi_wr(uchar posx,uchar posy,uchar *hanzi); 
void	lcd_str_wr(uchar row,uchar col,uchar n,uchar *str); 
void	lcd_bmp_wr(uchar posx,uchar posy,uchar wth,uchar hgh,uchar *bmp); 
void	lcd_rol(); 
void	lcd_init(); 
void	delay(uint nms);							//延时 n ms 
 
/****************主函数***********************/ 
 
void	main() 
{ 
	lcd_init(); 
 
	lcd_str_wr(0,1,4,hanzi1); 
	delay(100); 
	lcd_str_wr(1,1,5,hanzi2); 
	delay(100); 
	lcd_str_wr(2,1,4,hanzi3); 
	delay(100); 
	lcd_str_wr(3,1,4,hanzi4); 
	delay(100); 
	lcd_bmp_wr(0,0x60,32,32,bmp); 
	delay(100); 
 
	while(1) 
	{ 
		lcd_rol(); 
		delay(1000); 
	} 
	 
} 
 
/****************子函数***********************/ 
void	lcd_cmd_wr(uchar cmdcode, uchar right)		//写指令 
{ 
	chk_busy(right);		//检查是否忙???? 
 
	if(right == 1)			//如果right = 1,则对右半部进行读写 
	{ 
		RLCD_CMD_WR = cmdcode; 
	} 
	else					//否则写左半部LCD 
	{ 
		LLCD_CMD_WR = cmdcode; 
	} 
} 
 
void	lcd_data_wr(uchar ldata, uchar right)		//对LCD进行数据读写, 
{ 
	chk_busy(right);		//检测LCD忙,                  (对右面的检测???) 
	if(right == 1) 
	{ 
		RLCD_DATA_WR = ldata; 
	} 
	else 
	{ 
		LLCD_DATA_WR = ldata; 
	} 
} 
 
void	lcd_busy_rd(uchar right) 
{ 
	if( right == 1) 
	{ 
		 RLCD_CMD_RD;         //           输出命令!!!!! 
	} 
	else 
	{ 
		 LLCD_CMD_RD;	 
	} 
} 
									//这个函数调和完后LCD就一定不忙的 
void	chk_busy(uchar right)		//检测LCD忙,right = 1 为右半部, 
{ 
	lcd_busy_rd(right);				//right = 0为左半部,遇忙等待 
	while(busy);					//输出命令后,要等待???好方法 
} 
 
void	delay(uint nms)		//延时程序 
{ 
	uint i; 
	for(; nms > 0; nms--) 
		for(i = 0; i < 500; i++); 
} 
 
void	lcd_init()			//LCD初始化 
{ 
	uint k; 
	lcd_cmd_wr(0x3e+1,0);		//左半部显示开 
	lcd_cmd_wr(0xc0+0,0);		//左半部顶行为第0行 
	lcd_cmd_wr(0xb8+0,0);		//设定左半部页地址 
	lcd_cmd_wr(0x40+0,0);		//设定左半部列地址 
	lcd_cmd_wr(0x3e+1,1);		//右半部显示开 
	lcd_cmd_wr(0xc0+0,1);		//右半部顶行设定为第0行 
	lcd_cmd_wr(0x40+0,1);		//设定列地址 
	lcd_cmd_wr(0xb8+0,1);		//设定页地址 
 
	for(k = 0; k < 256; k++)	//LCD屏初始化 
	{ 
		lcd_data_wr(0x00,0); 
	lcd_data_wr(0x00,1); 
	} 
	lcd_cmd_wr(0xb8+4,0); 
	lcd_cmd_wr(0x40+0,0); 
	lcd_cmd_wr(0xb8+4,1); 
	lcd_cmd_wr(0x40+0,1); 
	for(k = 0; k < 256; k++) 
	{ 
		lcd_data_wr(0x00,0); 
		lcd_data_wr(0x00,1); 
	} 
} 
 
void	lcd_hanzi_wr1(uchar posx,uchar posy,uchar * hanzi)		//对LCD在指定位置写入单个汉字 
{ 
	uchar i; 
	if(posy < 4)		//posy < 4 在左半部写 
	{ 
		lcd_cmd_wr(0xb8+2*posx,0); 
		lcd_cmd_wr(0x40+16*posy,0); 
		for(i = 0; i < 16; i++) 
		{ 
			lcd_data_wr(hanzi[2*i],0);	 
		} 
		lcd_cmd_wr(0xb8+2*posx+1,0); 
		lcd_cmd_wr(0x40+16*posy,0); 
		for(i = 0; i < 16; i++) 
		{ 
			lcd_data_wr(hanzi[2*i+1],0); 
		} 
	} 
	else		//否则在右半部写 
	{ 
		lcd_cmd_wr(0xb8+posx*2,1); 
		lcd_cmd_wr(0x40+16*(posy-4),1); 
		for(i = 0; i < 16; i++) 
		{ 
			lcd_data_wr(hanzi[2*i],1);	 
		} 
		lcd_cmd_wr(0xb8+2*posx+1,1); 
		lcd_cmd_wr(0x40+16*(posy-4),1); 
		for(i = 0; i < 16; i++) 
		{ 
			lcd_data_wr(hanzi[2*i+1],1); 
		} 
	} 
} 
 
void	lcd_hanzi_wr(uchar posx,uchar posy,uchar * hanzi)		//对LCD在指定位置写入单个汉字 
{ 
	uchar i; 
	if(posy < 4)		//posy < 4 在左半部写 
	{ 
		lcd_cmd_wr(0xb8+2*posx,0); 
		lcd_cmd_wr(0x40+16*posy,0); 
		for(i = 0; i < 16; i++) 
		{ 
			lcd_data_wr(hanzi[i],0);	 
		} 
		lcd_cmd_wr(0xb8+2*posx+1,0); 
		lcd_cmd_wr(0x40+16*posy,0); 
		for(i = 16; i < 32; i++) 
		{ 
			lcd_data_wr(hanzi[i],0); 
		} 
	} 
	else		//否则在右半部写 
	{ 
		lcd_cmd_wr(0xb8+posx*2,1); 
		lcd_cmd_wr(0x40+16*(posy-4),1); 
		for(i = 0; i < 16; i++) 
		{ 
			lcd_data_wr(hanzi[i],1);	 
		} 
		lcd_cmd_wr(0xb8+2*posx+1,1); 
		lcd_cmd_wr(0x40+16*(posy-4),1); 
		for(i = 16; i < 32; i++) 
		{ 
			lcd_data_wr(hanzi[i],1); 
		} 
	} 
} 
 
void	lcd_str_wr(uchar row,uchar col,uchar n,uchar *str) 
{ 
	uchar i; 
	for(i = 0 ; i < n; i++) 
	{ 
		if( col > 7) 
		{ 
			row++; 
			col = col - 8;	 
		} 
		lcd_hanzi_wr(row,col,str+i*32); 
		col++;	 
	} 
} 
 
void	lcd_bmp_wr(uchar posx,uchar posy,uchar wth,uchar hgh,uchar *bmp)	//posx 取值为0~3,posy = 0~128,宽wth和高hgh必须为8的倍数 
{ 
	uchar i,j;																//这里行posx如果不取8的倍数,则要另外算 
	hgh =hgh/8; 
 
	for(i = 0; i < hgh; i++) 
	{		 
			if(posy < 64)					// 
			{ 
				lcd_cmd_wr(0xb8+posx+i,0); 
				lcd_cmd_wr(0x40+posy,0); 
				for(j = 0; j < wth;j++) 
				{ 
				lcd_data_wr(bmp[32*i+j],0); 
				} 
			} 
			else 
			{ 
				lcd_cmd_wr(0xb8+posx+i,1); 
				lcd_cmd_wr(0x40+posy-64,1); 
				for(j = 0; j < wth; j++) 
				{ 
				lcd_data_wr(bmp[32*i+j],1); 
				} 
			} 
		} 
	} 
 
 void	lcd_rol()					//向上滚屏 
 { 
 	uchar i; 
	for(i = 0; i < 64; i++) 
	{ 
		lcd_cmd_wr(0xc0+i,0); 
		lcd_cmd_wr(0xc0+i,1); 
		delay(10); 
	} 
 }