|
实现LCD接口
|
|
实验板上集成有1602A型LCD显示屏。该显示屏由EPM7128S来管理,需要通过在EMP728S实现的接口逻辑连接到89C52上,以便软件可以对其操作。 |
|
1602A型LCD显示屏的接口如图(1)所示,该接口属于典型的Motorola总线接口。其信号分为两部分,一部分是控制信号,另一部分是数据信号。控制信号由RS、RW、E组成,全部是单向传输的输入信号。其中RS是数据/指令选择信号,高电平时接口进行数据读写,低电平时接口接收指令。RW信号用于区分读/写操作,当RW为高电平时进行读操作,当RW为低电平时进行写操作。E信号是使能信,在读操作时,在E信号的高电平阶段,数由LCD送到数据总线上;在写操作时,数据总线上的数据数据在E信号的下降沿锁存到LCD的寄存器中。数据总由DB0-DB7组成,是双向传输的信号,用于传输读写操作的数据。该接口没有地址信号,控制信号中的使能信号E兼作地址信号的职责。 |
 |  |
图(1) | 图(2) |
|
由于51单片机诞生于Intel,所以其总线是Intel标准总线。因此,要把1602A挂在51单片机的总线上,就需要做一些逻辑上的变换。 |
 |
图(3) |
|
图(3)所示,是一个典型的应用实例。在这个电路中读和写使用地址信号A1进行区分。也就是,地址0x8000和地址0x8001是只能写操作,而地址0x8002和0x8003只能读操作。地址线A0用于区分指令还是数据,所以0x8000和0x8002是指令寄存器地址,而0x8001和0x8003是数据寄存器地址。整个接口的选通由A15实现,只有当A15为"1"时,写信号和读信号才可以传送到LCD的E端子,触发读写操作。 |
|
这个电路在低主频时可以很好的工作,但在高主频时会有问题。因为LCD的接口的速度不高,在高主频时会跟不上单片机总线的节拍。为了在高主频下使LCD接口匹配单片机总线的速度,可以在单片机总线上挂接两个端口,再由端口与LCD交换数据。 |
 |
图(4) |
|
如图(4)所示,可以由74377、74373、74244组成双向接口来驱动LCD。控制信号由74377产生,输数据先锁存在74373中再由74373传输给LCD,输入数据通过74244读回。由于读写时序由软件产生,避免了LCD与单片机总线速度不匹配的问题。 |
|
图(5)所示为EPM7128S的出厂逻辑设计中的LCD接口的输出部分。由74377产生LCDRS、LCDRW、LCDE这三个控制信号,分别输出给LCD的RS、RW、E管脚,其中LCDRW信号在输出给LCD的同时,也送给74373的输出使端子OE。在74373中锁存的是待输出的数据,若LCDRW为低电平则74373输出数据信号给LCD。74377的使能信号由CS2和A0的反向信号相"或"产生,对应的地址为0x8041。送给74373的WR信号由CS2和A0通过"或非"门控制,所以对应的地址为0x8040。 |
 |
图(5) |
|
LCD接口的输入通路如图(6)所示。数据在RD信号有效时,由CS2信号选通后经由两级多路选择器,再通过74244传送到单片机的数据总线上。可以用过地址0x8040读取这一数据。 |
 |
图(6) |
|
LCD接口的输入通路如图(6)所示。数据在RD信号有效时,由CS2信号选通后经由两级多路选择器,再通过74244传送到单片机的数据总线上。可以用过地址0x8040读取这一数据。 |
|
void LCDWriteCmd(unsigned char Cmd)
{
unsigned char RdData;
do
{
XBYTE[CAddr] = 0x02; // CAddr = 0x8041,74377地址,
// 写0x02则 LCDRS = 0,LCDRW = 1, LCDE = 0。
// 先置LCDRW = 1为了使74373在LCD输出之前转为高阻输出
XBYTE[CAddr] = 0x06; // 向74377写0x06,使LCDRS = 1,LCDRW=1,LCDE = 0。
// 发命令给LCD,让其送出状态字
RdData = XBYTE[DAddr]; // DAddr = 0x8040,74244的地址,读回LCD送出的状态字
}while((RdData&0x80) != 0); // 判断BF位是不为"1",不为"1"则控制器空闲,
// 可发送命令给LCD
XBYTE[CAddr] = 0x00; // 写74377,使LCDRS = 0,LCDRW = 0,LCDE = 0
// LCDRS = 0,代表写入LCD的是命令字
XBYTE[CAddr] = 0x04; // 写74377,使LCDE = 1
XBYTE[DAddr] = Cmd; // DAddr = 0x8040,是74373的写地址。将命令字写入74373
XBYTE[CAddr] = 0x00; // 写74377,使LCDE = 0,产生一个下降沿,
// 将74373中的命令字写入LCD
}
|
| |
|
void LCDWriteData(unsigned char WrData)
{
unsigned char RdData;
do
{
XBYTE[CAddr] = 0x02; // CAddr = 0x8041,74377地址,
// 写0x02则 LCDRS = 0,LCDRW = 1, LCDE = 0。
// 先置LCDRW = 1为了使74373在LCD输出之前转为高阻输出
XBYTE[CAddr] = 0x06; // 向74377写0x06,使LCDRS = 1,LCDRW=1,LCDE = 0。
// 发命令给LCD,让其送出状态字
RdData = XBYTE[DAddr]; // DAddr = 0x8040,74244的地址,读回LCD送出的状态字
}while((RdData&0x80) != 0); // 判断BF位是不为"1",不为"1"则控制器空闲,
// 可发送命令给LCD
XBYTE[CAddr] = 0x01; // 写74377,使LCDRS = 1,LCDRW = 0,LCDE = 0
// LCDRS = 1,表示写入LCD的是显示字符
XBYTE[CAddr] = 0x05; // 写74377,使LCDE = 1
XBYTE[DAddr] = WrData; // DAddr = 0x8040,是74373的写地址。将命令字写入74373
XBYTE[CAddr] = 0x01; // 写74377,使LCDE = 0,产生一个下降沿,
// 将74373中的字符写入LCD
}
|
| |
|
/* 设置显示模式,两行,8位数据传输 */
LCDWriteCmd(LCD_CMD_DATA|LCD_CMD_DT_8BIT|LCD_CMD_DT_2LINE);
/* 清屏 */
LCDWriteCmd(LCD_CMD_CLR);
/* 打开显示,打开光标,光标闪烁 */
LCDWriteCmd(LCD_CMD_SWITCH|LCD_CMD_SW_DISPLAY|LCD_CMD_SW_BAR|LCD_CMD_SW_FLASH);
/* 光标自动进移 */
LCDWriteCmd(LCD_CMD_MODE|LCD_CMD_MD_INC);
/* 光标回到屏幕起点 */
LCDWriteCmd(LCD_CMD_HOME);
/* 光标右移一个字符 */
LCDWriteCmd(LCD_CMD_SHIFT|LCD_CMD_SH_BAR|LCD_CMD_SH_RT);
|
| |
RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | - |
RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | M | S |
|
功能:设置光标、画面移动方式
M = 1: 数据读、写后光标位置前进 |
M = 0:数据读、写后光标位置后退 |
S = 1:数据读、写后画面平移 |
S = 0:数据读、写后画面不动 |
|
RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 |
0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | B |
|
功能:显示开关控制
D = 1: 显示开 |
D = 0:显示关 |
C = 1:光标开 |
C = 0:光标关 |
B = 1:闪烁开 |
B = 0:闪烁关 |
|
RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 |
0 | 0 | 0 | 0 | 0 | 1 | SC | RL | - | - |
|
功能:光标、画面移动控制
SC = 1: 画面平移一个字符 |
SC = 0:光标平移一个字符 |
RL = 1:右移 |
RL = 0:左移 |
|
RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 |
0 | 0 | 0 | 0 | 1 | DL | N | - | - | - |
|
功能:接口设置
DL = 1: 8位数据接口 |
DL = 0:4位数据接口 |
N = 1:两行显示 |
N = 0:一行显示 |
|
RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 |
0 | 0 | 0 | 1 | A5 | A4 | A3 | A2 | A1 | A0 |
RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 |
0 | 0 | 1 | A6 | A5 | A4 | A3 | A2 | A1 | A0 |
RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 |
0 | 1 | BF | A6 | A5 | A4 | A3 | A2 | A1 | A0 |
|
功能:读状态字
BF = 1: 控制器忙 |
BF = 0:控制器空闲 |
A6 - A0:最近一次地址设置的值 |
|
RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 |
1 | 0 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
RS | RW | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 |
1 | 1 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
|
|