596|1

682

帖子

108

资源

纯净的硅(中级)

【国产FPGA高云GW1N-4系列开发板测评】——11、点个LCD1602屏 [复制链接]

本帖最后由 gs001588 于 2022-1-20 20:55 编辑

   【国产FPGA高云GW1N-4系列开发板测评】——11、点个LCD1602屏

   

   之前用在FPGA上写过12864带字库屏的显示应用,间隔时间比较长了,之前备份的资料暂时没有找到。手头正好有LCD1602的LCD屏,不妨先拿LCD1602来做个显示实验。LCD1602作为一款经典的LCD屏,在各种学习平台上的应用自然是少不了的,在FPGA上也不例外。

   本着拿来主义的想法,参考网友资料,做了适当修改。原本打算做成显存方式模块,对外接口为异步RAM方式,模块内部完成LCD初始化,有新显存数据后自动显示刷新操作。这样就需要写顶层文件,需要提供变化的数据源,把问题复杂化,因此可作为之后的改进实验。本贴先显示一下LCD1602。

   参考网址(基于FPGA的LCD1602显示屏驱动 https://blog.csdn.net/qq_33231534/article/details/108484995

 

   本实验使用到的FPGA管脚资源配置如下:
2022-1-20_001.jpg

 

  GWIN-4B与LCD1602屏之间对应关系接线表:

LCD1602 功能说明 GWIN-4B
1、VCC 电源地 JP7.2-5V
2、GND 电源正极 J19.1-GND

3、V0(接5.1K到GND)

液晶显示偏压  
4、RS 命令/数据选择 J4.1-32
5、RW 读/写选择 J4.2-34
6、EN 使能信号 J4.3-38
7、DATA0 数据0 J4.4-39

8、DATA1

数据1 J4.5-40
9、DATA2 数据2 J4.6-41
10、DATA3 数据3 J4.7-42
11、DATA4 数据4 J4.8-43
12、DATA5 数据5 J4.9-44

13、DATA6

数据6 J4.10-45
14、DATA7 数据7 J4.11-46
15、A(5V) 背光正极 JP7.1-5V
16、K(GND) 背光负极 J19.16-GND

 

   LCD1602的1、3脚之间并个5.1K直插电阻,为3脚的液晶显示偏置电压V0提供参考。一般开发板上使用的话会在1、3脚之间接个10K的电位器来调节电压,为啥是5.1K?之前修过一块开发板,在板上3脚接到GND了,导致普通LCD1602不能显示。查询LCD1602数据手册,此管脚V0为液晶显示偏压,接地时对比度最高,对比度过高时会产生“鬼影”,显示发黑不易区分正常显示与底色;接正电源电压时对比度最弱,显示发白几乎看不见。接个5K左右的电阻即可正常显示,电阻不需要精确4到6K都可以。

IMG_20220113_222122_1.jpg

 

   正好JP7有两针5V引出,其中一个给LCD逻辑供电,另一个给背光正极供电;GND比较多,随意选了两个,一个作为电源地,另一个作为背光负极。

IMG_20220113_222052_1.jpg

 

   剩余11条数据线分别一一对应接到JP14的1到11脚。

IMG_20220113_222056_1.jpg

 

   逻辑代码见下。具体功能及LCD1602相关寄存器功能等可以参考上面的“参考网址”中相关内容。

module lcd(
	input				clk			,
	input				rst_n		,
	
	output	reg			lcd_rs		,
	output	wire		lcd_rw		,
	output	reg			lcd_en		,
	output	reg	[7:0]	lcd_data	
	);
 
	reg	[17:0]	cnt				;
	reg	[3:0]	state_c			;
	reg	[3:0]	state_n			;
	reg	[4:0]	char_cnt		;
	reg	[7:0]	data_display	;
 
	localparam
		IDLE			= 4'd0	,
		INIT 			= 4'd1	,
		S0				= 4'd2	,
		S1				= 4'd3	,
		S2				= 4'd4	,
		S3				= 4'd5	,
		ROW1_ADDR		= 4'd6	,
		WRITE			= 4'd7	,
		ROW2_ADDR		= 4'd8	,
		stop			= 4'd9	;

    reg [7:0]   disp_memory [0:31];
    reg	[4:0]	disp_cnt;
 
	assign lcd_rw = 1'b0;
  
	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			cnt <= 17'd0;
		end
		else begin
			if (cnt==17'd100_000 - 1) begin
				cnt <= 17'd0;
			end
			else begin
				cnt <= cnt + 1'b1;
			end
		end
	end
 
	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			lcd_en <= 0;
		end
		else if (cnt==17'd50_000 - 1) begin
			lcd_en <= 1;
		end
		else if (cnt==17'd100_000 - 1) begin
			lcd_en <= 0;
		end
	end
 
	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			char_cnt <= 0;
		end
		else if (state_c==WRITE && cnt==17'd50_000 - 1) begin
			if (char_cnt==5'd31) begin
				char_cnt <= 5'd0;
			end
			else begin
				char_cnt <= char_cnt + 1'b1;
			end
		end
	end

    integer i;

    always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
            for(i=0;i<32;i=i+1)
            begin
                case(i)
                    5'd0: data_display   = "W";
                    5'd1: data_display   = "e";
                    5'd2: data_display   = "l";
                    5'd3: data_display   = "c";
                    5'd4: data_display   = "o";
                    5'd5: data_display   = "m";
                    5'd6: data_display   = "e";
                    5'd7: data_display   = " ";
                    5'd8: data_display   = "t";
                    5'd9: data_display   = "o";
                    5'd10: data_display  = " ";
                    5'd11: data_display  = "G";
                    5'd12: data_display  = "O";
                    5'd13: data_display  = "W";
                    5'd14: data_display  = "I";
                    5'd15: data_display  = "N";

                    5'd16: data_display  = "M";
                    5'd17: data_display  = "i";
                    5'd18: data_display  = "n";
                    5'd19: data_display  = "i";
                    5'd20: data_display  = " ";
                    5'd21: data_display  = "K";
                    5'd22: data_display  = "i";
                    5'd23: data_display  = "T";
                    5'd24: data_display  = " ";
                    5'd25: data_display  = "G";
                    5'd26: data_display  = "W";
                    5'd27: data_display  = "I";
                    5'd28: data_display  = "N";
                    5'd29: data_display  = "-";
                    5'd30: data_display  = "4";
                    5'd31: data_display  = "B";

                    default:data_display = "P";
                endcase

                disp_memory = data_display;
            end
		end
	end

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			state_c <= IDLE;
		end
		else if(cnt==17'd50_000 - 1) begin
			state_c <= state_n;
		end
	end
 
	reg	[19:0]	cnt_15ms;
	reg		flag	;
	always@(posedge clk or negedge rst_n)begin
		if (!rst_n) begin
			cnt_15ms <= 0;
		end
		else if (state_c == IDLE) begin
			cnt_15ms <= cnt_15ms + 1'b1;
		end
	end
 
	always@(posedge clk or negedge rst_n)begin
		if (!rst_n) begin
			flag <= 0;
		end
		else if (state_c==IDLE && cnt_15ms==20'd750000) begin
			flag <= 1;
		end
	end
 
	always @(*) begin
		case(state_c)
			IDLE		:
				begin
					if (flag) begin
						state_n = INIT;
					end
					else begin
						state_n = state_c;
					end
				end
			INIT 	:
				begin
					state_n = S0;
				end
			S0  	:
				begin
					state_n = S1;
				end
			S1  	:
				begin
					state_n = S2;
				end
			S2  	:
				begin
					state_n = S3;
				end
			S3  	:
				begin
					state_n = ROW1_ADDR;
				end
			ROW1_ADDR:
				begin
					state_n = WRITE;
				end
			WRITE		:
				begin
					if (char_cnt==5'd15) begin
						state_n = ROW2_ADDR;
					end
					else if (char_cnt==5'd31) begin
						state_n = stop;
					end
					else begin
						state_n = state_c;
					end
				end
			ROW2_ADDR:
				begin
					state_n = WRITE;
				end
			stop		:
				begin
					state_n = stop;
				end
			default:state_n = IDLE;
		endcase
	end
 
	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			lcd_data <= 8'd0;
		end
		else begin
			case(state_c)
				IDLE		:begin lcd_data <= 8'h38; lcd_rs <= 0;end
				INIT 		:begin lcd_data <= 8'h38; lcd_rs <= 0;end
				S0			:begin lcd_data <= 8'h08; lcd_rs <= 0;end
				S1			:begin lcd_data <= 8'h01; lcd_rs <= 0;end
				S2			:begin lcd_data <= 8'h06; lcd_rs <= 0;end
				S3			:begin lcd_data <= 8'h0c; lcd_rs <= 0;end
				ROW1_ADDR	:begin lcd_data <= 8'h80; lcd_rs <= 0;end
				//WRITE		:begin lcd_data <= data_display; lcd_rs <= 1;end
                WRITE		:begin lcd_data <= disp_memory[char_cnt]; lcd_rs <= 1;end
				ROW2_ADDR	:begin lcd_data <= 8'hc0; lcd_rs <= 0;end
				stop		:begin lcd_data <= 8'h38; lcd_rs <= 0;end
				default:;
			endcase
		end
	end
endmodule
 

 

   本实验用到了复位功能,将双功能管脚选项中的RECONFIG_N作为普通IO选项打勾。

2022-1-20_002.jpg

 

   逻辑代码编译通过,下载到开发板,LCD1602两行分别显示“Welcome to GOWIN”、“Mini KiT GWIN-4B”,效果见下图。

IMG_20220113_221923_1.jpg

 

   本实验完成将LCD1602屏点亮显示字符。

   疫情原因无法正常上般,家里条件有限,手头缺少扩展模块来实验,更多扩展功能之后有时间补上。

 


回复

5020

帖子

235

资源

管理员

熟悉的lcd1602,我以为它已经被淘汰了

希望是疫情最后一波,明年可以解放啦


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

查找数据手册?

EEWorld Datasheet 技术支持

最新文章 更多>>
    推荐帖子
    Python Tinker学习笔记(一)

    本帖最后由 常见泽1 于 2019-2-20 13:23 编辑 此内容由EEWORLD论坛网友常见泽1原创,如需转载或用于商业用途需征得作者 ...

    【SAMR21新玩法】34. 模拟USB鼠标键盘

    和MicroPython一样,在CircuitPython中,可以非常容易的模拟USB HID设备,可以将设备作为USB键盘或者USB鼠标。先看一下USB HID的 ...

    异步串行收发器设计报告.docx

    异步串行收发器设计报告.

    TMS320F28335-CAN模块例程解释

    CAN(Controller Area Network)特点:所有单元可以同时发送消息,发送高优先级ID消息的单元。CAN总线最大的优点是其高效性和可 ...

    关于原理图的一个问题

    493021 想问下STM32L4系列能否通过STLINK烧录器从上图中的P2口烧录程序

    【机智云Gokit3测评】开箱入门

    非常感谢论坛版主给予机会,让我有机会使用机智云的智能硬件开发平台,与自己做的智能家居物联网进行配套。由于快递送货没有打电 ...

    关闭
    站长推荐上一条 1/9 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表