LCD显示图片和字符


前言

上一篇文章实现的驱动LCD显示一个移动的方块。本文要实现LCD显示图片和字符(汉字),图片直接初始化到RAM中,字符由取模软件取出。


一、图片的初始化与显示

图片转换成需要的RGB888

用Windows自带的画图打开图片,点击重新调整大小,256*256像素。

分辨率转换
另存为你需要的格式 我用的RGB888所以选择24位位图,bmp格式。
保存
打开图片转换的软件,加载图片,选择格式和输出的文件类型,我选的.coe类型。软件直接搜BMP2Mif就行。
图片转换软件

RAM IP核初始化数据

单端口RAM
RAM IP核配置
因为RGB888是24位,所以数据深度24,256*256等于65536。
RAM IP核配置
点击Browse选择.coe文件来加载初始化数据。
RAM IP核配置
点击OK完成配置之后直接例化就行,地址的输入看后面的代码。

二、字符显示

取模

设置字符的分辨率。
字符分辨率
字模配置,点阵4是因为32/8=4。32是横向分辨率,除8是因为是16进制。
字符配置
生成字模
生成字模
生成的字模是一个字一个字的我手动把四个字对齐写在一起。

数据

00000000000000000000000000000000;
00000000000000000000000000000000;
0000400000400000000C000000104100;
000E700000700000000F200000186180;
003E630000600000000C180018386180;
07E061C000600000000C0E0004706180;
086060E000600000000C070003606180;
0060606000600000000C030001C06188;
0060606000600030000C0110019FFFFC;
00606010007FFFF8000C003803C06180;
00606030006000003FFFFFFC06406180;
3FFFFFF800600000000C300008406180;
0060200000600000000C300010606180;
0060200000600000000C304020600000;
0060204000400020000C30E000E40010;
006030E000FFFFF0000C30C000E3FFF8;
006130C000C000600008318001A20C30;
006E3180000000600018330001220C30;
00703300000000600018360003220C30;
07E033000000006000183C0006220C30;
3E60160000000060003038000C220C30;
38601C0000001860003030080823FFF0;
106018003FFFFC600060700810220C30;
00603C04000000600060F00820620C30;
00606E040000006000C3300800620C30;
00618704000000C00184300800620C30;
0063038C000000C00318300C00620C30;
006C01CC000041C006003FFC00C20C30;
07F000FC00003F800C001FF807C3FFF0;
01C0003C00000F001000000003820030;
00800006000006002000000001020000;
00000000000000000000000000000000;

三、显示图像字符代码

lcd_display.v

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/05/16 19:54:26
// Design Name: 
// Module Name: lcd_display
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module lcd_display(
input				vpg_clk,
input				rst	,
input wire [12:0]	cnt_h,		//行计数器
input wire [12:0]	cnt_v,		//场计数器
output	reg[23:0]	RGB
    );
	
parameter  MAX = 65536 - 1; //256*256 - 1
reg			w_ram_en	;
reg [15:0]	r_addr		;
reg [23:0]	din			;
wire [23:0]	dout		;

//--------------------------vga时序参数--------------------
//场同步信号
parameter		H_TOTAL = 525 - 1;
parameter		H_SYNC  = 41 - 1;

parameter		H_START = 43 - 1;//数据开始结束计算值
parameter		H_END   = 523 - 1;
//行同步信号
parameter		V_TOTAL = 286 - 1;
parameter		V_SYNC  = 10 - 1;

parameter 		V_START	= 12 - 1;//数据开始结束计算值
parameter		V_END   = 284 - 1;

//场图像数据
parameter		IMG_X    = 256;//方块x
parameter		IMG_Y	 = 256;//方块y
parameter		STRING_X = 128;//字符x
parameter		STRING_Y = 32;//字符y
parameter		SCREEN_X = 480;//屏幕水平长度
parameter		SCREEN_Y = 272;//屏幕垂直长度
	
reg [127:0] char[31:0]; //字符数组

reg [11:0]		x;		//方块左上角横坐标
reg [11:0]		y;		//方块左上角纵坐标

//-----------------------------------字符赋值-----------------------
always @(posedge vpg_clk) begin
    char[0 ]  <= 128'h00000000000000000000000000000000;
    char[1 ]  <= 128'h00000000000000000000000000000000;
    char[2 ]  <= 128'h0000400000400000000C000000104100;
    char[3 ]  <= 128'h000E700000700000000F200000186180;
    char[4 ]  <= 128'h003E630000600000000C180018386180;
    char[5 ]  <= 128'h07E061C000600000000C0E0004706180;
    char[6 ]  <= 128'h086060E000600000000C070003606180;
    char[7 ]  <= 128'h0060606000600000000C030001C06188;
    char[8 ]  <= 128'h0060606000600030000C0110019FFFFC;
    char[9 ]  <= 128'h00606010007FFFF8000C003803C06180;
    char[10]  <= 128'h00606030006000003FFFFFFC06406180;
    char[11]  <= 128'h3FFFFFF800600000000C300008406180;
    char[12]  <= 128'h0060200000600000000C300010606180;
    char[13]  <= 128'h0060200000600000000C304020600000;
    char[14]  <= 128'h0060204000400020000C30E000E40010;
    char[15]  <= 128'h006030E000FFFFF0000C30C000E3FFF8;
    char[16]  <= 128'h006130C000C000600008318001A20C30;
    char[17]  <= 128'h006E3180000000600018330001220C30;
    char[18]  <= 128'h00703300000000600018360003220C30;
    char[19]  <= 128'h07E033000000006000183C0006220C30;
    char[20]  <= 128'h3E60160000000060003038000C220C30;
    char[21]  <= 128'h38601C0000001860003030080823FFF0;
    char[22]  <= 128'h106018003FFFFC600060700810220C30;
    char[23]  <= 128'h00603C04000000600060F00820620C30;
    char[24]  <= 128'h00606E040000006000C3300800620C30;
    char[25]  <= 128'h00618704000000C00184300800620C30;
    char[26]  <= 128'h0063038C000000C00318300C00620C30;
    char[27]  <= 128'h006C01CC000041C006003FFC00C20C30;
    char[28]  <= 128'h07F000FC00003F800C001FF807C3FFF0;
    char[29]  <= 128'h01C0003C00000F001000000003820030;
    char[30]  <= 128'h00800006000006002000000001020000;
    char[31]  <= 128'h00000000000000000000000000000000;
end

//RGB
always @(posedge vpg_clk ) begin 
	if (!rst) begin
		RGB <='d0;
	end
	else if(cnt_h >= H_START + x && cnt_h < H_START + IMG_X + x && cnt_v >= V_START + y && cnt_v < V_START +IMG_Y + y)begin
//		RGB <= 24'hFFB6C1;//输出方块
		RGB <= dout;
	end
	
	else if(cnt_h >= H_START + x + IMG_X && cnt_h < H_START + STRING_X + x + IMG_X && cnt_v >= V_START + y && cnt_v < V_START + STRING_Y + y)begin
		if(char[cnt_v - V_START - y - 1'b1][STRING_X - 1'b1 - (cnt_h - H_START - x - IMG_X)])
			RGB <= 24'hFFFF00; //显示字符黄色
			
		else if(cnt_h[4:0] >= 'd20)
			RGB <= 24'h00FF00;
		else if(cnt_h[4:0] >= 'd10)
			RGB <= 24'h0000FF;
		else if(cnt_h[4:0] <= 'd10)
			RGB <= 24'hFF0000;
	end
	

	else if (cnt_h >= H_START && cnt_h < H_END && cnt_v >=V_START && cnt_v < V_END && cnt_h[4:0] >= 'd20) begin
		RGB <=24'h00FF00;//green
	end
	else if (cnt_h >=H_START && cnt_h <H_END && cnt_v >=V_START && cnt_v <V_END && (cnt_h[4:0]>='d10 && cnt_h[2:0]<'d20)) begin
		RGB <=24'h0000FF;//bulue
	end
	else if (cnt_h >=H_START && cnt_h <H_END && cnt_v >=V_START && cnt_v <V_END && cnt_h[4:0]<'d10) begin
		RGB <=24'hFF0000;//red
	end
	
	else begin
		RGB <= 24'h000000;
	end
end

//RAM的例化
blk_mem_gen_0 init (
  .clka(vpg_clk),    // input wire clka
  .wea(w_ram_en),      // input wire [0 : 0] wea
  .addra(r_addr),  // input wire [15 : 0] addra
  .dina(din),    // input wire [23 : 0] dina
  .douta(dout)  // output wire [23 : 0] doutb
);

always @(posedge vpg_clk or negedge rst)
begin
	if(!rst)
	begin
		w_ram_en <= 'd0;
		r_addr <= 'd0;
		din <= 'd0;
		x <= 'd0;	//x y位显示图片左上角坐标
		y <= 'd0;
	end
	//因为RAM读数据有延时 把地址提前两个周期
	//如果不延后图像可能会上下平移 
	else if(cnt_h >= H_START + x  - 2&& cnt_h < H_START + IMG_X + x  - 2&& cnt_v >= V_START + y && cnt_v < V_START +IMG_Y + y )
	begin
		if(r_addr == MAX)
			r_addr <= 'd0;
		else
			r_addr <= r_addr + 1'b1;
	end
	else
		r_addr <= r_addr;
end
endmodule

总结

图片和字符正常显示,下次实现串口发送数据到RAM里在显示出来。
结果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值