您好,欢迎来到微智科技网。
搜索
您的当前位置:首页128(很好的资料)

128(很好的资料)

来源:微智科技网
````````````` 51单片机综合学习系统之 128点阵型液晶显示篇 《电子制作》2008年2月 站长原创,如需引用请注明出处

大家好,通过以前的学习,我们已经对51单片机综合学习系统的使用方法及学习方式有所了解与熟悉,学会了1602字符型液晶显示的基本知识,体会到了综合学习系统的易用性与易学性,这一期我们将一起学习128点阵型液晶显示屏的基本原理与使用方法。 点阵LCD的显示原理

在数字电路中,所有的数据都是以0和1保存的,对LCD控制器进行不同的数据操作,可以得到不同的结果。对于显示英文操作,由于英文字母种类很少,只需要8位(一字节)即可。而对于中文,常用却有6000以上,于是我们的DOS前辈想了一个办法,就是将ASCII表的高128个很少用到的数值以两个为一组来表示汉字,即汉字的内码。而剩下的低128位则留给英文字符使用,即英文的内码。

那么,得到了汉字的内码后,还仅是一组数字,那又如何在屏幕上去显示呢?这就涉及到文字的字模,字模虽然也是一组数字,但它的意义却与数字的意义有了根本的变化,它是用数字的各位信息来记载英文或汉字的形状,如英文的'A'在字模的记载方式如图1所示:

图1 “A”字模图

而中文的“你”在字模中的记载却如图2所示:

图2 “你”字模图 128点阵型LCD简介

128是一种图形点阵液晶显示器,它主要由行驱动器/列驱动器及128×全点阵液晶显示器组成。可完成图形显示,也可以显示8×4个(16×16点阵)汉字。 管脚号 1 2 3 4

管脚名称 VSS VDD V0 D/I(RS)

LEVER 0 +5.0V - H/L

管脚功能描述 电源地 电源电压

液晶显示器驱动电压

D/I=“H”,表示DB7∽DB0为显示数据 D/I=“L”,表示DB7∽DB0为显示指令数据

5

R/W

H/L

R/W=“H”,E=“H”数据被读到DB7∽DB0 R/W=“L”,E=“H→L”数据被写到IR或DR

6

E

H/L

R/W=“L”,E信号下降沿锁存DB7∽DB0 R/W=“H”,E=“H”DDRAM数据读到DB7∽DB0

7 8 9 10 11 12 13 14 15 16 17

DB0 DB1 DB2 DB3 DB4 DB5 DB6 DB7 CS1 CS2 RET

H/L H/L H/L H/L H/L H/L H/L H/L H/L H/L H/L

数据线 数据线 数据线 数据线 数据线 数据线 数据线 数据线

H:选择芯片(右半屏)信号 H:选择芯片(左半屏)信号 复位信号,低电平复位

18 19 20

VOUT LED+ LED-

-10V - -

LCD驱动负电压 LED背光板电源 LED背光板电源

表1:128LCD的引脚说明

在使用128LCD前先必须了解以下功能器件才能进行编程。128内部功能器件及相关功能如下: 1. 指令寄存器(IR)

IR是用于寄存指令码,与数据寄存器数据相对应。当D/I=0时,在E信号下降沿的作用下,指令码写入IR。

2.数据寄存器(DR)

DR是用于寄存数据的,与指令寄存器寄存指令相对应。当D/I=1时,在下降沿作用下,图形显示数据写入DR,或在E信号高电平作用下由DR读到DB7∽DB0数据总线。DR和DDRAM之间的数据传输是模块内部自动执行的。 3.忙标志:BF

BF标志提供内部工作情况。BF=1表示模块在内部操作,此时模块不接受外部指令和数据。BF=0时,模块为准备状态,随时可接受外部指令和数据。

利用STATUS READ指令,可以将BF读到DB7总线,从检验模块之工作状态。 4.显示控制触发器DFF

此触发器是用于模块屏幕显示开和关的控制。DFF=1为开显示(DISPLAY OFF),DDRAM的内容就显示在屏幕上,DFF=0为关显示(DISPLAY OFF)。

DDF的状态是指令DISPLAY ON/OFF和RST信号控制的。 5.XY地址计数器

XY地址计数器是一个9位计数器。高3位是X地址计数器,低6位为Y地址计数器,XY地址计数器实际上是作为DDRAM的地址指针,X地址计数器为DDRAM的页指针,Y地址计数器为DDRAM的Y地址指针。 X地址计数器是没有记数功能的,只能用指令设置。

Y地址计数器具有循环记数功能,各显示数据写入后,Y地址自动加1,Y地址指针从0到63。 6.显示数据RAM(DDRAM)

DDRAM是存储图形显示数据的。数据为1表示显示选择,数据为0表示显示非选择。DDRAM与地址和显示位置的关系见DDRAM地址表。

7.Z地址计数器

Z地址计数器是一个6位计数器,此计数器具备循环记数功能,它是用于显示行扫描同步。当一行扫描完成,此地址计数器自动加1,指向下一行扫描数据,RST复位后Z地址计数器为0。

Z地址计数器可以用指令DISPLAY START LINE预置。因此,显示屏幕的起始行就由此指令控制,即DDRAM的数据从哪一行开始显示在屏幕的第一行。此模块的DDRAM共行,屏幕可以循环滚动显示行。 128LCD的指令系统及时序

该类液晶显示模块(即KS0108B及其兼容控制驱动器)的指令系统比较简单,总共只有七种。其指令表如表2所示: 指令名称 显示开关 显示起始行设置 页设置 列地址设置 读状态 写数据 读数据

控制信号 R/W 0 0 0 0 1 0 1

RS 0 0 0 0 0 1 1

控制代码 DB7 0 1 1 0

DB6 0 1 0 1

DB5 1 X 1 X

DB4 1 X 1 X

DB3 1 X 1 X 0

DB2 1 X X X 0

DB1 1 X X X 0

DB0 1/0 X X X 0

BUSY 0 写数据 读数据

ON/OFF RST

表2:128LCD指令表 各功能指令分别介绍如下。

R/WRS 00

显示开/关指令

DB7 DB6 DB5 DB4 DB3DB2DB1 DB0 00111111/0

当DB0=1时,LCD显示RAM中的内容;DB0=0时,关闭显示。 2、显示起始行(ROW)设置指令 R/WRS 00

DB7 DB6 DB5 DB4 DB3DB2DB1 DB0 11显示起始行(0~63)

该指令设置了对应液晶屏最上一行的显示RAM的行号,有规律地改变显示起始行,可以使LCD实现显示滚屏的效果。

3、页(PAGE)设置指令 R/WRS 00

DB7 DB6 DB5 DB4 DB3DB2DB1 DB0 10111页号(0~7)

显示RAM共行,分8页,每页8行。 4、列地址(Y Address)设置指令 R/WRS 00

DB7 DB6 DB5 DB4 DB3DB2DB1 DB0 01显示列地址(0~63)

设置了页地址和列地址,就唯一确定了显示RAM中的一个单元,这样MPU就可以 用读、写指令读出该单元中的内容或向该单元写进一个字节数据。 5、读状态指令 R/WRS 10

DB7 DB6 DB5 DB4 DB3DB2DB1 DB0 BUSY0ON/OFFREST0000

该指令用来查询液晶显示模块内部控制器的状态,各参量含义如下: BUSY:1-内部在工作0-正常状态 ON/OFF:1-显示关闭0-显示打开 RESET:1-复位状态0-正常状态

在BUSY和RESET状态时,除读状态指令外,其它指令均不对液晶显示模块产生作用。 在对液晶显示模块操作之前要查询BUSY状态,以确定是否可以对液晶显示模块进行操作。 6、写数据指令 R/WRS 01

DB7 DB6 DB5 DB4 DB3DB2DB1 DB0 写数据

R/WRS 11

读数据指令

DB7 DB6 DB5 DB4 DB3DB2DB1 DB0 读显示数据

读、写数据指令每执行完一次读、写操作,列地址就自动增一。必须注意的是,进行读操作之前,必须有一次空读操作,紧接着再读才会读出所要读的单元中的数据

128液晶原理分析1

专业—51单片机 2010-02-24 14:50:31 阅读154 评论4 字号:大中小

[转自本人QQ空间,发表于2009年08月19日 22:14 ]

辛勤学习了好几天,终于对128液晶有了些初步了解~没有视频教程学起来真有些累,基本上内部程序写入顺序都是根据程序自我变动,然后逆向反推出原理……

芯片:YM128R P-1 控制芯片:ST7920A 带中文字库

初步小结:

1、 控制芯片不同,寄存器定义会不同 2、 显示方式有并行和串行,程序不同 3、 含字库芯片显示字符时不必对字符取模了 4、 对芯片的结构地址一定要理解清楚

5、 显示汉字时液晶芯片写入数据的顺序(即显示的顺序)要清楚 6、 显示图片时液晶芯片写入数据的顺序(即显示的顺序)要清楚 7、 显示汉字时的二级单元(一级为八位数据写入单元)要清楚 8、 显示图片时的二级单元(一级为八位数据写入单元)要清楚

128点阵液晶显示模块(LCM)就是由128*个液晶显示点组成的一个128列*行的阵列。每个显示点对应一位二进制数,1表示亮,0表示灭。存储这些点阵信息的RAM称为显示数据存储器。要显

示某个图形或汉字就是将相应的点阵信息写入到相应的存储单元中。图形或汉字的点阵信息由自己设计,问题的关键就是显示点在液晶屏上的位置(行和列)与其在存储器中的地址之间的关系。由于多数液晶显

示模块的驱动电路是由一片行驱动器和两片列驱动器构成,所以128液晶屏实际上是由左右两块的*液晶屏拼接而成,每半屏有一个512*8 bits显示数据RAM。左右半屏驱动电路及存储器分别由片选信号CS1和CS2选择。显示点在*液晶屏上的位置由行号(line,0~63)与列号(column,0~63)确定。512*8 bits RAM中某个存储单元的地址由页地址(Xpage,0~7)和列地址(Yaddress,0~63)确定。

每个存储单元存储8个液晶点的显示信息。

为了使液晶点位置信息与存储地址的对应关系更直观关,将*液晶屏从上至下8等分为8个显示块,每块包括8行*列个点阵。每列中的8行点阵信息构成一个8bits二进制数,存储在一个存储单元中。(注

意:二进制的高低有效位顺序与行号对应关系因不同商家而不同)存放一个显示块的RAM区称为存储页。即*液晶屏的点阵信息存储在8个存储页中,每页个字节,每个字节存储一列(8行)点阵信息。因此存储单元地址包括页地址(Xpage,0~7)和列地址(Yaddress,0~63)。例如点亮128*的屏中(20,30)位置上的液晶点,因列地址30小于,该点在左半屏第29列,所以CS1有效;行地址20除以8取整得2,取余得4,该点在RAM中页地址为2,在字节中的序号为4;所以将二进制数据00010000(也可能是00001000,高低顺序取决于制造商)写入Xpage=2,Yaddress=29的存储单元中即点亮(20,30)上的液晶点。

芯片的结构一定要清楚!

点阵LCD的显示原理

在数字电路中,所有的数据都是以0和1保存的,对LCD控制器进行不同的数据操作,可以得到不同的结果。对于显示英文操作,由于英文字母种类很少,只需要8位(一字节)即可。而对于中文,常用却有6000以上,于是我们的DOS前辈想了一个办法,就是将ASCII表的高128个很少用到的数值以两个为一组来表示汉字,即汉字的内码。而剩下的低128位则留给英文字符使用,即英文的内码。

那么,得到了汉字的内码后,还仅是一组数字,那又如何在屏幕上去显示呢?这就涉及到文字的字模,字模虽然也是一组数字,但它的意义却与数字的意义有了根本的变化,它是用数字的各位信息来记载英文或汉字的形状,如英文的'A'在字模的记载方式如图1所示:

图1 “A”字模图

而中文的“你”在字模中的记载却如图2所示:

图2 “你”字模图

图3 图4 字符二级单元(图3中阴影部分)

一个汉字的二级单元是一个16*16的区域,因些128*液晶可以显示4行8列共32个汉字(如图3)。而它的一个二级单元如图4(在无字库时,对汉字的取模有横向跟纵向两种,要注意),对于并行含有子库芯片的显示,只要设定好这个二级单元的地址(如0X80+i,这样设定i的范围为0~31,这里注意第一行会直接跳到第三行;或者根据自己需要如第二行0X90+i,i范围为0~7;第三行0X88+i,i范围为0

~7;),然后直接把汉字写入就OK了~(串行无字符库的后面再做分析)

图5:垂直坐标:上半屏00~1F,总共为32 水平坐标:上半屏水平坐标分别为0X80+(00~07) 下半屏00~1F,总共为32 下半屏水平坐标分别为0X88+(00~07)

图片显示芯片结构分块与汉字显示不一样

图象显示过程是这样的:首先设置垂直地址,再设水平地址(连续写入两个字节的资料来完成垂直与水平的坐标地址,然后在每个地址里写入16位数据)。 垂直地址范围 AC5...AC0 水平地址范围 AC3…AC0

绘图RAM 的地址计数器(AC)只会对水平地址(X 轴)自动加一,当水平地址=0FH 时会重新设为00H

但并不会对垂直地址做进位自动加一,故当连续写入多笔资料时,程序需自行判断垂直地址是否需重新设定。GDRAM的坐标地址与资料排列顺序如图5:分上下屏写入。

for(i=0;i<32;i++) // 上半屏32个垂直地址 {

write_com(0x80 + i); // 垂直地址

write_com(0x80); // 水平地址 for(j=0;j<16;j++)

{ write_data(*adder); adder++;

}

}

带中文字库的128X显示模块时应注意以下几点:

①欲在某一个位置显示中文字符时,应先设定显示字符位置,即先设定显示地址,再写入中文字符编码。

②显示ASCII字符过程与显示中文字符过程相同。不过在显示连续字符时,只须设定一次显示地址,由模块自动对地址加1指向下一个字符位置,否则,显示的字符中将会有一个空ASCII字符位置。 ③当字符编码为2字节时,应先写入高位字节,再写入低位字节。

④模块在接收指令前,向处理器必须先确认模块内部处于非忙状态,即读取BF标志时BF需为“0”,方可接受新的指令。如果在送出一个指令前不检查BF标志,则在前一个指令和这个指令中间必须延迟一

段较长的时间,即等待前一个指令确定执行完成。指令执行的时间请参考指令表中的指令执行时间说明。⑤“RE”为基本指令集与扩充指令集的选择控制位。当变更“RE”后,以后的指令集将维持在最后的状态,除

非再次变更“RE”位,否则使用相同指令集时,无需每次均重设“RE”位。

程序———————并行(串行后面再分析)——————————————————————————

#include #include #include #include

#define uchar unsigned char #define uint unsigned int

uchar code LCD_data1[]; uchar code LCD_data2[]; uchar code LCD_picture1[]; uchar code LCD_picture2[];

sbit RS = P2^4; sbit RW = P2^5; sbit EN = P2^6; sbit PSB = P2^1; sbit RES = P2^3; sbit Dataport = P0; sbit Busyport = P0^7;

//////////////////////////////////////////////////////////////

void delay_ms(unsigned int n) //延时10×n毫秒程序 {

unsigned int i,j; for(i=0;ivoid delay(unsigned int m) //1US延时程序 {

unsigned int i,j; for(i=0;ifor(j=0;j<10;j++); }

/////////////////////////////////////////////////////////////// //判LCM忙子函数

void check_LCD_busy (void) {

Dataport = 0xff; RS = 0; RW = 1; EN = 1;

while (Busyport); EN = 0;

}

/////////////////////////////////////////////////////////////// //写命令子函数

void write_com(uchar Command) {

check_LCD_busy(); RW=0; RS=0; delay(1); P0=Command; EN=1; delay(1); EN=0; }

//////////////////////////////////////////////////////////////// //写数据子函数

void write_data(uchar Data) {

check_LCD_busy(); RW=0; RS=1; delay(1); P0=Data; EN=1;

delay(1); EN=0; }

///////////////////////////////////////////////////////////////// //LCM清屏函数

void lcdClear (void) {

write_com(0x01); }

//////////////////////////////////////////////////////////////// //LCM复位函数

void reset () {

RES=0; //复位 delay(1); //延时 RES=1; //复位置高 delay(10); }

/////////////////////////////////////////////////////////////// //显示汉字

void dispString (uchar X, Y,uchar *msg) //X为哪一行,Y为哪一列。msg为汉字 {

if(X==0) X = 0x80; //第一行,汉字显示坐标 else if(X==1) X = 0x90; //第二行 else if(X==2) X = 0x88; //第三行 else X = 0x98; //第四行

Y = X + Y; //Y为1往右移一位 write_com(Y); //写入坐标 while (*msg) {

write_data(*msg++); //显示汉字 } }

/////////////////////////////////////////////////////////////// //显示图象

void disppicture(uchar code *adder) {

uint i,j;

//*******显示上半屏内容设置

for(i=0;i<32;i++) // 上半屏32个列地址 {

write_com(0x80 + i); //SET 垂直地址 VERTICAL ADD write_com(0x80); //SET 水平地址 HORIZONTAL ADD for(j=0;j<16;j++) {

write_data(*adder); adder++; } }

//*******显示下半屏内容设置 for(i=0;i<32;i++) // {

write_com(0x80 + i); //SET 垂直地址 VERTICAL ADD write_com(0x88); //SET 水平地址 HORIZONTAL ADD for(j=0;j<16;j++) {

write_data(*adder); adder++; } } }

/////////////////////////////////////////////////////////////// //LCD字库初始化函数

void lcdinit_str(void) {

delay(40); //大于40MS的延时程序 PSB=1; //设置为8BIT并口工作模式 delay(1); //延时

reset(); //复位

write_com(0x30); //Extended Function Set :8BIT设置,RE=0: basic instruction set, G=0 :graphic display OFF

delay(100); //大于100uS的延时程序

write_com(0x30); //Function Set

delay(37); ////大于37uS的延时程序

write_com(0x08); //Display on Control delay(100); //大于100uS的延时程序

write_com(0x10); //Cursor Display Control光标设置 delay(100); //大于100uS的延时程序 write_com(0x0C); //Display Control,D=1,显示开 delay(100); //大于100uS的延时程序 write_com(0x01); //Display Clear delay(10); //大于10mS的延时程序

write_com(0x06); //Enry Mode Set,光标从右向左加1位移动 delay(100); //大于100uS的延时程序 }

////////////////////////////////////////////////////////////////// //LCD图片(扩展)初始化函数

void lcdinit_pic(void) {

delay(40); //大于40MS的延时程序 PSB=1; //设置为8BIT并口工作模式 delay(1); //延时 reset();

write_com(0x36); //Extended Function Set RE=1: extended instruction

delay(100); //大于100uS的延时程序

write_com(0x36); //Extended Function Set:RE=1: extended instruction set delay(37); ////大于37uS的延时程序

write_com(0x3E); //EXFUNCTION(DL=8BITS,RE=1,G=1) delay(100); //大于100uS的延时程序

write_com(0x01);

//CLEAR SCREEN

delay(100); //大于100uS的延时程序 }

/////////////////////////////////////////////////////////////////

void main() {

while(1)

{

lcdinit_str();

delay_ms(10); //此延时如果没有的话第一行会一直在第一列 dispString(0, 1,\"祖国江山好\"); delay_ms(10);

dispString(1, 1,\"爱情少不了\"); delay_ms(10);

dispString(2, 1,\"为了下一代\"); delay_ms(10);

dispString(3, 1,\"赶紧谈恋爱\"); delay_ms(200); delay_ms(200);

lcdClear();

delay_ms(10);

dispString(0, 1,\"大名吴建峰\"); delay_ms(10);

dispString(1, 1,\"性别为非女\"); delay_ms(10);

dispString(2, 1,\"芳龄二十二\"); delay_ms(10);

dispString(3, 1,\"海拔一百六\"); delay_ms(200); delay_ms(200);

lcdinit_pic();

lcdClear(); delay_ms(10);

disppicture(LCD_picture1); delay_ms(300); delay_ms(300); } }

图象代码库见最后!~

成果——————————————————————————————————

图形取模方法(转):

128*的像素能显示的内容就有限,也无法要求它能多清楚,如果将一个彩色的图片转换为单色位图,效果就更差了,个人不建议用它来显示彩色的图片,如果真要用128*的液晶显示,建议如下: 1.尽量选择颜色比较单一的图片,当然一种颜色的效果最好不过了; 2.图片不能选择的太大,要不缩小了就看不清楚了; 3.图片的调整可以这样(仅供参考):

1>调整图片的宽高比大致为2:1; 2>将图片缩小到128*像素; 3>保存为单色位图;

图片的大小缩放不太好操作,我通常是这样做的:你用画图程序打开你要显示的图片后,首先要操作的查看属性(点击菜单栏的图像->属性,单位选择为像素后,宽高值就出来了),比如:宽:603,高:444,这显然宽高比不是2:1,你就要调整了,444*2=888,现在为603,所以888/603=1.47,所以宽要放大为147%(点击菜单栏的图像->拉伸/扭曲,在拉伸里面的水平处改为147),现在就调整为2:1了;接下来就要将图片缩小到128*像素,先计算缩放的比例,128/888=0.144,所以相同的操作(点击菜单栏的图像->拉伸/扭曲,在拉伸里面的水平处改为14,垂直里面也要改为14);最后就是保存为单色位图(文

件->另存为->文件类型选择为:单色位图(.bmp))?试过颜色比较单一的,效果还可以,复杂的彩色图片效果就很不理想了... 说明:在调整图片的宽高比大致为2:1的过程中图片会被拉伸变形,不过缩小到128*像素后也不是太明显...

图片取模

图片代码——————————————————————————————————

uchar code LCD_picture1[]= {

0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00, 0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00, 0x03,0x00,0x07,0xEC,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x37,0x80, 0x03,0x00,0x00,0xEC,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x18,0x3F,0xC0, 0x03,0x00,0x0F,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x18,0x79,0x80, 0x03,0x00,0x0F,0x6B,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x18,0x7F,0x00, 0x1F,0xF4,0x01,0xE9,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xE0,0x18,0xFF,0x80, 0x1F,0xFC,0x00,0xFB,0x30,0x00,0x00,0x00,0x00,0x00,0x01,0xC6,0x70,0x1B,0x1E,0xC0, 0x03,0x38,0x01,0xB3,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x86,0x38,0xDB,0xFF,0xE0, 0x03,0x70,0x07,0x9E,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x26,0x18,0xDB,0x8C,0x70, 0x7F,0xFF,0x87,0x27,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x01,0xFF,0xFF,0xB8, 0x7F,0xFF,0x80,0x3F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x00,0x0C,0x18, 0x07,0x80,0x00,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0xFF,0xE0, 0x0F,0x00,0x00,0xFB,0x1F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xF0,0xFF,0xE0, 0x1F,0x30,0x01,0xCF,0xFF,0xFF,0x09,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0x0C,0x00, 0x3B,0x36,0x03,0x07,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xCC,0x00, 0x73,0x76,0x03,0x3F,0xFF,0xFF,0xF7,0x00,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xFC,0x00, 0x63,0xE6,0x00,0x3F,0xFF,0xFF,0xDC,0x80,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFC,0x00, 0x03,0xFE,0x00,0x7F,0xFF,0xFF,0xAF,0x60,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFC,0x00,

0x03,0xFE,0x00,0xFF,0xFF,0xFF,0xF5,0xC0,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFC,0x00, 0x00,0x00,0x01,0xFF,0xFF,0xFF,0x23,0x20,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFE,0x00, 0x00,0x00,0x03,0xFF,0x8F,0xE3,0xEC,0xA0,0x00,0x00,0x03,0xFF,0x1F,0xC7,0xFF,0x00, 0x00,0x00,0x03,0xFF,0x07,0xC1,0x92,0xC0,0x00,0x00,0x07,0xFE,0x0F,0x83,0xFF,0x80, 0x00,0x00,0x07,0xFF,0x03,0xC0,0xE9,0xC0,0x00,0x00,0x0F,0xFE,0x07,0x81,0xFF,0x80, 0x00,0x00,0x07,0xFE,0x03,0x80,0xED,0xE0,0x00,0x00,0x0F,0xFC,0x07,0x01,0xFF,0xC0, 0x00,0x00,0x0F,0xFE,0x1B,0xB0,0xDD,0xE0,0x00,0x00,0x1F,0xFC,0x37,0x61,0xFF,0xC0, 0x00,0x00,0x0F,0xFE,0x1B,0xB0,0xFF,0xE0,0x00,0x00,0x1F,0xFC,0x37,0x61,0xFF,0xC0, 0x00,0x00,0x0F,0xFE,0x1B,0xB0,0xFF,0xF0,0x00,0x00,0x1F,0xFC,0x37,0x61,0xFF,0xE0, 0x00,0x00,0x1F,0xFE,0x1B,0xB0,0xFF,0xF0,0x00,0x00,0x3F,0xFC,0x37,0x61,0xFF,0xE0, 0x00,0x00,0x1F,0xFF,0x03,0xC0,0xFF,0xF0,0x00,0x00,0x3F,0xFE,0x07,0x81,0xFF,0xE0, 0x00,0x00,0x1F,0xFF,0x07,0xC1,0xFF,0xF0,0x00,0x00,0x3F,0xFE,0x0F,0x83,0xFF,0xE0, 0x00,0x00,0x1F,0xFF,0x8C,0x63,0xFF,0xF0,0x00,0x00,0x3F,0xFF,0x1F,0xC7,0xFF,0xE0, 0x00,0x00,0x1F,0xDF,0xFC,0x7F,0xF7,0xF0,0x00,0x00,0x3F,0xFF,0xF0,0x7F,0xFF,0xE0, 0x00,0x00,0x1F,0x07,0xFF,0xFF,0xD1,0xF0,0x00,0x00,0x3F,0xFF,0xE0,0x3F,0xFF,0xE0, 0x00,0x00,0x1E,0x03,0xFF,0xFF,0x80,0xF0,0x00,0x00,0x3F,0xC0,0x00,0x00,0x07,0xE0, 0x00,0x00,0x1E,0x03,0xFE,0xFF,0xC0,0xF0,0x00,0x00,0x3F,0xE0,0x00,0x00,0x0F,0xE0, 0x00,0x00,0x0C,0x01,0xF8,0x3F,0x80,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xC0, 0x00,0x00,0x0E,0x03,0xF0,0x1F,0xC0,0xE0,0x00,0x00,0x1F,0xF0,0x0F,0xC0,0x1F,0xC0, 0x00,0x00,0x1E,0x03,0xF0,0x1F,0x80,0xE0,0x00,0x00,0x1F,0xFC,0x0B,0x40,0x7F,0xC0, 0x00,0x00,0x7F,0x1F,0xF0,0x1F,0xC3,0xE0,0x00,0x00,0xFF,0xFF,0x0B,0x41,0xFF,0xC0, 0x00,0x00,0xFF,0xFF,0xF0,0x1F,0xF7,0xF0,0x00,0x01,0xFF,0xFF,0xC0,0x0F,0xFF,0xF0, 0x00,0x01,0xFF,0xFF,0xF8,0x3F,0xFF,0xFC,0x00,0x03,0xFF,0xFF,0xF8,0x7F,0xFF,0xF8, 0x00,0x03,0xFE,0x7F,0xFE,0xFF,0xFF,0xFE,0x00,0x07,0xFC,0xFF,0xFF,0xFF,0xFF,0xFC, 0x00,0x07,0xFC,0x1F,0xFF,0xFF,0xF8,0xFE,0x00,0x0F,0xF8,0x3F,0xFF,0xFF,0xF1,0xFC, 0x00,0x0F,0xF8,0x07,0xFF,0xFF,0xE0,0xFF,0x00,0x1F,0xF0,0x0F,0xFF,0xFF,0xC0,0xFE, 0x00,0x0F,0xF8,0x00,0xFF,0xFF,0x00,0x7F,0x80,0x1F,0xF0,0x01,0xFF,0xFE,0x00,0xFF, 0x00,0x1F,0xF0,0x00,0x02,0x00,0x00,0x7F,0x80,0x3F,0xE0,0x00,0x00,0x00,0x00,0x7F, 0x00,0x1F,0xF0,0x00,0x00,0x00,0x00,0x3F,0xC0,0x3F,0xE0,0x00,0x00,0x00,0x00,0x7F, 0x00,0x3F,0xF0,0x00,0x00,0x00,0x00,0x3F,0xC0,0x7F,0xE0,0x00,0x00,0x00,0x00,0x7F, 0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x1F,0xE0,0x7F,0xC0,0x00,0x00,0x00,0x00,0x3F, 0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x1F,0xE0,0x7F,0xC0,0x00,0x00,0x00,0x00,0x3F, 0x00,0x7F,0xE0,0x01,0xC0,0xE0,0x00,0x1F,0xE0,0xFF,0xC0,0x00,0x70,0xE0,0x00,0x3F, 0x00,0x7F,0xE0,0x03,0xF3,0xF0,0x00,0x1F,0xE0,0xFF,0xC0,0x00,0xF9,0xF0,0x00,0x3F, 0x00,0x7F,0xE0,0x07,0xFF,0xF8,0x00,0x1F,0xE0,0xFF,0xC0,0x01,0xFF,0xF8,0x00,0x3F, 0x00,0x7F,0xE0,0x07,0xFF,0xF8,0x00,0x1F,0xE0,0xFF,0xC0,0x01,0xFF,0xF8,0x00,0x3F, 0x00,0x7C,0xE0,0x07,0xFF,0xF8,0x00,0x1B,0xE0,0xF9,0xC0,0x01,0xFF,0xF8,0x00,0x37, 0x00,0x38,0xF0,0x03,0xFF,0xF0,0x00,0x39,0xE0,0xF1,0xE0,0x00,0xFF,0xF0,0x00,0x73, 0x00,0x30,0x70,0x01,0xFF,0xE0,0x00,0x30,0xC0,0x60,0xE0,0x00,0x7F,0xE0,0x00,0x61, 0x00,0x00,0x78,0x00,0xFF,0xC0,0x00,0x30,0x00,0x00,0xF0,0x00,0x3F,0xC0,0x00,0x60, 0x00,0x00,0x38,0x00,0x7F,0x80,0x00,0x60,0x00,0x00,0x70,0x00,0x1F,0x80,0x00,0xC0, 0x00,0x00,0x1C,0x00,0x3F,0x00,0x00,0xC0,0x00,0x00,0x38,0x00,0x0F,0x00,0x01,0x80, 0x00,0x00,0x0E,0x00,0x1E,0x00,0x00,0x80,0x00,0x00,0x1C,0x00,0x06,0x00,0x01,0x00, 0x00,0x00,0x07,0x00,0x0C,0x00,0x01,0x80,0x00,0x00,0x0E,0x00,0x06,0x00,0x03,0x00, };

128液晶原理分析2

专业—51单片机 2010-02-24 14:58:05 阅读165 评论5 字号:大中小

[转自本人QQ空间 发表于2009年09月04日 21:52 ]

一、接口引脚(注意并口与串口)

二、接线方式

1、并口直接访问

2、并口间接访问

3、串口访问

三、文本(汉字,字符)输入

1、文本显示RAM(DDRAM)

文本显示RAM提供8个×4行的汉字空间,当写入文本显示RAM时,可以分别显示CGROM、HCGROM与CGRAM的字型;

根据汉字显示坐标可以很容易地显示汉字以及其它字符~

四、图象输入

1、绘图RAM(GDRAM)

绘图显示RAM提供128×8个字节的记忆空间,在更改绘图RAM时,先连续写入水平与垂直的坐标值,再写入两个字节的数据到绘图RAM,而地址计数器(AC)会对水平地址(X地址)自动加一,当水平地址为0XFH时会重新设为00H;不会对垂直地址做进位自动加1.。在写入绘图RAM的期间,绘图显示必须关闭,整个写入绘图RAM的步骤如下: 1、关闭绘图显示功能。

2、先将水平的位元组坐标(X)写入绘图RAM地址; 再将垂直的坐标(Y)写入绘图RAM地址; 将D15——D8写入到RAM中; 将D7——D0写入到RAM中; 打开绘图显示功能。

绘图显示的缓冲区对应分布请参考“GDRAM坐标”

GDRAM地址坐标 对于图象显示,这个地址表才是王道

水平方向X—以字节单位 (2字节16位) 垂直方向Y—以位为单位

屏幕分上下两屏,垂直坐标上下屏都为Y:00—1F(也即0X80+Y),以位为单位; 水平坐标上半屏为X1:00—07(也即0X80+X1);下半屏为X2:08—0F(也0X80+X2)

由图可以看到水平坐标一个单位是两字节(即16位D15~D0),X地址会自动加1,是直接加一个单位(即两字节16位),比如00—》01(也即0X80+00—》0X80+01),从第一行第一列跳到第一行第二列。

(1)、整屏图象显示 程序:

void disppicture(uchar code *adder) {

uint i,j;

//*******显示上半屏内容设置 for(i=0;i<32;i++) {

write_com(0x80 + i); // 垂直地址 VERTICAL ADD write_com(0x80); // 水平地址 HORIZONTAL ADD

for(j=0;j<16;j++) //X坐标方向以2字节为单位,Y坐标方向以1位为单位,先连续写入垂直与水平坐标,

{ //再写入两字节数据到GDRAM。这里是这样进行的:i=0时,j=0,1时,写入两字节到垂直(0X80+00)水平(0X80+00)这格(D15~D0)里;然后X坐标地址自增1,地址变为垂直(0X80+00)水平(0X80+01)这格,在j=2,3时写入两字节,………一直到垂直(0X80+00)水平(0X80+07)这格,在j=14,15时写入两字节,此时循环for(j=0;j<16;j++)结束跳出,刚好第一行128位写完数据;然后i++,开始写第二行… write_data(*adder); adder++; } }

//*******显示下半屏内容设置 for(i=0;i<32;i++) // {

write_com(0x80 + i); //SET 垂直地址 下半屏的垂直地址中上半屏一样是0X80+Y(Y:00~1F)

write_com(0x88); //SET 水平地址 下半屏的水平地址是从0X80+08=0X88开始的 for(j=0;j<16;j++) {

write_data(*adder); adder++; } } }

整屏图形: (2)分块图形显示 程序:

void anti_nor_pic (uchar cpl_sign,uchar menu_num) {

uchar i,j,x,y;

……

x=menu_num*3; // 计算图片显示坐标,由坐标图知图片0/1/2/3/4/5的X坐标分别 if(x>6) x--; //为0X80+(00,03, 06,08,0B,0E)

if(menu_num<3) y=16; //0、1、2号图片Y坐标起始为0X80+16(上半屏从上往下第16行) else y=8; //3、4、5号图片Y坐标起始为0X80+8(下半屏从上往下第8行) if(cpl_sign==1) display_cnasc(0x82,4,menu_cn[menu_num]); for(j=0;j<24;j++) //图片32*24(宽*高),即有24行 {

for(i=0;i<2;i++) //一张图片在X方向上占两个单位(一个单位即16位两字节)在写

{ //完一个单位后要向下一个单位写,因为这里不是全屏显示,要设定 wr_lcd(comm,0x34); //关闭绘图显示功能 wr_lcd(comm,0x80+y); //垂直地址

wr_lcd(comm,0x80+x+i); //水平地址,事实上这里i可以不要,因为水平地址会自动加1,

wr_lcd(comm,0x30); //但因为是分块,要有个for(i=0;i<2;i++)的循环。

if(cpl_sign==1) // 图片反选 {

wr_lcd(dat,~menu_pic[menu_num][j*4+i*2]); //写入一字节 wr_lcd(dat,~menu_pic[menu_num][j*4+i*2+1]); //再写入一字节 }

else // 正常显示 {

wr_lcd(dat,menu_pic[menu_num][j*4+i*2]); wr_lcd(dat,menu_pic[menu_num][j*4+i*2+1]); }

}

y++; //垂直地址要由软件设定自动加1

if(y==32&&menu_num<3) {x+=8;y=0;} // 上下屏切换。0/1/2三幅图Y坐标由16加了 } //16行,跳入下半屏,水平坐标X变成0X80+08,垂直坐标变成0X80+00 wr_lcd(comm,0x36); }

分块图形续……

(旁边还未处理)待

一、ST7920控制IC的LCD128实现反白显示

从使用手册上可知,扩展指令里的0x03+行号即可实现反白对应行。但是ST7920 控制器的128× 点阵液晶其实原理上等同256×32 点阵,第三行对应的DDRAM 地址紧接第一行;第四行对应的DDRAM 地址紧接第二行。所以128× 点阵的液晶执行反白功能时实用意义不大,因为用户对第一行执行反白显示操作时,第三行必然也反白显示;第二行反白,第四行也必然反白。

其实还是有办法做到单行反白的,解决方法就是混用图形显示和字符显示。其理论支持在于:在ST7920中,字符显示的DDRAM和图形的GDRAM是相互的,而最后显示到液晶上的结果,是两个RAM中数据的异或。

具体来说:假如某个点上,绘图RAM的没有绘图(数据为0),而字符RAM上有点阵(数据为1),那么异或的结果就是1,也就是说正常显示字符;当字符上RAM没有点阵的时候,异或的结果是0,自然也就不显示了。假如该点上绘图RAM绘图了(数据为1),当字符RAM上有点阵(数据为1时),异或的结果为0,效果就是反白显示;如果字符RAM没有点阵(数据为0时),异或结果为1,效果就

是显示绘图的背景。

所以,如果要在某个地方反白显示,那么就在该点绘图并且写字,如果要取消反白,就重新用全0擦掉那个地方的绘图!这样一来可以实现任何地方、任意大小的反白显示,反而比原指令中的单行反白的功能更好更强大。

二、对于整屏既有图象又有文本,则可以用两种方式实现:

1、 首先文本DDRAM写入要写的字符,其余全部空格(即0X00),然后再在没有字符的地方(即非点亮的晶格中,0X00)绘入图象。DDRAM与GDRAM异或后就可以整屏实现图象与文本。参见程序实

例1。

2、 首先图象GDRAM绘入要绘的图象,其余全部用con_disp()反白(或显示图象)函数(见程序实例1)写入0X00,然后再在没有图象的地方(即0X00)处写入文本。同样DDRAM与GDRAM异或后就可以整屏实现图象与文本。参见程序实例2.

注意:根据最后显示到液晶上的结果,是两个RAM中数据的异或结果,我们可以知道,con_disp()反白(或显示图象)函数只能对文本字符进行反白,而不能对图形进行反白,因为con_disp()反白(或显示图象)函数本身是一个绘图函数,数据是写到GDRAM中去,只能与DDRAM(文本)异或,而不能与GDRAM(图象)异或。那么图象如何反白呢?我们在绘入图象时可以用按位取反符号“~”,如write_data(~date),

这样就可以对你要绘入的图象进行取反了!如果用con_disp()反白(或显示图象)函数对GDRAM进行反白,就会出现重叠覆盖现象,如下图:

//////////////////////////////////////////////////

程序实例1:(con_disp()反白(或显示图象)函数)

。。。第一幅图被反白函数覆盖了

//反白或显示图片 参数格式:(H)8bit数据,(L)8bit数据,X0坐标(16bit),

Y0坐标(1bit),X坐标(16bit),Y坐标(1bit)*/

void con_disp (uchar data1,uchar data2,uchar x0,uchar y0,uchar xl,uchar yl) {

uchar i,j; for(j=0;jfor(i=0;iwrite_com(0x34); // 扩展功能 write_com(y0+j); // 写Y坐标 write_com(x0+i); // 写X坐标 write_com(0x30); // 普通功能 write_data(data1); write_data(data2); } }

write_com(0x36); // 开绘图显示 }

1、这个函数,X0,Y0是左上角坐标,X1,Y1分别是列数(水平坐标)和行数(垂直坐标)。因为水平坐标是以二字节(16位)为单位,一次性要写入两字节(data1,data2),因此如果要反白则(data1,data2都为0XFF),如果要绘图(data1,data2可以为其它,此绘图函数主要用来绘制导航标头的)。

2、写入资料到内部RAM(包括DDRAM、GDRAM等)是基本操作指令,因此之前 要写write_com(0X30); 写DDRAM地址是基本操作指令,因此之前要写write_com(0X30);

写GDRAM地址是扩展操作指令,因此之前要写write_com(0X34);(此时要关绘图显示),然后写完GDRAM数据,最后要开绘图显示write_com(0X36);

///////////////////////////////////////////////////////// 程序实例2:(先文本再绘图)

/////////////////////////////////////////////////////////// //图片菜单标头 void dis_title_pic() {

display_cnasc(0x80,\"〓〓\"); display_cnasc(0x82,\"调 整\");

display_cnasc(0x86,\"〓〓\"); //第一行为文本

display_cnasc(0x90,\" \"); //第二行空格(即0X00) display_cnasc(0x88,\" \"); //第三行空格(即0X00) display_cnasc(0x98,\" \"); //第四行空格(即0X00) }

void main() {

init_lcd();

dis_title_pic(); //首先显示图片菜单标头,即先全屏覆盖文本 for(d=0;d<6;d++) //然后再绘入六幅图片 {

if(d==0) disppicture(1,d); //disppicture()函数见个人资料128分析2

else disppicture(0,d); } }

//////////////////////////////////////////// 程序实例3:(先绘图再文本) ///////////////////////////////////////////// //图片菜单标头 void dis_title_pic() {

display_cnasc(0x80,\"〓〓\");

~~~

display_cnasc(0x82,\"调 整\"); display_cnasc(0x86,\"〓〓\"); }

void main() {

Init_lcd();

for(d=0;d<6;d++) //绘入图象 {

if(d==0) disppicture(1,d); //第一幅图反白 else disppicture(0,d); //其余不反白 }

con_disp(0x00,0x00,0X80,0x80,8,16);

con_disp(0x00,0x00,0X82,0x80+16,1,16); con_disp(0x00,0x00,0X85,0x80+16,1,16); con_disp(0x00,0x00,0X8a,0x80,1,32); con_disp(0x00,0x00,0X8d,0x80,1,32);

dis_title_pic(); //写入文本

}

~~~

/////////////////////////////////////////////

程序实例4: 对于for(d=0;d<6;d++),我想也可以一个一个拆出来写,试验下反白结果

void dis_title_pic() {

display_cnasc(0x80,\"〓〓\"); display_cnasc(0x82,\"调 整\"); display_cnasc(0x86,\"〓〓\"); }

void main() {

init_lcd();

disppicture(1,0); //第一幅图反白显示 disppicture(0,1); //第二幅图正常显示 disppicture(1,2); //第三幅图反白显示 disppicture(0,3); //第四幅图正常显示

disppicture(1,4); //第五幅图反白显示

disppicture(0,5); //第六幅图正常显示

con_disp(0x00,0x00,0X80,0x80,8,16); //GDRAM其余地方写入0X00 con_disp(0x00,0x00,0X82,0x80+16,1,16); con_disp(0x00,0x00,0X85,0x80+16,1,16); con_disp(0x00,0x00,0X8a,0x80,1,32); con_disp(0x00,0x00,0X8d,0x80,1,32);

dis_title_pic(); //写入文本 }

~~1、3、5图反白显示~

至此,通过以上绘图原理以、反白原理和四个例程,就可以在128液晶上任何位置显示图象或文本,可以随意对液晶上任意块块进行反白显示,所以,可以通过128液晶完成类似MP3显示屏上的各种操作:

进入菜单页面,通过按键选择,被选择的模块反白,若MEU键按下刚进入此菜单(比如时钟)下面的页面,然后再进行各种设置……

当然,还有很多问题尚未解决,其中一个:就是单单写入文本(不占全屏),不出现花屏;而单单绘入图象(不占全屏)时,就会出现花屏,见下图……(可能是:绘图GDRAM要写入全屏数据,若只有部分数据,则其余地方芯片不知道写入什么就会随机写入,然后出现花屏;而文本DDRAM本身芯片已经有了一个分块控制。而128液晶不同的控制芯片具体情况不一样),当然我还不确定,有待以后继续分析……

~~

那么右边这块没有花屏的显示是根据程序实例2,3作出来的,运用GDRAM与DDRAM相异或原理,就是把左边花屏处用con_disp()反白(或显示图象)函数全部绘0X00.~~~

……好吧,暂时告一段落先……理解到这程度已经死了好大一批脑细胞了……

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 7swz.com 版权所有 赣ICP备2024042798号-8

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务