📄 lcd_driver.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 + -