12864lcd显示部分试验总结报告管岱2014.12.19【实验目的】在12864液晶显示屏上能够显示出在4×4小键盘上输入的激励源频率值,如输入“789HZ”、“8MHZ”、“2.3KHZ”,显示出“789H”、“8M”、“2.3K”。
并且要求此部分程序有较好的可移植性,在最后对电阻率值的显示上能够较好的应用。
【实验原理】12864-3A接口说明表:在12864液晶显示原理的基础上,通过在ise上编写vhdl语言,使之能够在fpga学习板上顺利显示数据。
【实验内容】12864的显示原理并不难理解,并且在以前也用汇编语言实现过,所以本次实验的难点不在于显示原理的理解,而在于VHDL语言的编写。
在实验初期,由于对vhdl语言的不熟练,我们“类比”汇编语言的显示程序,编写出如下的程序:发现编译时就出现了问题,出现如“multi-source in unit <*> on signal <*>”的报错。
在仔细调试检查后发现,我们错误的原因在于:在不同的进程中对同一个信号赋值。
例如,在写指令的进程中,将rs信号置‘0’,而在后面写数据的进程中又将rs置‘1’,由于在vhdl中各进程之间是并行的关系,因此这样编写程序会出现在同一时刻对同一个引脚赋高电平和低电平,从而出现矛盾。
虽然在程序实际运行中,写指令进程在系统一上电就会完成,远早于写数据进程,但是在逻辑上这样编写是不符合VHDL语言的规则的。
因此,我们利用状态机的思想,将写指令和写数据的两个进程合二为一。
程序片段如下:利用状态机,将写指令和写数据的各个步骤分为一个一个分立的状态,顺序执行。
这样编写将对同一个引脚信号的变化放在一个进程中,很好的解决了之前存在的问题。
并且受此启发,在写数据的程序段,对百位、十位、个位以及单位的译码程序中,将原本分别对各自数位信号敏感的四个单独进程改成了受一个的时钟上升沿敏感的一个进程,从而较好的保证了程序的时序性和同步性,经实验验证效果良好。
【实验改进】最初的设想是三位有效数字(k1、k2、k3),加上一个单位(hz、khz、mhz)就能够满足大部分数字范围。
但是后来发现这样不能实现例如“1200HZ”的数据。
因此改进实验程序,加入小数点。
在十位的译码程序中加入对小数点的译码,这样当输入第二位时按下小数点的按键,就能在显示屏上显示出小数点,且不影响其它位显示。
因此若要显示“1200HZ”的频率,则可显示出“1.2 K”。
【实验体会】对不熟悉的编程语言,我们不能拿别的语言的相关程序来生搬硬套,不能用别的语言的思维来考虑本语言的编程。
在VHDL语言中,“进程”的思想十分重要,进程之间相互并行的特点既可以帮助我们利用模块化的思想编写程序,但同时也给不熟悉VHDL的人带来了困难。
多阅读程序,多练习编程,多理解本语言的思想,不仅对VHDL语言是这样,在今后学习其他语言也是同样的道理。
【实验代码】library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;use ieee.std_logic_arith.all;use ieee.numeric_std.all;ENTITY lcd12864 ISPORT (clk : IN std_logic;--reset : IN std_logic;rs : OUT std_logic;rw : OUT std_logic;en : OUT std_logic;dat : OUT std_logic_vector(7 DOWNTO 0);--rst : OUT std_logic);LCD_N : OUT std_logic;LCD_P : OUT std_logic;PSB : OUT std_logic;LCD_RST : OUT std_logic;-----------------------------------------------------------------------------------------------------------k1 : in std_logic_vector(7 downto 0);k2 : in std_logic_vector(7 downto 0);k3 : in std_logic_vector(7 downto 0);k4 : in std_logic_vector(7 downto 0));---------------------------------------------------------------------------------------------------------END lcd12864;ARCHITECTURE fun OF lcd12864 IS--//状态定义SIGNAL e : std_logic;SIGNAL counter : std_logic_vector(15 DOWNTO 0);SIGNAL current : std_logic_vector(7 DOWNTO 0);SIGNAL clkr : std_logic;SIGNAL cnt : std_logic_vector(1 DOWNTO 0);CONSTANT set0 : std_logic_vector(7 DOWNTO 0) := "00000000";CONSTANT set1 : std_logic_vector(7 DOWNTO 0) := "00000001";CONSTANT set2 : std_logic_vector(7 DOWNTO 0) := "00000010";CONSTANT set3 : std_logic_vector(7 DOWNTO 0) := "00000011";CONSTANT set4 : std_logic_vector(7 DOWNTO 0) := "00100101";CONSTANT set5 : std_logic_vector(7 DOWNTO 0) := "00100110";DOWNTO 0) := "00000100";CONSTANT dat1 : std_logic_vector(7 DOWNTO 0) := "00000101";CONSTANT dat2 : std_logic_vector(7 DOWNTO 0) := "00000110";CONSTANT dat3 : std_logic_vector(7 DOWNTO 0) := "00000111";CONSTANT dat4 : std_logic_vector(7 DOWNTO 0) := "00001000";CONSTANT dat5 : std_logic_vector(7 DOWNTO 0) := "00001001";CONSTANT dat6 : std_logic_vector(7 DOWNTO 0) := "00001010";CONSTANT dat7 : std_logic_vector(7 DOWNTO 0) := "00001011";CONSTANT dat8 : std_logic_vector(7 DOWNTO 0) := "00001100";CONSTANT dat9 : std_logic_vector(7 DOWNTO 0) := "00001101";CONSTANT dat10 : std_logic_vector(7 DOWNTO 0) := "00001110";DOWNTO 0) := "00001111";CONSTANT dat12 : std_logic_vector(7 DOWNTO 0) := "00010000";CONSTANT dat13 : std_logic_vector(7 DOWNTO 0) := "00010001";CONSTANT dat14 : std_logic_vector(7 DOWNTO 0) := "00010010";CONSTANT nul : std_logic_vector(7 DOWNTO 0) := "00110000";SIGNAL dat_r : std_logic_vector(7 DOWNTO 0);SIGNAL rs_r : std_logic;SIGNAL rw_r : std_logic;SIGNAL en_r : std_logic;------------------------------------------------------------------------------------------------SIGNAL k1_r : std_logic_vector(7 DOWNTO 0);SIGNAL k2_r : std_logic_vector(7 DOWNTO 0);DOWNTO 0);SIGNAL k4_r : std_logic_vector(7 DOWNTO 0);SIGNAL a : std_logic_vector (7 DOWNTO 0);SIGNAL b : std_logic_vector (7 DOWNTO 0);SIGNAL c : std_logic_vector (7 DOWNTO 0);SIGNAL d : std_logic_vector (7 DOWNTO 0); --------------------------------------------------------------------------------------------------------BEGINdat <= dat_r;rs <= rs_r;rw <= rw_r;en <= en_r;k1_r<=k1;k2_r<=k2;k3_r<=k3;k4_r<=k4;PSB <= '1' ;LCD_RST <= '1' ;LCD_N<='0';LCD_P<='1';--时钟分频PROCESS(clk)BEGINIF(clk'EVENT AND clk = '1') THENcounter <= counter + "0000000000000001";IF (counter = "0000000000001111") THENclkr <= NOT clkr;END IF;END IF;END PROCESS;PROCESS(clkr)BEGINIF(clkr'EVENT AND clkr = '1') THENCASE current ISWHEN set0 =>rs_r <= '0';dat_r <= "00110000"; --初始化--基本指令集current <= set1;WHEN set1 =>rs_r <= '0';dat_r <= "00001100"; --开显示current <= set2;WHEN set2 =>rs_r <= '0';dat_r <= "00000110"; --光标右移current <= set3;WHEN set3 =>rs_r <= '0';dat_r <= "00000001"; --清屏current <= set4;WHEN set4 =>rs_r <= '0';dat_r <= "10000000"; --设置坐标位置(地址设置为第1行)current <= dat0;WHEN dat0 =>rs_r <= '1';dat_r <= a; --发送第一行数据current <= dat1;WHEN dat1 =>rs_r <= '1';dat_r <= b;current <= dat2;WHEN dat2 =>rs_r <= '1';dat_r <= c;current <= dat3;WHEN dat3 =>rs_r <= '1';dat_r <= d;current <= nul;WHEN nul => --这段保证前段显示部分至少执行一遍--然后把液晶的En脚拉高,完成一次读写过程rs_r <= '0';dat_r <= "00000000";IF (cnt /= "10") THENe <= '0';current <= set0;cnt <= cnt + "01";ELSEcurrent <= set0;e <= '1';cnt <= "00";END IF;WHEN OTHERS =>current <= nul;END CASE;END IF;END PROCESS;en_r <= clkr OR e ; --对LCD始终为写操作rw_r <= '0' ; --对LCD始终为写操作-- rst <= reset ;----------------------------------------------------------------------------------process(clkr)beginIF(clkr'EVENT AND clkr = '1') THENcase k1_r is --百位when "00000000"=>a<= x"30";when "00000001"=>a<= x"31";when "00000010"=>a<= x"32";when "00000011"=>a<= x"33";when "00000100"=>a<= x"34";when "00000101"=>a<= x"35";when "00000110"=>a<= x"36";when "00000111"=>a<= x"37";when "00001000"=>a<= x"38";when "00001001"=>a<= x"39";when others =>a<= x"20" ;end case;case k2_r is --十位when "00000000"=>b<= x"30";when "00000001"=>b<= x"31";when "00000010"=>b<= x"32";when "00000011"=>b<= x"33";when "00000100"=>b<= x"34";when "00000101"=>b<= x"35";when "00000110"=>b<= x"36";when "00000111"=>b<= x"37";when "00001000"=>b<= x"38";when "00001001"=>b<= x"39";when others =>b<= x"20" ;end case;case k3_r is --个位when "00000000"=>c<= x"30";when "00000001"=>c<= x"31";when "00000010"=>c<= x"32";when "00000011"=>c<= x"33";when "00000100"=>c<= x"34";when "00000101"=>c<= x"35";when "00000110"=>c<= x"36";when "00000111"=>c<= x"37";when "00001000"=>c<= x"38";when "00001001"=>c<= x"39";when others =>c<= x"20" ;end case;case k4_r is --单位when "00001010"=>d<= x"48"; --H when "00001011"=>d<= x"4B"; --K when "00001100"=>d<= x"4D"; --M when others =>d<=x"20";end case;end if;end process; END fun;。