图1所示是<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />89C51单片机与LCD12864的接口电路。
其中,74HC573作为地址锁存器。ZY12864D的D0~D7为8位双向数据线;RS为寄存器选择,高电平选择数据寄存器,低电平选择指令寄存器;R/W为读写信号线,高电平进行读操作,低电平进行写操作;E端为使能端,当E端由高电平跳变成低电平时,液晶执行命令;CS1和CS2为选屏信号,CS1高电屏选中左半屏,CS2高电屏选中右半屏。
从图中可以看出,CS2是通过CS1接的反相器得到的,所以CS1和CS2不能同时为高电平,即该实验中左、右半屏不能同时控制。模块及其背光源均由外部提供+5V电源。通过调节外接的电位器的阻值,用户可以控制LCD模块显示图形的清晰度。
通过分析可知,图中LCD液晶显示写左半屏指令的地址为7FFCH,写右半屏指令的地址为7FF8H,写左半屏数据的地址为7FFDH,写右半屏数据的地址为7FF9H。
图1、LCD12864与P89C51的接口电路
12864液晶模块内部的控制器共有7条控制指令,如表1所示。它的读写操作、屏幕和光标的操作都是通过指令编程实现的。
表1、12864液晶模块内部的控制命令
指令 | RS | RW | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
显示 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | D |
显示起始行 | 0 | 0 | 1 | 1 | 显示起始行(0……63) | |||||
设置X地址 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | X:0….7 | ||
设置Y地址 | 0 | 0 | 0 | 1 | Y地址(0…..63) | |||||
读状态 | 0 | 1 | BF | 0 | ON/OFF | RST | 0 | 0 | 0 | 0 |
写显示数据 | 1 | 0 | 要写的数 | |||||||
读显示数据 | 1 | 1 | 读出的数据 |
下面简单介绍一下表中指令的功能:
指令1:显示开关控制,D高电平开显示,低电平关显示。
指令2:设置显示起始行。
指令3:设置X地址(页地址)。
指令4:设置Y地址(列地址)。。
指令5:读状态。BF:忙标志,高电平表示忙,此时模块不能接受命令或数据,低电平表示空闲;RST:复位标志位,高电平表示正处于复位初始化状态,低电平表示正常状态。ON/OFF:显示标志位,高电平表示显示关闭,低电平表示显示开。
指令6:写显示数据。写指令执行后Y地址计数器自动加1。
指令7:读显示数据。写指令执行后Y地址计数器自动加1。
实验程序:
/* 包含头文件 */
#include "reg52.h"
#include "absacc.h"
#include "stdlib.h"
#include "intrins.h"
#define uint8 unsigned char
#define uint16 unsigned int
/* 定义LCM操作地址 */
#define LCMCS1W_COM (*((uint8 volatile xdata *) 0x7ffc)) /* 写左半屏指令 */
#define LCMCS1W_DAT (*((uint8 volatile xdata *) 0x7ffd)) /* 写左半屏数据 */
#define LCMCS2W_COM (*((uint8 volatile xdata *) 0x7ff8)) /* 写右半屏指令 */
#define LCMCS2W_DAT (*((uint8 volatile xdata *) 0x7ff9)) /* 写右半屏数据 */
/* 定义LCM操作的命令字 */
#define LCM_DISPON 0x3f /* 打开LCM显示 */
#define LCM_STARTROW 0xc0 /* 显示起始行0,可以用LCM_STARTROW+x设置起始行。(x<64) */
#define LCM_ADDRSTRX 0xb8 /* 页起始地址,可以用LCM_ADDRSTRX+x设置当前页(即行)。(x<8) */
#define LCM_ADDRSTRY 0x40 /* 列起始地址,可以用LCM_ADDRSTRY+x设置当前列。(y<64) */
/* LCM复位控制脚定义 */
sbit LCM_RST = P1^0;
uint8 code number[160]={
/*-- 文字: 0至9; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,
};
/***********************************************************************
* 名称:LCM_Wr1Command()
* 功能:写命令子程序,所选屏为左半屏(CS1)。
* 入口参数:command 要写入LCM的命令字
***********************************************************************/
void LCM_Wr1Command(uint8 command)
{
LCMCS1W_COM = command;
}
/***********************************************************************
* 名称:LCM_Wr2Command()
* 功能:写命令子程序,所选屏为右半屏(CS2)。
* 入口参数:command 要写入LCM的命令字
***********************************************************************/
void LCM_Wr2Command(uint8 command)
{
LCMCS2W_COM = command;
}
/***********************************************************************
* 名称:LCM_Wr1Data()
* 功能:写数据子程序,所选屏为左半屏(CS1)。
* 入口参数:wrdata 要写入LCM的数据
***********************************************************************/
void LCM_Wr1Data(uint8 wrdata)
{
LCMCS1W_DAT = wrdata;
}
/***********************************************************************
* 名称:LCM_Wr2Data()
* 功能:写数据子程序,所选屏为右半屏(CS2)。
* 入口参数:wrdata 要写入LCM的数据
***********************************************************************/
void LCM_Wr2Data(uint8 wrdata)
{
LCMCS2W_DAT = wrdata;
}
/****************************************************************************
* 名称: delayms()
* 功能: 延时子函数
* 入口参数:
****************************************************************************/
void delayms(uint8 ms)
{
uint8 s, t;
for(s = 0; s < ms; s++)
for(t = 0; t < 250; t++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
/***********************************************************************
* 名称:LCM_DispClr()
* 功能:LCM清屏
* 入口参数:无
* 出口参数:无
***********************************************************************/
void LCM_DispClr(void)
{
uint8 i, j;
for(i = 0; i < 8; i++)
{
LCM_Wr1Command(i + LCM_ADDRSTRX);
LCM_Wr2Command(i + LCM_ADDRSTRX); /*设置左右屏页地址*/
LCM_Wr1Command(LCM_ADDRSTRY);
LCM_Wr2Command(LCM_ADDRSTRY); /*设置左右屏初始列地址*/
for(j = 0; j < 64; j++) /*每清一位0,列地址会自动加1*/
{
LCM_Wr1Data(0x00);
LCM_Wr2Data(0x00); /*清显示屏*/
}
}
}
/***********************************************************************
* 名称:LCM_DispIni()
* 功能:LCM显示初始化。使能显示,设置显示起始行为0并清屏。
* 入口参数:无
* 出口参数:无
***********************************************************************/
void LCM_DispIni(void)
{
LCM_RST=0;
delayms(2);
LCM_RST=1;
LCM_Wr1Command(LCM_DISPON); // 打开显示
LCM_Wr1Command(LCM_STARTROW); // 设置显示起始行为0
LCM_Wr2Command(LCM_DISPON);
LCM_Wr2Command(LCM_STARTROW);
LCM_DispClr(); // 清屏
LCM_Wr1Command(LCM_ADDRSTRY+0); // 设置页(行)地址
LCM_Wr1Command(LCM_ADDRSTRX+0); // 设置列地址,即列
LCM_Wr2Command(LCM_ADDRSTRY+0);
LCM_Wr2Command(LCM_ADDRSTRX+0);
}
/***********************************************************************
* 名称:LCM_DispChar()
* 功能:指定地址显示字符。
* 入口参数:cx 显示行值(0-7)
* cy 显示列值(0-15)
* dispchar 所要显示的字符(ASCII码)
* 注:支持显示字符0-9,字符显示格式为5*7,模为16*8,所以
* 屏幕显示为4*16(共4行,每行16个字符)。
***********************************************************************/
void LCM_Dispchar(uint8 cx, uint8 cy, uint8 dispchar)
{
uint8 h, i;
if(cy < 0x08)//选择液晶控制芯片(即CS1--控制前8个字符,CS2--控制后8个字符)
{
i = cy << 3;
LCM_Wr1Command(LCM_ADDRSTRX + cx); // 设置当前页地址,即行
LCM_Wr1Command(LCM_ADDRSTRY + i); // 设置当前列地址,即列
for(h = 0; h < 8; h++)
LCM_Wr1Data(number[dispchar*16 + h]);
LCM_Wr1Command(LCM_ADDRSTRX + cx + 1); // 设置当前页地址,即行
LCM_Wr1Command(LCM_ADDRSTRY + i); // 设置当前列地址,即列
for(h = 0; h < 8; h++)
LCM_Wr1Data(number[dispchar*16 + h + 8]);
}
else
{
i = (cy & 0x07) << 3;
LCM_Wr2Command(LCM_ADDRSTRX + cx); // 设置当前页地址,即行
LCM_Wr2Command(LCM_ADDRSTRY + i); // 设置当前列地址,即列
for(h = 0; h < 8; h++)
LCM_Wr2Data(number[dispchar*16 + h]);
LCM_Wr2Command(LCM_ADDRSTRX + cx + 1); // 设置当前页地址,即行
LCM_Wr2Command(LCM_ADDRSTRY + i); // 设置当前列地址,即列
for(h = 0; h < 8; h++)
LCM_Wr2Data(number[dispchar*16 + h + 8]);
}
}
/* 在12864上起始行显示0123456789 */
void main()
{
LCM_Dispchar(0, 0, 0);
LCM_Dispchar(0, 1, 1);
LCM_Dispchar(0, 2, 2);
LCM_Dispchar(0, 3, 3);
LCM_Dispchar(0, 4, 4);
LCM_Dispchar(0, 5, 5);
LCM_Dispchar(0, 6, 6);
LCM_Dispchar(0, 7, 7);
LCM_Dispchar(0, 8, 8);
LCM_Dispchar(0, 9, 9);
}
用户738303 2009-5-13 15:14
用户1321768 2009-5-13 08:57
用户518079 2008-11-28 17:16
用户738303 2008-11-12 12:11
用户1480039 2008-11-11 16:47