本帖最后由 nklug 于 2018-4-5 11:36 编辑
看懂时序图,驱动LCD1602液晶屏 作者:赣州 卢刚(nklug) [本人原创,转载请保留署名。2018年4月2日] 网购了几个LCD1602液晶屏,用STC驱动它,开始只是一个点亮了的蓝屏,不见字符,费了一番功夫才成功显示出字符。现将驱动LCD1602液晶屏的经验总结如下,希望对初次使用的朋友有所帮助。 驱动液晶屏,按下列步骤进行: 1、 把的R/W接地(原因后述),调节对比度,使屏显出一行白色矩形块。
调对比度
我开始的不成功,是省了V0接的电阻,让它空着,以为也能显示字符,只不过不好看罢了,不知大错特错。记着一定要接V0脚的调节对比度电阻并调试好,否则只是蓝屏,不出字也不出矩形块。调整对比度有两种方法,介绍较多的是第一种标准接法,可调电阻用10K的。第二种接法据自己的实验,R可用510欧(最后调试成功后改用3.3K)。
这一步目的是让它显示出一行浅白色矩形块,注意无须太亮。
一行
1602液晶屏只要加上了电压,调整好对比度,没接单片机也能显示出一行矩形块,只有初始化后才会出现两行。利用这点可作液晶屏好坏的初步判断。 2、 设置显示模式,让液晶屏显示出两行白色矩形块。(实质是写好写命令的子程序。)
两行
通常推荐的初始化过程: 延时15ms 写指令38H 延时5ms 写指令38H 延时5ms 写指令38H 延时5ms (以上都不检测忙信号) (以下都要检测忙信号) 写指令38H ———————— 写指令08H关闭显示 写指令01H显示清屏 写指令0cH显示开及光标设置 完毕 我们让程序完成四次写38H指令就停下来,后四步暂不执行。只要四次写指令38H成功,液晶屏就会出现两行矩形块。为什么要四次呢?不清楚。就照他的办好了。 能出现两行矩形块,说明写指令的子程序是正确的,后面的事也就好办了。若不成功,则对照1602屏的写操作时序,仔细修改程序。我开始的不成功,第二个原因就是没弄清时序,胡乱写没成功就生搬硬套网上程序。 1602屏写操作的时序图:
时序
时序时间参数:
参数
从时序图确定子程序步骤如下:①为RS和R/W赋值;②为D0~D7数据口赋值,延时后再设置E;③将E置高电平,E=1;延时tpw;④将E清零,产生重要的执行下降沿;⑤下降沿后要延时tHD2,确保数据口在这段时间内不变;⑥依靠子程序以后的延时,来满足E信号周期最小值tc。 我用STC12C5201AD 6M晶振驱动1602屏,根据每步程序所要用的时间和时序要求,写的代码如下,实际运行通过。 ;***************************** ;1602写命令,命令存在LCD_DAT, ;***************************** PR_CMD: CLR LCD_RS ; ①为RS和R/W赋值 CLR LCD_RW ;实际上R/W脚接地了,此句可无 MOV LCD_DATA,LCD_DAT ; ②为D0~D7数据口赋值
SETB LCD_EN ;③将E置高电平 NOP ;延时 CLR LCD_EN ; ④将E清零,产生重要的下降沿 lcall uS40 ;⑤下降沿后延时 RET 将38H改为34H,是一行5*10模式,显示如下图:
一行5*10
3、 完成初始化程序的后四步。 资料说写指令38H后,后面的每步都要检测忙信号。因为1602屏是个慢性子,上步没执行完就来下一步,下一步就执行不了。我这样想,若上一步没完成,则检忙这步也应该不能运行,检忙能运行则上一步定是已经完成了。很多人说是用延时替代检忙。我呢?用延时1mS来代替检忙。 不读读忙信号,也不读数据了(不用命令9和命令11),则可直接将R/W接地,还可省一根接线。这就是第一步把R/W接地的原因。 我的初始化过程: 延时15ms 写指令38H 延时5ms 写指令38H 延时5ms 写指令38H 延时5ms 写指令38H 延时1mS 写指令08H关闭显示 延时1mS 写指令01H显示清屏 延时1mS 延时1mS 写指令0cH显示开及光标设置 延时1mS 完毕 后面的五步都将原来的检测忙改为延时,试验结果延时160uS不够,延时1mS至5mS都行,其余没试。 我试验过,整个初始化过程中,只用第一步写38H指令和最后一步写指令0CH也可以,中间六步省去也行。为保险其见,仍写八个指令。 4、 显示字符。 写数据子程序与写命令子程序基本相同,仅R/S的值不同。运行本子程序前先延时1mS,确保前一步运行已经完成。 ;***************************** ;1602写数据,数据存在LCD_DAT ;***************************** PR_DATA: SETB LCD_RS ;RS高 数据 CLR LCD_RW ; 实际上R/W脚接地了,此句可无 MOV LCD_DATA,LCD_DAT
SETB LCD_EN ;先置高 nop ;延时 CLR LCD_EN ;产生下降沿 执行 lcall us40 RET 写字符成功,屏的白色块上就会出现更亮的字符,所以调对比度时白色块不要调得太亮了。
块上字
5、 再次调整对比度。 调v0脚上的电阻,使得白色块消失,只留下的清晰字符。我原是用一个510欧电阻接地,现改为用一个3.3K电阻接地。若是用第一种接法,旋转一下中间触点位置就行了。 液晶屏A,K分别接电源正负点亮背景灯,可在电源正与A之间串一个10~15欧电阻,适当降低点亮度,延长灯寿命。 这是试验程序显示了几个字母的样子:
字符
6、 总结:先设置好硬件(显出白色矩形块),再把握好时序写程序。 能显示字符,自然也就能在实际应用中显示时间电压之类的数据了。 7、 我的试验程序: - ;STC12C5201AD6M晶体 驱动LCD1602屏
- ;作者:赣州 卢刚(nklug)
- ;2018年3月
- ;*******************
- ;端口引脚定义
- LCD_RS BIT P2.6 ;1602数据命令选择端口
- LCD_RW BIT P2.7 ;1602读写选择端口
- LCD_EN BIT P3.7 ;1602使能端口
- LCD_DATA EQU P1 ;1602数据端口
- ;变量声明
- ALL_FLAG EQU 20H ;标志位
- LCD_FLAG EQU ALL_FLAG.7 ;1602读忙标志位
- LCD_DAT EQU 30H ;1602数据命令字
- DELAYED EQU 31H ;延时字
- ORG 0000H
- SJMPSTART
- ORG 0030H
- START:
- lcall LCD_INIT ;初始化液晶
- lcall uS160
- MOV lcd_dat,#84H ;写在何位置
- lcall PR_CMD
- mov 50H,#3
- lcall uS160
- mov LCD_DAT,#01101110B ;字母n的代码
- lcall PR_DATA
- lcall uS160
- mov LCD_DAT,#01101011B ;字母k的代码
- lcall PR_DATA
- lcall uS160
- mov LCD_DAT,#01101100B ;字母l的代码
- lcall PR_DATA
- lcall uS160
- mov LCD_DAT,#01110101B ;字母u的代码
- lcall PR_DATA
- lcall uS160
- mov LCD_DAT,#01100111B ;字母g的代码
- lcall PR_DATA
- AJMP $
- ;***************
- ;1602初始化
- ;***************
- LCD_INIT:
- MOV DELAYED,#15
- LCALL DELAY1MS
- MOV LCD_DAT,#38H
- LCALL PR_CMD
- MOV DELAYED,#5
- LCALL DELAY1MS
- MOV LCD_DAT,#38H
- LCALL PR_CMD
- MOV DELAYED,#5
- LCALL DELAY1MS
- MOV LCD_DAT,#38H ;上三次下一次设38H,在运行过多次的片子试过仅用第一次设38H也是可以的。
- LCALL PR_CMD ;估计这是多次初始化后的原故,为保险还是这样多次的设置38H好。
- ;*****上面要重复3次*****
- ;*****下面设置的间隔若用延时160uS则不行,用1mS至5mS都可****
- MOV DELAYED,#1
- LCALL DELAY1MS
- ; LCALL uS160
- MOV LCD_DAT,#38H ;#00111000B 使用8位数据,显示两行,使用5×7的字型
- LCALL PR_CMD
- MOV DELAYED,#1
- LCALL DELAY1MS
- ; LCALL uS160
- MOV LCD_DAT,#08H ;显示关无光标 光标闪 无也可以
- LCALL PR_CMD
- MOV DELAYED,#1
- LCALL DELAY1MS
- ; LCALL uS160
- MOV LCD_DAT,#01H ;#00000001H ;清屏 无也可以
- LCALL PR_CMD
- MOV DELAYED,#1
- LCALL DELAY1MS
- ; LCALL uS160
- MOV LCD_DAT,#06H ;;字符不动,光标自动右移一格 无也可以
- LCALL PR_CMD
- MOV DELAYED,#1
- LCALL DELAY1MS
- ; LCALL uS160
- MOV LCD_DAT,#00001100B ;显示器开,无光标
- LCALL PR_CMD
- RET
- ;*******************************
- ;1602写数据,数据存在LCD_DAT
- ;*******************************
- PR_DATA:
- SETB LCD_RS ;RS高 数据
- CLR LCD_RW ;RW低 写
- MOV LCD_DATA,LCD_DAT
-
- SETB LCD_EN ;先置高
- nop ;延时
- CLR LCD_EN ;产生下降沿 执行
- lcall us40
- RET
- ;********************************
- ;1602写命令,命令存在LCD_DAT
- ;*******************************
- PR_CMD:
- CLR LCD_RS
- CLR LCD_RW
- MOV LCD_DATA,LCD_DAT
-
- SETB LCD_EN ;先置高
- NOP
- CLR LCD_EN
- lcall uS40
- RET
- ;;*****************************************
- ;延时,延时时间=1毫秒*次数 次数在DELAYED
- ;*****************************************
- DELAY1MS: ;6.000MHz 1ms
- mov R7,#6
- D_1:mov R6,#200
- D_2: djnzR6,D_2
- djnz R7,D_1
- djnz DELAYED,DELAY1MS
- ret
- ;***********
- ;160uS延时
- ;***********
- uS160:
- mov 42H,#192
- us160_a:
- djnz 42h,us160_a
- ret
- ;***********
- ;40uS延时
- ;***********
- uS40:
- mov 42H,#192
- us40_a:
- djnz 42h,us40_a
- ret
- END
复制代码
|