/***测试OK,我的是12864-15型引脚。并口驱动****/
#include "reg52.h"
#include
#define LCD12864_IOP0
#define LINE10
#define LINE21
#define HIGH1
#define LOW 0
#defineCLERADISPLAYLCD12864_command(0x01);
code unsigned char gImage_test[1024] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04} ;
sbit LCD12864_EN=P2^7;
sbit LCD12864_DIN=P2^6;
sbit LCD12864_CLK=P2^5;
void LCD12864_busy(void);
void LCD12864_command(unsigned char command);
void LCD12864_data(unsigned char dat);
void LCD12864_address(unsigned char row,unsigned char line);
void LCD12864_char(unsigned char dat);
void LCD12864_string(unsigned char row,unsigned char line,unsigned char *s);
void LCD12864_picture(unsigned char *gImage);
void LCD12864_init(void);
/********************************************************************/
void Mcu_init(void)
{
LCD12864_init();
CLERADISPLAY
CLERADISPLAY
LCD12864_init();
}
void Delay(void)
{
unsigned char i;
unsigned int j;
for(i=0;i<200;i++)
for(j=1000;j>0;j--);
}
void main(void)
{
Mcu_init();
LCD12864_picture((unsigned char*)gImage_test);
Delay();Delay();
CLERADISPLAY
while(1)
{
LCD12864_string(1,1," LCD12864-15 ");
LCD12864_string(1,2,"中文显示测试实验");
LCD12864_string(1,3," 少占鱼 ");
LCD12864_string(1,4," 2010-1-26 ");
}
}
void LCD12864_DELAY(unsigned int a)
{
for(;a>0;a--)
_nop_();
}
/*******************************************************************/
void LCD12864_busy(void)
{
bit BF = 0;
LCD12864_EN=0;
LCD12864_DIN=0;
LCD12864_CLK=1;
LCD12864_IO=0xff;//单片机读数据之前必须先置高位
do
{
LCD12864_EN=1;
BF=LCD12864_IO&0x80;
LCD12864_EN=0;
} while(BF);
}
/*******************************************************************/
// 写入命令
/*******************************************************************/
void LCD12864_command(unsigned char command)
{
LCD12864_busy();
LCD12864_EN=0;
LCD12864_DIN=0;
LCD12864_CLK=0;
LCD12864_EN=1;
LCD12864_IO=command;
LCD12864_EN=0;
}
/*******************************************************************/
// 写入一字节数据
/*******************************************************************/
void LCD12864_data(unsigned char dat)
{
LCD12864_busy();
LCD12864_EN=0;
LCD12864_DIN=1;
LCD12864_CLK=0;
LCD12864_EN=1;
LCD12864_IO=dat;
LCD12864_EN=0;
}
//读数据函数
unsigned char LCD12864_ReadData()
{
unsigned char read_data;
LCD12864_busy();
LCD12864_IO=0xff;
LCD12864_RS=1;
LCD12864_RW=1;
LCD12864_EN=0;
LCD12864_EN=1;
read_data=LCD12864_IO;
LCD12864_EN=0;
return(read_data);
}
void LCD12864_char(unsigned char dat)
{
if((dat>=0)&&(dat<=9))
dat|=0x30;
LCD12864_data(dat);
}
/*******************************************************************/
// 设置显示位置 X(1~8),Y(1~4)
/*******************************************************************/
void LCD12864_address(unsigned char line,unsigned char row)
{
switch(row)
{
case 1:LCD12864_command(0x7f + line);
break;
case 2:LCD12864_command(0x8f + line);
break;
case 3:LCD12864_command(0x87 + line);
break;
case 4:LCD12864_command(0x97 + line);
default:
break;
}
}
// 在指定位置显示字符串
/*******************************************************************/
void LCD12864_string(unsigned char row,unsigned char line,unsigned char *s)
{
unsigned char LCD12864_temp;
LCD12864_address(row,line);
LCD12864_temp=*s;
while(LCD12864_temp != 0x00)
{
LCD12864_data(LCD12864_temp);
LCD12864_temp=*(++s);
}
}
// 绘制一幅图片
/*******************************************************************/
void LCD12864_picture(unsigned char *gImage)
{
unsigned char X = 0x80,Y = 0x80;
unsigned char i,j;
for(i=0;i<64;i++)
{
for(j=0;j<16;j++)
{
LCD12864_command(0x34);
LCD12864_command(Y);
LCD12864_command(X);
LCD12864_data(*(gImage+i*16+j)); // low 8 bits
LCD12864_data(*(gImage+i*16+j+1)); // high 8 bits
LCD12864_command(0x36);
X++;
j++;
}
Y++;
if(Y>0x9f)
Y=0x80;
X=0x80+((i+1)/32)*8;
}
LCD12864_command(0x30);
}
// 初始化设置
/*******************************************************************/
void LCD12864_init(void)
{
CLERADISPLAY // clear DDRAM
LCD12864_command(0x30); // 8 bits unsigned interface,basic instrument
LCD12864_command(0x02); // cursor return
LCD12864_command(0x0c); // display,cursor on
LCD12864_command(0x03);
LCD12864_command(0x06);
CLERADISPLAY // clear DDRAM
}
/****************************
0x80 0x81 0x82 0x83 0x84 0x85 0x86 0x87 上半屏行坐标,表示的是多少列
0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 下半屏行坐标,每组8列,每列16位,共128位,
0x80
0x81
0x82
0x83
........
0x9f //列坐标,共32个,表示的是行数 ,分两个半屏,每个32行,共64行
//Y坐标 只是用来确定具体坐标,在哪一行
功能:图形模式下,显示(X,Y)点
输入:X(0~127) Y(0~63) 相对屏幕坐标
输出:无
点亮某一点的操作步骤: 1.求出水平坐标X对应的地址和是哪一位 0x80-----0x8f (范围0-15) X/16求地址 X%16求该地址哪一位
2.求垂直坐标Y对应的地址和上下半屏 0x80------0x9f(范围0-63) Y本身就是8位地址,Y=63-Y ,Y--(0-31)
3.写入行列地址(Y是行X是列),0x80+Y ,0X80+X/16
4.读要显示的数据 DAT
5.区分上下半屏(X%16<=7&&X%16>=0是上半屏)写入数据每一位 DAT|0x80 ;DAT<<1
注意:这个函数显示某一点时,可能会把上次显示的处于同一地址的其他位的点擦掉,所以先保存所有数据,最后显示,就连贯起来了
*******************************/
/*******************************************************************/
/**************************************************************/
//------------------清整个GDRAM空间----------------------------
/**************************************************************/
void clrgdram()
{
unsigned char x,y ;
for(y=0;y<64;y++)
for(x=0;x<16;x++)
{
LCD12864_command(0x34);
LCD12864_command(y+0x80);
LCD12864_command(x+0x80);
LCD12864_command(0x30);
LCD12864_data(0x00);
LCD12864_data(0x00);
}
}
/******************************************/
/*******8==========================================================================
功能:图形模式下,显示(X,Y)点
输入:X(0~127) Y(0~63)
输出:无
0x80 0x81 0x82 0x83 0x84 0x85 0x86 0x87 上半屏行坐标,表示的是多少列,X地址
0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 下半屏行坐标,X地址 (水平地址 )
0x80 (垂直地址)
0x81
0x82
0x83
........
0x9f //列坐标,共32个,表示的是行数 ,分两个半屏,每个32行,共64行
====================================================================**********/
void LCD12864_Drawpoint(uchar X,uchar Y)
{
uchar i= 0, j = 0,ok=0;
uchar temp1 = 0x00,temp2 = 0x00;
LCD12864_command(0x34); //8位,扩充指令,绘图关
LCD12864_command(0x36); //8位,扩充指令,绘图开
i = X/16; //计算出X字节地址(0X80-0X8F)
j = X%16; //计算出该字节的具体位(0-15)
//Y = 63 - Y;
if(Y>=0 && Y<=31)//判断上下半屏
{
ok=1;
}
else if(Y>=32 && Y<=63)//下半屏
{
Y = Y - 32;//Y只有0-31共32个 地址
i = i + 8;//X地址进入下半屏 (0X88-0X8F)
ok=1;
}
if(ok)
{
//读数据操作
LCD12864_command(0x80+Y); //第一步:设置Y坐标,读数据先写地址,写GDRAM时先写垂直地址(0X80-0X9F)
LCD12864_command(0x80+i); //第二步:设置X坐标
LCD12864_ReadData(); //第三步:空读取一次
temp1 =LCD12864_ReadData(); //第四步:读取高字节,先读高字节
temp2 =LCD12864_ReadData(); //第五步:读取低字节
//图形模式下的写数据操作
LCD12864_command(0x80+Y); //第一步:设置Y坐标
LCD12864_command(0x80+i); //第二步:设置X坐标
if(j>=0 && j<=7) //判断是高字节
{
LCD12864_data(temp1|(0x80>>j)); //第三步:写高字节数据
LCD12864_data(temp2); //第四步:写低字节数据
}
else if(j>7 && j<=15) //判断是低字节
{
j = j - 8;
LCD12864_data(temp1);
LCD12864_data(temp2|(0x80>>j)); //改变字节里的位
}
}
}
/******************************************/
//画线
/********************************************/
//画水平线
void LCD12864_LineX(unsigned char X0, unsigned char X1, unsigned char Y)
{
unsigned char Temp ;
if( X0 > X1 )
{
Temp = X1 ; //交换X0 X1值
X1 = X0 ; //大数存入X1
X0 = Temp; //小数存入X0
}
for( ; X0 <= X1 ; X0++ )
LCD12864_Drawpoint(X0,Y);
}
//画垂直线
void LCD12864_LineY( unsigned char X, unsigned char Y0, unsigned char Y1)
{
unsigned char Temp ;
if( Y0 > Y1 )//交换大小值
{
Temp = Y1 ;
Y1 = Y0 ;
Y0 = Temp ;
}
for(; Y0 <= Y1 ; Y0++)
LCD12864_Drawpoint( X, Y0) ;
}
/******************************************/
/**************画图************************/
void LCD12864_DrawPicture( unsigned char code *pic)
{
unsigned char i, j, k ;
LCD12864_command(0x34);//开扩充指令
LCD12864_command(0x36);//开绘图功能
for( i = 0 ; i < 2 ; i++ )//分上下两屏写
{
for( j = 0 ; j < 32 ; j++)//垂直地址递加 ,行扫方式
{
LCD12864_command( 0x80 + j ) ;//写Y坐标(Y的范围: 0X80-0X9F )
if( i == 0 ) //写X坐标
{
LCD12864_command(0x80);//上半屏
}
else
{
LCD12864_command(0x88);//下半屏开始地址
}
for( k = 0 ; k < 16 ; k++ ) //写一整行数据
{
LCD12864_data( *pic++ );//前面只写入首地址,后面依次写入数据,地址会自动递增
}
}
}
LCD12864_command( 0x30);//恢复到一般模式
}
//