LCD1602的简单使用原理跟大家分享我学习1602的总结与体会.docx
《LCD1602的简单使用原理跟大家分享我学习1602的总结与体会.docx》由会员分享,可在线阅读,更多相关《LCD1602的简单使用原理跟大家分享我学习1602的总结与体会.docx(13页珍藏版)》请在冰点文库上搜索。
LCD1602的简单使用原理跟大家分享我学习1602的总结与体会
LCD1602的简单使用原理——跟大家分享我学习1602的总结与体会
我的总结主要分为这几部分:
①LCD1602的硬件特性及引脚功能
②LCD1602的时序特性
③LCD1602的使用原理(包括带字库和不带字库的简要使用方法,控制显示指令)
④基于FPGA的LCD1602使用案例
Part1.LCD1602的硬件特性及引脚功能
LCD1602顾名思义是一种02*16,即为两行十六列的液晶显示屏,液晶两行,每行可以显示16个字符,但是CGRAM及CGROM里面一共有160个字符,包括阿拉伯数字,英文字母大小写,常用符号及日文。
每个字符对应于一个ASCII码值,在液晶显示屏上显示对应的字符时候,只需要将对应的ASCII码写到DDRAM中就好,详细的步骤会在下面细说。
液晶板上排列着5*8的字符点阵,8行,每行5个点位,高电平1就是该点显示,低电平0就是该点不显示。
1、引脚功能:
RS,R/W,E控制数据端口DB0~DB7,数据的命令的读写由控制端口控制,并通过数据端口传输。
端口其他特性这里不再赘述,详细见1602液晶手册。
O(∩_∩)O
二、硬件特性:
①CGRAM和CGROM
CGRAM:
charactergeneratorramCGROM:
charactergeneratorrom
CGRAM的地址空间:
CGRAM的地址是0x40~0x7F,64个地址空间,每个地址双字节,一共128字节,一个字符是8个字节,所以一共能显示8个自定义字符(每个双字节地址只有一个字节是被自定义字符数据写入的,另外个字节无效,因为CGARM的字符代码的规定,详细原因见下面)
字符对应的区位码如下图所示:
CGRAM:
字符产生ram,用来存放用户自定义的字符,如上图的两条
(1)~(8),区位码为0x00~0x0F.0x00~0x07对应于
(1)~(8);0x08~0x0F对应于下一条
(1)~(8),虽然看起来有16个地址,但是其实只要8个地址可用,CGRAM的“字符码”规定0~2为地址,3位无效,4~7位全为0,因此CGRAM的字符码等效为0000X111,X为无效位,最后三位的地址只要八个,所以实际能用的只有8个。
其他为CGROM中自带的字符,区位码从0x21~0x7F,以各自的ASCII码作为区位码表示的基本字符。
将自定义的字符字模数8*8据写入,字符数据有八行,每行八位点阵。
②DDRAM
DDRAM:
datadisplayram数据显示存储器
DDRAM的地址空间与屏幕的对应关系如下图:
DDRAM的地址空间一共有80字节
在1602中,我们只要前面16行就行,其地址和屏幕的对应关系:
Part2.LCD1602的时序特性
读状态:
RS=0,RW=1,E=1
读数据:
RS=1,RW=1,E=1
写命令:
RS=0,RW=0,E=下降沿脉冲;DB0~DB7指令字
写数据:
RS=1,RW=0,E=下降沿脉冲;DB0~DB7数据
在E=1的时候写入数据,在数据写完之后,E来一个下降沿,把数据送到LCD。
1602的指令功能
1、DisplayClear清屏指令设置
<1>cursormovetofirstdigit
<2>地址计数器AC的值设置为0;
2、ReturnHome光标归位
<1>把光标撤回到显示器的左上方
<2>把地址计数器Ac设置为0;
<3>保持DDRAM的值不变
3、EntryModeset输入模式设置指令
Function:
I/DsetcursormovedirectionH:
increaseL:
decrease
写入数据之后的光标移动的方向H:
右移L:
左移
SspecifiesshiftofdisplayH:
displayisshiftedL:
displayisnotshifted
写入一个数据之后显示屏移动或者不移动
4、DisplayOn/off显示开关控制指令
D:
H:
显示开;L:
显示关
C:
H:
光标开L:
光标关
B:
H:
光标闪烁L:
光标不闪烁
5、Shift设置显示屏或者光标移动的方向
S/C:
显示屏还是光标H:
显示屏移动L:
光标移动
R/L:
向左移动还是向右移动H:
右移L;左移(光标右移:
AC值加1;光标左移:
AC值减1)
6、SetFunction
DL:
datalength L:
数据总线为4位H:
数据总线为8位
N :
numberline L:
1行显示H:
2行显示
F:
L:
5×7点阵/每字符 H:
5×10点阵/每字符
7、SetCGRAMAddress
设置CGRAM的地址,我们将我们自定义的字模数据存入对应的地址,从0x40~0x7F,128字节,8个字符的字模数据可存入。
8、SetDDRAMAddress,(表格中写错了,是DDRAM)
与CGRAM一样,在往DDRAM里面写入想要显示的字符的字符区位码的之前需要将存储字符区位码的地址首先写入。
DDRAM的地址空间以上已述。
(加地址的时候我们要加上0x80,因为写入地址的时候DB7必须为1)
9、ReadBusyFlagandtheAddress读取忙碌标志和地址计数器的值
BF:
H:
忙碌,表示无法结束单片机送来的数据;L:
准备就绪,可以接受数据
当内部操作正在进行的时候,读取BF的值
AC:
读取地址计数器的值
10、数据写入CGRAM和DDRAM
11、从CGRAM和DDRAM读取数据
1602的简要原理
显示字库中本来就有的字符和显示自定义的字符
1、显示字库中本来就有的字符
步骤一:
系统初始化和LCD初始化
步骤二:
LCD液晶屏上面每个字符对应于DDRAm的地址,你想要把字符写进屏幕哪个位置,就往DDRAM写入该位置所对应的地址。
(对应的地址在上述已说)
步骤三:
字库中本来已经存在的字符各自有对应的字符区位码,其实就是每个字符对应的ASCII码(见字符表格)。
你要显示哪个字符,只要将该字符对应的ASCII码写入DDRAM就搞定了,这个是很简单的。
2、显示自定义的字符
其实显示自定义的字符和字库字符差不多的,只需要将你自定义的字符用取模工具得到字模的数组数据之后。
之后的步骤和显示字库字符是一样一样滴。
步骤一:
系统初始化和LCD初始化
步骤二:
搞清楚字符点阵的格式是5*8,通过取字模工具得出自定义字符的字模数据,再写入相应的CGRAM地址,一个地址写入一个一个字节数据(一个字节的8位,前3位为0,点阵的格式5*8)
步骤三:
同显示字库中本来就有的字符一样的做法
Part6.基于FPGA的LCD1602使用案例
以下的程序例子是基于FPGA的液晶1602时钟,是利用自带字库的方式显示实时时钟,主要通过时钟控制状态机来实现1602的工作程序(尚未验证嘿嘿)
libraryieee;
use_logic_;
use_logic_;
use_logic_;
entitylcdis
port(
clk:
instd_logic;
rw:
outstd_logic;
rs:
outstd_logic;
lcd_rst:
outstd_logic;
data:
outstd_logic_vector(7downto0);
en:
outstd_logic
);
endlcd;
architecturelcd1602oflcdis
signalclk_1m:
std_logic:
='1';
signalclk_1s:
std_logic:
='1';
typestateis(s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10);--定义状态类型case语句上有具体说明
signalcurrent_s:
state:
=s0;
typedata_bufferisarray(0to9)ofstd_logic_vector(7downto0);---定义数组类型
signal
date_buf:
data_buffer:
=(x"30",x"31",x"3a",x"33",x"34",x"3a",x"36",x"37",x"2a",x"2a");
signalshi,fen,miao:
integerrange0to100:
=0;
signalshi1,fen1,miao1:
integerrange0to100:
=0;
begin
process(clk)---对CLK50M进行分频系数为50的分频clk_1m
variablecnt:
integerrange0to10000;---得到1M的时钟
begin
ifclk'eventandclk='1'then
ifcnt=24then
clk_1m<=notclk_1m;cnt:
=0;
elsecnt:
=cnt+1;
endif;
endif;
endprocess;
process(clk)
variablecnt:
integerrange0to10000;
variablecnt1:
integerrange0to5000;
begin
ifclk'eventandclk='1'then
ifcnt=then---cnt:
0~counter
clk_1s<=notclk_1s;cnt:
=0;------fenpinclk_1s
elsifcnt1=2000thencnt:
=cnt+1;cnt1:
=0;---cnt1:
0~2000counter
elsecnt1:
=cnt1+1;
endif;
endif;
endprocess;
process(clk_1s)
begin
ifclk_1s'eventandclk_1s='1'then
ifmiao=59then
miao<=0;
iffen=59then
fen<=0;
ifshi=23then
shi<=0;
elseshi<=shi+1;
endif;
elsefen<=fen+1;
endif;
elsemiao<=miao+1;
endif;
endif;
date_buf(0)<=conv_std_logic_vector(shi/10,8)+x"30";--强制转换逻辑矢量,8bit
date_buf
(1)<=conv_std_logic_vector(shimod10,8)+x"30";
date_buf(3)<=conv_std_logic_vector(fen/10,8)+x"30";
date_buf(4)<=conv_std_logic_vector(fenmod10,8)+x"30";
date_buf(6)<=conv_std_logic_vector(miao/10,8)+x"30";
date_buf(7)<=conv_std_logic_vector(miaomod10,8)+x"30";
endprocess;
process(clk_1m,current_s,date_buf)
variablei:
integerrange0to11:
=0;
variablecnt1:
integerrange0to100;
variablecnt2:
integerrange0to100;
variablecnt3:
integerrange0to100;
variablecnt4:
integerrange0to100;
variablecnt5:
integerrange0to100;
variablecnt6:
integerrange0to100;
variablecnt7:
integerrange0to100;
variablecnt8:
integerrange0to60000;
begin
current_s<=s0;
if(clk_1m'eventandclk_1m='1')then
current_s<=current_s;
casecurrent_sis
whens0=>
ifcnt1<5000then
lcd_rst<='0';cnt1:
=cnt1+1;
elsifcnt1<10000then
lcd_rst<='1';cnt1:
=cnt1+1;
elsifcnt1=10000thenlcd_rst<='1';current_s<=s1;cnt1:
=0;
endif;
whens1=>cnt2:
=cnt2+1;----设置功能指令字:
8位数据总线,两行显示,5*7点阵
ifcnt2<10thenrw<='0';rs<='0';----command0
elsifcnt2<20thendata<=x"38";
elsifcnt2<30thenen<='1';
elsifcnt2<70thenen<='0';
elsifcnt2=100thencnt2:
=0;current_s<=s2;
endif;
whens2=>----显示开关控制指令:
D显示开,C光标开,B光标闪烁
cnt3:
=cnt3+1;
ifcnt3<10thenrw<='0';rs<='0';
elsifcnt3<20thendata<=x"0f";----
elsifcnt3<30thenen<='1';
elsifcnt3<70thenen<='0';
elsifcnt3=100thencnt3:
=0;current_s<=s3;
endif;
whens3=>-----输入模式设置指令,写入一个字符后光标右移,显示屏不
cnt4:
=cnt4+1;-----移动
ifcnt4<10thenrw<='0';rs<='0';
elsifcnt4<20thendata<=x"06";---
elsifcnt4<30thenen<='1';
elsifcnt4<70thenen<='0';
elsifcnt4=100thencnt4:
=0;current_s<=s5;
endif;
whens4=>-----displayclear显示清屏
cnt5:
=cnt5+1;
ifcnt5<10thenrw<='0';rs<='0';
elsifcnt5<20thendata<=x"01";---
elsifcnt5<30thenen<='1';
elsifcnt5<70thenen<='0';
elsifcnt5=100thencnt5:
=0;current_s<=s5;
endif;
whens5=>-----写DDRAM地址0X00+0X80
cnt6:
=cnt6+1;
ifcnt6<10thenrw<='0';rs<='0';
elsifcnt6<20thendata<=x"80";---
elsifcnt6<30thenen<='1';
elsifcnt6<70thenen<='0';
elsifcnt6=100thencnt6:
=0;current_s<=s6;
endif;
whens6=>
cnt7:
=cnt7+1;
ifcnt7<10thenrw<='0';rs<='1';----WRITEDATA
elsifcnt7<20thendata<=date_buf(i);--date_buf(i);时分秒的数据的ASCII码
elsifcnt7<30thenen<='1';---执行时间为40us
elsifcnt7<70thenen<='0';
elsifcnt7=100then
ifi=9thencnt7:
=0;current_s<=s7;i:
=0;
elsei:
=i+1;current_s<=s6;cnt7:
=0;endif;
endif;
whens7=>ifcnt8<8000thencnt8:
=cnt8+1;
elsecnt8:
=0;current_s<=s5;----循环等待8000的计数器,回到S5,继续写入DDRAM地------址,进而
endif;-------------------------写入数据
whenothers=>null;
endcase;
endif;
endprocess;
endlcd1602;
LCD1602总结
漫WU雪飞
如有错误不妥的地方请欢迎纠正,XXID:
漫WU雪飞
祝您幸福~~~~,O(∩_∩)O~