【问题标题】:Why does the LCD of a Spartan 3AN is not working?为什么 Spartan 3AN 的 LCD 不工作?
【发布时间】:2013-09-24 12:50:07
【问题描述】:

这是 LCD 的子程序:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity VideoTest is
    port( LCD_E, LCD_RS, LCD_RW : OUT std_logic;
            LCD_DB : OUT std_logic_vector(7 downto 0);
            counter: IN integer;
            clk: IN std_logic);

end VideoTest;

architecture Behavioral of VideoTest is
    signal InitDone: std_logic :='0';
begin

InitAndSet: process (InitDone, counter, clk) is
    variable tencounter: integer :=0;
    variable tempcounter: integer :=0;
begin
    if (clk'event and clk='1') then
        if (InitDone = '0') then
        -- Enabling
            LCD_E <='1';

        -- Clear Screen
            LCD_RS<='0';
            LCD_RW<='0';
            LCD_DB(7 downto 1) <= "0000000";
            LCD_DB(0) <= '1';

        -- Return Cursor Home

            LCD_RS<='0';
            LCD_RW<='0';
            LCD_DB(7 downto 2) <= "000000";
            LCD_DB(1) <= '1';
            LCD_DB(0) <= '0';

        -- Setting incrementation and moving cursor;

            LCD_RS<='0';
            LCD_RW<='0';
            LCD_DB(7 downto 3) <= "00000";
            LCD_DB(2) <= '1';
            LCD_DB(1) <= '1';
            LCD_DB(0) <= '0';

        -- Display On, show cursor, blink cursor

            LCD_RS<='0';
            LCD_RW<='0';
            LCD_DB(7 downto 4) <= "0000";
            LCD_DB(3) <= '1';
            LCD_DB(2) <= '1';
            LCD_DB(1) <= '1';
            LCD_DB(0) <= '1';

        -- Function set

            LCD_RS<='0';
            LCD_RW<='0';
            LCD_DB(7 downto 6) <= "00";
            LCD_DB(5) <= '1';
            LCD_DB(4) <= '0';
            LCD_DB(3) <= '1';
            LCD_DB(2) <= '0';
            LCD_DB(1) <= '1';
            LCD_DB(0) <= '1';

        -- Set DD Adress to 0

            LCD_RS<='0';
            LCD_RW<='0';
            LCD_DB(7)<='1';
            LCD_DB(6 downto 0) <= "0000000";

            InitDone <= '0';
        end if;

        -- Setting the value (0 to 9 is equal to 00110000 to 00111001)
        if (InitDone = '1') then
            if (counter < 10) then
                LCD_RS<='1';
                LCD_RW<='0';
                case counter is
                    when 0 =>
                            LCD_DB <="00110000";
                    when 1 =>
                            LCD_DB <="00110001";
                    when 2 =>
                            LCD_DB <="00110010";
                    when 3 =>
                            LCD_DB <="00110011";
                    when 4 =>
                            LCD_DB <="00110100";
                    when 5 =>
                            LCD_DB <="00110101";
                    when 6 =>
                            LCD_DB <="00110110";
                    when 7 =>
                            LCD_DB <="00110111";
                    when 8 =>
                            LCD_DB <="00111000";
                    when 9 =>
                            LCD_DB <="00111001";
                    when others =>
                            LCD_DB <="00000000";
                end case;
            -- if counter is greater than 10, then put the number in two addresses.
            elsif (counter > 9) then

                LCD_DB <="00000000";
                tempcounter :=counter;
                for i in 0 to 8 loop
                    if tempcounter > 9 then
                        tempcounter := tempcounter - 10;
                    end if;
                end loop;
                tencounter := counter - tempcounter;

                case tencounter is
                    when 0 =>
                            LCD_DB <="00110000";
                    when 1 =>
                            LCD_DB <="00110001";
                    when 2 =>
                            LCD_DB <="00110010";
                    when 3 =>
                            LCD_DB <="00110011";
                    when 4 =>
                            LCD_DB <="00110100";
                    when 5 =>
                            LCD_DB <="00110101";
                    when 6 =>
                            LCD_DB <="00110110";
                    when 7 =>
                            LCD_DB <="00110111";
                    when 8 =>
                            LCD_DB <="00111000";
                    when 9 =>
                            LCD_DB <="00111001";
                    when others =>
                            LCD_DB <="00000000";
                end case;

                LCD_RS<='0';
                LCD_RW<='0';
                LCD_DB(7)<='1';
                LCD_DB(6 downto 1) <= "000000";
                LCD_DB(0) <='1';

                case tempcounter is
                    when 0 =>
                            LCD_DB <="00110000";
                    when 1 =>
                            LCD_DB <="00110001";
                    when 2 =>
                            LCD_DB <="00110010";
                    when 3 =>
                            LCD_DB <="00110011";
                    when 4 =>
                            LCD_DB <="00110100";
                    when 5 =>
                            LCD_DB <="00110101";
                    when 6 =>
                            LCD_DB <="00110110";
                    when 7 =>
                            LCD_DB <="00110111";
                    when 8 =>
                            LCD_DB <="00111000";
                    when 9 =>
                            LCD_DB <="00111001";
                    when others =>
                            LCD_DB <="00000000";
                end case;

            end if;
        end if;
    end if;

end process InitAndSet;


end Behavioral;

以下是用户约束:

-- Constraints
NET "LCD_E" LOC = "AB4" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LCD_RS" LOC = "Y14" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LCD_RW" LOC = "W13" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LCD_DB<7>" LOC = "Y15" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LCD_DB<6>" LOC = "AB16" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LCD_DB<5>" LOC = "Y16" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LCD_DB<4>" LOC = "AA12" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LCD_DB<3>" LOC = "AB12" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LCD_DB<2>" LOC = "AB17" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LCD_DB<1>" LOC = "AB18" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
NET "LCD_DB<0>" LOC = "Y13" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

正如我所见,这个程序应该激活 LCD 显示器,因为我已经清除了内存中所有旧的保存的东西,我已经将光标设置为 0 位置,然后在特定的数字上增加(在主项目)它指示屏幕上的数字。我直接从 Spartan 3AN - Beginner Kit 的用户手册中获取了约束和编码。

我错过了什么吗?它的行为就像它没有通电一样。

提前致谢, 博扬·马托夫斯基

【问题讨论】:

    标签: initialization vhdl lcd


    【解决方案1】:
    if (clk'event and clk='1') then
        if (InitDone = '0') then
        -- Enabling
            LCD_E <='1';
    
        -- Clear Screen
            LCD_RS<='0';
            LCD_RW<='0';
            LCD_DB(7 downto 1) <= "0000000";
            LCD_DB(0) <= '1';
            etc etc etc.....
    

    一个问题:您在第一部分中缺少状态机。查看 Case 语句以及它们如何与状态机一起使用。您编写的代码中会发生的情况是 LCD_RD、LCD_RW 等将被替换为您在该 if 语句中拥有的最后一行代码。在此之前的所有内容都将被使用。

    另一个问题:InitDone 永远不会设置为“1”。永远。

    还有一个问题:

    for i in 0 to 8 loop
        if tempcounter > 9 then
             tempcounter := tempcounter - 10;
        end if;
    end loop;
    

    这个 for 循环的行为不像你想象的那样。您需要阅读可综合代码中的 for 循环。它们的行为不像 C 中的 for 循环。

    【讨论】:

    • 是的,它不应该是“InitDone
    • 我不想粗鲁,但你真的需要拿起一本关于编写可合成的 VHDL 的书并仔细阅读。您编写代码就像软件程序员编写 C 代码一样。你需要像硬件程序员一样写作。 VHDL 并行执行,C 串行执行。您不能从超过 1 个进程中驱动相同的信号。
    • 我专业编写VHDL。意味着这是我的工作。意思是我知道我在说什么。你的 for 循环不会做任何事情。 VHDL 中的 for 循环用于复制逻辑。它们实际上不能像 C 那样遍历代码行。所以如果我有这个for循环: for i in 0 to 8 loop temp[i]
    • 那么你实际上是在写这个:temp(0)
    • 1. tempcount 从 85 开始,每个时钟周期减少 10。 for 循环没有做任何事情。 2. 复位是高电平有效还是低电平有效?如果它是低电平有效,为清楚起见,您应该将其称为 RESET_N。 3. 您将 int 分配给递减 10 的 tempcount 值,因此它将从 85 开始,下一个时钟为 75,然后是 65,依此类推,直到达到 5,此时 LED 亮起。顺便说一句,没有什么会再次关闭它,它总是会打开。我实际上不确定 tempcount 会发生什么。它只会永远递减!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-23
    • 1970-01-01
    • 2016-11-19
    • 1970-01-01
    • 1970-01-01
    • 2015-06-15
    相关资源
    最近更新 更多