集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 1276|回复: 1

请大神帮忙看看LCD1602的问题?

[复制链接]
ytphrx 发表于 2013-11-2 20:28:46 | 显示全部楼层 |阅读模式
感谢先。上程序请大神观赏,本程序是要在LCD1602上显示字符,至于什么字符不重要,本来是想做一个LCD1602的驱动,结果卡壳了:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.All;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY driver_hd44780_lcd1602 IS
PORT(Clk:IN STD_LOGIC;   --50兆输入时钟
     Reset:IN STD_LOGIC;    --复位信号
     LCD_RS:OUT STD_LOGIC;  --数据和指令模式的选择信号
     LCD_RW:OUT STD_LOGIC; --读写使能信号
     LCD_EN:OUT STD_LOGIC;  --指令执行时序信号
     LCD_Data:OUT STD_LOGIC_VECTOR(7 DOWNTO 0) --LCD1602的8条数据线
     );
END ENTITY driver_hd44780_lcd1602;
ARCHITECTURE Behavioral OF driver_hd44780_lcd1602 IS
TYPE State IS(clear_screen,setup_function,setup_input,setup_screen,setup_ddram,write_ddram); --状态机
SIGNAL Current_State:State;
TYPE Ram2 IS ARRAY(0 to 7) OF STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL ddram_line:Ram2:=(("01000000"),("01000001"),("01000010"),("01000011"),("01000100"),("01000101"),("01000110"),("01000111"));                      --2维数组存储要在LCD上显示的字符代码@ABCDEFG
SIGNAL Count:INTEGER RANGE 0 TO 25000 :=0;       --时钟分频计数器,目的是分频50兆输入时钟成1KHZ时钟。
SIGNAL Clk_Out:STD_LOGIC;              --1khz的clk输出
BEGIN
LCD_EN<=Clk_Out;          --置LCD_EN信号为1kHZ的信号
LCD_RW<='0';                 --置写LCD DDRAM模式
PROCESS(Clk,Reset)         --分频器,用于产生1KHZ的信号
BEGIN
    IF(Reset='0') THEN
       Count<=0;
    ELSIF(RISING_EDGE(Clk)) THEN
       IF(Count=25000) THEN
       Count<=0;
       Clk_out<=not Clk_out;
       ELSE
       Count<=Count+1;
       END IF;
    END IF;
END PROCESS;
PROCESS(Clk_Out,Reset,Current_State)
VARIABLE cnt1:STD_LOGIC_VECTOR(2 DOWNTO 0);
BEGIN
     IF(Reset='0')THEN      --复位
        LCD_RS<='0';
        Current_State<=clear_screen;  --置状态机初始状态
        cnt1:="000";     --要显示的字符计数器赋0
     ELSIF(RISING_EDGE(Clk_Out))THEN    --每个1khz clk的上升边沿执行如下操作:
        LCD_RS<='0';                                 --置LCD1602写指令状态
        CASE Current_State IS
        WHEN clear_screen => LCD_Data <= "00000001";Current_State<=setup_function; --向LCD发出清屏命令
        WHEN setup_function=>LCD_Data <= "00111100";Current_State<=setup_input;--向LCD发出显示布局设置命令
        WHEN setup_input => LCD_Data <= "00000110";Current_State<=setup_screen;--向LCD发出每次写入数据后的光标自动移动方向
        WHEN setup_screen => LCD_Data<="00001111";Current_State<=setup_ddram;--设置屏幕光标闪烁否
        WHEN setup_ddram => LCD_Data<="10000000";Current_State<=write_ddram; --设置初始写ddram的地址
        WHEN write_ddram => LCD_RS<='1';LCD_Data<=ddram_line(CONV_INTEGER(cnt1));cnt1:=cnt1+1;开始顺序写入ddram预先设置好的数组中的字符,直到数组结束。
        WHEN OTHERS => NULL;
        END CASE;
     END IF;
END PROCESS;
END ARCHITECTURE Behavioral;

问题描述:
Q1:预置数组是8个数据,当cnt1加到数据8以上时再输出就是第9个数据,数组没有第9个数据,所以应该是空的才对,为什么我的LCD上居然循环重复二维数组输出16个字符:@ABCDEFG@ABCDEFG。
请大神告知怎么回事,并给一个处理办法?
Q2:这个程序需要按reset键才能开始显示,枚举状态机不是会自动取值第一个状态clear_screen,然后根据时钟继续其他输出在开机的时候?奇怪的是开机不能显示,必须按reset键之后才会显示?
Q3:第一次按reset键会开始显示东西,虽然内容多输出了一遍。但是再次按reset之后居然没有复位,而是没有内容显示了。这个是为什么?只有第一次复位成功。
感谢大神指点。
 楼主| ytphrx 发表于 2013-11-2 22:17:28 | 显示全部楼层
Q1:已经解决:
方法:在其中一行增加一个控制语句,使输出超过8个字符时程序运行进入空状态,如下:
        WHEN write_ddram => LCD_RS<='1';LCD_Data<=ddram_line(CONV_INTEGER(cnt1));cnt1:=cnt1+1;IF cnt1="000" THEN Current_State <= null_state; END IF;
Q23,已经解决,按reset的时间间隔太短导致系统出错。慢慢按就可以了。
把输入数据更改成端口,然后映射到数组就应该可以按照元件的格式调用,输出任意英文数字了。
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2025-6-22 03:24 , Processed in 0.063520 second(s), 20 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表