2)摘自《开拓者FPGA开发指南》关注官方微信号公众号,获取更多资料:正点原子
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-13912-1-1.html
第二十三章 RGB TFT-LCD字符显示实验
我们在RGB TFT-LCD彩条显示实验中通过对VGA彩条显示程序稍作修改,成功的在ATK-
7’RGBLCD液晶屏模块上显示出了彩条。本章我们同样参考VGA字符显示实验,在LCD上完成汉
字“正点原子”的显示。
本章包括以下几个部分:
23.1 RGB TFT-LCD简介
23.2 实验任务
23.3 硬件设计
23.4 程序设计
23.5 下载验证
RGB TFT-LCD简介
我们在“RGB TFT-LCD彩条显示实验”中对ATK-7’RGBLCD液晶屏模块作了详细的介绍,包
括数据输入时序、同步方式、以及分辨率等。如果大家对这部分内容不是很熟悉的话,请参考
“RGB TFT-LCD彩条显示实验”中的简介部分。
实验任务
本章的实验任务是通过开拓者开发板上的RGB TFTLCD接口在ATK-7’RGBLCD液晶屏的中心
位置显示四个汉字“正点原子”,每个汉字的大小为32*32。
硬件设计
RGB TFTLCD接口部分的硬件设计原理及本实验中各端口信号的管脚分配与“RGB TFT-LCD
彩条显示实验”完全相同,请参考“RGB TFT-LCD彩条显示实验”中的硬件设计部分。
程序设计
图 23.4.1是根据本章实验任务画出的系统框图。其中,时钟分频模块负责产生像素时钟,
LCD驱动模块产生同步信号,LCD显示模块输出图像数据。
图 23.4.1 RGB TFT-LCD字符显示实验系统框图
字符显示的原理及字模的提取方法请大家参考“VGA字符显示实验”中的程序设计部分。
由于本章实验任务要求显示汉字的大小为32*32,那么四个汉字的点阵每行为128个像素点,需
要16个Byte的数据来表示。因此在导出字模数据前,需要在“字模选项”中将“每行显示数据
—点阵”处设置为16,如下图所示:
图 23.4.2 字模格式配置界面
最终由四个汉字“正点原子”提取到的字模数据如图 23.4.3所示。数据以十六进制显示,
每行有16个Byte,对应每行四个汉字共128个像素点;共有32行,对应每个汉字的高度为32。
图 23.4.3 “正点原子”32*32字模
提取字模完成后,我们需要在LCD显示模块中将获取的点阵数据映射到液晶屏中心32*128
个的像素点的字符显示区域,从而实现字符的显示。
程序中各模块端口及信号连接如图 23.4.4所示:
图 23.4.4 顶层模块原理图
图 23.4.4中的顶层模块(lcd_rgb_char)、时钟分频模块(lcd_pll)以及LCD驱动模块
(lcd _driver)均与“RGB TFT-LCD彩条显示实验”完全相同,只对LCD显示模块(lcd_display)
作了修改。因此,这里我们重点讲解LCD显示模块,其他部分大家可以参考“RGB TFT-LCD彩条
显示实验”。
LCD显示模块的代码如下:
1
module lcd_display
(
2
input lcd_clk
, //lcd驱动时钟
3
input sys_rst_n
, //复位信号
4
5
input [10
:0
] pixel_xpos
, //像素点横坐标
6
input [10
:0
] pixel_ypos
, //像素点纵坐标
7
output reg [15
:0
] pixel_data //像素点数据,
8
);
9
10 //parameter define
11
parameter H_DISP
= 11'd800
; //分辨率——行
12
parameter V_DISP
= 11'd480
; //分辨率——列
13
14
localparam POS_X
= 11'd336
; //字符区域起始点横坐标
15
localparam POS_Y
= 11'd224
; //字符区域起始点纵坐标
16
localparam WIDTH
= 11'd128
; //字符区域宽度
17
localparam HEIGHT
= 11'd32
; //字符区域高度
18
localparam RED
= 16'b11111_000000_00000
; //屏幕背景色
19
localparam BLUE
= 16'b00000_000000_11111
; //字符颜色
20
localparam BLACK
= 16'b00000_000000_00000
; //字符区域背景色
21
22 //reg define
23
reg [127
:0
] char
[31
:0
]; //字符数组
24
25 //wire define
26
wire [10
:0
] x_cnt
;
27
wire [10
:0
] y_cnt
;
28
29 //*****************************************************
30 //** main code
31 //*****************************************************
32
assign x_cnt
= pixel_xpos
- POS_X
; //像素点相对于字符区域起始点水平坐标
33
assign y_cnt
= pixel_ypos
- POS_Y
; //像素点相对于字符区域起始点竖直坐标
34
35 //给字符数组赋值,显示汉字“正点原子”,汉字大小为32*32
36
always @(posedge lcd_clk
) begin
37 char
[0
] <= 128'h00000000000000000000000000000000
;
38 char
[1
] <= 128'h00000000000000000000000000000000
;
39 char
[2
] <= 128'h00000000000100000000002000000000
;
40 char
[3
] <= 128'h000000380001800002000070000000C0
;
41 char
[4
] <= 128'h0000007C0001800003FFFFF803FFFFE0
;
42 char
[5
] <= 128'h0FFFFFFE0001800003006000000001E0
;
43 char
[6
] <= 128'h0001E000000180600300600000000300
;
44 char
[7
] <= 128'h0001E0000001FFF00300C00000000600
;
45 char
[8
] <= 128'h0001E000000180000310804000001800
;
46 char
[9
] <= 128'h0001E00000018000031FFFE000003000
;
47 char
[10
] <= 128'h0001E00000018000031800400001C000
;
48 char
[11
] <= 128'h0181E00000018000031800400001C000
;
49 char
[12
] <= 128'h01E1E000018181800318004000018000
;
50 char
[13
] <= 128'h01F1E00001FFFFC0031FFFC000018010
;
51 char
[14
] <= 128'h01E1E0E0018001800318004000018038
;
52 char
[15
] <= 128'h01E1FFF001800180031800403FFFFFFC
;
53 char
[16
] <= 128'h01E1E018018001800318004000018000
;
54 char
[17
] <= 128'h01E1E000018001800218004000018000
;
55 char
[18
] <= 128'h01E1E00001800180021FFFC000018000
;
56 char
[19
] <= 128'h01E1E000018001800210304000018000
;
57 char
[20
] <= 128'h01E1E00001FFFF800200300000018000
;
58 char
[21
] <= 128'h01E1E000018001800606300000018000
;
59 char
[22
] <= 128'h01E1E000018001000607370000018000
;
60 char
[23
] <= 128'h01E1E00000000000060E31C000018000
;
61 char
[24
] <= 128'h01E1E000001000400418307000018000
;
62 char
[25
] <= 128'h01E1E000020830600430303800018000
;
63 char
[26
] <= 128'h01E1E038020C18300860301800018000
;
64 char
[27
] <= 128'h01E1E07C060E18180883700800018000
;
65 char
[28
] <= 128'h7FFFFFFE0C0618181100F008003F8000
;
66 char
[29
] <= 128'h000000001C0408182000600000070000
;
67 char
[30
] <= 128'h00000000000000000000000000020000
;
68 char
[31
] <= 128'h00000000000000000000000000000000
;
69
end
70
71 //给不同的区域绘制不同的颜色
72
always @(posedge lcd_clk
or negedge sys_rst_n
) begin
73
if (!sys_rst_n
)
74 pixel_data
<= BLACK
;
75
else begin
76
if((pixel_xpos
>= POS_X
) && (pixel_xpos
< POS_X
+ WIDTH
)
77
&& (pixel_ypos
>= POS_Y
) && (pixel_ypos
< POS_Y
+ HEIGHT
)) begin
78
if(char
[y_cnt
][11'd127
- x_cnt
])
79 pixel_data
<= BLUE
; //绘制字符为蓝色
80
else
81 pixel_data
<= BLACK
; //绘制字符区域背景为黑色
82
end
83
else
84 pixel_data
<= RED
; //绘制屏幕背景为红色
85
end
86
end
87
88
endmodule
LCD显示模块直接在“VGA字符显示实验”中VGA显示模块的基础上稍作修改即可。由于在
代码的10至20行声明了一系列的变量,定义了屏幕分辨率、字符在屏幕上显示的位置、以及字
符的大小、颜色等,因此我们可以非常方便地通过修改这些变量来满足本章的实验要求。
因为字符的大小相比于VGA字符显示实验发生了改变,因此在程序的第23行我们将字符数
组的位宽调整为128bit,并将前面提取的字模数据赋值给该字符数组,如程序中第35~69行所
示。另外程序第78行将字符显示区域内的像素点与字符数组char中的点阵数据一一映射,此处
需要将字符数组的索引调整为char[y_cnt][11'd127 - x_cnt]。有关该模块更详细的设计思路
请大家参考“VGA字符显示实验”。
图 23.4.5为LCD显示模块显示汉字“正点原子”第13行时SignalTap抓取的波形图。对照
取模得到的点阵数据第13行(01E1E000018181800318004000018000)可以看出,当点阵数据为
0时,像素点被赋值为黑色(0000);当点阵数据为1时,像素点被赋值为蓝色(001F);字符
显示区域外的屏幕背景为红色(F800)。各区域中的像素点能够被赋以正确的颜色值。
图 23.4.5 SignalTap波形图
下载验证
RGB TFT-LCD字符显示实验的工程位于lcd_rgb_char文件夹中,请大家参考RGB TFT-LCD彩
条 显 示 实 验 中 的 下 载 验 证 方 法 , 将 lcd_rgb_char/par/output_files 目 录 下 的
“lcd_rgb_char.sof”文件下载至开发板。下载完成后在ATK-7’RGBLCD液晶屏模块上观察显
示的汉字如图 23.5.1所示,说明RGB TFT-LCD字符显示程序下载验证成功。
图 23.5.1 RGB TFT-LCD字符显示