📄 lcd_driver.vhd
字号:
--文件名:lcd_driver.vhd
--功 能:驱动LCD显示,并可以对显示的数据进行设置
--说 明:液晶显示的数值
--------------############################################-------------
--------- AB:CD:EF
-- “S4”键控制“A”段的数据
-- “S6”键控制“B”段的数据
-- “S7”键控制“C”段的数据
-- “S8”键控制“D”段的数据
-- “S9” 键控制“E”段的数据
-- “S10”键控制“F”段的数据
--------------############################################-------------
--注 意:在使用液晶的时候,千万要注意防静电(手最好不要触碰液晶表面)
-- 否则液晶很容易被损坏;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity lcd_driver is
generic(N:integer:=5000;
delay:integer:=10);
Port ( clk : in std_logic; --系统时钟输入
reset : in std_logic; --复位信号,在下完程序之后需要对液晶进行复位清零
set1,set2,set3,set4,set5,set6,set7 : in std_logic;
--set1~set6为数据的预置位,set7是复位清零信号;
lcden : out std_logic; --接LCD使能端
lcdda : out std_logic; --接LCD_da信号输入端
lcdrw : out std_logic; --接LCD读写信号输入端
data :inout std_logic_vector(7 downto 0));--接LCD数据输入位
end lcd_driver;
architecture Behavioral of lcd_driver is
type state is (set_dlnf,clear_lcd,set_cursor,set_dcb,set_location,write_data);
signal current_state:state;
type ram is array(0 to 7) of std_logic_vector(7 downto 0);
signal dataram :ram;
signal yz1:std_logic_vector(3 downto 0);
signal yz2:std_logic_vector(3 downto 0);
signal tq1: std_logic_vector(3 downto 0);
signal tq2: std_logic_vector(3 downto 0);
signal jb1: std_logic_vector(3 downto 0);
signal jb2: std_logic_vector(3 downto 0);
signal yz_dout1: std_logic_vector(7 downto 0);
signal yz_dout2: std_logic_vector(7 downto 0);
signal tq_dout1: std_logic_vector(7 downto 0);
signal tq_dout2: std_logic_vector(7 downto 0);
signal jb_dout1: std_logic_vector(7 downto 0);
signal jb_dout2: std_logic_vector(7 downto 0);
signal clk_2hz,clk_500hz: std_logic;
begin
--(液晶)数据交换频率
lcd_clk:process(clk,reset)
variable c: integer range 0 to 10000;
variable clk0: std_logic;
begin
if reset='0' then c:=0; clk0:='0';
elsif clk'event and clk='1' then c:=c+1;
if c=N then clk0:='1';
elsif c=2*N then clk0:='0';c:=0;
end if;
end if;
clk_500hz<=clk0;
end process;
--2赫兹的分频模块
set_clk:process(clk,reset)
variable c: integer range 0 to 25000000;
variable clk0: std_logic;
begin
if reset='0' then c:=0;clk0:='0';
elsif clk'event and clk='1' then c:=c+1;
if c=12500000 then clk0:='1';
elsif c=25000000 then clk0:='0';c:=0;
end if;
end if;
clk_2hz<=clk0;
end process;
--按键置数模块
set:process(clk_2hz,set7)
variable p1,p2,p3,p4,p5,p6:std_logic_vector(3 downto 0);
begin
if set7='0' then yz1<="0000";yz2<="0000";tq1<="0000";tq2<="0000";jb1<="0000";jb2<="0000";
p1:="0000";p2:="0000"; p3:="0000";p4:="0000"; p5:="0000"; p6:="0000";
elsif clk_2hz'event and clk_2hz='1' then
if set1='0' then if p1="1001" then p1:="0000";
else p1:=p1+1;
end if;
end if;
if set2='0' then if p2="1001" then p2:="0000";
else p2:=p2+1;
end if;
end if;
if set3='0' then if p3="1001" then p3:="0000";
else p3:=p3+1;
end if;
end if;
if set4='0' then if p4="1001" then p4:="0000";
else p4:=p4+1;
end if;
end if;
if set5='0' then if p5="1001" then p5:="0000";
else p5:=p5+1;
end if;
end if;
if set6='0' then if p6="1001" then p6:="0000";
else p6:=p6+1;
end if;
end if;
end if;
yz1<=p1;yz2<=p2;tq1<=p3;tq2<=p4;jb1<=p5;jb2<=p6;
end process;
--数据译码
lcd_decoder_yz1: process(clk)
begin
if clk'event and clk='1' then
case yz1 is
when "0000"=>yz_dout1<="00110000";
when "0001"=>yz_dout1<="00110001";
when "0010"=>yz_dout1<="00110010";
when "0011"=>yz_dout1<="00110011";
when "0100"=>yz_dout1<="00110100";
when "0101"=>yz_dout1<="00110101";
when "0110"=>yz_dout1<="00110110";
when "0111"=>yz_dout1<="00110111";
when "1000"=>yz_dout1<="00111000";
when "1001"=>yz_dout1<="00111001";
when "1010"=>yz_dout1<="01000001";
when "1011"=>yz_dout1<="01000010";
when "1100"=>yz_dout1<="01000011";
when "1101"=>yz_dout1<="01000100";
when "1110"=>yz_dout1<="01000101";
when "1111"=>yz_dout1<="01000110";
when others=>yz_dout1<="00111111";
end case;
end if;
end process;
lcd_decoder_yz2:process(clk)
begin
if clk'event and clk='1' then
case yz2 is
when "0000"=>yz_dout2<="00110000";
when "0001"=>yz_dout2<="00110001";
when "0010"=>yz_dout2<="00110010";
when "0011"=>yz_dout2<="00110011";
when "0100"=>yz_dout2<="00110100";
when "0101"=>yz_dout2<="00110101";
when "0110"=>yz_dout2<="00110110";
when "0111"=>yz_dout2<="00110111";
when "1000"=>yz_dout2<="00111000";
when "1001"=>yz_dout2<="00111001";
when "1010"=>yz_dout2<="01000001";
when "1011"=>yz_dout2<="01000010";
when "1100"=>yz_dout2<="01000011";
when "1101"=>yz_dout2<="01000100";
when "1110"=>yz_dout2<="01000101";
when "1111"=>yz_dout2<="01000110";
when others=>yz_dout2<="00111111";
end case;
end if;
end process;
lcd_decoder_tq1:process(clk)
begin
if clk'event and clk='1' then
case tq1 is
when "0000"=>tq_dout1<="00110000";
when "0001"=>tq_dout1<="00110001";
when "0010"=>tq_dout1<="00110010";
when "0011"=>tq_dout1<="00110011";
when "0100"=>tq_dout1<="00110100";
when "0101"=>tq_dout1<="00110101";
when "0110"=>tq_dout1<="00110110";
when "0111"=>tq_dout1<="00110111";
when "1000"=>tq_dout1<="00111000";
when "1001"=>tq_dout1<="00111001";
when "1010"=>tq_dout1<="01000001";
when "1011"=>tq_dout1<="01000010";
when "1100"=>tq_dout1<="01000011";
when "1101"=>tq_dout1<="01000100";
when "1110"=>tq_dout1<="01000101";
when "1111"=>tq_dout1<="01000110";
when others=>tq_dout1<="00111111";
end case;
end if;
end process;
lcd_decoder_tq2:process(clk)
begin
if clk'event and clk='1' then
case tq2 is
when "0000"=>tq_dout2<="00110000";
when "0001"=>tq_dout2<="00110001";
when "0010"=>tq_dout2<="00110010";
when "0011"=>tq_dout2<="00110011";
when "0100"=>tq_dout2<="00110100";
when "0101"=>tq_dout2<="00110101";
when "0110"=>tq_dout2<="00110110";
when "0111"=>tq_dout2<="00110111";
when "1000"=>tq_dout2<="00111000";
when "1001"=>tq_dout2<="00111001";
when "1010"=>tq_dout2<="01000001";
when "1011"=>tq_dout2<="01000010";
when "1100"=>tq_dout2<="01000011";
when "1101"=>tq_dout2<="01000100";
when "1110"=>tq_dout2<="01000101";
when "1111"=>tq_dout2<="01000110";
when others=>tq_dout2<="00111111";
end case;
end if;
end process;
lcd_decoder_jb1:process(clk)
begin
if clk'event and clk='1' then
case jb1 is
when "0000"=>jb_dout1<="00110000";
when "0001"=>jb_dout1<="00110001";
when "0010"=>jb_dout1<="00110010";
when "0011"=>jb_dout1<="00110011";
when "0100"=>jb_dout1<="00110100";
when "0101"=>jb_dout1<="00110101";
when "0110"=>jb_dout1<="00110110";
when "0111"=>jb_dout1<="00110111";
when "1000"=>jb_dout1<="00111000";
when "1001"=>jb_dout1<="00111001";
when "1010"=>jb_dout1<="01000001";
when "1011"=>jb_dout1<="01000010";
when "1100"=>jb_dout1<="01000011";
when "1101"=>jb_dout1<="01000100";
when "1110"=>jb_dout1<="01000101";
when "1111"=>jb_dout1<="01000110";
when others=>jb_dout1<="00111111";
end case;
end if;
end process;
lcd_decoder_jb2:process(clk)
begin
if clk'event and clk='1' then
case jb2 is
when "0000"=>jb_dout2<="00110000";
when "0001"=>jb_dout2<="00110001";
when "0010"=>jb_dout2<="00110010";
when "0011"=>jb_dout2<="00110011";
when "0100"=>jb_dout2<="00110100";
when "0101"=>jb_dout2<="00110101";
when "0110"=>jb_dout2<="00110110";
when "0111"=>jb_dout2<="00110111";
when "1000"=>jb_dout2<="00111000";
when "1001"=>jb_dout2<="00111001";
when "1010"=>jb_dout2<="01000001";
when "1011"=>jb_dout2<="01000010";
when "1100"=>jb_dout2<="01000011";
when "1101"=>jb_dout2<="01000100";
when "1110"=>jb_dout2<="01000101";
when "1111"=>jb_dout2<="01000110";
when others=>jb_dout2<="00111111";
end case;
end if;
end process;
--设定数据显示的位置
loaddata:process(clk,set7)
begin
if reset='0'then
dataram<=(("00110000"),("00110000"),("00111010"),("00110000"),
("00110000"),("00111010"),("00110000"),("00110000"));
elsif rising_edge(clk)then
dataram(0)<=yz_dout1;
dataram(1)<=yz_dout2;
dataram(2)<="00111010";
dataram(3)<=tq_dout1;
dataram(4)<=tq_dout2;
dataram(5)<="00111010";
dataram(6)<=jb_dout1;
dataram(7)<=jb_dout2;
end if;
end process;
--液晶驱动部分
control: process(clk_500hz,reset)
variable cntt,cnt2:integer;
variable cnt3:std_logic_vector(3 downto 0);
begin
if reset='0'then
current_state<=set_dlnf;
cntt:=0;cnt2:=0;
elsif rising_edge(clk_500hz)then cnt3:=cnt3+1;
case current_state is
when set_dlnf=> --功能设置
lcden<='0';
lcdda<='0';
lcdrw<='0';
data<="00111100";
cntt:=cntt+1;
if cntt>delay and cntt<=delay*2 then --延时操作
lcden<='1'; --保证液晶有足够的使能时间
else
lcden<='0';
end if;
if cntt=delay*3 then
current_state<=clear_lcd;
cntt:=0;
end if;
when clear_lcd=> --清屏操作
lcden<='0';
lcdda<='0';
lcdrw<='0';
data<="00000001";
cntt:=cntt+1;
if cntt>delay and cntt<=delay*2 then --延时操作
lcden<='1'; --保证液晶有足够的使能时间
else
lcden<='0';
end if;
if cntt=delay*3 then
current_state<=set_cursor;
cntt:=0;
end if;
when set_cursor=> --光标显示设置
lcden<='0';
lcdda<='0';
lcdrw<='0';
data<="00000110";
cntt:=cntt+1;
if cntt>delay and cntt<=delay*2 then --延时操作
lcden<='1'; --保证液晶有足够的使能时间
else
lcden<='0';
end if;
if cntt=delay*3 then
current_state<=set_dcb;
cntt:=0;
end if;
when set_dcb=> --显示开关控制
lcden<='0';
lcdda<='0';
lcdrw<='0';
data<="00001111";
cntt:=cntt+1;
if cntt>delay and cntt<=delay*2 then --延时操作
lcden<='1'; --保证液晶有足够的使能时间
else
lcden<='0';
end if;
if cntt=delay*3 then
current_state<=set_location;
cntt:=0;
end if;
when set_location=> --设置显示数据的初始位置
lcden<='0';
lcdda<='0';
lcdrw<='0';
data<="11000000";
cntt:=cntt+1;
if cntt>delay and cntt<=delay*2 then --延时操作
lcden<='1'; --保证液晶有足够的使能时间
else
lcden<='0';
end if;
if cntt=delay*3 then
current_state<=write_data;
cntt:=0;
end if;
when write_data=> --将数据写入液晶
lcden<='0';
lcdda<='1';
lcdrw<='0';
if cnt2<=7 then
data<=dataram(cnt2);
cntt:=cntt+1;
if cnt3<="1000"then
if cnt2=2 then
data<="00100000";
end if;
end if;
if cntt>delay and cntt<=delay*2 then
lcden<='1';
else
lcden<='0';
end if;
if cntt=delay*3 then
current_state<=write_data;
cntt:=0;
cnt2:=cnt2+1;
end if;
else
cnt2:=0;
current_state<=set_location;
end if;
end case;
end if;
end process;
end Behavioral;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -