12864 带字库(ST7920 控制器)液晶学习
之前说学完 12864字库液晶后和大家交流一下心得,一直没有时间,今天整理一下发上来,
希望对想学习的朋友能有点帮助…
首先说明一点,本人也是初学者,自感水平不高,若有不足及不对之处,望情指正…
以下以并行口传输为例,别的还不会,呵呵!
一、首先说一下关于驱动函数的书写,这些是液晶显示的基础
一般包括四个函数:
1、写命令函数;
2、写数据函数;
3、读状态函数;
4、读数据函数;
这四个函数并不是必须全部写的,具体要看你实现的功能,如果只是单纯的显示汉字和
字符,写命令、写数据、读状态这三个函数就够了,如过你还需要进行一些绘图的操作,那
读数据函数也必须书写。
另外关于读状态函数,其实也就是用于判忙操作,我看郭天祥的书里面是这样说的:原
则上每次对控制器进行读写操作之前,都必须进行读写检测,由于单片机的操作速度慢于液
晶控制器的反应速度,因此可不进行读写检测,或者只进行简短的延时即可。因此,读状态
函数也可以不写,只用简短的延时函数替换即可。
1、写操作的编写:
首先看一下时序图
写操作时序.jpg
由图可见操作很简单:
以下是我的驱动函数,仅供参考:
/********************************液晶端口定义**************************/
#define lcd_data P0 //数据口
sbit RS = P2^4; //选择寄存器(并行) 0:指令寄存器 1:数据寄存器;
sbit RW = P2^5; //读写控制脚(并行) 0:写入 1:读出
sbit E = P2^6; //读写数据启始脚(并行)
sbit PSB = P2^1; //串并方式选择引脚,0为串行模式,1为 8/4位数据口模式
sbit RST = P2^3; //复位引脚
//********************************************************
//延时函数
//********************************************************
void delay(unsigned int k)
{
unsigned int i;
unsigned char j;
for(i=0;i
0;x--)
for(y=121;y>0;y--);
}
//********************************************************
//写命令函数
//********************************************************
void LcdWcom(unsigned char WCom)
{
delay(1);
RS=0; //指明操作对象为指令寄存器
RW=0; //指明为写操作
E=1;
lcd_data=WCom; //将命令写入总线
E=0;
}
//********************************************************
//写数据函数
//********************************************************
void LcdWdata(unsigned char WData)
{
delay(1);
RS=1; //指明操作对象为数据寄存器
RW=0; //指明为写操作
E=1;
lcd_data=WData; //将数据写入总线
E=0;
}[p=30, 2, left]
二、初始化操作
初始化操作如下:
1>芯片上电;
2>延时 40ms以上;
3>复位操作:RST出现一个上升沿(RST=1;RST=0;RST=1;);
4>功能设定;
5>延时 100us以上;
6>再次进行功能设定;
7>延时 37us;
8>显示开关控制;
9>延时 100us以上;
10>清除显示;
11>延时 10ms以上;
12>进入点设置;
13>初始化结束;
这里我遇到了一个小问题,我的液晶按照这个顺序进行初始化结果不正确,无法显示,
最后我把调整了一下就可以了,调整后的顺序为:清除显示?进入点设置?显示开关控制,不
知道是什么原因,知道的告诉我一声…
//********************************************************
//********************************************************
void Display_Init(void)
{
设置为 8位并行口,基本指令集
再次设置为 8位并行口,基本指令集
游标显示关,正常显示,整体显示开
设置为游标右移,DDRAM位地址加 1,画面不移动
}
三、显示基本的字符和汉字
1、要想显示汉字或字符,首先要确定显示的位置,看看芯片说明书上关于屏幕地址的分配:
由于此液晶为 128*64,即是横向 128个点,竖向 64个点,由于该液晶控制器支持的字符
为 8*16,汉字为 16*16,因此只能显示四行,如果是汉字,为每行显示 8个,如果是字符,
每行显示 16个。
由上图设置 DDRAM 地址的指令可知,最高位为 1,余下 7 位为地址值,因此就对应了
为什么起始地址为 80H的原因(即对应的写地址指令为 1000 0000);
因此如果你要设定显示的地址为第一行的第一个位置,只需要调用写指令函数,写入 0x80
即可。
存在的问题:参考网上的程序及在试验过程中发现,实际能显示出来的地址分布式这样的
0x80 0x81 0x82 0x83 0x84 0x85 0x86 0x87 //第一行汉字位置
0x90 0x91 0x92 0x93 0x94 0x95 0x96 0x97 //第二行汉字位置
0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f //第三行汉字位置
0x98 0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f //第四行汉字位置
百思不得其解,尤其让人受不了的是居然是第一行和第三行地址接续,而不是第二行,有明
白的高手给讲解一下…
//********************************************************
//设置光标函数
//参数说明:x为行号,y为列号
//********************************************************
void Set_Cursor(unsigned char x, unsigned char y)
{
unsigned char i;
switch(x)//确定行号
{
case 0x00: i=0x80; break;//第一行
case 0x01: i=0x90; break;//第二行
case 0x02: i=0x88; break;//第三行
case 0x03: i=0x98; break;//第四行
default : break;
}
i = y+i;//确定列号
LcdWcom(i);//写地址
}
由数据
手册
华为质量管理手册 下载焊接手册下载团建手册下载团建手册下载ld手册下载
可查看可以显示的字符及其显示码:
因此,当你设置好所要显示的光标位置后,即可调用写数据函数,写入对应相应字符的显示
码,比如要显示!就应该写入 0x21。
//********************************************************
//********************************************************
void Disp_Char(unsigned char Alphabet)
{
写入需要显示字符的显示码
}
显示!实例:
/**********************显示单个字符*************************/
效果图:
扩展程序:在指定位置显示字符串
//********************************************************
//指定位置显示字符串函数
//参数说明:x为行号,y为列号
//********************************************************
void Display_String(unsigned char x,unsigned char y,unsigned char *Alphabet)
{
unsigned char i=0;
Set_Cursor(x,y); //设置显示的起始地址
while(Alphabet[i]!='\0')
{
LcdWdata(Alphabet[i]); //写入需要显示字符的显示码
i++;
}
}
显示字符串实例:
/***********************显示字符串*************************/
Display_String(1,0,"WWW.CEPARK.COM"); //显示字符串
效果图:
因为一个汉字占用两个字节的大小,因此要想显示一个汉字,需要进行两个数据写入操作。
所支持的 8192个 16*16的汉字详见数据手册附录中的 ST7920GB中文字型码表。
参考程序:
//********************************************************
//********************************************************
void Disp_HZ(unsigned char x,unsigned char y,unsigned char *HZ)
{
DispSetCursor(x,y); //设置显示的起始地址
LcdWdata(HZ[0]); //写入需要显示汉字的高八位数据
LcdWdata(HZ[1]); //写入需要显示字符的低八位数据
}
显示汉字实例:
/************************显示汉字*************************/
Display_HZ(0,1,"电"); //显示电
Display_HZ(0,2,"子"); //显示子
Display_HZ(0,3,"园"); //显示园
效果图:
照片 003.jpg
扩展程序:
//********************************************************
//********************************************************
void Disp_HZ_line(unsigned char x,unsigned char y,unsigned char *HZ)
{
DispSetCursor(x,y); //设置显示的起始地址
while(HZ!='\0')
LcdWdata(HZ[i++]); //写入需要显示汉字的高八位数据
LcdWdata(HZ[i++]); //写入需要显示字符的低八位数据
if((y+i)%16= =0) //如果满一行
if(x= =4) //如果满一屏
x=0;
DispSetCursor(x,0); //重新设置显示的起始地址
}
显示一行汉字实例:
/************************显示一行汉字*********************/
Display_HZ_Line(2,0,"欢迎转载,转载请注明出处,谢谢!");//显示一行汉字
效果图:
再来一个整体的现实效果
//**************************************************************************
//说明:程序主函数
//**************************************************************************
void main(void)
{
/***********************液晶初始化***************************/
Display_Init();
/**********************显示单个字符*************************/
Set_Cursor(0,0); //光标地址设定
Display_Char(0x21); //显示字符!
/***********************显示字符串*************************/
Display_String(1,0,"WWW.CEPARK.COM"); //显示字符串
/************************显示汉字*************************/
Display_HZ(0,1,"电"); //显示电
Display_HZ(0,2,"子"); //显示子
Display_HZ(0,3,"园"); //显示园
/************************显示一行汉字*********************/
Display_HZ_Line(2,0,"欢迎转载,转载请注明出处,谢谢!");//显示一行汉字
while(1);
}
LcdWdata(HZ[i++]); //写入需要显示汉字的高八位数据
LcdWdata(HZ[i++]); //写入需要显示字符的低八位数据
if((y+i)%16= =0) //如果满一行
if(x= =4) //如果满一屏
x=0;
DispSetCursor(x,0); //重新设置显示的起始地址
}
显示一行汉字实例:
/************************显示一行汉字*********************/
Display_HZ_Line(2,0,"欢迎转载,转载请注明出处,谢谢!");//显示一行汉字
效果图:
再来一个整体的现实效果
//**************************************************************************
//说明:程序主函数
//**************************************************************************
void main(void)
{
/***********************液晶初始化***************************/
Display_Init();
/**********************显示单个字符*************************/
Set_Cursor(0,0); //光标地址设定
Display_Char(0x21); //显示字符!
/***********************显示字符串*************************/
Display_String(1,0,"WWW.CEPARK.COM"); //显示字符串
/************************显示汉字*************************/
Display_HZ(0,1,"电"); //显示电
Display_HZ(0,2,"子"); //显示子
Display_HZ(0,3,"园"); //显示园
/************************显示一行汉字*********************/
Display_HZ_Line(2,0,"欢迎转载,转载请注明出处,谢谢!");//显示一行汉字
while(1);
}
四、关于 CGRAM的使用:
可以参考这个网站的程序: http://bbs.友好站点,请勿转贴.com/ShowTopic.aspx?id=81220
ST7920自行产生 RAM提供使用者图像定义(造字)功能,可以提供四组 16*16点的自定义图
像空间,使用者可以将内部自行没有提供的图像自行定义到 CGRAM 中,便可以通过
DDRAM显示在液晶屏上。注意:网上介绍说 ST7920芯片同屏幕不能显示 4个以上自定义
汉字(用 CGRAM)。显示 CGRAM 字型:将 16 位元资料写入 DDRAM 中,一共有
0000H,0002H,0004H,0006H四种编码。
操作步骤:
写入自定义数据);
五、关于 GDRAM绘图模式的操作
ST7920 提供 64×32 个字节的空间(由扩充指令设定绘图 RAM 地址),最多可以控制
256×64 点阵的二维绘图缓冲空间,在更改绘图 RAM时,由扩充指令设置 GDRAM地址先
垂直地址后水平地址(连续 2个字节的数据来定义垂直和水平地址),再 2个字节的数据给
绘图 RAM(先高 8位后低 8 位)。地址分布如下:
GDRAM地址.jpg
操作步骤:
2>写两字节的 GDRAM地址,先写垂直地址,后写水平地址地址;
应用实例:
/*************************GUI全屏填充********************/
GUI_Fill_GDRAM(0xcc); //竖条显示
实物图:
打点操作是作图的基础,众所周知,画任何图形均可以由画一个个点来实现。
具体打点的操作步骤:
3>修改该点相应的位的值,对于单色液晶来说,只有两种操作,已是点亮该点,二是熄灭
该点;
由于打点首先需要进行读操作,因此需要编写读数据的驱动函数:
读操作的编写:
时序图:
读操作时序.jpg
读操作时序.jpg
操作如下:
读操作参考程序:
打点参考程序:
应用实例:
/***************************GUI作图操作**********************/
GUI_Point(64,32,1); //打点操作
有了打点函数,下面的画线画圆灯函数就简单了,下面的程序大部分都是我由 ZLG/GUI修
改过来的:
应用例子:
GUI_HLine(10,120,10,1); //画水平线操作
GUI_RLine(10,10,60,1); //画垂直线操作
照片 009.jpg
[i=s] 本帖最后由 zhaoshan413 于 2009-8-31 21:16 编辑
任意两点画线:
应用例子:
GUI_Line(0,0,127,63,1); //画线操作