//=============================================================================
//LCM1602字符型液晶显示器程序(仿真通过)
//本程序改编自周坚书
//注意:使用硬件时要把检测忙打开
//使用HD44780及兼容芯片作为控制器
//程序员: 舒杰刚 2009年9月23日
//=============================================================================
#include "reg51.h" //包含51头文件
#include "intrins.h" //包含_nop_()
#define uint unsigned int //定义一下方便输入
#define uchar unsigned char //定义一下方便输入
//-----------------------------------------------------------------------------
#define DPORT P0 //定义总线
sbit RS=P2^5; //定义数据命令选择端
sbit RW=P2^6; //定义读写选择端
sbit E=P2^7; //定义使能信号
//-----------------------------------------------------------------------------
const uchar cur_add=3; //0:显示 1:有显示无光标 2:有光标但不闪烁 3:有光标且闪烁
//
void lcdpos(uchar,uchar); //确定光标位置
void lcdwc(uchar); //送控制字(检测忙信号)
void mdelay(uint); //延时,毫秒数由j决定
void waitidle(); //正常读/写操作之前检测LCD控制器状态
//=============================================================================
//功能:在指定的行与列显示指定的字符
//参数:xpos ypos光标所在行列:c 待显示字符
//=============================================================================
void writechar(uchar c,uchar xpos,uchar ypos)
{ lcdpos(xpos,ypos); //写入坐标
//写数据-------------------------------------------------------------------
waitidle(); //测忙
RS=1;RW=0; //写数据到LCD
DPORT=c; //将待写的数据送到数据端口
E=1;_nop_();_nop_();E=0; //
}
//=============================================================================
//功能:显示字符串
//参数:*s 指向待显示的字符串,x pos光标所在行; ypos 光标所在列
//说明:如果指定的行显示不下,将余下字符截断,不换行显示
//=============================================================================
void writestring(uchar *s,uchar xpos,uchar ypos)
{ uchar i;
if(*s==0)return; //遇到字符串结束
for(i=0;;i++)
{
if(*(s+i)==0){break;} //到了字符串未尾,退出.字符串尾数"\0".
writechar(*(s+i),xpos,ypos);
xpos++;
if(xpos>=16){break;} //如果xpos中的值大于16(可显示的最多位),原程序为15
}
}
//=============================================================================
//功能:设置光标
//参数:para 4种光标类型
//=============================================================================
void setcur(uchar para) //设置光标
{ mdelay(2);
switch(para)
{ case 0:{lcdwc(0x08);break;} //关显示
case 1:{lcdwc(0x0c);break;} //开显示但无光标
case 2:{lcdwc(0x0e);break;} //开显示有光标但不闪烁
case 3:{lcdwc(0x0f);break;} //开显示有光标且闪烁
default: break;
}
}
//=============================================================================
//功能:清屏
//=============================================================================
void clrlcd()
{ lcdwc(0x01);}
//=============================================================================
//功能:正常读/写操作之前检测LCD控制器状态
//=============================================================================
void waitidle()
{// uchar tmp;
mdelay(1); //延时等待总线稳定(少这句将不能仿真)
RS=0;RW=1; //读取忙信号或AC地址指令
E=1; //当E为高电平时,如果R/W为0,则LCD从单片机读入指令或者数据
//如果R/W为1,则单片机可以从LCD中读出状态字(BF忙状态)和地址
//而E的下降沿指示LCD执行其读入的指令或者显示其读入的数据
_nop_();
/* //仿真时不要,硬件要加上
for(;;) //测忙
{ tmp=DPORT;
tmp&=0x80;
if(tmp==0)break;
}
*/
E=0;
}
//=============================================================================
//功能:送控制字子程序(检测忙信号)
//参数:c 控制字
//=============================================================================
void lcdwc(uchar c)
{ waitidle(); //测忙
RS=0;RW=0; //写命令到lcd
DPORT=c;
E=1;_nop_();E=0; //
}
//=============================================================================
//功能:设置第(xpos,ypos)个字符的地址
//参数:xpos,ypos光标所在位置
//=============================================================================
void lcdpos(uchar xpos,uchar ypos)
{
uchar tmp;
xpos&=0x0f; //x位置范围是0-15
ypos&=0x01; //y位置范围是0-1
if(ypos==0) //显示第1行
tmp=xpos;
else
tmp=xpos+0x40;
tmp|=0x80;
lcdwc(tmp);
}
//=============================================================================
//功能:复位LCD控制器
//=============================================================================
void rstlcd()
{ mdelay(15); //使用12M或以下不必修改,12M以上改为30
lcdwc(0x38); //8位数据总线,显示2行,5X7点阵
lcdwc(0x08); //显示功能关
lcdwc(0x01); //显示清屏,地址计数器清0
lcdwc(0x06); //写入数据后,光标右移
lcdwc(0x0c); //显示开,无光标无闪烁
}
//=============================================================================
//功能:延时
//参数:j待延时的毫秒数
//=============================================================================
void mdelay(uint j)
{ uchar i;
for(;j>0;j--)
{ for(i=0;i<124;i++){;}
}
}
//==============================================================================
//主程序
//==============================================================================
void main()
{ uchar xpos,ypos;
uchar *s1="welcome SJG to";
xpos=1;ypos=0;
rstlcd(); //复位初始化
clrlcd(); //清屏
setcur(cur_add); //开启光标显示,闪烁
writestring(s1,xpos,ypos); //写字符串
s1="Oceanpower"; //指针指向字符串首地址
xpos=2;ypos=1;
writestring(s1,xpos,ypos); //写字符串
for(;;){;}
} |