⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 t6963b.c

📁 c8051学习机实验程序
💻 C
字号:
/*写汉字液晶子程 

  本例程未使用6963的文本模式,使用程序填入字模也足够快。程序以Youth所提供
的51例程移植过来,同时对有些地方做了简化处理,增加了画线画圆的例程,好在
6963的画点有专用指令,所以不用读屏就可以直接画点。
  
;************************************************************************
;连线图:  液晶屏分为8行*15列汉字,使用总线接口方式(C8051F020的高端口)   *
;*LCM---C8051*	  *LCM---C8051*    *LCM----C8051*      *LCM----C8051*   *
;*DB0-----P70*	  *DB4-----P74*	   *Rd ------P46*      *C/D------P50*	*
;*DB1-----P71*	  *DB5-----P75*	   *Wr ------P47*      *CE ------P57*	*
;*DB2-----P72*	  *DB6-----P76*	   *RST------VCC*      *FS ------Vcc*	* 
;*DB3-----P73*	  *DB7-----P77*						*
;注:C8051F020的晶振频率为22.1184MHz,发现偶尔会丢失数据	*
;************************************************************************/

#include "stdhead.h"
#include "zimo.h"

//#define ulong	unsigned long
//#define uint	unsigned int
//#define uchar	unsigned char

#define N_MAX_WAIT 10

// ASCII字符控制代码解释定义
#define STX	0x02
#define ETX	0x03
#define EOT	0x04
#define ENQ	0x05
#define BS	0x08
#define CR	0x0D
#define LF	0x0A
#define DLE	0x10
#define ETB	0x17
#define SPACE	0x20
#define COMMA	0x2C
                	
#define TRUE	1
#define FALSE	0
                	
#define HIGH	1
#define LOW	0

// T6963C 端口定义
#define LCMDW		XBYTE[0xfc00]		// 数据口
#define LCMCW		XBYTE[0xfd00]		// 命令口


// T6963C 命令定义
#define LC_CUR_POS	0x21		// 光标位置设置
#define LC_CGR_POS	0x22		// CGRAM偏置地址设置
#define LC_ADD_POS	0x24		// 地址指针位置
#define LC_TXT_STP	0x40		// 文本区首址
#define LC_TXT_WID	0x41		// 文本区宽度
#define LC_GRH_STP	0x42		// 图形区首址
#define LC_GRH_WID	0x43		// 图形区宽度
#define LC_MOD_OR	0x80		// 显示方式:逻辑“或”
#define LC_MOD_XOR	0x81		// 显示方式:逻辑“异或”
#define LC_MOD_AND	0x82		// 显示方式:逻辑“与”
#define LC_MOD_TCH	0x83		// 显示方式:文本特征
#define LC_DIS_SW	0x90		// 显示开关:D0=1/0:光标闪烁启用/禁用;
					// D1=1/0:光标显示启用/禁用;
					// D2=1/0:文本显示启用/禁用;
					// D3=1/0:图形显示启用/禁用;
#define LC_CUR_SHP	0xA0		// 光标形状选择:0xA0-0xA7表示光标占的行数
#define LC_AUT_WR	0xB0		// 自动写设置
#define LC_AUT_RD	0xB1		// 自动读设置
#define LC_AUT_OVR	0xB2		// 自动读/写结束
#define LC_INC_WR	0xC0		// 数据一次写,地址加1
#define LC_INC_RD	0xC1		// 数据一次读,地址加1
#define LC_DEC_WR	0xC2		// 数据一次写,地址减1
#define LC_DEC_RD	0xC3		// 数据一次读,地址减1
#define LC_NOC_WR	0xC4		// 数据一次写,地址不变
#define LC_NOC_RD	0xC5		// 数据一次读,地址不变
#define LC_SCN_RD	0xE0		// 屏读
#define LC_SCN_CP	0xE8		// 屏拷贝
#define LC_BIT_OP	0xF0		// 位操作:
					// D0-D2:定义D0-D7位;D3:1置位;0:清除

//uchar const uPowArr[]  = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar code turnf[8] = {7,6,5,4,3,2,1,0};
uchar gCurRow,gCurCol;	// 当前行、列存储,行高16点,列宽8点
uchar black = 0;
/*  取当前行数据  */
uchar fnGetRow(void)
{
	return gCurRow;
}

/*  取当前列数据  */
uchar fnGetCol(void)
{
	return gCurCol;
}

/************************************************/
/* 状态位STA1,STA0判断(读写指令和读写数据)	*/
/* 在读写数据或者写入命令前必须保证均为1	*/
/************************************************/
uchar fnSTA01(void)			
{
	uchar i;
	
	for(i=N_MAX_WAIT;i>0;i--)
	{
		if((LCMCW & 0x03) == 0x03)		// 读取状态
			break;
	}
	return i;					// 若返回零,说明错误
}
#if 0
/********************************************************/
/*检查STA2,如果 STA2=1 为自动读状态			*/
/********************************************************/
uchar fnSTA2(void)
{
	uchar i;
	
	for(i=N_MAX_WAIT;i>0;i--)
	{
		if((LCMCW & 0x04) == 0x04)
			break;
	}
	return i;					// 若返回零,说明错误
}
#endif
/********************************************************/
/* 状态位STA3判断(STA3 = 1 数据自动写状态)		*/
/********************************************************/
uchar fnSTA3(void)
{
	uchar i;
	
	for(i=N_MAX_WAIT;i>0;i--)
	{
		if((LCMCW & 0x08) == 0x08)
			break;
	}
	return i;					// 若返回零,说明错误
}
#if 0
/********************************************************/
/* 状态位STA6判断(STA6 =1 屏读/屏拷贝状态)		*/
/********************************************************/
uchar fnSTA6(void)
{
	uchar i;
	
	for(i=N_MAX_WAIT;i>0;i--)
	{
		if((LCMCW & 0x40) == 0x40)
			break;
	}
	return i;					// 若返回零,说明错误
}
#endif
/********************************************************/
/* 写双参数的指令					*/
/********************************************************/
uchar fnPR1(uchar uCmd,uchar uPar1,uchar uPar2)
{
	if(fnSTA01() == 0)
		return 1;
	LCMDW = uPar1;
	if(fnSTA01() == 0)
		return 2;
	LCMDW = uPar2;
	if(fnSTA01() == 0)
		return 3;
	LCMCW = uCmd;
	return 0;					// 返回0成功
}
#if 0
/********************************************************/
/* 写单参数的指令					*/
/********************************************************/
uchar fnPR11(uchar uCmd,uchar uPar1)
{
	if(fnSTA01() == 0)
		return 1;
	LCMDW = uPar1;
	if(fnSTA01() == 0)
		return 2;
	LCMCW = uCmd;
	return 0;					// 返回0成功
}
#endif
/********************************************************/
/* 写无参数的指令					*/
/********************************************************/
uchar fnPR12(uchar uCmd)
{
	if(fnSTA01() == 0)
		return 1;
	LCMCW = uCmd;
	return 0;					// 返回0成功
}

/********************************************************/
/*  写数据						*/
/********************************************************/
uchar fnPR13(uchar uData)
{
	if(fnSTA3() == 0)
		return 1;
	LCMDW = uData;
	return 0;					// 返回0成功
}
#if 0
/********************************************************/
/* 读数据						*/
/********************************************************/
uchar fnPR2(void)
{
	if(fnSTA01() == 0)return 1;			// 获取状态,如果状态错
	return LCMDW;					// 返回数据
}
#endif
/********************************************************/
/* 设置当前地址						*/
/********************************************************/
void fnSetPos(uchar urow, uchar ucol)
{
	uint  iPos;

	iPos = urow * 30 + ucol;
	fnPR1(LC_ADD_POS,iPos & 0xFF,iPos / 256);
	gCurRow = urow;
	gCurCol = ucol;
}

/********************************************************/
/* 设置当前显示行、列					*/
/********************************************************/
void cursor(uchar uRow, uchar uCol)
{
	fnSetPos(uCol* 16, uRow);
}

/********************************************************/
/* 清屏							*/
/********************************************************/
void cls(void)
{
	uint  i;

	fnPR1(LC_ADD_POS,0x00,0x00);	// 置地址指针为从零开始
	fnPR12(LC_AUT_WR);		// 自动写
	for(i=0;i<240*128/8;i++)	// 清一屏
		{
		fnSTA3();
		fnPR13(0x0);		// 写数据,实际使用时请将0x55改成0x0
		}
	fnPR12(LC_AUT_OVR);		// 自动写结束
	fnPR1(LC_ADD_POS,0x00,0x00);	// 重置地址指针
	gCurRow = 0;			// 置地址指针存储变量
	gCurCol = 0;
}

/********************************************************/
/* LCM 初始化						*/
/********************************************************/
char fnLCMInit(void)
{
	if(fnPR1(LC_TXT_STP,0x00,0x00) != 0)	// 文本显示区首地址
		return (0xff);
	fnPR1(LC_TXT_WID,0x1E,0x00);		// 文本显示区宽度
	fnPR1(LC_GRH_STP,0x00,0x00);		// 图形显示区首地址
	fnPR1(LC_GRH_WID,0x1E,0x00);		// 图形显示区宽度
	fnPR12(LC_CUR_SHP | 0x01);		// 光标形状
	fnPR12(LC_MOD_OR);			// 显示方式设置
	fnPR12(LC_DIS_SW | 0x08);		// 显示开关设置
	
	return 0;
}

/********************************************************/
/* ASCII(8*16) 及 汉字(16*16) 显示函数			*/
  /* 其中有全局变量black表示是否反显   1: 反显  0: 正常 */

/********************************************************/
uchar dprintf(char *fmt,...)
{
	va_list arg_ptr;
	char c1,c2,cData;

	char tmpBuf[80];// _at_ 0x40;  	// LCD显示数据缓冲区
	uchar i=0,j,uLen,uRow,uCol;
	uint k;

	va_start(arg_ptr, fmt);
	uLen = (uchar) vsprintf(tmpBuf, fmt,arg_ptr);
	va_end(arg_ptr);

       // EA=0;
	while(i<uLen)
	{

		c1 = tmpBuf[i];
		c2 = tmpBuf[i+1];
		uRow = fnGetRow();
		uCol = fnGetCol();
		if(c1 > 0 )
		{	// ASCII
			if(c1 < 0x20)
			{
				switch(c1)
				{
					case CR:
					case LF:		// 回车或换行
						i++;
						if(uRow < 144)
							fnSetPos(uRow+16,0);
						else
							fnSetPos(0,0);
						continue;
					case BS:		// 退格
						if(uCol > 0)
							uCol--;
						fnSetPos(uRow,uCol);
						cData = 0x00;
						break;
					default:		// 其他
						c1 = 0x1f;
				}
			}
			for(j=0;j<16;j++)
			{
				fnPR12(LC_AUT_WR);		// 写数据
				if(c1 >= 0x20)
				{
					if( j < (16-ASC_CHR_HEIGHT) )
						fnPR13(0x00);	// 写数据0输出空
					else
						fnPR13((0xff*black)^ASC_MSK[(c1-0x20)*ASC_CHR_HEIGHT+j-(16-ASC_CHR_HEIGHT)]);
				}
				else
					fnPR13(cData);
				fnPR12(LC_AUT_OVR);
				fnSetPos(uRow+j+1,uCol);
			}
			if(c1 != BS)		// 非退格
				uCol++;
		}

		else
		{	// 中文
			for(j=0;j<sizeof(GB_16)/sizeof(GB_16[0]);j++)
			{
				if(c1 == GB_16[j].Index[0] && c2 == GB_16[j].Index[1])
					break;
			}
			for(k=0;k<sizeof(GB_16[0].Msk)/2;k++)
			{
				fnSetPos(uRow+k,uCol);
				fnPR12(LC_AUT_WR);			// 写数据
				if(j < sizeof(GB_16)/sizeof(GB_16[0]))
				{
					fnPR13((0xff*black)^GB_16[j].Msk[k*2]);
					fnPR13((0xff*black)^GB_16[j].Msk[k*2+1]);
				}
				else						// 未找到该字
				{
					if(k < sizeof(GB_16[0].Msk)/4)
					{
						fnPR13(0x00);
						fnPR13(0x00);
					}
					else
					{
						fnPR13(0xff);
						fnPR13(0xff);
					}
				}
				fnPR12(LC_AUT_OVR);
			}
			uCol += 2;
			i++;
		}
		if(uCol >=30)			// 光标后移
		{
			uRow +=16;
			if(uRow < 0x80)
				uCol -= 30;
			else
			{
				uRow = 0;
				uCol = 0;
			}
		}
		fnSetPos(uRow,uCol);
		i++;
	}
       // EA=1;
	return uLen;
}        
#if 1
/*==============================*/
/* 延时				*/
/*==============================*/
void shortdelay(uint tt)
	{
        uchar i;
        while (tt)
        	{
                i=100;
                while (i)i--;
                tt--;
                };
        }        
/****************************************/
/*	画点				*/
/****************************************/

void point(uchar x,uchar y,uchar s)
	{
	uchar	x1;
	x1=x>>3;			//取Y方向分页地址
	fnSetPos(y,x1);			//起点定位
        x1 = turnf[ x & 0x07 ];
	x1=0xF0|x1|s;			//字节内位置计算
	fnPR12(x1);			//画上屏幕,S显示属性8画点0擦除点
	}


/************************************************/
/*画线。任意方向的斜线,直线数学方程 aX+bY=1	*/
/************************************************/
void Linexy(uchar x0,uchar y0,uchar xt,uchar yt,uchar s)
{
	register uchar t;
	int xerr=0,yerr=0,delta_x,delta_y,distance;
	int incx,incy,uRow,uCol;

	delta_x = xt-x0;				//计算坐标增量
	delta_y = yt-y0;
	uRow = x0;
	uCol = y0;
	if(delta_x>0) incx=1;				//设置单步方向
	else if( delta_x==0 ) incx=0;			//垂直线
		else {incx=-1;delta_x=-delta_x;}

	if(delta_y>0) incy=1;
	else if( delta_y==0 ) incy=0;			//水平线
		else {incy=-1;delta_y=-delta_y;}

	if( delta_x > delta_y )	distance=delta_x;	//选取基本增量坐标轴
	else distance=delta_y;

	for( t=0;t <= distance+1; t++ )
        	{					//画线输出
		point(uRow,uCol,s);			//画点
		xerr +=	delta_x	;
		yerr +=	delta_y	;
		
		if( xerr > distance )
                	{
			xerr-=distance;
			uRow+=incx;
			}
		if( yerr > distance )
                	{
			yerr-=distance;
			uCol+=incy;
			}
		}
}


/************************************************/
/*画圆。数学方程(X-Ox)^2+(Y-Oy)^2=Rx^2			*/
/************************************************/

void circle(uchar Ox,uchar Oy,uchar Rx,uchar s)
{
	unsigned int xx,rr,xt,yt,rs,row,col;
	yt=Rx;
	rr=Rx*Rx+1;			//补偿 1 修正方形
	rs=(yt+(yt>>1))>>1;		//(*0.75)分开1/8圆弧来画
	for (xt=0;xt<=rs;xt++)
	{
		xx=xt*xt;
		while ((yt*yt)>(rr-xx))yt--;
		row=Ox+xt;		//第一象限
		col=Oy-yt;
		point(row,col,s);
		row=Ox-xt;		//第二象限
		point(row,col,s);
		col=Oy+yt;		//第三象限
		point(row,col,s);
		row=Ox+xt;		//第四象限
		point(row,col,s);

/***************45度镜象画另一半***************/

		row=Ox+yt;		//第一象限
		col=Oy-xt;
		point(row,col,s);
		row=Ox-yt;		//第二象限
		point(row,col,s);
		col=Oy+xt;		//第三象限
		point(row,col,s);
		row=Ox+yt;		//第四象限
		point(row,col,s);
	}
}
        

void LCDTest(void)	// 测试用
{
	uchar i;
	float xx=3.1415926;
	shortdelay(1200);
	fnLCMInit();
	cls();
	cursor(0,0);
	dprintf("This is a test: 中文测试\n");
	cursor(0,5);
	dprintf("%1.4f\n",xx);
	cursor(0,6);
	dprintf("LCM Example in C8051F020&T6963\n");
	cursor(7,7);
	black = 1;
	dprintf("---HuangYang---\n");
	Linexy(10,20,239,110,8);			// 画斜线1
	Linexy(10,20,217,1,8);				// 斜线2
	Linexy(239,110,217,1,8);			// 斜线3
	circle(185,45,40,8);				// 画圆
	circle(185,45,41,8);				// 画同心圆加粗
	shortdelay(24000);

	P3 = 0xff;
	while(P3 == 0xff)
        {
//变化圆演示,直径不断的变化,由大到小再由小到大来回缩放
		for (i=40;i>5;i--)
        	{
            	circle(185,45,i+1,0);		//擦除外圆
	    	circle(185,45,i,8);
    		circle(185,45,i-1,8);
		shortdelay(3600);
            	};

		shortdelay(8000);

		for (i=5;i<40;i++)
        	{
            	circle(185,45,i-1,0);		//擦除内圆
	    	circle(185,45,i,8);					
    		circle(185,45,i+1,8);
		shortdelay(1800);
            	};

		shortdelay(4000);

        };
}
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -