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

📄 lcd_driver.c

📁 ylf128X64无字库液晶驱动程序
💻 C
字号:
//===================================================
//=               LCD控制驱动程序                   =
//===================================================
//=  本程序可对于YLF12864J 128*64 20针液晶屏进行控制=
//=输出输入。                                       =
//=                                                 =
//=                 北京信息科技大学电子电工实习中心=
//=                                        易恺迪   =
//=                                     2008.8.17   =
//=                                                 =
//=                                                 =
//===================================================


/*基本操作时序
1,读状态:输入:D/I=L,CS1或CS2=H,R/W=H,E=H									输出:D0-D7=状态字
2,写指令:输入:D/I=L,CS1或CS2=H,R/W=L,E=高脉冲 D0-D7=指令码				输出:无
3,读数据:输入:D/I=H,CS1或CS2=H,R/W=H,E=H									输出:D0-D7=数据
4,写数据:输入:D/I=H,CS1或CS2=H,R/W=L,E=高脉冲 D0-D7=数据					输出:无

状态字说明:D0-D7中D5为液晶显示状态:1为关闭,0为显示。D7为读写操作使能:1为禁止,0为允许。其他D0-D4,D6未使用

指令说明

1,初始化设置

1.1显示开/关设置
		指令码			功能
		 3EH            关显示
		 3FH            开显示
1.2显示初始设定
		指令码			功能
		 0C0H           设置显示初始行
2,数据控制
   控制器内部设有一个数据地址页指针和一个数据地址列指针,用户可通过它们来访问内部的全部512字节RAM
   数据指针设置
   		指令码			功能
		0B8H+页码(0-7)  设置数据地址页指针
		40H+列码(0-63)  设置数据地址列指针

3,初始化过程
   写指令0C0H:设置显示初始行
   写指令3FH: 开显示
*/

#include<REG51.H>
#include<INTRINS.H>
#include"config.c"//引入管脚配置文件

#define LCD_CMD_COL 		0x40//定义128X64液晶屏幕每个分控制器列基地址
#define LCD_CMD_PAGE		0XB8//定义128X64液晶屏幕每个分控制器页基地址
#define LCD_CMD_ON			0x3F//初始化开指令
#define LCD_CMD_OFF			0x3E//初始化关指令
#define LCD_CMD_STARTLINE	0xC0//初始化显示初始行
#define LCD_LEFT			0x00//LCD左上角坐标X定义
#define LCD_TOP				0x00//LCD左上角坐标Y定义
#define LCD_RIGHT			0x7F//LCD右下角坐标Y定义
#define LCD_BOTTOM			0x3F//LCD右下角坐标X定义
#define LCD_DS				CON_DS//配置D0-D7数据管脚
#define LCD_ACT_CS1			0x01//控制器1活动标志
#define LCD_ACT_CS2			0x02//控制器2活动标志

//这里为了使用方便把需要更改的管脚定义放到CONFIG.C文件中,用户可以到CONFIG.C中更改自己的管脚连接配置关系
//sbit LCDRS;//数据/命令选择管脚定义
//sbit LCDWR;//读写控制管脚定义
//sbit LCDEN;//使能管脚定义
//sbit LCDCS1;//片选CS1管脚定义
//sbit LCDCS2;//片选CS2管脚定义
//sbit LCDRST;//重起管脚定义

unsigned char LCD_CurrentX,LCD_CurrentY;//定义当前操作LCD位置指针

void Delay(unsigned int uiTime);//延时
void CheckBusy(unsigned char ucACT);//忙检测,参数传递片选端
void SendCMD(unsigned char ucACT,unsigned char ucCMD);//向控制器传输命令,参数1为片选,2为命令
void SendData(unsigned char ucACT,unsigned char ucData);//写数据,参数1为片选,2为数据
void LCDWriteCMD(unsigned char ucCMD);//向LCD写入命令,此函数根据当前液晶屏操作位置自动片选,参数为命令
void LCDWriteData(unsigned char ucData);//向LCD写入数据,此函数根据当前液晶屏操作位置自动片选,参数为数据
void SwitchPos();//坐标转换函数,将可视坐标转换成存储器物理地址坐标
void LCDMoveNextPos();// 将可视坐标移动到下一个位置
void DisplayByte(unsigned char ucData);//向LCD写一个字节显示到液晶屏上
void LCDFill(unsigned char FillData);//整屏填充数据
void LocatePos(unsigned char XPos,unsigned char YPos);//定位液晶屏可视坐标,范围:X:0-127,y:0-63(每次按8递增)
void LCDInit();//初始化
unsigned char RDState(unsigned char ucACT);//读取控制器状态,返回一个字节信息
unsigned char RDData(unsigned char ucACT);//读数据,参数为片选
unsigned char LCDReadData();//从LCD读取数据,此函数自动根据液晶屏当前操作位置进行片选


/////////////////////////////////////////////////////////////////////////////////////////////
void LocatePos(unsigned char XPos,unsigned char YPos)
{
	if (0x00<XPos<0x80)//如果不超出范围则赋值
	{
		LCD_CurrentX=XPos;
	}
	if ((0x00<YPos<0x40)&&(YPos%8==0))//如果满足要求则赋值
	{
		LCD_CurrentY=YPos;
	}
}
//////////////////////////////////////////////////////////////////////////////////////////////
void LCDInit()//初始化
{
	SendCMD(LCD_ACT_CS1,LCD_CMD_ON);//开启左边的第一个LCD控制器
	SendCMD(LCD_ACT_CS2,LCD_CMD_ON);//开启右边的第二个LCD控制器
	SendCMD(LCD_ACT_CS1,LCD_CMD_STARTLINE);//设置第一个LCD控制器显示初始行
	SendCMD(LCD_ACT_CS2,LCD_CMD_STARTLINE);//设置第二个LCD控制器显示初始行
}
//////////////////////////////////////////////////////////////////////////////////////////////
void LCDFill(unsigned char FillData)//填充液晶屏屏幕,一般用于清空数据或者测试液晶屏
{
	for(LCD_CurrentX=LCD_LEFT,LCD_CurrentY=LCD_TOP;1;)
	{
		DisplayByte(FillData);//显示数据
		if ((LCD_CurrentX==LCD_LEFT)&&(LCD_CurrentY==LCD_TOP))//当达到右下角坐标清0,退出填充显示
		{
			break;
		}
	}
}
//////////////////////////////////////////////////////////////////////////////////////////////
void DisplayByte(unsigned char ucData)//在液晶屏显示一个字节的数据
{
	SwitchPos();//坐标转换,将可视坐标转换为物理存储器地址
	LCDWriteData(ucData);//传输显示数据
	LCDMoveNextPos();//坐标向后移动一个
}
//////////////////////////////////////////////////////////////////////////////////////////////
void LCDMoveNextPos()//后移一个坐标
{
	LCD_CurrentX++;//向后移动一列,一共0-63列
	if (LCD_CurrentX>LCD_RIGHT)//当达到最后一列时,初始到最左边一列,并且下移一行
	{
		LCD_CurrentX=LCD_LEFT;
	    LCD_CurrentY+=8;
		if (LCD_CurrentY>LCD_BOTTOM)//移到最后一行时,初始到第一行
		{
			LCD_CurrentY=LCD_TOP;
		}
	}
}
//////////////////////////////////////////////////////////////////////////////////////////////
void SwitchPos()
{
	LCDWriteCMD(LCD_CMD_COL|(LCD_CurrentX&0x3f));//列转换,范围0-127,当0-63时默认值,当超过63,转换为第二片控制器的0-63
	LCDWriteCMD(LCD_CMD_PAGE|((LCD_CurrentY/8)&0x07));//页转换,范围0-63,以8递增,将液晶屏分为8页
}
//////////////////////////////////////////////////////////////////////////////////////////////
void LCDWriteData(unsigned char ucData)//向LCD写数据,此函数自动判断写哪一块控制器
{
	if (LCD_CurrentX<0x40)//当大于63列,就写到第二片控制器上,否则第一片
	{
		SendData(LCD_ACT_CS1,ucData);
	}
	else
	{
		SendData(LCD_ACT_CS2,ucData);
	}
}
//////////////////////////////////////////////////////////////////////////////////////////////
unsigned char LCDReadData()//从LCD读取数据,根据当前可视坐标选择控制器
{
	unsigned char ucData;
	if(LCD_CurrentX<0x40)
	{
		ucData=RDData(LCD_ACT_CS1);//从一控制器读取2遍
		ucData=RDData(LCD_ACT_CS1);
    }
	else
	{
		ucData=RDData(LCD_ACT_CS2);//从二控制器读取2遍
		ucData=RDData(LCD_ACT_CS2);
	}
	return ucData;
}
//////////////////////////////////////////////////////////////////////////////////////////////
void LCDWriteCMD(unsigned char ucCMD)//向LCD写命令,自动识别控制端
{
	if(LCD_CurrentX<0x40)
	{
		SendCMD(LCD_ACT_CS1,ucCMD);
	}
	else
	{
		SendCMD(LCD_ACT_CS2,ucCMD);
	}
}
//////////////////////////////////////////////////////////////////////////////////////////////
unsigned char RDData(unsigned char ucACT)//读取数据,每次读取一个字节
{
	unsigned char ucData;
	LCD_DS=0xFF;
	CheckBusy(ucACT);//等待LCD空闲
	LCDRS=1;//操作数据
	LCDWR=1;//读取命令
	if(ucACT==0x01)
	{
		LCDCS1=1;//片选
		LCDEN=1;//开启LCD
		_nop_();
		ucData=LCD_DS;//读取
        LCDEN=0;//关闭LCD
		LCDCS1=0;//片选结束
	}
	else
	{	
		LCDCS2=1;
		LCDEN=1;
		_nop_();
        ucData=LCD_DS;
		LCDEN=0;
		LCDCS1=0;
	}
	return ucData;
}
//////////////////////////////////////////////////////////////////////////////////////////////
void SendData(unsigned char ucACT,unsigned char ucData)//向LCD发送数据
{
	CheckBusy(ucACT);
	LCD_DS=ucData;//D0-D7数据口发送数据
	LCDRS=1;//数据操作
	LCDWR=0;//写命令
	if (ucACT==0x01)
	{
		LCDCS1=1;
		LCDEN=1;
		_nop_();
		LCDEN=0;
		LCDCS1=0;
	}
	else
	{
		LCDCS2=1;
		LCDEN=1;
		_nop_();
		LCDEN=0;
		LCDCS2=0;
	}
}
//////////////////////////////////////////////////////////////////////////////////////////////
void SendCMD(unsigned char ucACT,unsigned char ucCMD)//向LCD下命令
{
	CheckBusy(ucACT);
	LCD_DS=ucCMD;
	LCDRS=0;//指令操作
	LCDWR=0;//写操作
	if (ucACT==0x01)
	{
		LCDCS1=1;
		LCDEN=1;
		_nop_();
		LCDEN=0;
		LCDCS1=0;
	}
	else
	{
		LCDCS2=1;
		LCDEN=1;
		_nop_();
		LCDEN=0;
		LCDCS2=0;
	}
}
//////////////////////////////////////////////////////////////////////////////////////////////
void Delay(unsigned int uiTime)//延时
{
	unsigned int i,j;
	for(i=0;i<uiTime;i++)
	{
		for(j=0;j<10;j++)
		{
			;
		}
	}
}
//////////////////////////////////////////////////////////////////////////////////////////////
unsigned char RDState(unsigned char ucACT)//读取LCD状态
{
	unsigned char ucData=0xFF;
    LCDRS=0;//命令操作
	LCDWR=1;//读取状态
	if (ucACT==0x01)
	{
		LCDCS1=1;
		LCDEN=1;
	    _nop_();
		ucData=LCD_DS;//读取数据
	    LCDEN=0;
		LCDCS1=0;
    }
	else
	{
		LCDCS2=1;
		LCDEN=1;
	    _nop_();
		ucData=LCD_DS;
	    LCDEN=0;
		LCDCS2=0;
	}
	return ucData;
}
//////////////////////////////////////////////////////////////////////////////////////////////
void CheckBusy(unsigned char ucACT)
{
	while((RDState(ucACT)&0x80)==0x80);//直到读取的状态数据中D7位为0时退出等待,D7位是忙标志位
}
/////////////////////////////////////////////////////////////////////////////////////////////



⌨️ 快捷键说明

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