内容包括液晶屏常识,12864液晶显示原理,点阵型LCD文字与图形软硬件设计实例。紫色文字是超链接,点击自动跳转至相关博文。持续更新,原创不易!
目录:
一、12864液晶显示原理
1、点阵LCD的显示原理
2、12864点阵型LCD简介
3、12864LCD的指令系统及时序
4、12864点阵型LCD软硬件设计实例
1)硬件原理图 2)程序流程图 3)字模代码
5、12864点阵型LCD应用举例
1)硬件部分 2)软件部分(常用数据类型内存存储形式)
二、12864液晶显示任何图像
1、所需软件
2、DIY一副图画
3、C语言代码
附录
1、机内码和区位码的区别
2、液晶屏常识
1)什么是COG型LCD
2)LCD显示模块的外部接口
(1)8080模式,并行 (2)6800模式,并行 (3)串行模式
------------------------------------------------------------------------------------------------------------------------
一、12864液晶显示原理
1、点阵LCD的显示原理
在数字电路中,所有的数据都是以0和1保存的,对LCD控制器进行不同的数据操作,可以得到不同的结果。对于显示英文操作,由于英文字母种类很少,只需要8位(一字节)即可。而对于中文,常用却有6000以上,于是我们的DOS前辈想了一个办法,就是将ASCII表的高128个很少用到的数值以两个为一组来表示汉字,即汉字的内码(汉字ASCII码)。而剩下的低128位则留给英文字符使用,即英文的内码。机内码和区位码的区别见附录。
那么,得到了汉字的内码后,还仅是一组数字,那又如何在屏幕上去显示呢?这就涉及到文字的字模,字模虽然也是一组数字,但它的意义却与数字的意义有了根本的变化,它是用数字的各位信息来记载英文或汉字的形状,如英文的'A'在字模的记载方式如图1所示:
图1 “A”字模图
而中文的“你”在字模中的记载却如图2所示:
图2 “你”字模图
如果需要反白只要取反“位代码”即可。
------------------------------------------------------------
2、12864点阵型LCD简介
12864是一种图形点阵液晶显示器,它主要由行驱动器/列驱动器及128*64全点阵液晶显示器组成。可完成图形显示,也可以显示8*4个(16*16点阵)汉字。
管脚号 | 管脚名称 | LEVER | 管脚功能描述 |
1 | VSS | 0 | 电源地 |
2 | VDD | +5.0V | 电源电压 |
3 | V0 | - | 液晶显示器驱动电压 |
4 | D/I(RS) | H/L | D/I=“H”,表示DB7~DB0为显示数据 |
D/I=“L”,表示DB7~DB0为显示指令数据 | |||
5 | R/W | H/L | R/W=“H”,E=“H”数据被读到DB7DB0 |
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 | DB0 | H/L | 数据线 |
8 | DB1 | H/L | 数据线 |
9 | DB2 | H/L | 数据线 |
10 | DB3 | H/L | 数据线 |
11 | DB4 | H/L | 数据线 |
12 | DB5 | H/L | 数据线 |
13 | DB6 | H/L | 数据线 |
14 | DB7 | H/L | 数据线 |
15 | CS1 | H/L | H:选择芯片(右半屏)信号 |
16 | CS2 | H/L | H:选择芯片(左半屏)信号 |
17 | RET | H/L | 复位信号,低电平复位 |
18 | VOUT | -10V | LCD驱动负电压 |
19 | LED+ | - | LED背光板电源 |
20 | LED- | - | LED背光板电源 |
表1:12864LCD的引脚说明
在使用12864LCD前先必须了解以下功能器件才能进行编程。12864内部功能器件及相关功能如下:
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 ON),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共64行,屏幕可以循环滚动显示64行。
------------------------------------------------------------
3、12864LCD的指令系统及时序
该类液晶显示模块(即KS0108B及其兼容控制驱动器)的指令系统比较简单,总共只有七种。其指令表如表2所示:
指令名称 | 控制信号 | 控制代码 | ||||||||
R/W | RS | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 | |
显示开关 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1/0 |
显示起始行设置 | 0 | 0 | 1 | 1 | X | X | X | X | X | X |
页设置 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | X | X | X |
列地址设置 | 0 | 0 | 0 | 1 | X | X | X | X | X | X |
读状态 | 1 | 0 | BUSY | 0 | ON/OFF | RST | 0 | 0 | 0 | 0 |
写数据 | 0 | 1 | 写数据 | |||||||
读数据 | 1 | 1 | 读数据 |
表2:12864LCD指令表
各功能指令分别介绍如下。
- 1)显示开/关指令
R/WRS | DB7 DB6 DB5 DB4 DB3DB2DB1 DB0 |
00 | 00111111/0 |
当DB0=1时,LCD显示RAM中的内容;DB0=0时,关闭显示。
2)显示起始行(ROW)设置指令
R/WRS | DB7 DB6 DB5 DB4 DB3DB2DB1 DB0 |
00 | 11显示起始行(0~63) |
该指令设置了对应液晶屏最上一行的显示RAM的行号,有规律地改变显示起始行,可以使LCD实现显示滚屏的效果。
3)页(PAGE)设置指令
R/WRS | DB7 DB6 DB5 DB4 DB3DB2DB1 DB0 |
00 | 10111页号(0~7) |
显示RAM共64行,分8页,每页8行。
4)列地址(Y Address)设置指令
R/WRS | DB7 DB6 DB5 DB4 DB3DB2DB1 DB0 |
00 | 01显示列地址(0~63) |
设置了页地址和列地址,就唯一确定了显示RAM中的一个单元,这样MPU就可以用读、写指令读出该单元中的内容或向该单元写进一个字节数据。
5)读状态指令
R/WRS | DB7 DB6 DB5 DB4 DB3DB2DB1 DB0 |
10 | BUSY0ON/OFFREST0000 |
该指令用来查询液晶显示模块内部控制器的状态,各参量含义如下:
BUSY: 1-内部在工作,0-正常状态
ON/OFF:1-显示关,0-显示打开
RESET: 1-复位状态,0-正常状态
在BUSY和RESET状态时,除读状态指令外,其它指令均不对液晶显示模块产生作用。
在对液晶显示模块操作之前要查询BUSY状态,以确定是否可以对液晶显示模块进行操作。
6)写数据指令
R/WRS | DB7 DB6 DB5 DB4 DB3DB2DB1 DB0 |
01 | 写数据 |
- 7)读数据指令
R/WRS | DB7 DB6 DB5 DB4 DB3DB2DB1 DB0 |
11 | 读显示数据 |
读、写数据指令每执行完一次读、写操作,列地址就自动增一。必须注意的是,进行读操作之前,必须有一次空读操作,紧接着再读才会读出所要读的单元中的数据。
------------------------------------------------------------
4、12864点阵型LCD软硬件设计实例
通过以上学习,现在就来实际应用12864LCD的软硬件设计。本实例将在LCD上显示如图3所示内容:
图3 模拟显示效果图
在调试前先将显示切换开关切换到LCD显示状态。
图4 128*64LCD实验演示图
---------------------------------
1)硬件原理图
图5 硬件原理图
---------------------------------
2)程序流程图
图6 软件流程图
---------------------------------
3)字模代码
(1)选择小四号字体(12号):宽*高=16*16(横向16点,竖向16点)。
在编写软件代码之前必须要先掌握汉字取模的方法。要得到上表中的文字,可以借助取模软件来完成。目前点阵LCD的取模软件有很多,本处使用的软件移步:https://download.csdn.net/download/liht_1634/85095577。
打开取模软件出现如下显示界面:
在文字输入区中输入文字,我们以输入一个欢迎的“欢”字为例,了解其取模过程。在文字输入区中输入“欢”后按CTRL+ENTER组合键后就看到“欢”字已经在模拟显示区显示出来了。
在“取模方式”中选择“C51格式”就可以在“点阵生成区”得到你要的汉字“欢”的显示代码。
经过以上步骤后一个汉字就取模成功了,在程序中只要调用这段代码就可显示出汉字“欢”了,其它汉字也用同样的方法。取完要显示的全部汉字代码后我们就可以编程了。
------------------
(2)选择五号字体(11号):横向取模16*14,纵向取模14*16。
横向取模:
0001 0010,0000 0000 0x12,0x00
0001 0010,0000 0000 0x12,0x00
0001 0111,1111 1000 0x17,0xF8
0010 0100,0000 1000 0x24,0x08
横向取模,字节倒序,所得点阵数据如下:
即对上面“横向取模,字节正序”的每一字节倒过来,即:
0100 1000,0000 0000 0x48,0x00
0100 1000,0000 0000 0x48,0x00
1110 1000,0001 1111 0xE8,0x1F
0010 0100,0001 0000 0x24,0x10
纵向取模:
0000 0010,0000 0100 0x02,0x04
0001 1111,0111 0000 0x1F,0xE0
1110 0001,0010 0000 0x08,0x30
0010 0111,0010 0111 0xE1,0x20
纵向取模,字节倒序,所得点阵数据如下:
即对上面“纵向取模,字节正序”的每一字节倒过来,即:
0100 0000,0010 0000
1111 1000,0000 0111
0010 0000,0000 1100
1000 0111,0000 0100
------------------------------------------------------------
5、12864点阵型LCD应用举例
1)硬件部分
1.1 整体电路
一块驱动器控制64*64个点,左右显示,这就是为什么引脚有CS1和CS2的原因。
1.2 原件列表
---------------------------------
2)软件部分(常用数据类型内存存储形式)
汉字在内存中的存储形式见“7、使用C-Free查看数据在内存中的存储”。
2.1 程序架构
2.2 主程序
#include "includes.h"
void main()
{
lcd_init(); //初始化
lcd_clear(0); //清屏
lcd_set_line(0); //设置起始行为0
display(1,2,2*16,jiao); //交
display(1,2,3*16,liu); //流
display(2,2,4*16,shi); //使
display(2,2,5*16,yong); //用
while(1);
}
2.3 LCD12864驱动程序
#include "lcd.h>"
#include "intrins.h"
#define lcd_databus P2 //LCD的8位数据总线
void lcd_r_busy()
{
P2=0x00;
RS=0;
RW=1;
EN=1;
while(P2&0x80);
EN=0;
}
void lcd_w_cmd(uchar value)
{
lcd_r_busy(); //每次读写操作前都要忙判断
RS=0;
RW=0;
lcd_databus=value;
EN=1; //下降沿锁存写入的数据/命令
_nop_();
_nop_();
EN=0;
}
void lcd_w_data(uchar value)
{
lcd_r_busy();
RS=1;
RW=0;
lcd_databus=value;
EN=1; //下降沿锁存写入的数据/命令
_nop_();
_nop_();
EN=0;
}
void lcd_set_page(uchar page)
{
page=0xb8 | page; //页的首地址为0xb8:page或上0xb8=选择page页
lcd_w_cmd(page);
}
void lcd_set_line(uchar sline)
{
sline=0xc0 | sline; //起始行地址为0xc0:sline或上0xc0=选择行
lcd_w_cmd(sline);
}
void lcd_set_column(uchar column)
{
column=0x3f & column; //与上列的最大值63:0x3f 可得所选列值<63
column=0x40 | column; //得列的首地址
lcd_w_cmd(column);
}
void lcd_on_off(uchar set)
{
set=0x3e | set; //=0011 111x----0x3e为关闭显示;0x3f为开启显示
lcd_w_cmd(set);
}
void lcd_cs(uchar sel)
{
switch(sel)
{
case 0:CS1=0; CS2=0; break; //全屏显示
case 1:CS1=0; CS2=1; break; //左显示
case 2:CS1=1; CS2=0; break; //右显示
default:break;
}
}
void lcd_clear(uchar sel)
{
uchar i,j;
lcd_cs(sel);
for(i=0;i<8;i++)
{
lcd_set_page(i);
lcd_set_column(0);
for(j=0;j<64;j++)
{
lcd_w_data(0x00); //每列全部写0,列地址指针自动+1
}
}
}
void lcd_init()
{
lcd_r_busy();
lcd_cs(0);
lcd_on_off(0); //关显示
lcd_cs(0);
lcd_on_off(1); //开显示
lcd_cs(0);
lcd_clear(0); //清全屏
lcd_set_line(0); //起始行设为0
}
void display(uchar cs, uchar page, uchar column, uchar *p)
{
uchar i;
lcd_cs(cs);
lcd_set_page(page); //要在本页写上半个汉字8*16
lcd_set_column(column); //选