第一次接触液晶屏,花了将近一个星期的时间,终于搞定了软件和硬件。
虽然现在看来,其实液晶屏不难,但是不管什么东西,第一次做都是会比较棘手的嘛!现在我把我做的软件程序和仿真发上来,希望能够对第一次做液晶屏的朋友能有一定的帮助!
#i nclude<reg52.h>
#i nclude <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define DPORT P0 // 命令数据输出端口
sbit RS = P1^2;
sbit RW = P1^1;
sbit E = P1^0;
/*---函数声明---*/
void RstLcd(void);
void LcdWcn(uchar);
void LcdWc(uchar);
void LcdWd(uchar);
void LcdWdn(uchar);
void WaitIdle(void);
void display(uchar code*,uchar,uchar);//依次为:显示内容的首地址,数据长度,屏幕坐标(高位是行,低位是列)
void LcdPos(uchar);
void mWord(void);
void delay(uint);
/*--- 自己创建的字符,字符码为 00--07 ---*/
uchar code TAB[]={ 0x08,0x0F,0x12,0x0F,0x0A,0x1F,0x02,0x02, //年
0x0f,0x09,0x0F,0x09,0x0F,0x09,0x11,0x00, //月
0x0F,0x09,0x09,0x0F,0x09,0x09,0x0F,0x00, //日
0x11,0x0A,0x04,0x1F,0x04,0x1F,0x04,0x00, //¥
0x0E,0x00,0x1F,0x0A,0x0A,0x0A,0x13,0x00, //元
0x18,0x18,0x07,0x08,0x08,0x08,0x07,0x00, //℃
0x04,0x0A,0x15,0x04,0x04,0x04,0x04,0x00, //↑
0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f }; //
uchar code dis_buffer[]={0x49,0x20,0x6c,0x6f,0x76,0x65,0x20,0x79,0x6f,0x75};//显示缓冲区 ;
uchar code start[]={0x73,0x74,0x61,0x72,0x74,0xa5,0xa5,0xa5,0xa5,0xa5,0xa5};//"start......"
uchar code OK[]={0x4f,0x4b,0x20,0x21,0x00,0x01,0x02}; //" OK !"
uchar code NYR[]={0x32,0x30,0x30,0x38,0x00,0x30,0x38,0x01,0x30,0x38,0x02};//"2008年08月08日"
uchar code ts[]={0,1,2,3,4,5,6,7} ;
/***************************************************************************/
void main(void)
{
delay(500); //开机延时一段时间
RstLcd(); //复位LCD
mWord(); //创建自定义字符
display(start,11,0x03); // start 是显示内容的首地址,10 是要显示的数据长度,
// 0x03 是屏幕坐标,例如 0x03 表示 第 0 行 第 3列 (坐标要小于 0x1f );
delay(8000);
LcdWc(0x01); // 清屏
display(OK,4,0x05);
delay(2000);
LcdWc(0x01); // 清屏
while(1)
{
display(NYR,11,0x02); //在第 0 行 第 2 列 显示
display(dis_buffer,10,0x13); //在第 1 行 第 3 列 显示
delay(8000);
}
}
/******************************************************************************************/
/*--------------------------LCD 显示部分的全部程序----------------------------------------*/
/******************************************************************************************/
/*-------------------LCD 的复位程序----------------------*/
void RstLcd()
{
DPORT=0;
delay(15); //延时15ms
LcdWcn(0x38); //显示模式设置 ,设置 3 次(不能少,而且可以不检测忙的状态)
delay(5);
LcdWcn(0x38);
delay(5);
LcdWcn(0x38);
delay(5);
//以下必须检测忙的状态
LcdWc(0x38); //显示模式设置
LcdWc(0x08); //显示关闭
LcdWc(0x01); //显示清屏
LcdWc(0x06); //显示光标移动设置 (0x07 移动)
LcdWc(0x0c); //显示开关及光标设置(0x0d 闪动,0x0e 关标开,0x0f闪动同时关标开 )
}
/*-------------------创建自定义字符------------------------*/
void mWord(void)
{
uchar i;
LcdWc(0x40); //设置 CGRAM
for(i=0;i<64;i++)
{
LcdWd(TAB[i]);
}
}
/*----------------带忙检测的写 数据 子程序------------------*/
void LcdWd(uchar c)
{
WaitIdle(); //忙检测
LcdWdn(c);
}
/* 写数据 */
void LcdWdn(uchar c)
{
DPORT=c; //写入待写 数据
RS=1;
RW=0;
E=1;
E=0;
}
/*-------------检测忙信号的送 命令 子程序-----------------*/
void LcdWc(uchar c)
{
WaitIdle();
LcdWcn(c);
}
/* 写命令 */
void LcdWcn(uchar c)
{
DPORT=c; //写入待写 命令
RS=0;
RW=0;
E=1;
E=0;
}
/*------------------ 忙 信 号 检 测 ------------------------*/
void WaitIdle(void)
{
uchar i;
DPORT=0xff;
RS=0;
RW=1;
delay(10);
E=1; //在把 E 置高电平之前一定要进行足够的延时
while(1)
{
i=DPORT;
i&=0x80;
if(i==0) break;
}
E=0;
/*DPORT=0xFF; //忙信号检测的另外一种写法
RS=0;
RW=1;
E=0;
delay(10);
E = 1;
while(DPORT & 0x80) ; //检测忙信号
//return(LCM_Data); */
}
/*------------------显示程序--------------------------*/
void display(uchar code *p,uchar length,uchar Pos)
{
uchar i;
for(i=0;i<length;i++)
{
if(i<1) LcdPos(Pos); // 设置待显示的行与列
// LcdPos(Pos) 只需要执行一次,因为 AC 会自动加 1
LcdWd(*p); //写待显示的字符
delay(10);
p++;
}
}
/*-----------------定位显示位置子程序------------------*/
void LcdPos(uchar Pos)
{
uchar data temp=Pos;
uchar data Xpos=temp&0x0f;
uchar data Ypos=temp&0xf0;
temp=Xpos;
if(Ypos==0x10) temp+=0x40; // Ypos==0x10,在第二行显示(因为高四位才是行地址)
temp|=0x80;
LcdWc(temp); //设置 DDRAM
}
/*------------------延时子程序------------------------- */
void delay(uint Delay)
{
uchar i;
while(Delay)
{
for(i=125;i>0;i--) {;} //12M 晶振延时时间为 1ms
Delay--;
}
}
/**************************************************************************************/
仿真文件.rar