little_bee 发表于 2009-6-27 20:17:59

1602LCM的使用经历----初学者独白

很多人都有谈到1602 LCM的使用方法,但站在一个初学者的角度来说,除了这些方法,还有很多初学者需要知道的,比如你当时的一些想法及其它的一些细节。我是一个AVR的初学者,也是偶然进入马老师专栏后,看到有足够的技术支持之后才开始学AVR的(之前本来想学PIC)。
   我的学习环境很简单:电脑一台:通过关系把公司的一块坏主板拿回家修好(其实是看到了主板的5,6个电解电容账了觉得还有得救,果然一换了就好了),显视器也是七拼八凑的(LCD屏+别人给的底座+直接从主机上接12V电源供电).
         从 www.iccavr.com上购的"AVR仿真器AVR下载线二合一工具"(365元) ,M16贴片封装1PCS(13元,本来要的是DIP的,他寄错了,只能自已腐蚀PCB做成DIP型式的好操作),TS1602 LCM(20元, www.iccavr.com一直下不了说明书,链接不成功).DC5V 1A电源(自已做的,市场有外壳,装一下就OK) 这就是全部家当了。
       在不了解AVR内部结构和指令系统情况下,我选择了用汇编来写程序。现在谈谈LCM的使用经历:
1。找相关的说明书,按说明书把1602的16根线接好,要注意引脚名称要以LCM本身标的为准。
2。了解一下1602的原理,最基本的要知道以下几点:16个引脚分别做什么用的,13组指令粗略了解一下,写与读的操作时序一定要看懂记在心里。
3。最后了解LCM的驱动步骤,现把说明书的COPY下来:

;1----延时15ms
;2----写指令38H(写入之前不用检测Busy信号)
;3----延时5ms
;4----再次写入38H指令(写入之前不用检测Busy信号),至于为什么要重复写入现在不清楚,而且下面还要写一次.
;5----延时5ms
;4----再次写入38H指令(写入之前不用检测Busy信号)
;5----检测Busy信号;
;6----写指令38H,此条指令是将LCD显示模块设置为8位数据线,双行,5X7点阵显示
;7----检测Busy信号;
;8----写指令08H,关闭显示
;9----检测Busy信号;
;10---写指令01H,显示清屏
;以后写入光标等的控制指令.

按照上面说的,对初学者其实不太好理解,其实LCM启动方式有两种:一种是自启动(冷启动),另一种就是指令启动(热启动)。加在LCM上的电源时序变化符合自动启动的特性时(时序图就不画了),则LCM会自动执行以下工作:
1。自动清屏
2。自动功能设置:设成8位,显示1行,5X7字型
3。自动设置显示屏为关,不闪烁。
4。字符进入模式为I/D=1,S=0,即光标右移1格,AC值加1,字符不动。


另外要说明的是一般的LCM都能自启动,而说明书所讲其实属于指令启动的模式。对于自启动的话,可以按以下步骤:
1。按照你的LCM和MCU的实际连接,定义好RS,R/W,E及DB0-DB7。
2。LCM初始化:
A 判断LCM是否忙(稍后讲如何检测),不忙时对LCM写入功能设置的指令(8BIT还是4BIT,单行还是双行显示,5X10还是5X7的字型)
B 判断LCM是否忙,不忙时对LCM写入显示屏开关控制指令(显示屏开还是关,光标要不要出现,如果出现的话要不要闪烁)
C 判断LCM是否忙,不忙时对LCM写入字符进入模式 设置指令(字符进入时,光标不动,左移还是右移,AC加1还是减1,字符不动,左移还是右移)
A,B,C完成后,LCM初始化就完成了。接下来要显示东西了。
3。设置字符显示的位置,可以查DDRAM地址与显示位置映射图,如在第一行第四列显示,即它的地址为0x03,但因为DDRAM地址设置指令规定DB7必须为1,所以最终写入指令寄存器的应该是0b10000000+0b00000011=0b10000011.设置时也是先判断LCM是否忙,不忙才对LCM写入这个地址。注意这里依然是对IR(指令寄存器的操作)
4。设置要显示的字符,这里是唯一对数据寄存器的操作。设置时也是先判断LCM是否忙,不忙才对LCM写入这个字符的ASCII码。到这里,完成了字符的显示。

如何检测LCM是否忙?在设置好读取的状态下,对DB7进行检测,测得DB7=0时就表是不忙了。
如何设置读的状态?这就要结合LCM读的时序了,首先让RS=0,对IR(指令寄存器操作),然后让R/W=1,告诉LCM我要的读操作。R/W=1再经过(TSP1)最小30NS,然后让E=1,此时最好不要马上测DB7,因为E=1后,要经TD(最大100ns)DB上的数据才稳定。加入个NOP再读是最可靠的。
LCM内部可以看作两组寄存器,一个是指令寄存器,一个是数据寄存器,由RS来控制。对LCM判忙是对指令寄存器的读的操作,功能设置,显示方式设置是在对
指令寄存器写的操作。对于数据寄存器也有读写操作。如要显视字符,就把对应的ASCII写入数据寄存器中。是写的操作。
另外,写操作时,也是在E由1变为0时,LCM才会将数据打入数据寄存器中。所以要确保在E=1至E=0这一时段,你的DB数据是正确恒定的。
    只要明白了LCM的原理,写LCM的驱动可以很灵活。如我以下这个程序,就没有按说明书的格式来写的。显示依然是稳定的。
;******************************************************
;ts1620 lcd diaplay
;第一行第11列显视"F"
;*******************************************************

.include "m16def.inc"
;定义程序中使用的变量名(在寄存器空间)
.equRS = PD5
.equ RW =PD6
.equ E = PD7
;DB0-DB7 接PC0-PC7,所以JTAG功能要取消掉
.def temp = r16
.def value =r17


;中断向量区定义,flash程序空间$000-$029
.org $000
rjmp reset
nop
reti


.org $002A
reset:
;-----------I/O初始化------------
ldi temp,0xff
out ddrd,temp
;---------堆栈位置设置-----------
ldi r16,high(ramend)
out sph,r16
ldi r16,low(ramend)
out spl,r16
;-------------------------
      
rcall lcm_int
rcall lcm_clr


ldi value ,0b11001010         ;设置初始显视的地址
rcall write_ir                  ;写入控制字
               
LDI value ,0x46               ;设置要显示的数
rcall write_dr                  ;显视字符
loop:
    rjmp loop

;***********************************************************




;===============   LCM初始化 ===============================
lcm_int:
;设置显示模式:数据长度,双行或单行显示,5X10或5X7字型
LDI value ,0b00111000          ;设置显示模式:8位2行5x7点阵
rcall write_ir                  ;写入控制字
;------------------------------------------------------------
;显示器开关,光标是否出现,是否闪烁
LDI value ,0b00001110         ;显示器开、光标开、光标允许闪烁
rcall write_ir                   ;写入控制字
;------------------------------------------------------------
;字符进入模式。光标是否移动,移动方向,AC变化,字符变化
LDI value ,0b00000110         ;光标右移1格,AC加1,字符不动
rcall write_ir                   ;写入控制字
;-----------------------------------------------------------
;显示光标移位
;ldi value,0b00010000
;rcall enable
RET
;=============================================================

;=============================判忙===========================
Busycheck:                  
ldi temp,0x00
out ddrc,temp
checkagain:
cbi portd,RS;RS=0,选择IR
SBI portd,RW;RW=1 ;写操作
SBI portd,E ;准备读
nop         ;延时一下
in temp, pinc
cbi portd,e;下降沿出现,DR数据DB0-DB7出现
sbrc temp,7
rjmp checkagain
ldi temp ,0xff
out ddrc,temp
RET
;==================================================================

;============写入控制命令的到IR寄存器中===========
write_ir:            
rcall Busycheck

cbi portd,RS                  ;RS=0,选择IR      
cbi portd,RW                  ;RW=0 ;写操作
cbi portd,E                   ;E=0 准备
out portc,value               ;选送上数据
SBI portd,E                   ;准备好数据
nop                           ;让数据稳定一点
cbi portd,E                   ;下降沿出现,数据被锁进IR里
RET
;==================================================



;================写数据到DR寄存器中======================
write_dr:
                     
rcall Busycheck                ;判忙

SBI portd,RS                  ;RS=1,选择DR
cbi portd,RW                  ;RW=0 ;写操作
cbi portd,E                   ;E=0 准备
out portc,value               ;选送上数据
sbi portd,E                   ;准备好数据
nop                           ;让数据稳定一点
cbi portd,e
RET                     ;下降沿出现,数据被锁进DR里
;====================================================

;========清屏,让光标回到左上角=======================

lcm_clr:

ldi value,0b00000001          ;清屏并光标复位
rcall write_ir                ;写入控制字
ret
;=================================================

lanlanx 发表于 2009-6-27 21:13:12

顶一个,支持一下

airland 发表于 2009-8-26 09:43:01

谢谢楼主 我也是刚学AVR的 最近也在搞1602 虽然用的是C语言 不过还得顶一下 前面那些东东蛮有用的

feifeimao 发表于 2009-9-1 10:46:34

我的液晶是这样连接的
4引脚数据指令寄存器
5引脚读写控制

我的4,5引脚连接的A0A1都在cpld的74373
6引脚使能操作从avr单片机引出来的

怎么来控制啊?

feifeimao 发表于 2009-9-1 10:47:10

我的
qq:150216708请求指点。

alice5208 发表于 2011-1-21 16:05:44

标记

soni2c 发表于 2011-5-13 22:19:41

支持论坛正规化管理,单片机初学者,请求通过审核

polun2011 发表于 2011-8-15 14:11:59

我之前使用1602也费了很大力气,一遍遍的去调程序,就是不能正常显示,最后还是在论坛上看到M16的PC口有四个默认的用于JTAG仿真,换到PB口,果然显示了
页: [1]
查看完整版本: 1602LCM的使用经历----初学者独白