实验四有限状态机的设计——LCD显示控制实验一、实验目的1、了解LCD1602液晶显示器的工作原理。2、了解时序电路FPGA的实现。3、学习用VHDL语言来描述时序电路的过程。二、硬件要求1、可变时钟源。2、LCD1602液晶显示模块3、A/D转换芯片ADC08094、主芯片CycloneIIEP2C35F672C6。三、实验原理该实验是利用FPGA控制LCD1602的时序,进行液晶显示。LCD是一个可以显示两行字符或数字的液晶显示模块。该芯片管脚如右图所示。芯片引脚及其说明如下:1602采用标准的16脚接口,其中:第1脚:VSS为地电源第2脚:VDD接5V正电源第3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。第5脚:RW为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和RW共同为低电平时可以写入指令或者显示地址,当RS为低电平RW为高电平时可以读忙信号,当RS为高电平RW为低电平时可以写入数据。第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。第7~14脚:D0~D7为8位双向数据线。第15~16脚:空脚1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,如表1所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”LCD1602的工作时序可查阅其他资料。四、实验内容及步骤本实验的内容就是用FPGA模拟产生LCD1602的时序,使其正常工作,显示字符,实验步骤如下:1、编写LCD1602时序的VHDL代码。2、用QuartusII6.0对其进行编译仿真。3、在时序确定无误后,选择芯片CycloneIIEP2C35F672C6。4、给芯片进行管脚绑定,在此进行编译。5、观看实验结果。五、实验结果与分析这是LCD1602的仿真波形图。在RS,RW均为高电平时,LCD显示从DB0~DB7的数据。六、问题与质疑1.LCD1602的工作时序是怎样的?答:读操作时序:写操作时序:七、程序代码libraryIEEE;useIEEE.STD_LOGIC_1164.ALL;useIEEE.STD_LOGIC_ARITH.ALL;useIEEE.STD_LOGIC_UNSIGNED.ALL;entityLCD1602isPort(Clk:instd_logic;--状态机时钟信号,同时也是液晶时钟信号,其周期应该满足液晶数据的建立时间Reset:instd_logic;LCD_RS:outstd_logic;--寄存器选择信号LCD_RW:outstd_logic;--液晶读写信号LCD_EN:outstd_logic;--液晶时钟信号LED:outstd_logic;LCD_ON:outstd_logic;LCD_BLON:outstd_logic;LCD_Data:outstd_logic_vector(7downto0));--液晶数据信号endLCD1602;architectureBehavioralofLCD1602istypestateis(set_clc,set_dlnf,set_cursor,set_dcb,set_cgram,write_cgram,set_ddram,write_LCD_Data,set_ddram2,write_LCD_Data2);signalCurrent_State:state;typeram2isarray(0to7)ofstd_logic_vector(7downto0);signalClkk:std_logic;signalCount:std_logic_vector(20downto0);signalClk_Out:std_logic;signalLCD_Clk:std_logic;beginLCD_EN=Clk_Out;--液晶时钟信号LED=Clk_Out;LCD_RW='0';--写数据LCD_ON='1';LCD_BLON='1';clock:process(Clk,Reset)beginif(Reset='0')thenCount=(others='0');elsif(rising_edge(clk))thenCount=Count+1;if(Count=0)thenClk_Out=notClk_Out;endif;endif;LCD_Clk=Clk_Out;endprocess;control:process(LCD_Clk,Reset,Current_State)--液晶驱动控制器variablecnt1:std_logic_vector(2downto0);beginifReset='0'thenCurrent_State=set_clc;cnt1:=(others='1');LCD_RS='0';elsifrising_edge(LCD_Clk)thenCurrent_State=Current_State;LCD_RS='0';caseCurrent_Stateiswhenset_clc=LCD_Data=00000001;--01HCurrent_State=set_dlnf;whenset_dlnf=LCD_Data=00111100;--3cHCurrent_State=set_cursor;whenset_cursor=LCD_Data=00000110;--06HCurrent_State=set_dcb;whenset_dcb=LCD_Data=00001100;--0cHCurrent_State=set_cgram;whenset_cgram=LCD_Data=01000000;--40HCurrent_State=write_cgram;whenwrite_cgram=--向CGRAM中写入年LCD_RS='1';Current_State=set_ddram;whenset_ddram=--从第一行的起始地址开始显示LCD_Data=10000000;--80HCurrent_State=write_LCD_Data;whenwrite_LCD_Data=LCD_RS='1';LCD_Data=01000110;Current_State=set_ddram2;whenset_ddram2=LCD_RS='0';LCD_Data=10000001;--80HCurrent_State=write_LCD_Data2;whenwrite_LCD_Data2=LCD_RS='1';LCD_Data=01010111;Current_State=set_ddram;whenothers=null;endcase;endif;endprocess;endBehavioral;