Verilog液晶显示

-------------12864液晶的显示-----------
----时钟:10MHZ

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity lcd12864 is
generic(
    divide_500k:integer:=20;--20分频后:500KHZ:2us
    cnt1_value:integer:=50
    );
port(
   clk,reset:in std_logic;
   rs,rw,en:out std_logic;
   data:out std_logic_vector(7 downto 0)
   );
end entity;

architecture behavior of lcd12864 is
type word is array(0 to 3) of std_logic_vector(7 downto 0);--因为大家的习惯,数组中的左起第1个数为数组中的最低位对应的数,所以设置为array(0 to 3),而不是array(3 downto 0)。此处若不注意,容易出错。

type state is(
     set_dlnf1,set_dlnf2,set_cursor,set_dcb,set_shift,
     set_ddram,
     write_name,
     over
     );

constant name:word:=("11010110","11010000","10111001","11111010");--中D6D0 国B9FA
--constant name:word:=("11010000","11101100","10111110","10101001");--徐D6D0 京B9FA
signal pr_state:state;
signal newclk:std_logic;
begin

process(clk) is
variable num:integer range 0 to divide_500k;
begin
   if(clk'event and clk='1')then
    num:=num+1;
    if(num=divide_500k) then
     num:=0;
    end if;
    if(num<divide_500k/2) then--设置占空比
     newclk<='0';
    else newclk<='1';
    end if;   
   end if;
end process;

process(newclk,reset,pr_state) is
   variable cnt1:integer range 0 to 100*cnt1_value:=0;
   variable cnt2:integer range 0 to 100:=0;
begin
   if(reset='0') then
    pr_state<=set_dlnf1;       --把状态set_dlnf1赋于pr_state
    cnt1:=0;
    cnt2:=0;
    en<='0';
    data<="ZZZZZZZZ";
   elsif(newclk'event and newclk='1') then
    case pr_state is
     when set_dlnf1=>
      cnt1:=cnt1+1;
      if(cnt1<cnt1_value) then
       en<='0';
       rs<='0';       --命令
       rw<='0';       --写
      elsif(cnt1<2*cnt1_value) then
       data<="00110000";     --选择8位数据基本指令集:0x30
      elsif(cnt1<20*cnt1_value) then
       en<='1';
      elsif(cnt1=20*cnt1_value) then
       en<='0';
       cnt1:=0;
       pr_state<=set_dlnf2;
      end if;
    
     when set_dlnf2=>
      cnt1:=cnt1+1;
      if(cnt1<cnt1_value) then
       en<='0';
      elsif(cnt1<2*cnt1_value) then
       data<="00110000";     --选择8位数据基本指令集:0x30
      elsif(cnt1<20*cnt1_value) then
       en<='1';
      elsif(cnt1=20*cnt1_value) then
       en<='0';
       cnt1:=0;
       pr_state<=set_cursor;
      end if;
     when set_cursor=>
      cnt1:=cnt1+1;
      if(cnt1<cnt1_value) then
       en<='0';
      elsif(cnt1<2*cnt1_value) then
       data<="00001100";     --整体显示设置:光标OFF 反光0FF:0x0c
      elsif(cnt1<20*cnt1_value) then
       en<='1';
      elsif(cnt1=20*cnt1_value) then
       en<='0';
       cnt1:=0;
       pr_state<=set_dcb;
      end if;
     when set_dcb=>
      cnt1:=cnt1+1;
      if(cnt1<cnt1_value) then
       en<='0';
      elsif(cnt1<2*cnt1_value) then
       data<="00000001";     --清除显示,并且认定地址指针为00h:0x01
      elsif(cnt1<20*cnt1_value) then
       en<='1';
      elsif(cnt1=20*cnt1_value) then
       en<='0';
       cnt1:=0;
       pr_state<=set_shift;
      end if;
     when set_shift=>
      cnt1:=cnt1+1;
      if(cnt1<cnt1_value) then
       en<='0';
      elsif(cnt1<2*cnt1_value) then
       data<="00000110";     --指定游标的移动方向及指定显示的移位:0x06
      elsif(cnt1<20*cnt1_value) then
       en<='1';
      elsif(cnt1=20*cnt1_value) then
       en<='0';
       cnt1:=0;
       pr_state<=set_ddram;
      end if;
     when set_ddram=>
      cnt1:=cnt1+1;
      if(cnt1<cnt1_value) then
       en<='0';
      elsif(cnt1<2*cnt1_value) then
       data<="10000011";     --从第一行的第一个字开始显示:0x80
               --从第一行的第四个字开始显示:0x80+3
      elsif(cnt1<20*cnt1_value) then
       en<='1';
      elsif(cnt1=20*cnt1_value) then
       en<='0';
       cnt1:=0;
       pr_state<=write_name;
      end if;
     when write_name=>
      cnt1:=cnt1+1;
      if cnt1<1*cnt1_value then
       en<='0';
       rs<='1';                   ------------选择数据
       rw<='0';
      elsif cnt1<2*cnt1_value then
       data<=name(cnt2);        ------------送数据
      elsif cnt1<20*cnt1_value then
       en<='1';                 -----在上升沿时,数据才能写入液晶,所以要先送数据,再让使能端变高
      elsif cnt1=20*cnt1_value then  
       en<='0';       -----通过液晶的时序图知:使能端先低,送数据,使能端升高,再变低。
       cnt1:=0;
       cnt2:=cnt2+1;
       if cnt2=4 then----倘若使能端的触发方式错误,此处也许要大于4的数才有显示
        pr_state<=over;
        cnt2:=0;
       end if;
      end if;
     when over=>
      null;
     when others=>
      en<='Z';
      rs<='Z';
      rw<='Z';
      data<=(others=>'Z');
      cnt1:=0;
      cnt2:=0; 
    end case;
   end if;
end process;
end architecture;

    这个液晶程序,花了十来天的时间,今天总算与它有了了结。程序中,之所以只在第一行的第四列起,显示了“中国”两个字,主要是简单,便于网友理解。

 

这个程序我试过,管用的,第二篇也是管用的
是不是你的时钟频率不一样呢?
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ANTRK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值