1602显示屏C语言驱动程序及相关上传资料.docx
《1602显示屏C语言驱动程序及相关上传资料.docx》由会员分享,可在线阅读,更多相关《1602显示屏C语言驱动程序及相关上传资料.docx(41页珍藏版)》请在冰豆网上搜索。
1602显示屏C语言驱动程序及相关上传资料
1602液晶驱动程序及相关资料
简介:
本文的内容包括1602的电路连接图,C语言编写的驱动程序,及说明书资料。
初学者按图连接并烧好程序就可以直接点亮显示屏。
是初学者不可多得的参考资料,可大大节约初学者的学习时间。
需要说明的是本例用到的单片机是AT89S52或AT89S51型单片机。
如果别的型号的单片机需要足以更新头文件。
1602液晶屏通用连接图
C语言编写的程序再说明的下面
1602显示屏的使用方面的知识。
一般市场上的1602液晶使用的驱动器为HD44780U或HD44780S,市场上大部分液晶用的是后者。
HD44780S的供电电压为5V±10%,而HD44780U的供电电压为2.7V~5.5V。
也就是说,绝大部分1602液晶只能工作在5V电压下,其供电电压必须为5V。
经过试验发现,1602液晶的供电虽然必须为5V,但其控制总线和数据总线可以用3.3V电平(因为对于TTL电平,一般大于2.5V以上都算高电平,不过最可靠的是大于3.6V),只不过在3.3V电平下,数据的通信速度会大大降低,这一点需要在写驱动时注意。
需要时,可以将MCU的IO配置为漏极开路方式,用上拉电阻拉到5V电平;实在不能配置为漏极开路方式时,请查阅MCU的电气参数,在允许的条件下,直接使用电阻弱上拉也可以。
2、硬件连接
1602液晶可以使用4位或8位通信模式,通信可以是双向的或单向的,双向通信主要是为了读取LCD忙标志和AC地址寄存器和DDRAM和CGRAM中的值,一般用处不大,因为1602不支持点阵绘图功能。
在连接时,注意4位通信方式下,LCD只使用DB7~DB4,一般情况下会使用MCU某端口的高4位或低4位与之连接,注意写驱动时在必要的情况下对端口的其它几位要保护,防止破坏其数据;当然如果没有使用其它4位时则不必要保护(奇怪,不使用其它4位干嘛用4位通信方式嘛?
)。
还要注意的是,如果需要双向通信,则必须选择既能做输入又能做输出的IO口,特别是对于RS、RW和E这三条控制线,若能选择支持位寻址的IO口则可以方便编程。
3、底层驱动问题
通用1602液晶的时序如图:
(1)、写时序
(2)、读时序
总的说来,按照这个时序图来编写驱动程序是不会出什么问题的,只是要深刻理解时序图中各参数的涵义。
编程中要特别关注E这根控制线。
写操作的时序应该是:
①、RS=0(写指令寄存器)或RS=1(写数据寄存器);②、RW=0(写操作);③、将数据写到数据线上;④、E=1;⑤、E=0。
在写操作时,LCD是在E的下降沿将数据锁存,即写操作时E下降沿有效。
但尽管这样,为防止LCD出错,在E变为高电平后,尽量不要再改变数据线上的数据值。
即最好按照上述的时序来操作。
读操作的时序应该是:
①、RS=0(读忙标志BF和地址计数器AC)或RS=1(读数据寄存器);②、RW=1(读操作);③、E=1;④、从数据线上读取数据;⑤、E=0。
在读操作时,E一旦变为高电平,LCD马上将数据发到数据线上并保持,一直到E=0为止。
即写操作时E高电平有效。
一般如果时序没有错,不会出什么问题。
绝大部分问题都是延时不够造成的,注意看上面两个图表,有许多时间参数的。
要注意的是这些参数的条件,如“Vdd=5V5V±5%,Vss=0,Ta=25℃”,其它条件下这些指标都要留有余量。
此外,电源电压、MCU数据线的电平、驱动能力、PCB布局……均会影响速度,注意留有足够的余量,建议先留大的余量,调通后再逐渐减小延时。
4、1602液晶的初始化
通用1602液晶的初始化需要注意一个问题,即一定要在最开始写入功能设定指令,该指令用以控制LCD的数据通信位数,及显示行数和字型。
并且强烈建议将此指令写两次,因为LCD启动后并不知道您使用的是4位数据通信方式还是8位方式,所以它总是先执行高4位的指令,也就是说第一次写入该指令时,低四位的数据可能被忽略(这是我根据使用其它液晶的猜测)。
总之为了可靠,最好写两遍该指令。
#include
//***************************************************************************************
//硬件连接:
1602VDD接5V,VO接地,BL1接5V,BL2接地,8根数据线接P0口,RSRWE分别接P2.0、P2.1、P.4口
下载下面的程序可直接点亮显示屏
//***************************************************************************************
#include
#defineBusy0x80//用于检测LCM状态字中的Busy标识
#defineLCM_DataP0
sbitLCM_RS=P2^0;//寄存器选择
sbitLCM_RW=P2^1;//读/写控制
sbitLCM_E=P2^2;//读/写使能
inti,j;
//自定义字符列表
//=====================================================================================
unsignedcharcharacter0[8]={0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02},//年
character1[8]={0x0f,0x09,0x0f,0x09,0x0f,0x09,0x0b,0x11},//月
character2[8]={0x0f,0x09,0x09,0x09,0x0f,0x09,0x09,0x0f},//日
characterN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//日
//=====================================================================================
//=====================================================================================
//延时程序
//=====================================================================================
voidDelay5Ms(void)
{
unsignedlongintTempCyc=5552;
while(TempCyc--);
}
voidDelay400Ms(void)
{
unsignedcharTempCycA=5;
unsignedintTempCycB;
while(TempCycA--)
{
TempCycB=7269;
while(TempCycB--);
};
}
//=====================================================================================
//读写子程序
//=====================================================================================
/////******读数据************
unsignedcharReadDataLCM(void)
{
LCM_RS=1;
LCM_RW=1;
LCM_E=1;
LCM_E=0;
for(i=0;i<100;i++);
LCM_E=1;
return(LCM_Data);
}
///********读状态**************
unsignedcharReadStatusLCM(void)
{
LCM_Data=0xFF;
LCM_RS=0;
LCM_RW=1;
LCM_E=1;
LCM_E=0;
for(i=0;i<100;i++);
LCM_E=1;
return(LCM_Data);/////反回读取的数据。
}
//************写数据子汉字子函数
voidWriteDataLCM(unsignedcharWDLCM)
{
ReadStatusLCM();//检测忙
LCM_Data=WDLCM;///送数据到IO口。
LCM_RS=1;
LCM_RW=0;
LCM_E=1;
LCM_E=0;//若晶振速度太高可以在这后加小的延时
for(i=0;i<100;i++);//延时
LCM_E=1;////使能
}
//写指令
voidWriteCommandLCM(unsignedcharWCLCM,BuysC)//BuysC为0时忽略忙检测
{
if(BuysC)ReadStatusLCM();//根据需要检测忙
LCM_Data=WCLCM;///送指令到IO口。
LCM_RS=0;
LCM_RW=0;
LCM_E=1;
LCM_E=0;
for(i=0;i<100;i++);
LCM_E=1;
}
//=====================================================================================
//初始化子程序
//=====================================================================================
voidLCMInit(void)//LCM初始化设置
{
LCM_Data=0;
WriteCommandLCM(0x38,0);//三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,1);//显示模式设置,开始要求每次检测忙信号
Delay5Ms();
WriteCommandLCM(0x08,1);//关闭显示
Delay5Ms();
WriteCommandLCM(0x01,1);//清屏
Delay5Ms();
WriteCommandLCM(0x06,1);//显示光标移动设置
Delay5Ms();
WriteCommandLCM(0x0c,1);//显示开及光标设置
Delay5Ms();
}
//=====================================================================================
//按指定位置显示一个字符
//=====================================================================================
voidDisplayOneChar(unsignedcharX,unsignedcharY,unsignedcharDData)