一天一个设计实例-LCD12864的应用设计
LCD12864的应用设计
LCD12864的应用基本和LCD1602的自定义字库非常类似,下面就简单介绍下LCD12864。
12864 中文 汉字图形点阵液晶显示模块,可显示汉字及图形,内置 8192 个中文汉字(16X16 点阵)、128个字符(8X16 点阵)及 64X256 点阵显示 RAM(GDRAM)。
主要技术参数和显示特性:
电源:VDD 3.3V~+5V(内置升压电路,无需负压);
显示内容:128 列× 64 行
显示颜色:黄绿/蓝屏/灰屏
显示角度:6:00 钟直视
LCD 类型:STN
与 MCU 接口:8 位或 4 位并行/3 位串行
配置 LED 背光
多种软件功能:光标显示、画面移位、自定义字符、睡眠模式等
1.1.1LCD12864的引脚说明
表6‑22 LCD12864模块引脚说明
|
引脚号 |
引脚名称 |
方向 |
功能说明 |
|
1 |
GND |
- |
模块的电源地 |
|
2 |
VCC |
- |
模块的电源正端 |
|
3 |
V0 |
- |
LCD 驱动电压输入端 |
|
4 |
RS(CS) |
H/L |
并行的指令/数据选择信号;串行的片选信号 |
|
5 |
R/W(SID) |
H/L |
并行的读写选择信号;串行的数据口 |
|
6 |
E(CLK) |
H/L |
并行的使能信号;串行的同步时钟 |
|
7 |
DB0 |
H/L |
数据 0 |
|
8 |
DB1 |
H/L |
数据 1 |
|
9 |
DB2 |
H/L |
数据 2 |
|
10 |
DB3 |
H/L |
数据 3 |
|
11 |
DB4 |
H/L |
数据 4 |
|
12 |
DB5 |
H/L |
数据 5 |
|
13 |
DB6 |
H/L |
数据 6 |
|
14 |
DB7 |
H/L |
数据 7 |
|
15 |
PSB |
H/L |
并/串行接口选择:H-并行;L-串行 |
|
16 |
NC |
空脚 |
|
|
17 |
/RST |
H/L |
复位 低电平有效 |
|
18 |
VOUT |
倍压输出脚 (VDD=+3.3V 有效) |
|
|
19 |
LED_A |
- |
背光源正极(LED+5V) |
|
20 |
LED_K |
- |
背光源负极(LED-OV) |
逻辑工作电压(VDD):4.5~5.5V
电源地(GND):0V
工作温度(Ta):0~60℃(常温) / -20~75℃(宽温)
1.1.2接口时序
模块有并行和串行两种连接方法(时序如下):
8 位并行连接时序图:

图6‑30 主控写资料到模块

图6‑31 主控读资料从模块

图6‑32 串行连接时序图
串行数据传送共分三个字节完成:
第一字节:串口控制—格式 11111ABC
A 为数据传送方向控制:H 表示数据从 LCD 到 MCU,L 表示数据从 MCU 到 LCD
B 为数据类型选择:H 表示数据是显示数据,L 表示数据是控制指令
C 固定为 0
第二字节:(并行)8 位数据的高 4 位—格式 DDDD0000
第三字节:(并行)8 位数据的低 4 位—格式 0000DDDD
表6‑23 串行接口时序参数:(测试条件:T=25℃ VDD=4.5V)

1.1.3用户指令集
表6‑24 指令表 1:(RE=0:基本指令集)
|
指令 |
指令码 |
说明 |
执行时间 (540KHZ) |
|||||||||
|
RS |
R W |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|||
|
清除显示 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
将 DDRAM 填满“20H”,并且设定 DDRAM 的地址计数器(AC)到“00H” |
4.6ms |
|
地址归位 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
X |
设定 DDRAM 的地址计数器(AC)到“00H”,并且将游标移到开头原点位置;这个指令并不改变DRAM 的内容 |
4.6ms |
|
进入点设定 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
I/D |
S |
指定在资料的读取与写入时,设定游标移动方向及指定显示的移位 |
72us |
|
显示状态 开/关 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
D |
C |
B |
D=1:整体显示 ON C=1:游标 ON B=1:游标位置 ON |
72us |
|
游标或显示移位控制 |
0 |
0 |
0 |
0 |
0 |
1 |
S/C |
R/L |
X |
X |
设定游标的移动与显示的移位控制位元;这个指令并不改变DDRAM 的内容 |
72us |
|
功能设定 |
0 |
0 |
0 |
0 |
1 |
DL |
X |
0RE |
X |
X |
DL=1 (必须设为 1) RE=1:扩充指令集动作 RE=0:基本指令集动作 |
72us |
|
设 定CGRAM 地址 |
0 |
0 |
0 |
1 |
AC5 |
AC4 |
AC3 |
AC2 |
AC1 |
AC0 |
设定 CGRAM 地址到地址计数器(AC) |
72us |
|
设 定DDRAM地址 |
0 |
0 |
1 |
AC6 |
AC5 |
AC4 |
AC3 |
AC2 |
AC1 |
AC0 |
设定 DDRAM 地址到地址计数 |
72us |
|
读取忙碌标志(BF)和地址 |
0 |
1 |
BF |
AC6 |
AC5 |
AC4 |
AC3 |
AC2 |
AC1 |
AC0 |
读取忙碌标志(BF)可以确认内部动作是否完成,同时可以读出地址计数器(AC)的值 |
0us |
|
写资料到RAM |
1 |
0 |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
写 入 资 料 到 内 部 的 RAM( DDRAM/CGRAM/IRAM/GDRAM) |
72us |
|
读 出RAM的值 |
1 |
1 |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
从 内 部 RAM 读 取 资 料( DDRAM/CGRAM/IRAM/GDRAM) |
72us |
表6‑25 指令表-2:(RE=1:扩充指令集)
|
指令码 |
指令 |
说明 |
执 行 时 间(540KHZ) |
|||||||||
|
RS |
R W |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|||
|
待 命 模式 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
将 DDRAM 填 满“ 20H ”, 并 且 设 定DDRAM 的地址计数器(AC)到“00H” |
72us |
|
卷动 地址 或IRAM 地址选择 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
SR |
SR=1:允许输入垂直卷动地址SR=0:允许输入 IRAM地址 |
72us |
|
反白 选择 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
R1 |
R0 |
选择 4 行中的任一行作反白显示,并可决定反白与否 |
72us |
|
眠 模式 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
SL |
X |
X |
SL=1:脱离睡眠模式SL=0:进入睡眠模式 |
72us |
|
扩充 功能设定 |
0 |
0 |
0 |
0 |
1 |
1 |
X |
1RE |
G |
0 |
RE=1:扩充指令集动作RE=0:基本指令集动作G=1 :绘图显示 ONG=0 :绘图显示 OFF |
72us |
|
设定IRAM 地址 或卷动地址 |
0 |
0 |
0 |
1 |
AC5 |
AC4 |
AC3 |
AC2 |
AC1 |
AC0 |
SR=1:AC5—AC0 为垂直卷动地址SR=0:AC3—AC0 为ICON IRAM 地址 |
72us |
|
设定 绘图 RAM地址 |
0 |
0 |
1 |
AC6 |
AC5 |
AC4 |
AC3 |
AC2 |
AC1 |
AC0 |
设定 CGRAM 地址到地址计数器(AC) |
72us |
备注:
1、当模块在接受指令前,微处理顺必须先确认模块内部处于非忙碌状态,即读取 BF 标志时 BF 需为 0,方可接受新的指令;如果在送出一个指令前并不检查 BF 标志,那么在前一个指令和这个指令中间必须延迟一段较长的时间,即是等待前一个指令确实执行完成,指令执行的时间请参考指令表中的个别指令说明。
2、“RE”为基本指令集与扩充指令集的选择控制位元,当变更“RE”位元后,往后的指令集将维持在最后的状态,除非再次变更“RE”位元,否则使用相同指令集时,不需每次重设“RE”位元。
具体指令介绍:
(1)清除显示
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
L |
L |
L |
L |
L |
L |
L |
H |
功能:清除显示屏幕,把 DDRAM 位址计数器调整为“00H”
(2)位址归位
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
L |
L |
L |
L |
L |
L |
H |
X |
功能:把 DDRAM 位址计数器调整为“00H”,游标回原点,该功能不影响显示 DDRAM
(3)位址归位
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
L |
L |
L |
L |
L |
H |
I/D |
S |
功能:把 DDRAM 位址计数器调整为“00H”,游标回原点,该功能不影响显示 DDRAM 功能:执行该命令后,所设置的行将显示在屏幕的第一行。显示起始行是由 Z 地址计数器控制的,该命令自动将 A0-A5 位地址送入 Z 地址计数器,起始地址可以是 0-63 范围内任意一行。Z 地址计数器具有循环计数功能,用于显示行扫描同步,当扫描完一行后自动加一。
(4)显示状态 开/关
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
L |
L |
L |
L |
H |
D |
C |
B |
功能:D=1;整体显示 ON C=1;游标 ON B=1;游标位置 ON
(5)游标或显示移位控制
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
L |
L |
L |
H |
S/C |
R/L |
X |
X |
功能:设定游标的移动与显示的移位控制位:这个指令并不改变 DDRAM 的内容
(6)功能设定
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
L |
L |
H |
DL |
X |
0 RE |
X |
X |
功能:DL=1(必须设为 1) RE=1;扩充指令集动作 RE=0:基本指令集动作
(7)设定 CGRAM 位址
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
L |
H |
AC5 |
AC4 |
AC3 |
AC2 |
AC1 |
AC0 |
功能:设定 CGRAM 位址到位址计数器(AC)
(8)设定 DDRAM 位址
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
H |
AC6 |
AC5 |
AC4 |
AC3 |
AC2 |
AC1 |
AC0 |
功能:设定 DDRAM 位址到位址计数器(AC)
(9)读取忙碌状态(BF)和位址
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
H |
BF |
AC6 |
AC5 |
AC4 |
AC3 |
AC2 |
AC1 |
AC0 |
功能:读取忙碌状态(BF)可以确认内部动作是否完成,同时可以读出位址计数器(AC)的值
(10)写资料到 RAM
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
H |
L |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
功能:写入资料到内部的 RAM(DDRAM/CGRAM/TRAM/GDRAM)
(11)读出 RAM 的值
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
H |
H |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
功能:从内部 RAM 读取资料(DDRAM/CGRAM/TRAM/GDRAM)
(12)待命模式(12H)
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
L |
L |
L |
L |
L |
L |
L |
H |
功能:进入待命模式,执行其他命令都可终止待命模式
(13)卷动位址或 IRAM 位址选择(13H)
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
L |
L |
L |
L |
L |
L |
H |
SR |
功能:SR=1;允许输入卷动位址 SR=0;允许输入 IRAM 位址
(14)反白选择(14H)
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
L |
L |
L |
L |
L |
H |
R1 |
R0 |
功能:选择 4 行中的任一行作反白显示,并可决定反白的与否
(15)睡眠模式(015H)
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
L |
L |
L |
L |
H |
SL |
X |
X |
功能:SL=1;脱离睡眠模式 SL=0;进入睡眠模式
(16)扩充功能设定(016H)
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
L |
L |
H |
H |
X |
1 RE |
G |
L |
功能:RE=1;扩充指令集动作 RE=0;基本指令集动作 G=1;绘图显示 ON G=0;绘图显示 OFF
(17)设定 IRAM 位址或卷动位址(017H)
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
L |
H |
AC5 |
AC4 |
AC3 |
AC2 |
AC1 |
AC0 |
功能:SR=1;AC5~AC0 为垂直卷动位址 SR=0;AC3~AC0 写 ICONRAM 位址
(18)设定绘图 RAM 位址(018H)
|
CODE |
RW |
RS |
DB7 |
DB6 |
DB5 |
DB4 |
DB3 |
DB2 |
DB1 |
DB0 |
|
L |
L |
H |
AC6 |
AC5 |
AC4 |
AC3 |
AC2 |
AC1 |
AC0 |
功能:设定 GDRAM 位址到位址计数器(AC)
1.1.4显示坐标关系
1、图形显示坐标
水平方向 X—以字节单位
垂直方向 Y—以位为单位

图6‑33 图形显示坐标
表6‑26 汉字显示坐标
|
X 坐标 |
||||||||
|
Line1 |
80H |
81H |
82H |
83H |
84H |
85H |
86H |
87H |
|
Line2 |
90H |
91H |
92H |
93H |
94H |
95H |
96H |
97H |
|
Line3 |
88H |
89H |
8AH |
8BH |
8CH |
8DH |
8EH |
8FH |
|
Line4 |
98H |
99H |
9AH |
9BH |
9CH |
9DH |
9EH |
9FH |
1.1.5显示RAM
1、文本显示 RAM(DDRAM)
文本显示 RAM 提供 8 个×4 行的汉字空间,当写入文本显示 RAM 时,可以分别显示 CGROM、HCGROM与 CGRAM 的字型;ST7920A 可以显示三种字型 ,分别是半宽的 HCGROM 字型、CGRAM 字型及中文CGROM 字型。三种字型的选择,由在 DDRAM 中写入的编码选择,各种字型详细编码如下:
显示半宽字型 :将一位字节写入 DDRAM 中,范围为 02H-7FH 的编码。
显示 CGRAM 字型:将两字节编码写入 DDRAM 中,总共有 0000H,0002H,0004H,0006H 四种编码
显示中文字形:将两字节编码写入 DDRAMK ,范围为 A1A0H-F7FFH(GB 码)或 A140H-D75FH(BIG5 码)的编码。
2、绘图 RAM(GDRAM)
绘图显示 RAM 提供 128×8 个字节的记忆空间,在更改绘图 RAM 时,先连续写入水平与垂直的坐标值,再写入两个字节的数据到绘图 RAM,而地址计数器(AC)会自动加一;在写入绘图 RAM 的期间,绘图显示必须关闭,整个写入绘图 RAM 的步骤如下:
1)关闭绘图显示功能。
2)先将水平的位元组坐标(X)写入绘图 RAM 地址;
再将垂直的坐标(Y)写入绘图 RAM 地址;
将 D15——D8 写入到 RAM 中;将 D7——D0 写入到 RAM 中;
打开绘图显示功能。
绘图显示的缓冲区对应分布请参考“显示坐标”
3、游标/闪烁控制
ST7920A 提供硬件游标及闪烁控制电路,由地址计数器(address counter)的值来指定 DDRAM 中的游标或闪烁位置
1.1.6并口LCD12864应用设计
LCD12864设计思路和1602一样,这里直接贴出代码:
代码6‑9 lcd_basemod代码
|
1.//****************************************************************************// 2.//# @Author: 碎碎思 3.//# @Date: 2019-05-19 20:56:01 4.//# @Last Modified by: zlk 5.//# @WeChat Official Account: OpenFPGA 6.//# @Last Modified time: 2019-07-07 17:16:46 7.//# Description: 8.//# @Modification History: 2019-05-19 20:57:52 9.//# Date By Version Change Description: 10.//# ========================================================================= # 11.//# 2019-05-19 20:57:52 12.//# ========================================================================= # 13.//# | | # 14.//# | OpenFPGA | # 15.//****************************************************************************// 16.module lcd_basemod 17.( 18. input CLOCK, RST_n, 19. //lcd1602 interface 20. output LCD_RS, //H: Data; L: Instruction code 21. output LCD_RW, //H: Read; L: Write 22. output LCD_EN, //LCD1602 Chip enable signal 23. output [7:0] LCD_D //LCD1602 Data interface 24. 25. // input iCall, 26. //output oDone, 27. //input [5:0]iData 28. 29.); 30. 31.//****************************************************************************// 32.// 取模数据 33.//****************************************************************************// 34.//-------------------------------- 35.//Driver of LCD1602 36.localparam [127:0] line_rom1 = " Subscriptions: ";//"Hello World*^_^*";//第一行固定显示 37.wire [127:0] line_rom2; //= "OpenFPGA *^_^*";//"I am OpenFPGA!"; //第二行滚动显示 38.localparam [127:0] line_rom3 = " I am OpenFPGA!!"; 39.localparam [127:0] line_rom4 = "!!!!Welcome!!!!"; 40. 41.//***************************************************************************// 42.wire DoneU1; 43.//wire [7:0] oDATA; 44. 45. 46. lcd_funcmod U1 47. ( 48. .CLOCK( CLOCK ), 49. .RST_n( RST_n ), 50. .LCD_RS( LCD_RS ), // > top 51. .LCD_RW( LCD_RW ), // > top 52. .LCD_EN( LCD_EN ), // <> top 53. .LCD_D(LCD_D), 54. .line_rom1( line_rom1 ), // > top 55. .line_rom2( line_rom2 ), // > U2 56. .line_rom3( line_rom3 ), // > U2 57. .line_rom4( line_rom4 ), // > U2 58. .iCall( 1'b1 ), // < U1 59. .oDone( DoneU1 ) // > U1 60. 61. 62. ); 63. 64. reg [7:0]i; 65.// reg [127:0]isLine_rom2; 66. reg [23:0] Data; 67. reg [7:0]isData; 68. always @ ( posedge CLOCK or negedge RST_n ) 69. if( !RST_n ) 70. begin 71. i <= 8'd0; 72. Data <= 24'd0; 73. isData <= 8'd0; 74.// isLine_rom2 <= {"Number:",Data}; 75. end 76. else 77. case( i ) 78.//************************初始化操作*********************************// 79. 0 : 80. 81. if( DoneU1 ) begin i <= i + 1'b1;end 82. 83. 84. 1 : 85. if( DoneU1) begin isData<= isData+1'b1;i <= i + 1'b1; end 86.// else begin isCall[1]<= 1'b1; end//Display off 87. 88. 2 : 89. if( DoneU1 ) begin 90. 91. if(isData==16) begin isData<=8< span="">'d0;i <= i + 1'b1; end 92. else begin i <= i + 1'b1; end 93. 94. end//Clear the LCD 95. 96. 3: 97. case (isData) 98. 0: 99. begin Data = "00";i <=i+1'b1; end 100. 1: 101. begin Data = "01";i <=i+1'b1; end 102. 2: 103. begin Data = "02";i <=i+1'b1; end 104. 3: 105. begin Data = "03";i <=i+1'b1; end 106. 4: 107. begin Data = "04";i <=i+1'b1; end 108. 5: 109. begin Data = "05";i <=i+1'b1; end 110. 6: 111. begin Data = "06";i <=i+1'b1; end 112. 7: 113. begin Data = "07";i <=i+1'b1; end 114. 8: 115. begin Data = "08";i <=i+1'b1; end 116. 9: 117. begin Data = "09";i <=i+1'b1; end 118. 10: 119. begin Data = "10";i <=i+1'b1; end 120. 11: 121. begin Data = "11";i <=i+1'b1; end 122. 12: 123. begin Data = "12";i <=i+1'b1; end 124. 13: 125. begin Data = "13";i <=i+1'b1; end 126. 14: 127. begin Data = "14";i <=i+1'b1; end 128. 15: 129. begin Data = "15";i <=i+1'b1; end 130. 16: 131. begin Data = "16";i <=i+1'b1; end 132. 133. default :begin Data = "000";i <=i+1'b1; end 134. 135. endcase 136. 137. 4: 138. i <= 8'd0;//8'd7 139. endcase 140. 141. 142. assign line_rom2 = {" My Number:",Data};//; 143.// assign oDATA = D1; 144. 145. 146.endmodule |
代码6‑10 lcd_funcmod代码
|
1.//****************************************************************************// 2.//# @Author: 碎碎思 3.//# @Date: 2019-05-19 21:06:32 4.//# @Last Modified by: zlk 5.//# @WeChat Official Account: OpenFPGA 6.//# @Last Modified time: 2019-07-07 17:28:02 7.//# Description: 8.//# @Modification History: 2019-05-19 20:58:19 9.//# Date By VerDATAn Change Description: 10.//# ========================================================================= # 11.//# 2019-05-19 20:58:19 12.//# ========================================================================= # 13.//# | | # 14.//# | OpenFPGA | # 15.//****************************************************************************// 16.module lcd_funcmod 17.( 18. input CLOCK, RST_n, 19. 20. //lcd1602 interface 21. output LCD_RS, //H: Data; L: Instruction code 22. output LCD_RW, //H: Read; L: Write 23. output LCD_EN, //LCD1602 Chip enable signal 24. output [7:0] LCD_D, //LCD1602 Data interface 25. 26. input [127:0] line_rom1, //LCD1602 1th row display 27. input [127:0] line_rom2, //LCD1602 2th row display 28. input [127:0] line_rom3, //LCD1602 2th row display 29. input [127:0] line_rom4, //LCD1602 2th row display 30. //Signal 31. input iCall, 32. output oDone 33.); 34. parameter DELAY_TIME = 1000_000; //Delay for 20ms 35. //localparam DELAY_TIME = 20'd1000; //Just for test 36. parameter FCLK = 20'd100_000, FHALF = 20'd50_000; // 500hz,(1/500hz)/(1/50Mhz) FCLK 为一个周期 37. //localparam FCLK = 20'd100, FHALF = 20'd50; //Just for test 38. parameter FF_Write = 8'd125;//FHALF 为半周期 //tsp1的延时 39. //localparam FF_Write = 20'd16; //Just for test 40. 41. 42. assign LCD1602_RW=1'b0; 43. reg [19:0]C1,C2; 44. reg [7:0]i,Go; 45. reg [7:0]T; //D1 为暂存读取结果 T 为伪函数的操作空间 46. reg rRS, rEN; 47. reg [7:0]rDATA; 48. reg isDone; //isQ 为 IO 的控制输出 49. 50.//LCD1602 init 51.localparam DISP_SET = 8'h30; //Display mode: Set 16X2,5X8, 8 bits data 52.localparam DISP_OFF = 8'h08; //Display off 53.localparam CLR_SCR = 8'h01; //Clear the LCD 54.localparam CURSOR_SET1 = 8'h06; //Set Cursor 55.localparam CURSOR_SET2 = 8'h0C; //Display on 56.//Display 1th line 57.localparam ROW1_ADDR = 8'h80; //Line1's first address 58. 59.//Display 2th line 60.localparam ROW2_ADDR = 8'h90; //Line2's first address 61. 62.//Display 3th line 63.localparam ROW3_ADDR = 8'h88; //Line3's first address 64. 65.//Display 4th line 66.localparam ROW4_ADDR = 8'h98; //Line4's first address 67. 68. always @ ( posedge CLOCK or negedge RST_n ) 69. if( !RST_n ) 70. begin 71. { C1,C2 } <={ 20'd0,20'd0 }; 72. { i,Go } <= { 8'd0,8'd0 }; 73. T <= 8'd0; 74. { rRS, rEN, rDATA } <= 3'b000; 75. isDone <= 1'b0; 76. end 77./*********************************************************************** 78.下面步骤是写一个字节的伪函数。步骤 0 拉高片选,准备访问字节,并且进入伪函数。 79.步骤 1 准备写入数据并且进入伪函数。 80.步骤 2 拉低片选,步骤 3~4 则是用来产生完成信号。 81.***********************************************************************/ 82. else if( iCall ) 83. case( i ) 84. 85. 0://延时20ms 86. begin 87. { rRS,rEN } <= 2'b01; 88. if( C2 == DELAY_TIME -1) begin C2 <= 20'd0; i <= i + 1'b1; end 89. else C2 <= C2 + 1'b1; 90. end 91. 92. 1: 93. begin rRS <=1< span="">'b0;i <= i + 1'b1; end //{ rRS,rEN } <= 2'b01; 94. 95. 2: 96. begin T <= 8'h00; i <= FF_Write; Go <= i + 1'b1; end //IDLE 97. 98. 3: 99. begin T <= DISP_SET; i <= FF_Write; Go <= i + 1'b1; end 100. 101. 4: 102. begin T <= DISP_OFF; i <= FF_Write; Go <= i + 1'b1; end 103. 104. 5: 105. begin T <= CLR_SCR; i <= FF_Write; Go <= i + 1'b1; end 106. 107. 6: 108. begin T <= CURSOR_SET1; i <= FF_Write; Go <= i + 1'b1; end 109. 110. 7: 111. begin T <= CURSOR_SET2; i <= FF_Write; Go <= i + 1'b1; end 112. 113. 114. 8: 115. begin isDone <= 1'b1; i <= i + 1'b1; end 116. 117. 9: 118. begin isDone <= 1'b0; i <= i + 1'b1; end 119. 120. 10: 121. begin rRS <=1< span="">'b0; i <= i + 1'b1; end//{ rRS,rEN } <= 2'b00; 122. 11: 123. begin T <= ROW1_ADDR; i <= FF_Write; Go <= i + 1'b1; end 124. 12: 125. begin rRS <=1< span="">'b1; i <= i + 1'b1; end//{ rRS,rEN } <= 2'b11; 126. 127. 13: 128. begin T <= line_rom1[127:120]; i <= FF_Write; Go <= i + 1'b1; end 129. 14: 130. begin T <= line_rom1[119:112]; i <= FF_Write; Go <= i + 1'b1; end 131. 15: 132. begin T <= line_rom1[111:104]; i <= FF_Write; Go <= i + 1'b1; end 133. 16: 134. begin T <= line_rom1[103: 96]; i <= FF_Write; Go <= i + 1'b1; end 135. 17: 136. begin T <= line_rom1[ 95: 88]; i <= FF_Write; Go <= i + 1'b1; end 137. 18: 138. begin T <= line_rom1[ 87: 80]; i <= FF_Write; Go <= i + 1'b1; end 139. 19: 140. begin T <= line_rom1[ 79: 72]; i <= FF_Write; Go <= i + 1'b1; end 141. 20: 142. begin T <= line_rom1[ 71: 64]; i <= FF_Write; Go <= i + 1'b1; end 143. 21: 144. begin T <= line_rom1[ 63: 56]; i <= FF_Write; Go <= i + 1'b1; end 145. 22: 146. begin T <= line_rom1[ 55: 48]; i <= FF_Write; Go <= i + 1'b1; end 147. 23: 148. begin T <= line_rom1[ 47: 40]; i <= FF_Write; Go <= i + 1'b1; end 149. 24: 150. begin T <= line_rom1[ 39: 32]; i <= FF_Write; Go <= i + 1'b1; end 151. 25: 152. begin T <= line_rom1[ 31: 24]; i <= FF_Write; Go <= i + 1'b1; end 153. 26: 154. begin T <= line_rom1[ 23: 16]; i <= FF_Write; Go <= i + 1'b1; end 155. 27: 156. begin T <= line_rom1[ 15: 8]; i <= FF_Write; Go <= i + 1'b1; end 157. 28: 158. begin T <= line_rom1[ 7: 0]; i <= FF_Write; Go <= i + 1'b1; end 159. 160. /**********************************************************************/ 161. 29: 162. begin rRS <=1< span="">'b0; i <= i + 1'b1; end//{ rRS,rEN } <= 2'b00; 163. 30: 164. begin T <= ROW2_ADDR; i <= FF_Write; Go <= i + 1'b1; end 165. 31: 166. begin rRS <=1< span="">'b1;i <= i + 1'b1; end//{ rRS,rEN } <= 2'b11; 167. 32: 168. i <= i + 1'b1; 169. 33: 170. begin T <= line_rom2[127:120]; i <= FF_Write; Go <= i + 1'b1; end 171. 34: 172. begin T <= line_rom2[119:112]; i <= FF_Write; Go <= i + 1'b1; end 173. 35: 174. begin T <= line_rom2[111:104]; i <= FF_Write; Go <= i + 1'b1; end 175. 36: 176. begin T <= line_rom2[103: 96]; i <= FF_Write; Go <= i + 1'b1; end 177. 37: 178. begin T <= line_rom2[ 95: 88]; i <= FF_Write; Go <= i + 1'b1; end 179. 38: 180. begin T <= line_rom2[ 87: 80]; i <= FF_Write; Go <= i + 1'b1; end 181. 39: 182. begin T <= line_rom2[ 79: 72]; i <= FF_Write; Go <= i + 1'b1; end 183. 40: 184. begin T <= line_rom2[ 71: 64]; i <= FF_Write; Go <= i + 1'b1; end 185. 41: 186. begin T <= line_rom2[ 63: 56]; i <= FF_Write; Go <= i + 1'b1; end 187. 42: 188. begin T <= line_rom2[ 55: 48]; i <= FF_Write; Go <= i + 1'b1; end 189. 43: 190. begin T <= line_rom2[ 47: 40]; i <= FF_Write; Go <= i + 1'b1; end 191. 44: 192. begin T <= line_rom2[ 39: 32]; i <= FF_Write; Go <= i + 1'b1; end 193. 45: 194. begin T <= line_rom2[ 31: 24]; i <= FF_Write; Go <= i + 1'b1; end 195. 46: 196. begin T <= line_rom2[ 23: 16]; i <= FF_Write; Go <= i + 1'b1; end 197. 47: 198. begin T <= line_rom2[ 15: 8]; i <= FF_Write; Go <= i + 1'b1; end 199. 48: 200. begin T <= line_rom2[ 7: 0]; i <= FF_Write; Go <= i + 1'b1; end//Go <= i + 1'b1; 201. 49: 202. begin { rRS,rEN } <= 2'b01; i <= i + 1'b1; end 203. 204. 50: 205. begin isDone <= 1'b1; i <= i + 1'b1; end 206. 207. 51: 208. begin isDone <= 1'b0; i <= i + 1'b1; end// 209. 210./************ **********************************************************/ 211. 52: 212. begin rRS <=1< span="">'b0; i <= i + 1'b1; end//{ rRS,rEN } <= 2'b00; 213. 53: 214. begin T <= ROW3_ADDR; i <= FF_Write; Go <= i + 1'b1; end 215. 54: 216. begin rRS <=1< span="">'b1;i <= i + 1'b1; end//{ rRS,rEN } <= 2'b11; 217. 55: 218. i <= i + 1'b1; 219. 56: 220. begin T <= line_rom3[127:120]; i <= FF_Write; Go <= i + 1'b1; end 221. 57: 222. begin T <= line_rom3[119:112]; i <= FF_Write; Go <= i + 1'b1; end 223. 58: 224. begin T <= line_rom3[111:104]; i <= FF_Write; Go <= i + 1'b1; end 225. 59: 226. begin T <= line_rom3[103: 96]; i <= FF_Write; Go <= i + 1'b1; end 227. 60: 228. begin T <= line_rom3[ 95: 88]; i <= FF_Write; Go <= i + 1'b1; end 229. 61: 230. begin T <= line_rom3[ 87: 80]; i <= FF_Write; Go <= i + 1'b1; end 231. 62: 232. begin T <= line_rom3[ 79: 72]; i <= FF_Write; Go <= i + 1'b1; end 233. 63: 234. begin T <= line_rom3[ 71: 64]; i <= FF_Write; Go <= i + 1'b1; end 235. 64: 236. begin T <= line_rom3[ 63: 56]; i <= FF_Write; Go <= i + 1'b1; end 237. 65: 238. begin T <= line_rom3[ 55: 48]; i <= FF_Write; Go <= i + 1'b1; end 239. 66: 240. begin T <= line_rom3[ 47: 40]; i <= FF_Write; Go <= i + 1'b1; end 241. 67: 242. begin T <= line_rom3[ 39: 32]; i <= FF_Write; Go <= i + 1'b1; end 243. 68: 244. begin T <= line_rom3[ 31: 24]; i <= FF_Write; Go <= i + 1'b1; end 245. 69: 246. begin T <= line_rom3[ 23: 16]; i <= FF_Write; Go <= i + 1'b1; end 247. 70: 248. begin T <= line_rom3[ 15: 8]; i <= FF_Write; Go <= i + 1'b1; end 249. 71: 250. begin T <= line_rom3[ 7: 0]; i <= FF_Write; Go <= i + 1'b1; end//Go <= i + 1'b1; 251. 72: 252. begin { rRS,rEN } <= 2'b01; i <= i + 1'b1; end 253. 73:i <= i + 1'b1; 254. 255. 74: 256. begin isDone <= 1'b1; i <= i + 1'b1; end 257. 258. 75: 259. begin isDone <= 1'b0; i <= i + 1'b1; end// 260. 261./*************** *******************************************************/ 262. 76: 263. begin rRS <=1< span="">'b0; i <= i + 1'b1; end//{ rRS,rEN } <= 2'b00; 264. 77: 265. begin T <= ROW4_ADDR; i <= FF_Write; Go <= i + 1'b1; end 266. 78: 267. begin rRS <=1< span="">'b1;i <= i + 1'b1; end//{ rRS,rEN } <= 2'b11; 268. 79: 269. i <= i + 1'b1; 270. 80: 271. begin T <= line_rom4[127:120]; i <= FF_Write; Go <= i + 1'b1; end 272. 81: 273. begin T <= line_rom4[119:112]; i <= FF_Write; Go <= i + 1'b1; end 274. 82: 275. begin T <= line_rom4[111:104]; i <= FF_Write; Go <= i + 1'b1; end 276. 83: 277. begin T <= line_rom4[103: 96]; i <= FF_Write; Go <= i + 1'b1; end 278. 84: 279. begin T <= line_rom4[ 95: 88]; i <= FF_Write; Go <= i + 1'b1; end 280. 85: 281. begin T <= line_rom4[ 87: 80]; i <= FF_Write; Go <= i + 1'b1; end 282. 86: 283. begin T <= line_rom4[ 79: 72]; i <= FF_Write; Go <= i + 1'b1; end 284. 87: 285. begin T <= line_rom4[ 71: 64]; i <= FF_Write; Go <= i + 1'b1; end 286. 88: 287. begin T <= line_rom4[ 63: 56]; i <= FF_Write; Go <= i + 1'b1; end 288. 89: 289. begin T <= line_rom4[ 55: 48]; i <= FF_Write; Go <= i + 1'b1; end 290. 90: 291. begin T <= line_rom4[ 47: 40]; i <= FF_Write; Go <= i + 1'b1; end 292. 91: 293. begin T <= line_rom4[ 39: 32]; i <= FF_Write; Go <= i + 1'b1; end 294. 92: 295. begin T <= line_rom4[ 31: 24]; i <= FF_Write; Go <= i + 1'b1; end 296. 93: 297. begin T <= line_rom4[ 23: 16]; i <= FF_Write; Go <= i + 1'b1; end 298. 94: 299. begin T <= line_rom4[ 15: 8]; i <= FF_Write; Go <= i + 1'b1; end 300. 95: 301. begin T <= line_rom4[ 7: 0]; i <= FF_Write; Go <= i + 1'b1; end//Go <= i + 1'b1; 302. 96: 303. begin { rRS,rEN } <= 2'b01; i <= i + 1'b1; end 304. 305. 97: 306. begin isDone <= 1'b1; i <= i + 1'b1; end 307. 308. 98: 309. begin isDone <= 1'b0; i <= 8'd10; end// 310. 311. /******************/ 312. 313. 125: 314. begin 315. 316. rDATA <= T;// 317. 318. if( C1 == 0 ) rEN <= 1'b1; 319. else if( C1 == FHALF ) rEN <= 1'b0; 320. 321. if( C1 == FCLK -1) begin C1 <= 20'd0; i <= i + 1'b1; end 322. else C1 <= C1 + 1'b1; 323. end 324. 325. 126: 326. i <= Go; 327. 328. endcase 329. 330./*********************************************************************** 331.以下内容为相关输出驱动声明,其中 rDATA 驱动 LCD1602_D_DATA, D 驱动 oData 。 332.***********************************************************************/ 333. assign { LCD_RS,LCD_EN } = { rRS,rEN }; 334. assign LCD_D = rDATA ; //isQ ? rDATA : 1'bz; 335. assign oDone = isDone; 336. 337.endmodule |
综合后下载代码,会在LCD12864上显示下图字体:

图6‑34 实验结果图
1.1.7四线SPILCD12864应用设计
详见代码。

