求大虾帮忙看下FPGA控制液晶1602的程序

crystal3379   2010-4-21 15:56 楼主
  这个程序是用VHDL编写的,直接上程序了:
  LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY LC IS
      PORT(RS,RW:OUT STD_LOGIC;
           ENA:OUT STD_LOGIC;
           CLK:IN STD_LOGIC;
           DATA:INOUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END LC;
ARCHITECTURE ARC OF LC IS
SIGNAL CLKF:STD_LOGIC:='0';
SIGNAL CLKEN:STD_LOGIC:='0';
SIGNAL OCEN1:BOOLEAN:=FALSE;
SIGNAL OCEN2:BOOLEAN:=FALSE;
--SIGNAL ENCO:BOOLEAN:=FALSE;
BEGIN


PROCESS(CLK)   --分频,所分的的频率为其他操作执行的最小时间 1ms左右
VARIABLE COUNT:INTEGER RANGE 0 TO 25000:=0;
BEGIN
IF(CLK'EVENT AND CLK='1')THEN
  IF(COUNT<=12500) THEN
    COUNT:=COUNT+1;
  ELSE
      COUNT:=0;
      CLKF<=NOT CLKF;  
  END IF;
END IF;
END PROCESS;

PROCESS(CLK)       --分频,这个clken信号用来维持rw、rs信号与enable信号的最小建立时间 (100ns下)
VARIABLE COUNT:INTEGER RANGE 0 TO 5:=0;
BEGIN
IF(CLK'EVENT AND CLK='1')THEN
  IF(COUNT<3)THEN
    COUNT:=COUNT+1;
  ELSE
      COUNT:=0;
      CLKEN<=NOT CLKEN;
  END IF;
END IF;
END PROCESS;

PROCESS(CLKEN,OCEN1,OCEN2)   --单独用此进程来控制enable信号也是为了搭配上一个进程,建立一个符合时需要求的最小 地址建立时间、地址保持时间
BEGIN
IF(CLKEN'EVENT AND CLKEN='1')THEN
  IF(OCEN1=TRUE)THEN
    ENA<='1';
--   ENCO<=FALSE;
  END IF;
  IF(OCEN2=TRUE)THEN
    ENA<='0';
--       ENCO<=TRUE;
  END IF;
END IF;
END PROCESS;         


INITIAL:PROCESS(CLKF)           --通过case语句及相关变量(入syb)来进行初始化和最后的数据输入
VARIABLE SYB:INTEGER RANGE 0 TO 15:=0;     --标志应该为哪一步初始动作
VARIABLE COUNT:INTEGER RANGE 0 TO 6:=0;   
VARIABLE BZYN:BOOLEAN:=FALSE;
BEGIN
IF(CLKF'EVENT AND CLKF='1')THEN     --时钟触发
  CASE SYB IS
      WHEN 0=>          --初始话命令38H
          IF(COUNT<=5)THEN     --要count《=5的目的在于让此步骤维持5ms以上
            RW<='0';
            RS<='0';
            DATA<="00111000";
            OCEN1<=TRUE;      --触发进程,使enable信号变高,当然,由于使用了专门的进程来控制enable,所以rs、rw会比enable早80ns左右
            OCEN2<=FALSE;
            COUNT:=COUNT+1;
          ELSE
              OCEN1<=FALSE;    --enable变为低
              OCEN2<=TRUE;
              SYB:=1;          --标志变为1
              COUNT:=0;
          END IF;
      WHEN 1=>
          IF(COUNT<=5)THEN     --同上,再次进行5ms的38H的命令写入
            RW<='0';
            RS<='0';
            DATA<="00111000";
            OCEN1<=TRUE;
            OCEN2<=FALSE;
            COUNT:=COUNT+1;
          ELSE
              OCEN1<=FALSE;
              OCEN2<=TRUE;
              SYB:=2;
              COUNT:=0;
          END IF;
      WHEN 2=>           --进行一次38H命令写入
          IF(COUNT<1)THEN
            RW<='0';
            RS<='0';
            COUNT:=1;
            DATA<="00111000";
            OCEN1<=TRUE;
            OCEN2<=FALSE;
          ELSE
              OCEN2<=TRUE;
              OCEN1<=FALSE;
              COUNT:=0;
              SYB:=3;
              BZYN:=FALSE;
          END IF;   
      WHEN 3=>             --进行一次有检测data(7)忙的38H命令写入
          IF(COUNT<2)THEN
            IF(BZYN=FALSE)THEN
              RS<='0';     --进行读状态操作
              RW<='1';
              DATA(7)<='1';
              OCEN1<=TRUE;
              OCEN2<=FALSE;
              BZYN:=TRUE;
            ELSE
                IF(DATA(7)='0')THEN    --检测data(7)
                  IF(COUNT=0)THEN
                    OCEN2<=TRUE;       --在得知不忙后,进行一次enable信号拉低操作
                    OCEN1<=FALSE;
                    COUNT:=1;
                  ELSE  
                      RS<='0';       --38H
                      RW<='0';
                      DATA<="00111000";
                      OCEN1<=TRUE;
                      OCEN2<=FALSE;
                      COUNT:=2;
                  END IF;   
                END IF;
            END IF;
          ELSE        
              SYB:=4;
              BZYN:=FALSE;
              COUNT:=0;     
              OCEN1<=FALSE;       --在使用完enable后,将它拉低
              OCEN2<=TRUE;
          END IF;
      WHEN 4=>              --写入08H命令
          IF(COUNT<2)THEN
            IF(BZYN=FALSE)THEN
              RS<='0';
              RW<='1';
              DATA(7)<='1';
              OCEN1<=TRUE;
              OCEN2<=FALSE;
              BZYN:=TRUE;
            ELSE
                IF(DATA(7)='0')THEN
                  IF(COUNT=0)THEN
                    OCEN2<=TRUE;
                    OCEN1<=FALSE;
                    COUNT:=1;
                  ELSE  
                      RS<='0';
                      RW<='0';
                      DATA<="00001000";
                      OCEN1<=TRUE;
                      OCEN2<=FALSE;
                      COUNT:=2;
                  END IF;   
                END IF;
            END IF;
          ELSE        
              SYB:=5;
              BZYN:=FALSE;
              COUNT:=0;
              OCEN2<=TRUE;
              OCEN1<=FALSE;
          END IF;   
      WHEN 5=>       --写入01H命令
          IF(COUNT<2)THEN
            IF(BZYN=FALSE)THEN
              RS<='0';
              RW<='1';
              DATA(7)<='1';
              OCEN1<=TRUE;
              OCEN2<=FALSE;
              BZYN:=TRUE;
            ELSE
                IF(DATA(7)='0')THEN
                  IF(COUNT=0)THEN
                    OCEN2<=TRUE;
                    OCEN1<=FALSE;
                    COUNT:=1;
                  ELSE  
                      RS<='0';
                      RW<='0';
                      DATA<="00000001";
                      OCEN1<=TRUE;
                      OCEN2<=FALSE;
                      COUNT:=2;
                  END IF;   
                END IF;
            END IF;
          ELSE        
              SYB:=6;
              BZYN:=FALSE;
              COUNT:=0;
              OCEN2<=TRUE;
              OCEN1<=FALSE;
          END IF;
      WHEN 6=>    -- 写入06H命令
          IF(COUNT<2)THEN
            IF(BZYN=FALSE)THEN
              RS<='0';
              RW<='1';
              DATA(7)<='1';
              OCEN1<=TRUE;
              OCEN2<=FALSE;
              BZYN:=TRUE;
            ELSE
                IF(DATA(7)='0')THEN
                  IF(COUNT=0)THEN
                    OCEN2<=TRUE;
                    OCEN1<=FALSE;
                    COUNT:=1;
                  ELSE  
                      RS<='0';
                      RW<='0';
                      DATA<="00000110";
                      OCEN1<=TRUE;
                      OCEN2<=FALSE;
                      COUNT:=2;
                  END IF;   
                END IF;
            END IF;
          ELSE        
              SYB:=7;
              BZYN:=FALSE;
              OCEN2<=TRUE;
              OCEN1<=FALSE;
              COUNT:=0;
          END IF;
      WHEN 7=>     写入0fH命令
          IF(COUNT<2)THEN
            IF(BZYN=FALSE)THEN
              RS<='0';
              RW<='1';
              DATA(7)<='1';
              OCEN1<=TRUE;
              OCEN2<=FALSE;
              BZYN:=TRUE;
            ELSE
                IF(DATA(7)='0')THEN
                  IF(COUNT=0)THEN
                    OCEN2<=TRUE;
                    OCEN1<=FALSE;
                    COUNT:=1;
                  ELSE  
                      RS<='0';
                      RW<='0';
                      DATA<="00001111";
                      OCEN1<=TRUE;
                      OCEN2<=FALSE;
                      COUNT:=2;
                  END IF;   
                END IF;
            END IF;
          ELSE        
              SYB:=8;
              BZYN:=FALSE;
              COUNT:=0;
              OCEN2<=TRUE;
              OCEN1<=FALSE;
          END IF;  
      WHEN 8=>      --写入ddram地址0000000h
          IF(COUNT<2)THEN
            IF(BZYN=FALSE)THEN
              RS<='0';
              RW<='1';
              DATA(7)<='1';
              OCEN1<=TRUE;
              OCEN2<=FALSE;
              BZYN:=TRUE;
            ELSE
                IF(DATA(7)='0')THEN
                  IF(COUNT=0)THEN
                    OCEN2<=TRUE;
                    OCEN1<=FALSE;
                    COUNT:=1;
                  ELSE  
                      RS<='0';
                      RW<='0';
                      DATA<="10000000";
                      OCEN1<=TRUE;
                      OCEN2<=FALSE;
                      COUNT:=2;
                  END IF;   
                END IF;
             END IF;
         ELSE
             BZYN:=FALSE;
             COUNT:=0;
             OCEN2<=TRUE;
             OCEN1<=FALSE;
             SYB:=9;
         END IF;                                                
      WHEN 9=>     --写入数据38H,以后循环此
          IF(COUNT<2)THEN
            IF(BZYN=FALSE)THEN
              RS<='0';
              RW<='1';
              DATA(7)<='1';
              OCEN1<=TRUE;
              OCEN2<=FALSE;
              BZYN:=TRUE;
            ELSE
                IF(DATA(7)='0')THEN
                  IF(COUNT=0)THEN
                    OCEN2<=TRUE;
                    OCEN1<=FALSE;
                    COUNT:=1;
                  ELSE  
                      RS<='1';
                      RW<='0';
                      COUNT:=2;
                      DATA<="01000001";
                      OCEN1<=TRUE;
                      OCEN2<=FALSE;
                  END IF;   
                END IF;
            END IF;      
          ELSE
              BZYN:=FALSE;
              COUNT:=0;
              OCEN2<=TRUE;
              OCEN1<=FALSE;
          END IF;
      WHEN OTHERS=>OCEN2<=TRUE;    --异常处理
                   OCEN1<=FALSE;        
  END CASE;
END IF;  
END PROCESS INITIAL;
END ARC;   
最后在实验板上跑出来的结果不是高一行没显示,第一行全黑,就是两行都没显示,我用的是cycloneII的EP2C8Q208C8,ps,在quartus上仿时序没有错误啊,汗。。。
希望高人前来踢场子

回复评论 (4)

oh,mygod,帖子沉了,自己来顶起
点赞  2010-4-22 09:23
这个程序···网上很多啊。楼主现在应该调试,忍耐。

我大学搞过一阵子,现在一直arm
友情帮顶了!
点赞  2010-4-22 11:43

B1AdMtB3WWjFsFXIiJnDl



KvaXfGmUW6qjxpQz2OasC
点赞  2010-4-22 12:04

5楼 gdq 

引用: 引用 2 楼 gooogleman 的回复:

这个程序···网上很多啊。楼主现在应该调试,忍耐。

我大学搞过一阵子,现在一直arm
友情帮顶了!
谢谢你的友情帮顶,看来我的耐心还不够,这个程序还是我自己来调试吧
点赞  2010-4-23 08:36
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复