找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6772|回复: 11
收起左侧

单片机汇编程序驱动带字库LCD12864液晶屏详细教程

  [复制链接]
ID:996149 发表于 2022-1-3 22:00 | 显示全部楼层 |阅读模式
一丶引脚说明
Lcd12864(带字库版本,ST7920为主芯片驱动)
(正面)
(反面)
由于是带字库版本,与不带字库版本有出入,其部分引脚有不同
二丶接口时序
Mpu从模块写入资料
(时序图很重要,能够保证命令正确写入ST7920芯片,让12864屏幕正常使用)


  

这里我们采用并行模式,PSB,RS全部置高(PSB,RS所对应的引脚置高电平)
(P2.6RS对应口,P2.5 RWP2.7 ED0-D7接在P0串口,PSB P3.2,RST P3.3  vcc5v 下面统一采取这种接法)
写入指令:

CLR P2.7(使能信号先置低电平)

CLR P2.6(RS低电平)

CLR P2.5(RW低电平)

LCALL DELAY1(延时一段时间 对应时序图TAS)

CLR P2.7(使使能信号置低电平)

SETB P2.7(使能信号置换高电平)

MOV P0,#08H(输入08#对应指令)

LCALL DELAY1(延时一段时间,对应TC)

CLR P2.7

LCALL DELAY1

SETB P2.7

LCALL DELAY(此处延时大于60ms相当于读忙了)

这个程序段可以看作一个指令

写入数据:

同上     CLR P2.6,改为SETB P2.6即可,其余相同

其中延时时间如上图,只要超过最小值即可,最好不要过长了。



三丶对12864的所有操作概括起来有4种

1)、读忙状态(同时读出指针地址内容),初始化之后每次对12864的读写均要进行忙检测。(我每次写一次完整指令都延时一段时间,相当于读忙了,下面就不再赘述)

2)、写命令:所有的命令可以查看指令表,后续讲解指令的详细用法。写地址也是写指令。

3)、写数据:操作对象有DDRAM、CGRAM、GDRAM。

4)、读数据:操作对象也是DDRAM、CGRAM、GDRAM。

忙标志:BF
BF标志提供内部工作情况。BF=1表示模块在内部操作,此时模块不接受外部指令和数据。BF=0时,模块为准备状态,随时可接受外部指令和数据。
利用STATUS READ指令,可以将BF读到DB7总线,从检验模块之工作状态。

那我们要如何在12864上面显示图像或者字符呢?

下面就来介绍一下DDRAM

上图所对应的四个区是DDRAM所对应的在ST7920上面的地址,其中能够显示的只有壹贰区,那么我们只需要把字符所对应的数据写进DDRAM中,那么就可以让12864显示出我们想要的字符。

其中80H到87H为第一行

90H到97H为第二行(上半屏)

88H到8FH为第三行

98H到9FH 为第四行(下半屏)

下面我们来试着编写一下程序

(这几个步骤很重要,学会了步骤就学会了12864的使用)

*网上有带字库12864详细指令集,这里我就不打出来了,注意,我编写的输入指令的指令码是只对应DB0到DB7的,和下面绿框那种一样是没有RW,RS,E位的,那些位我在编指令的时候就设定好了。

(1)功能设定


(2)清屏指令



(3)进入设定点

(4)显示状态开关设置


上面为初始化程序
(绿色框代表指令码,可以输入二进制也可以输入16进制,只要保证p0口电平信号相对应就行了)

  • 设置DDRAM地址

对应指令1000 0000也就是给p0输入#80H

DDRAM从80H开始输入指令,12864的DDRAM横向地址会自动读取表中的数据,每输入两个16位的数据如#41H,#41H,地址会自动从80H跳到81H以此类推,网上有详细的运作方式,可以上网查阅。



上图很明显,我输入了三个#41H进80H中,12864就自动将第三个41#也就是大写A写进81H中,这里提一下,带字库DDRAM12864一个地址可以写一个汉字两个字母(厂家规定的,无法修改)


  • 输入DDRAM地址

这里可以用查表的方式,一直往DDRAM写入数据,但是写进去的数据是这样的,先填满第一行,再填满第三行,再填满第二行,再填满第四行

,那我这里就采用查不同表的方式,设DDRAM起始地址为80H的时候只查16个数据,再设90H再查16个数据,以此类推。


下面我给仿真图和指令

(注意,这里仿真要带字库的12864,不带字库的不能成功仿真,带字库的模型上网搜)




我设置的引脚和开发板的设置引脚一致,直接插上去使用了,大家使用的时候可以看看开发板的原理图,一般都是一样的,不行就改引脚


那普通的字符可以了,那怎么画图呢,广告的需求肯定不能只有字符,还要有图案,那怎么定制呢。下面就来介绍另一个RAM,CGRAM,也叫绘图RAM。




这些都是点阵,绘图RAM就是给这些点阵置1或置0,可以看到其实它本来是32行×256列的,但是分成了上下两屏显示,每个点对应了屏幕上的一个点。要使用绘图功能需要开启扩展指令。然后写地址,再读写数据。


这幅图就是CDRAM对应的地址,其实也是12864实际的样子,水平位址对应着DDRAM的80H到8FH,一共16格,每8格对应一个半屏,共两个半屏。一格一行一共对应了16位的二进制数字那么半个屏幕就是16*8(共8格,一格16列)*32(32行),一个半屏32行,一个整屏就是16*8*32*2=128*64所以称之为12864屏幕(很重要,一定要理解了)


那看到上图bit0和bit15,可以知道,一个地址是先从高位读到低位置,看起来很麻烦。但是后面取字模软件可以帮你修改,那我这里向CGRAM输入还是像DDRAM一样,当然,CGRAM和DDRAM的地址是一样的,一旦读够16个二进制数字,也就是两个16进制数,也就是两个字节,就会自动加一,DDRAM从80H到81H,那CGRAM对应的地址也是一样下面会提到。这是x坐标,但是y坐标不会,y坐标要你输入了16个数值后自己修改,也就是写完一行后要自己改。

(我这里写得不太清楚,LCD12864点阵型液晶显示器总结 - 吃不了就兜着走 可以看一下这个作者写的他写的很详细)


  GDRAM的读写:

  首先说明对GDRAM的操作基本单位是一个字,也就是2个字节,就是说读写GDRAM时一次最少写2个字节,一次最少读2个字节。


  写数据:先开启扩展指令集(0x36,然后送地址,这里的地址与DDRAM中的略有不同,DDRAM中的地址只有一个,那就是字地址。而GDRAM中的 地址有2个,分别是字地址(列地址/水平地址X)和位地址(行地址/垂直地址Y),上图中的垂直地址就是00H~31H,水平地址就是00H~15H,写 地址时先写垂直地址(行地址)再写水平地址(列地址),也就是连续写入两个地址,然后再连续写入2个字节的数据。这里列举个写地址的例子:写GDRAM地址指令是0x80+地址。被加上的地址就是上面列举的XY,假设我们要写 第一行的2个字节,那么写入地址就是0x00H(写行地址)然后写0x80H(列地址),之后才连续写入2个字节的数据(先高字节后低字节)。

下面说说指令,其实和DDRAM基本一致,就是写写入CGRAM指令要先写x坐标,再写y坐标,其余步骤基本一样,但是查表要注意了,因为我编写的程序RA寄存器只能读到256位置,那我要分成4个表才能读完整个屏


下面给出指令和仿真。


下面拉屏和闪烁我就简要说一下思路


闪烁我是通过不停地睡眠唤醒来实现,这里睡眠指令要开拓展指令,然后写一个循环和跳出循环的指令,通过两个按钮或者一个开关实现,也可以通过反白来实现,其实会写步骤就完成大部分了,剩余的其实都是不断地调试和检查错误。


拉屏(仿真跑不了卷屏)

功能:SR=1: AC5~AC0 为垂直卷动地址,SR=0:。

那这里要说一下了,怎么实现拉屏呢。其实12864里自带了一个指令叫做卷动地址设置,它规定了只会向上滚动,而因为一共是有64列的但是上面CGRAM为什么只有32行呢,那是因为其中

A0到A7对应第一个屏中实际的第三行,其实它们也是可以输入数据的,只是没使用卷动指令时无法看到,那我假设


设置拉屏的行数为16吧,那80H就到了原来的B0哪里,一整行都替换了,然后A0就到90H一行,90H就到80H,其实就是一行推着整个半屏都在运动,但是12864的一行实际上是80H到8FH,上下半屏都在动,但不会相互影响


实际的一行:

80H





























8FH

90H





























9FH

A0H





























AFH

B0H





























BFH

所以一整个屏都会移动




(下图是半个屏,下面因为我已经实现全屏不方便改了,就只看上半屏吧)


那我要怎么实现全屏滚动呢,那么A0和B0行就开始有用了,那我只要将80H

对应的行,假设是CGRAM中的y  00H,x80H向上移,那我就设置成看起来从下半屏的最下面开始往上面升起,那就是Y 32H  X  88H,这一行。那这就开始有思路了,那我吧80H到88H的数据一起输入到A8到AFH区域不就行了吗,以此类推90H区到98H的就输入到B8到BF中,88H的输入到A0,98H的输入到B0就ok了。

下面试一下

成功了(此处要说明一下,CGRAM的y坐标是到0到63,是可以设置到A0和B0位置的,网上教程说的不清不楚的,花费了我很多精力,上面说y是0到31是因为不设置卷动看不见,所以不显示)


说明书心得:

说实话,这次我选的课题确实不算难度大的那一批了,网上也有很多的教程,但是由于要全部用汇编实现,工作量大了很多,我以为很快就能成功,没想到过程真的是千辛万苦,一个是仿真,可以说网上带字库的仿真几乎没有,那个Proteus的带字库模型还要自己在网上买,不断调试,不断测试才终于和开发板的一致。

不断在网上搜索教程,看了半天居然是不带字库的,差点晕倒在桌子上。后面终于在网上找到ST7920的说明书,一看和天书一样晦涩难懂,没办法,一个个不会的知识点慢慢学,实在不行就先看了1602的,这里很感谢知乎的北鸮他写的一篇文章超详细讲解,LCD1602电路与驱动 真的很详细清楚

然后是烧录的问题,烧录还好,因为网上的教程很详尽明白,没什么问题。然后就是不断地写程序,调仿真一直反复。然后不断地看网上作者们写的程序,吐槽一下,网上都是c语言的程序,汇编几乎没有,少有的几个甚至有语法错误,看的时候都有点头痛,那只好看着c语言思路来写汇编了,感谢网络上各位热心的作者,他们无偿地分享知识,而且教的很棒,真的非常感谢他们。


86e0d05fe8f56c817af3f618db2bc8c.jpg 284c762113d0210cfc0e5014be9e0fa.jpg

单片机源程序如下:
  1. AJMP MAIN
  2. TAB1:
  3. DB #41H,#41H,#41H,#41H,#41H,#41H,#41H,#41H,#41H,#41H,#41H,#41H,#41H,#41H
  4. ,#41H,#41H
  5. TAB2: DB "元旦快乐大家好"
  6. //带字库的很方便,直接按这个格式输入汉字就行 一行7汉字,没有字的地方记得输入空格,空格占半个地址位
  7. TAB3: DB "我你不合格 ",07FH,05FH,06FH
  8. TAB4: DB "哦哦哦哦哦 ",07FH,05FH,06FH            
  9. //想改字符汉字直接改表就行,汉字要打在引号里面
  10. MAIN:
  11. SETB P3.2
  12. LCALL DELAY1
  13. CLR  P3.3
  14. LCALL DELAY1
  15. SETB P3.3
  16. LCALL DELAY1
  17. //初始化
  18. CLR P2.6
  19. CLR P2.5
  20. MOV P0,#30H
  21. LCALL DELAY1
  22. SETB P2.7
  23. LCALL DELAY1
  24. CLR P2.7
  25. LCALL DELAY1
  26. //写入#30H对应的指令
  27. CLR P2.7
  28. CLR P2.6
  29. LCALL DELAY1
  30. CLR P2.5
  31. MOV P0,#08H
  32. LCALL DELAY1
  33. SETB P2.7
  34. LCALL DELAY1
  35. CLR P2.7
  36. LCALL DELAY1
  37. //写入#08H的指令
  38. CLR P2.7
  39. CLR P2.6
  40. LCALL DELAY1
  41. CLR P2.5
  42. MOV P0,#0CH
  43. LCALL DELAY1
  44. SETB P2.7
  45. LCALL DELAY1
  46. CLR P2.7
  47. LCALL DELAY1
  48. //开屏
  49. CLR P2.7
  50. CLR P2.6
  51. LCALL DELAY1
  52. CLR P2.5
  53. MOV P0,#01H
  54. LCALL DELAY1
  55. SETB P2.7
  56. LCALL DELAY1
  57. CLR P2.7
  58. LCALL DELAY1
  59. //清屏指令
  60. CLR P2.7
  61. CLR P2.6
  62. ACALL DELAY1
  63. CLR P2.5
  64. MOV P0,#80H
  65. LCALL DELAY1
  66. SETB P2.7
  67. LCALL DELAY1
  68. CLR P2.7
  69. LCALL DELAY1
  70. //光标设置
  71. CLR P2.7
  72. CLR P2.6
  73. LCALL DELAY1
  74. CLR P2.5
  75. MOV P0,#80H
  76. LCALL DELAY1
  77. SETB P2.7
  78. LCALL DELAY1
  79. CLR P2.7
  80. LCALL DELAY1
  81. //设置DDRAM地址

  82. CLR P2.7
  83. SETB P2.6
  84. ACALL DELAY1
  85. CLR P2.5
  86. MOV R2,#15D
  87. MOV DPTR,#TAB1
  88. LOOP:MOV A,R0
  89. INC R0
  90. MOVC A,@A+DPTR
  91. SETB P2.6
  92. LCALL DELAY1
  93. CLR P2.5
  94. MOV P0,A
  95. SETB P2.7
  96. LCALL DELAY1
  97. CLR P2.7
  98. LCALL DELAY1
  99. DJNZ R2,LOOP
  100. //查表指令


  101. CLR P2.6
  102. ACALL DELAY1
  103. CLR P2.5
  104. MOV P0,#90H
  105. LCALL DELAY1
  106. SETB P2.7
  107. LCALL DELAY1
  108. CLR P2.7
  109. LCALL DELAY1
  110. //设置DDRAM地址
  111. MOV R2,#15D
  112. MOV DPTR,#TAB2
  113. MOV R0,#00H
  114. LOOP1:MOV A,R0
  115. INC R0
  116. MOVC A,@A+DPTR
  117. SETB P2.6
  118. LCALL DELAY1
  119. CLR P2.5
  120. MOV P0,A
  121. SETB P2.7
  122. LCALL DELAY1
  123. CLR P2.7
  124. LCALL DELAY1
  125. DJNZ R2,LOOP1
  126. //查表指令
  127. CLR P2.6
  128. ACALL DELAY1
  129. CLR P2.5
  130. MOV P0,#88H
  131. LCALL DELAY1
  132. SETB P2.7
  133. LCALL DELAY1
  134. CLR P2.7
  135. LCALL DELAY1
  136. //设置DDRAM地址
  137. MOV R2,#15D
  138. MOV DPTR,#TAB3
  139. MOV R0,#00H
  140. LOOP2:MOV A,R0
  141. INC R0
  142. MOVC A,@A+DPTR
  143. SETB P2.6
  144. LCALL DELAY1
  145. CLR P2.5
  146. MOV P0,A
  147. SETB P2.7
  148. LCALL DELAY1
  149. CLR P2.7
  150. LCALL DELAY1
  151. DJNZ R2,LOOP2
  152. //查表指令
  153. CLR P2.6
  154. ACALL DELAY1
  155. CLR P2.5
  156. MOV P0,#98H
  157. LCALL DELAY1
  158. SETB P2.7
  159. LCALL DELAY1
  160. CLR P2.7
  161. LCALL DELAY1
  162. //设置DDRAM地址

  163. MOV R2,#15D
  164. MOV DPTR,#TAB4
  165. MOV R0,#00H
  166. LOOP3:MOV A,R0
  167. INC R0
  168. MOVC A,@A+DPTR
  169. SETB P2.6
  170. LCALL DELAY1
  171. CLR P2.5
  172. MOV P0,A
  173. SETB P2.7
  174. LCALL DELAY1
  175. CLR P2.7
  176. LCALL DELAY1
  177. DJNZ R2,LOOP3

  178. //查表指令

  179.             
  180. DELAY1:
  181. MOV  R7,#100   ;单周期指令(1us)
  182. D1:  
  183.   MOV  R6,#100  ;单周期指令(1us)        
  184.   DJNZ R6,[        DISCUZ_CODE_3        ]nbsp;     ;双周期指令(2us)//该指令自身执行R6次        
  185.   DJNZ R7,D1     ;双周期指令(2us)//D1执行R7次  
  186. RET
  187. END
复制代码

以上图文的Word格式文档下载(内容和本网页上的一模一样,方便大家保存):
12864汇编教程.docx (2.48 MB, 下载次数: 69)

评分

参与人数 1黑币 +40 收起 理由
admin + 40 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:262 发表于 2022-1-4 18:23 | 显示全部楼层
好资料,51黑有你更精彩!!!
回复

使用道具 举报

ID:996149 发表于 2022-1-7 18:53 | 显示全部楼层
感谢admin
回复

使用道具 举报

ID:1000958 发表于 2022-1-11 15:19 | 显示全部楼层
太感谢了,之前看的12864都是有CS1、CS2接口的,这个是PSB真不错
回复

使用道具 举报

ID:612823 发表于 2022-5-22 12:49 | 显示全部楼层
讲的详细,新手感谢你
回复

使用道具 举报

ID:996149 发表于 2022-12-30 00:08 | 显示全部楼层
不好意思各位,现在我才发现我的代码有问题
回复

使用道具 举报

ID:996149 发表于 2022-12-30 00:10 | 显示全部楼层
下面是改正过的代码:
AJMP MAIN
TAB1:DB 041H,041H,041H,041H,041H,041H,041H,041H,041H,041H,03H,03H,03H,03H,041H,041H
TAB2: DB "祝大家圣诞快乐"

TAB3: DB "记得吃饭睡觉",05FH,06FH
TAB4: DB "小心啊啊啊啊",05FH,06FH            
//????????????,?????????
MAIN:
SETB P3.2
LCALL DELAY1
CLR  P3.3
LCALL DELAY1
SETB P3.3
LCALL DELAY1
//???
CLR P2.6
CLR P2.5
MOV P0,#30H
LCALL DELAY1
SETB P2.7
LCALL DELAY1
CLR P2.7
LCALL DELAY1
//??#30H?????
CLR P2.7
CLR P2.6
LCALL DELAY1
CLR P2.5
MOV P0,#08H
LCALL DELAY1
SETB P2.7
LCALL DELAY1
CLR P2.7
LCALL DELAY1
//??#08H???
CLR P2.7
CLR P2.6
LCALL DELAY1
CLR P2.5
MOV P0,#0CH
LCALL DELAY1
SETB P2.7
LCALL DELAY1
CLR P2.7
LCALL DELAY1
//??
CLR P2.7
CLR P2.6
LCALL DELAY1
CLR P2.5
MOV P0,#01H
LCALL DELAY1
SETB P2.7
LCALL DELAY1
CLR P2.7
LCALL DELAY1
//????
CLR P2.7
CLR P2.6
ACALL DELAY1
CLR P2.5
MOV P0,#80H
LCALL DELAY1
SETB P2.7
LCALL DELAY1
CLR P2.7
LCALL DELAY1
//????
CLR P2.7
CLR P2.6
LCALL DELAY1
CLR P2.5
MOV P0,#80H
LCALL DELAY1
SETB P2.7
LCALL DELAY1
CLR P2.7
LCALL DELAY1
//??DDRAM??

CLR P2.7
SETB P2.6
ACALL DELAY1
CLR P2.5
MOV R2,#15D
MOV DPTR,#TAB1
LOOP:MOV A,R0
INC R0
MOVC A,@A+DPTR
SETB P2.6
LCALL DELAY1
CLR P2.5
MOV P0,A
SETB P2.7
LCALL DELAY1
CLR P2.7
LCALL DELAY1
DJNZ R2,LOOP
//????


CLR P2.6
ACALL DELAY1
CLR P2.5
MOV P0,#90H
LCALL DELAY1
SETB P2.7
LCALL DELAY1
CLR P2.7
LCALL DELAY1
//??DDRAM??
MOV R2,#15D
MOV DPTR,#TAB2
MOV R0,#00H
LOOP1:MOV A,R0
INC R0
MOVC A,@A+DPTR
SETB P2.6
LCALL DELAY1
CLR P2.5
MOV P0,A
SETB P2.7
LCALL DELAY1
CLR P2.7
LCALL DELAY1
DJNZ R2,LOOP1
//????
CLR P2.6
ACALL DELAY1
CLR P2.5
MOV P0,#88H
LCALL DELAY1
SETB P2.7
LCALL DELAY1
CLR P2.7
LCALL DELAY1
//??DDRAM??
MOV R2,#15D
MOV DPTR,#TAB3
MOV R0,#00H
LOOP2:MOV A,R0
INC R0
MOVC A,@A+DPTR
SETB P2.6
LCALL DELAY1
CLR P2.5
MOV P0,A
SETB P2.7
LCALL DELAY1
CLR P2.7
LCALL DELAY1
DJNZ R2,LOOP2
//????
CLR P2.6
ACALL DELAY1
CLR P2.5
MOV P0,#98H
LCALL DELAY1
SETB P2.7
LCALL DELAY1
CLR P2.7
LCALL DELAY1
//??DDRAM??

MOV R2,#15D
MOV DPTR,#TAB4
MOV R0,#00H
LOOP3:MOV A,R0
INC R0
MOVC A,@A+DPTR
SETB P2.6
LCALL DELAY1
CLR P2.5
MOV P0,A
SETB P2.7
LCALL DELAY1
CLR P2.7
LCALL DELAY1
DJNZ R2,LOOP3

//????

            
DELAY1:
MOV  R7,#10   ;?????(1us)
D1:  
  MOV  R6,#10  ;?????(1us)        
  DJNZ R6,$;     ;?????(2us)//???????R6?        
  DJNZ R7,D1     ;?????(2us)//D1??R7?  
RET
END
回复

使用道具 举报

ID:1060196 发表于 2023-1-3 21:23 | 显示全部楼层
讲的详细,新手感谢你
回复

使用道具 举报

ID:433219 发表于 2023-1-5 14:07 | 显示全部楼层
asm+并行驱动,,,,没啥玩的
回复

使用道具 举报

ID:1057863 发表于 2023-1-13 09:52 | 显示全部楼层
很棒啊,这汇编整的
回复

使用道具 举报

ID:996149 发表于 2023-2-8 15:06 | 显示全部楼层
无名!! 发表于 2023-1-13 09:52
很棒啊,这汇编整的

谢谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表