LCM1602通用驱动程序。
注意:这种硬件接法是8位直接接在单片机的一个口上。
/*============================================================
使用1602液晶显示的实验例子 明浩 2004/2/27
==============================================================
smc1602a(16*2)模拟口线接线方式
连接线图:
---------------------------------------------------
|lcm-----51 | lcm-----51 | lcm------51 |
---------------------------------------------|
|db0-----p1.0 | db4-----p1.4 | rw-------p3.5 |
|db1-----p1.1 | db5-----p1.5 | rs-------p3.4 |
|db2-----p1.2 | db6-----p1.6 | e--------p3.3 |
|db3-----p1.3 | db7-----p1.7 | vlcd接1k电阻到gnd|
---------------------------------------------------
[注:at89s51使用12m晶振]
=============================================================*/
#define lcm_rw p3_5 //定义引脚
#define lcm_rs p3_4
#define lcm_e p3_3
#define lcm_data p1
#define busy 0x80 //用于检测lcm状态字中的busy标识
#include <at89x51.h>
void writedatalcm(unsigned char wdlcm);
void writecommandlcm(unsigned char wclcm,buysc);
unsigned char readdatalcm(void);
unsigned char readstatuslcm(void);
void lcminit(void);
void displayonechar(unsigned char x, unsigned char y, unsigned char ddata);
void displaylistchar(unsigned char x, unsigned char y, unsigned char code *ddata);
void delay5ms(void);
void delay400ms(void);
unsigned char code c1[] = {"0.000pf"}; //这里4行是本人的测试代码,不必照抄--by bg4uvr
unsigned char code d1[] = {"0.0000%"};
unsigned char code c2[] = {"0.000pf"};
unsigned char code d2[] = {"0.0000%"};
void main(void)
{
delay400ms(); //启动等待,等lcm讲入工作状态
lcminit(); //lcm初始化
delay5ms(); //延时片刻(可不要)
displaylistchar(1, 0, c1);
displaylistchar(9, 0, c2);
displaylistchar(1, 1, d1);
displaylistchar(9, 1, d2);
readdatalcm();//测试用句无意义
while(1);
}
//写数据
void writedatalcm(unsigned char wdlcm)
{
readstatuslcm(); //检测忙
lcm_data = wdlcm;
lcm_rs = 1;
lcm_rw = 0;
lcm_e = 0; //若晶振速度太高可以在这后加小的延时
lcm_e = 0; //延时
lcm_e = 1;
}
//写指令
void writecommandlcm(unsigned char wclcm,buysc) //buysc为0时忽略忙检测
{
if (buysc) readstatuslcm(); //根据需要检测忙
lcm_data = wclcm;
lcm_rs = 0;
lcm_rw = 0;
lcm_e = 0;
lcm_e = 0;
lcm_e = 1;
}
//读数据
unsigned char readdatalcm(void)
{
lcm_rs = 1;
lcm_rw = 1;
lcm_e = 0;
lcm_e = 0;
lcm_e = 1;
return(lcm_data);
}
//读状态
unsigned char readstatuslcm(void)
{
lcm_data = 0xff;
lcm_rs = 0;
lcm_rw = 1;
lcm_e = 0;
lcm_e = 0;
lcm_e = 1;
while (lcm_data & busy); //检测忙信号
return(lcm_data);
}
void lcminit(void) //lcm初始化
{
lcm_data = 0;
writecommandlcm(0x38,0); //三次显示模式设置,不检测忙信号
delay5ms();
writecommandlcm(0x38,0);
delay5ms();
writecommandlcm(0x38,0);
delay5ms();
writecommandlcm(0x38,1); //显示模式设置,开始要求每次检测忙信号
writecommandlcm(0x08,1); //关闭显示
writecommandlcm(0x01,1); //显示清屏
writecommandlcm(0x06,1); // 显示光标移动设置
writecommandlcm(0x0c,1); // 显示开及光标设置
}
//按指定位置显示一个字符
void displayonechar(unsigned char x, unsigned char y, unsigned char ddata)
{
y &= 0x1;
x &= 0xf; //限制x不能大于15,y不能大于1
if (y) x |= 0x40; //当要显示第二行时地址码+0x40;
x |= 0x80; //算出指令码
writecommandlcm(x, 0); //这里不检测忙信号,发送地址码
writedatalcm(ddata);
}
//按指定位置显示一串字符
void displaylistchar(unsigned char x, unsigned char y, unsigned char code *ddata)
{
unsigned char listlength;
listlength = 0;
y &= 0x1;
x &= 0xf; //限制x不能大于15,y不能大于1
while (ddata[listlength]>0x20) //若到达字串尾则退出
{
if (x <= 0xf) //x坐标应小于0xf
{
displayonechar(x, y, ddata[listlength]); //显示单个字符
listlength++;
x++;
}
}
}
//5ms延时
void delay5ms(void)
{
unsigned int tempcyc = 5552;
while(tempcyc--);
}
//400ms延时
void delay400ms(void)
{
unsigned char tempcyca = 5;
unsigned int tempcycb;
while(tempcyca--)
{
tempcycb=7269;
while(tempcycb--);
};
}