• 【小月电子】XILINX FPGA开发板(XLOGIC_V1)系统学习教程-LESSON8 LCD1602液晶显示


    LCD1602显示例程讲解

    若要观看该博客配套的视频教程,可点击此链接

    在这里插入图片描述
    根据多年工作经验,总结出的FPGA的设计流程,概括起来总共有以上12步,其中根据项目难易度可省去其中一些步骤。比如非常简单的项目,我们可以省去虚线框里面的步骤,但是我们的入门级课程,即使再简单,也按照这12个步骤来进行讲解。

    1. 需求解读

    1.1 需求

    在液晶屏第一行显示“HELLO FPGA 1234!”

    1.2 知识背景

    1602液晶也叫1602字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此所以它不能很好地显示图形(用自定义CGRAM,显示效果也不好)。
    LCD1602是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。一般来说,LCD1602有16条引脚,据说还有14条引脚的,与16脚的相比缺少了背光电源A(15脚)和地线K(16脚)。实物如下图所示:
    在这里插入图片描述
    引脚定义如下:
    在这里插入图片描述

    说明:

    1. VSS接电源地。
    2. VDD接+5V。
    3. VO是液晶显示的偏压信号,可接10K的电位器用于调节显示效果。
    4. RS是命令/数据选择引脚,当RS为低电平时,选择命令;当RS为高电平时,选择数据。
    5. RW是读/写选择引脚,当RW为低电平时,向LCD1602写入命令或数据;当RW为高电 平时,从LCD1602读取状态或数据。如果不需要进行读取操作,可以直接将其接VSS。
    6. E,执行命令的使能引脚。
    7. D0—D7,并行数据输入/输出引脚 。
    8. A背光正极,与VDD相连接。
    9. K背光负极,接VSS。
      在这里插入图片描述
    写操作时序

    在这里插入图片描述

    时序参数

    1.3 硬件设计

    在这里插入图片描述

    有源晶振

    在这里插入图片描述

    液晶接口电路图

    在这里插入图片描述

    FPGA管脚映射图

    在这里插入图片描述

    PCB板上管脚标注

    在这里插入图片描述

    LCD1602液晶与开发板管脚连接图

    1.4 接口说明

    信号名方向FPGA管脚号说明
    CLK50M输入B10时钟信号,50MHZ
    LCD_RS输出K12命令/数据选择引脚,当RS为低电平时,选择命令;当RS为高电平时,选择数据
    LCD_RW输出L16是读/写选择引脚,当RW为低电平时,向LCD1602写入命令或数据;当RW为高电平时,从LCD1602读取状态或数据
    LCD_CLK输出K15执行命令的使能引脚
    LCD_DB0输出H15并行数据输入/输出引脚
    LCD_DB1输出H13并行数据输入/输出引脚
    LCD_DB2输出D14并行数据输入/输出引脚
    LCD_DB3输出C15并行数据输入/输出引脚
    LCD_DB4输出F12并行数据输入/输出引脚
    LCD_DB5输出A10并行数据输入/输出引脚
    LCD_DB6输出G6并行数据输入/输出引脚
    LCD_DB7输出G5并行数据输入/输出引脚

    2. 绘制理论波形图

    在这里插入图片描述

    理论波形图

    3.新建ISE工程

    为了让工程看起来整洁,同时方便工程移植。我们新建4个文件夹,分别是Project,Source,Sim,Doc。
    Project — 工程文件夹,里面放的ISE工程
    Source — 源代码文件夹,里面放的工程源码(.v文件或.vhd文件)
    Sim — 仿真文件夹,里面放的仿真相关的文件
    Doc — 存放相关资料,比如数据手册,需求文档等

    4.编写代码

    ///
    //QQ:3181961725
    //TEL/WX:13540738439
    //作者:Mr Wang
    //模块介绍:LCD1602显示驱动
    ///
    module lcd ( 
    	input 				clk		,//系统时钟输入50M
    	input				rst_n	,//复位,低电平有效
     	output 	reg	[7:0] 	dat		,//LCD的8位数据口
     	output  reg			rs		,//数据命令选择信号,高电平表示数据,低电平表示命令
     	output				rw		,//读写标志,高电平表示读,低电平表示写,该程序我们只对液晶屏进行写操作
     	output				en		//LCD的控制脚
     );
     reg	[15:0]	counter	; 
     reg 	[ 5:0] 	current	; 
     reg 			clkr	; 
     reg			e		;
     //定义了LCD状态机需要的状态。
     parameter  set0 =6'd0; 
     parameter  set1 =6'd1; 
     parameter  set2 =6'd2; 
     parameter  set3 =6'd3; 
     parameter  set4 =6'd4;   
     parameter  dat0 =6'd5; 
     parameter  dat1 =6'd6; 
     parameter  dat2 =6'd7; 
     parameter  dat3 =6'd8; 
     parameter  dat4 =6'd9; 
     parameter  dat5 =6'd10;
     parameter  dat6 =6'd11; 
     parameter  dat7 =6'd12; 
     parameter  dat8 =6'd13; 
     parameter  dat9 =6'd14;
     parameter  dat10=6'd15; 
     parameter  dat11=6'd16;
     parameter	dat12=6'd17;  
     parameter	dat13=6'd18; 
     parameter	dat14=6'd19; 
     parameter	dat15=6'd20; 
     parameter  fini=6'hF1; 
    always @(posedge clk or negedge rst_n)         //da de data_w1 zhong pinlv 
     begin 
     	if(!rst_n)
     		begin
     			counter<=0;
     			clkr<=0;
     		end
     	else
     		begin
      			counter<=counter+1; 
      			if(counter==16'h000f)  
      				clkr<=~clkr; 
      			else
      				;
      		end
    end 
    always @(posedge clkr or negedge rst_n) 
    begin 
    	if(!rst_n)
    		begin
    			current<=set0;
    			dat<=0;
    			rs<=0;
    			e<=1;
    		end
    	else
    		begin
      			case(current) 
        		set0:   begin  e<=0;rs<=0; dat<=8'h38; 	current<=set1; 		end //*设置8位格式,2行,5*7*
        		set1:   begin  e<=0;rs<=0; dat<=8'h0C; 	current<=set2; 		end //*整体显示,关光标,不闪烁*/  
        		set2:   begin  e<=0;rs<=0; dat<=8'h06; 	current<=set3; 		end //*设定输入方式,增量不移位*/  
        		set3:   begin  e<=0;rs<=0; dat<=8'h01; 	current<=set4; 		end //*清除显示*/   
    			set4:   begin  e<=0;rs<=0; dat<=8'h80; 	current<=dat0; 		end //设置显示第一行
        		dat0:   begin  e<=0;rs<=1; dat<="H"; 	current<=dat1; 		end    
        		dat1:   begin  e<=0;rs<=1; dat<="E"; 	current<=dat2; 		end 
        		dat2:   begin  e<=0;rs<=1; dat<="L"; 	current<=dat3; 		end 
        		dat3:   begin  e<=0;rs<=1; dat<="L";	current<=dat4; 		end 
        		dat4:   begin  e<=0;rs<=1; dat<="O"; 	current<=dat5; 		end 
        		dat5:   begin  e<=0;rs<=1; dat<=" "; 	current<=dat6; 		end 
        		dat6:   begin  e<=0;rs<=1; dat<="F"; 	current<=dat7; 		end 
        		dat7:   begin  e<=0;rs<=1; dat<="P";	current<=dat8; 		end 
        		dat8:   begin  e<=0;rs<=1; dat<="G"; 	current<=dat9; 		end 
        		dat9:   begin  e<=0;rs<=1; dat<="A";	current<=dat10 ; 	end 
        		dat10:  begin  e<=0;rs<=1; dat<="!"; 	current<=dat11; 	end 
        		dat11:  begin  e<=0;rs<=1; dat<="1"; 	current<=dat12; 	end 
        		dat12:  begin  e<=0;rs<=1; dat<="2"; 	current<=dat13; 	end 
    			dat13:  begin  e<=0;rs<=1; dat<="3"; 	current<=dat14; 	end 
    			dat14:  begin  e<=0;rs<=1; dat<="4"; 	current<=dat15; 	end 
    			dat15:  begin  e<=0;rs<=1; dat<="6"; 	current<=fini; 		end 
        		fini:   begin  e<=1;rs<=0; dat<=8'h00;       				end
       			default:   current<=set0; 
        		endcase 
        	end
     end 
    assign en=clkr|e; 
    assign rw=0; 
    endmodule  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98

    5.编写仿真测试激励文件

    `timescale 1ns/1ns
    module lcd1602_tb;
    	reg					clk		;
    	reg					rst_n	;
    initial
    begin
    	clk = 0;
    	rst_n=0;
    	#1000
    	rst_n=1;
    end
    always #10 clk=~clk;
    lcd Ulcd( 
    	.clk		(clk),//系统时钟输入50M
    	.rst_n		(rst_n),//复位,低电平有效
     	.dat		(),//LCD的8位数据口
     	.rs			(),//数据命令选择信号,高电平表示数据,低电平表示命令
     	.rw			(),//读写标志,高电平表示读,低电平表示写,该程序我们只对液晶屏进行写操作
     	.en			()//LCD的控制脚
     );
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    6.Modelsim仿真

    Modelsim仿真一般有两种方法

    1. 图形化界面仿真,即所有的操作都是在Modelsim软件界面上来完成,该方式的优点是,简单易学,适用于简单的项目,缺点是操作步骤繁琐。

    2. 批处理仿真,这种方式在仿真前需要编写相应的脚本文件,该方式的优点是,一键即可完成仿真,省时省力,缺点是前期需要编写脚本文件。前两讲采用的是图形化界面仿真的方式;为了更贴近工程实际,从第三讲开始,我们就采用批处理方式仿真。具体操作步骤可参考我们的视频教程
      仿真出的波形如下图所示:
      在这里插入图片描述

    7.对比波形图

    将第二步绘制的理论波形图与第六步Modelsim仿真出来的波形图进行对比,结果一致,说明我们的逻辑设计是正确的。如果发现比对结果不一致,就需要找到不一致的原因,最终要保证对比结果一致。通过对比,理论波形与仿真波形一致,说明功能符合设计要求。

    8.绑定管脚(编写UCF文件)

    NET "clk" TNM_NET = "clk";
    TIMESPEC TS_sys_clk_i = PERIOD "clk" 20 ns HIGH 50 %;
    NET "clk" 			LOC = B10	| IOSTANDARD = LVCMOS33 ;
    
    NET "rst_n" 		LOC = E4	| IOSTANDARD = LVCMOS33;
    
    NET "en" 			LOC = K15	| IOSTANDARD = LVCMOS33;
    NET "rw" 			LOC = L16	| IOSTANDARD = LVCMOS33;
    NET "rs" 			LOC = K12	| IOSTANDARD = LVCMOS33;
    NET "dat[7]" 		LOC = G5	| IOSTANDARD = LVCMOS33;
    NET "dat[6]" 		LOC = G6	| IOSTANDARD = LVCMOS33;
    NET "dat[5]" 		LOC = A10	| IOSTANDARD = LVCMOS33;
    NET "dat[4]" 		LOC = F12	| IOSTANDARD = LVCMOS33;
    NET "dat[3]" 		LOC = C15	| IOSTANDARD = LVCMOS33;
    NET "dat[2]" 		LOC = D14	| IOSTANDARD = LVCMOS33;
    NET "dat[1]" 		LOC = H13	| IOSTANDARD = LVCMOS33;
    NET "dat[0]" 		LOC = H15	| IOSTANDARD = LVCMOS33;
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    9.添加.v和.ucf文件

    在这里插入图片描述

    10.编译综合,同时将未使用管脚设置为悬空状态

    1.设置未使用管脚为悬空状态
    在这里插入图片描述
    在这里插入图片描述

    2.编译综合
    在这里插入图片描述

    11.下载BIT文件

    编译综合成功后便可以将生成的BIT文件下载到开发板(记得插上下载器,同时开发板上电)
    1.打开IMPACT
    在这里插入图片描述

    2.搜索器件

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    3.选择bit文件

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    下载成功后,便可以观察到开发板上的实验现象,如果实验现象与设计需求相符,那说明我们的设计是没有问题的,即可进行下一步生成MCS文件

    12.生成MCS文件,同时固化到配置芯片中

    FPGA有一个特性,就是掉电后配置信息会丢失,所以我们需要将配置信息存储在配置芯片(FLASH)中,待开发板上电后,FPGA便会读取配置芯片中的配置信息,这样开发板掉电再上电后同样可正常工作。要将程序固化到配置芯片,需要先生成MCS文件。
    BIT文件转换成MCS文件步骤:

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    固化MCS文件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    固化成功后,开发板断电再重新上电,可以观察到开发板仍然可以执行刚刚的功能。

  • 相关阅读:
    考虑颜色信息的特征描述符----学习笔记
    哈工大李治军老师操作系统笔记【14】:进程同步与信号量(Learning OS Concepts By Coding Them !)
    全球与中国车辆到电网V2G市场:增长趋势、竞争格局与前景展望
    51单片机学习笔记2 仿真器的使用及STC89Cxx简介
    求职刷题力扣DAY14 ---二叉树的基础遍历,迭代、递归
    C++ Reference: Standard C++ Library reference: Containers: deque: deque: rend
    Java IO 字节和字符数组的相关简介说明
    看表情包学Linux:基本指令介绍
    Nginx简单使用
    腾讯云2023年最新优惠券领取入口
  • 原文地址:https://blog.csdn.net/Moon_3181961725/article/details/126712753