реклама на сайте
подробности

 
 
> LCD-Display, Отказывается работать в железе :-(
artur
сообщение Sep 2 2016, 21:11
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 18
Регистрация: 11-09-15
Пользователь №: 88 369



Доброе время суток,

помогите разобраться почему описаная схема по управлению лцд-дисплеем отказывается работать в железе...

Компелятор не ругаеться, в симуляторе тоже все хорошо выглядит. Я с начала думал что паузы между командами слишком маленькие, увеличил, всеравно не работает, но не так чтобы совсем не работает, не пишит текст. Инициализацию принемает, а текст не пишит








ну и сам Код:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;


entity lcd_v5 is port
(
clk : in std_logic; -- System clk
-- daten_bereit : in std_logic;
-- data_input : in std_logic_vector(7 downto 0);
busy : out std_logic := '1'; -- busy Flag
rs : out std_logic := '0'; -- data or instruction, instruction = '0', data = '1'
rw : out std_logic := '0'; -- read or write, read = '1', write = '0'
enable_lcd : out std_logic := '0'; -- enable for read of write
data : out std_logic_vector(7 downto 0) := (others => '0') -- daten
);
end entity;

architecture beh of lcd_v5 is


type zustaende is (begining, waitx, ini_data_send, lcd_enable, lcd_desable, ini_loop, ready);

signal zustand : zustaende := begining;


type mem_data is array(0 to 11) of std_logic_vector(7 downto 0);
constant daten : mem_data :=
(
x"30", -- data_reset(0) "0011 0000"
x"30", -- data_reset(1) "0011 0000"
x"30", -- data_reset(2) "0011 0000"
x"3c", -- data_ini_1(3) "0011 1100"
x"0f", -- data_ini_2(4) "0000 1111"
x"07", -- data_ini_3(5) "0000 0111"
x"01", -- data_ini_4(6) "0000 0001"

x"59", -- Y(7)
x"65", -- e(8)
x"61", -- a(9)
x"21", -- !(10)
x"00" -- (11)
);



type delay_type is array(0 to 6) of std_logic_vector(23 downto 0);
constant delay : delay_type :=
(
x"4c4b40", -- 100 ms(0)
x"033450", -- 4.2ms(1)
x"0013ba", -- 101us(2)
x"0009c4", -- delay_50us(3)
x"000032", -- delay_1us(4)
x"2625a0", -- delay_50ms(5)
x"030d40" -- delay_4ms(6)
);


signal addr_delay : integer range 0 to 6 := 0;
signal addr_delay_i : integer range 0 to 6 := 0;
signal addr_data : integer range 0 to 11 := 0;


signal counter : std_logic_vector(23 downto 0) := (others => '0');
signal cnt_en : std_logic := '0';
signal cnt_fert : boolean := false;
signal initialisierung : boolean := false;
signal pause_halten : boolean := true;
signal daten_gesendet : std_logic_vector(1 downto 0) := "00";
signal versions_nr : boolean := false;
signal load : std_logic := '0';
signal data_out : std_logic_vector(7 downto 0) := (others => '0');

begin


process(clk)
variable cnt_intern : integer range -2 to 5000000 := 2;
begin

if rising_edge(clk) then

if cnt_en = '1' then

if load = '1' then

cnt_intern := to_integer(unsigned(counter));

else

cnt_intern := cnt_intern - 1;
cnt_fert <= false;

end if;

if cnt_intern = 0 then
cnt_fert <= true;
end if;
end if;
end if;
end process;



-- automat --

process(clk)
variable durchlauf : integer range 0 to 12 := 0;
begin

if (rising_edge(clk)) then

case zustand is


when begining => counter <= delay(addr_delay);
cnt_en <= '1';
load <= '1';
rw <= '0';
busy <= '1';
zustand <= waitx;

if versions_nr = true then
rs <= '1';
else
rs <= '0';
end if;

when waitx => load <= '0';

if cnt_fert = true then

if initialisierung = false then

case daten_gesendet is

when "01" => zustand <= lcd_enable;
cnt_en <= '0';

when "10" => cnt_en <= '0';
zustand <= lcd_desable;

when others => data_out <= (others => '0');

if pause_halten = true then
enable_lcd <= '0';
cnt_en <= '0';
pause_halten <= false;
zustand <= ini_data_send;
else
cnt_en <= '0';
enable_lcd <= '0';
addr_delay <= addr_delay_i;
zustand <= ini_loop;
durchlauf := durchlauf + 1;
end if;
end case;
else
cnt_en <= '0';
zustand <= ready;
durchlauf := 0;
end if;

else
zustand <= waitx;
end if;

when ini_data_send => data_out <= daten(addr_data);
addr_delay <= 4;
daten_gesendet <= "01";
zustand <= begining;

when lcd_enable => addr_delay <= 4;
enable_lcd <= '1';
zustand <= begining;
daten_gesendet <= "10";

when lcd_desable => enable_lcd <= '0';
zustand <= begining;
daten_gesendet <= "00";

when ini_loop => data_out <= (others => '0');

if durchlauf > 2 then

addr_data <= addr_data + 1;
addr_delay_i <= 3;
addr_delay <= 3;
pause_halten <= true;
zustand <= begining;

if durchlauf = 7 then

versions_nr <= true;
addr_data <= addr_data + 1;
addr_delay <= 5;
addr_delay_i <= 5;
pause_halten <= true;
zustand <= begining;
end if;
else
addr_delay <= addr_delay + 1;
addr_delay_i <= addr_delay_i + 1;
addr_data <= addr_data + 1;
pause_halten <= true;
zustand <= begining;
end if;

if durchlauf >= 11 then

durchlauf := 0;
addr_data <= addr_data + 1;
addr_delay <= 6;
initialisierung <= true;
zustand <= begining;
end if;

when ready => zustand <= ready;

end case;
end if;
end process;
data <= data_out;
end beh;
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 10)
Andrew Su
сообщение Sep 3 2016, 10:39
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 301
Регистрация: 18-09-07
Из: Украина
Пользователь №: 30 647



А какой LCD?
Go to the top of the page
 
+Quote Post
Александр77
сообщение Sep 3 2016, 19:06
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 608
Регистрация: 10-07-09
Из: Дубна, Московская область
Пользователь №: 51 111



Вот что сильно путает, так это вложенность Ifов друг в друга при проверке одной и той же переменной
Код
.....
if durchlauf > 2 then
   addr_data <= addr_data + 1;
   addr_delay_i <= 3;
   addr_delay <= 3;
   pause_halten <= true;
   zustand <= begining;
   if durchlauf = 7 then
      .....

Получается железу надо проверить что durchlauf больше 2, а в каких то случаях при этом еще и равно 7.
На мой взгляд, лучше разбить проверку на две части
1) значение больше 2, но меньше 7
2) значение равно 7.
Go to the top of the page
 
+Quote Post
iosifk
сообщение Sep 3 2016, 19:14
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 4 011
Регистрация: 8-09-05
Из: спб
Пользователь №: 8 369



Цитата(artur @ Sep 3 2016, 00:11) *
Доброе время суток,

помогите разобраться почему описаная схема по управлению лцд-дисплеем отказывается работать в железе...

Компелятор не ругаеться, в симуляторе тоже все хорошо выглядит.

У Вас очень сложный и неправильный путь для написания кода. Могу рассказать как надо... По скайпу...


--------------------
www.iosifk.narod.ru
Go to the top of the page
 
+Quote Post
artur
сообщение Sep 4 2016, 19:36
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 18
Регистрация: 11-09-15
Пользователь №: 88 369



Цитата(iosifk @ Sep 3 2016, 21:14) *
У Вас очень сложный и неправильный путь для написания кода. Могу рассказать как надо... По скайпу...


очень хорошая идея, давайте, напишите когда вам позвонить

Цитата(Andrew Su @ Sep 3 2016, 12:39) *
А какой LCD?


1602a-1 v1.3
Go to the top of the page
 
+Quote Post
iosifk
сообщение Sep 4 2016, 19:57
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 4 011
Регистрация: 8-09-05
Из: спб
Пользователь №: 8 369



Цитата(artur @ Sep 4 2016, 22:36) *
очень хорошая идея, давайте, напишите когда вам позвонить

Да хоть завтра, после 11-ти... Как увидите мою машину в сети, так и звоните...
а сейчас можете прислать запрос на включение в адресную книгу...


--------------------
www.iosifk.narod.ru
Go to the top of the page
 
+Quote Post
artur
сообщение Sep 4 2016, 19:59
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 18
Регистрация: 11-09-15
Пользователь №: 88 369



Цитата(Александр77 @ Sep 3 2016, 21:06) *
Вот что сильно путает, так это вложенность Ifов друг в друга при проверке одной и той же переменной
Код
.....
if durchlauf > 2 then
   addr_data <= addr_data + 1;
   addr_delay_i <= 3;
   addr_delay <= 3;
   pause_halten <= true;
   zustand <= begining;
   if durchlauf = 7 then
      .....

Получается железу надо проверить что durchlauf больше 2, а в каких то случаях при этом еще и равно 7.
На мой взгляд, лучше разбить проверку на две части
1) значение больше 2, но меньше 7
2) значение равно 7.


Дело в том что только при "durchlauf = 7" должна произойти задержка в 50мс (т.е. когда цепь "durchlauf = 7" это значит что инитиализазия закончина и начинается текст который должен выдаваться при каждом включении), потом должна опять выполняться цепь "durchlauf > 2" пока не достигнет "durchlauf >= 11".

Инитиализацию он понимает, а вот текст не пишит

Go to the top of the page
 
+Quote Post
Maverick
сообщение Sep 5 2016, 05:43
Сообщение #8


я только учусь...
******

Группа: Модераторы
Сообщений: 3 447
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839



может пример поможет, также смотрим state flow


CODE
-- LCD INITIALIZATION SETTINGS: to change, comment/uncomment lines:
--
-- Function Set
-- 2-line mode, display on Line 93 lcd_data <= "00111100";
-- 1-line mode, display on Line 94 lcd_data <= "00110100";
-- 1-line mode, display off Line 95 lcd_data <= "00110000";
-- 2-line mode, display off Line 96 lcd_data <= "00111000";
-- Display ON/OFF
-- display on, cursor off, blink off Line 104 lcd_data <= "00001100";
-- display on, cursor off, blink on Line 105 lcd_data <= "00001101";
-- display on, cursor on, blink off Line 106 lcd_data <= "00001110";
-- display on, cursor on, blink on Line 107 lcd_data <= "00001111";
-- display off, cursor off, blink off Line 108 lcd_data <= "00001000";
-- display off, cursor off, blink on Line 109 lcd_data <= "00001001";
-- display off, cursor on, blink off Line 110 lcd_data <= "00001010";
-- display off, cursor on, blink on Line 111 lcd_data <= "00001011";
-- Entry Mode Set
-- increment mode, entire shift off Line 127 lcd_data <= "00000110";
-- increment mode, entire shift on Line 128 lcd_data <= "00000111";
-- decrement mode, entire shift off Line 129 lcd_data <= "00000100";
-- decrement mode, entire shift on Line 130 lcd_data <= "00000101";
--
--------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY lcd_controller IS
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --active low reinitializes lcd
lcd_enable : IN STD_LOGIC; --latches data into lcd controller
lcd_bus : IN STD_LOGIC_VECTOR(9 DOWNTO 0); --data and control signals
busy : OUT STD_LOGIC := '1'; --lcd controller busy/idle feedback
rw, rs, e : OUT STD_LOGIC; --read/write, setup/data, and enable for lcd
lcd_data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); --data signals for lcd
END lcd_controller;

ARCHITECTURE controller OF lcd_controller IS
TYPE CONTROL IS(power_up, initialize, ready, send);
SIGNAL state : CONTROL;
CONSTANT freq : INTEGER := 50; --system clock frequency in MHz
BEGIN
PROCESS(clk)
VARIABLE clk_count : INTEGER := 0; --event counter for timing
BEGIN
IF(clk'EVENT and clk = '1') THEN

CASE state IS

--wait 50 ms to ensure Vdd has risen and required LCD wait is met
WHEN power_up =>
busy <= '1';
IF(clk_count < (50000 * freq)) THEN --wait 50 ms
clk_count := clk_count + 1;
state <= power_up;
ELSE --power-up complete
clk_count := 0;
rs <= '0';
rw <= '0';
lcd_data <= "00110000";
state <= initialize;
END IF;

--cycle through initialization sequence
WHEN initialize =>
busy <= '1';
clk_count := clk_count + 1;
IF(clk_count < (10 * freq)) THEN --function set
lcd_data <= "00111100"; --2-line mode, display on
--lcd_data <= "00110100"; --1-line mode, display on
--lcd_data <= "00110000"; --1-line mdoe, display off
--lcd_data <= "00111000"; --2-line mode, display off
e <= '1';
state <= initialize;
ELSIF(clk_count < (60 * freq)) THEN --wait 50 us
lcd_data <= "00000000";
e <= '0';
state <= initialize;
ELSIF(clk_count < (70 * freq)) THEN --display on/off control
lcd_data <= "00001100"; --display on, cursor off, blink off
--lcd_data <= "00001101"; --display on, cursor off, blink on
--lcd_data <= "00001110"; --display on, cursor on, blink off
--lcd_data <= "00001111"; --display on, cursor on, blink on
--lcd_data <= "00001000"; --display off, cursor off, blink off
--lcd_data <= "00001001"; --display off, cursor off, blink on
--lcd_data <= "00001010"; --display off, cursor on, blink off
--lcd_data <= "00001011"; --display off, cursor on, blink on
e <= '1';
state <= initialize;
ELSIF(clk_count < (120 * freq)) THEN --wait 50 us
lcd_data <= "00000000";
e <= '0';
state <= initialize;
ELSIF(clk_count < (130 * freq)) THEN --display clear
lcd_data <= "00000001";
e <= '1';
state <= initialize;
ELSIF(clk_count < (2130 * freq)) THEN --wait 2 ms
lcd_data <= "00000000";
e <= '0';
state <= initialize;
ELSIF(clk_count < (2140 * freq)) THEN --entry mode set
lcd_data <= "00000110"; --increment mode, entire shift off
--lcd_data <= "00000111"; --increment mode, entire shift on
--lcd_data <= "00000100"; --decrement mode, entire shift off
--lcd_data <= "00000101"; --decrement mode, entire shift on
e <= '1';
state <= initialize;
ELSIF(clk_count < (2200 * freq)) THEN --wait 60 us
lcd_data <= "00000000";
e <= '0';
state <= initialize;
ELSE --initialization complete
clk_count := 0;
busy <= '0';
state <= ready;
END IF;

--wait for the enable signal and then latch in the instruction
WHEN ready =>
IF(lcd_enable = '1') THEN
busy <= '1';
rs <= lcd_bus(9);
rw <= lcd_bus(8);
lcd_data <= lcd_bus(7 DOWNTO 0);
clk_count := 0;
state <= send;
ELSE
busy <= '0';
rs <= '0';
rw <= '0';
lcd_data <= "00000000";
clk_count := 0;
state <= ready;
END IF;

--send instruction to lcd
WHEN send =>
busy <= '1';
IF(clk_count < (50 * freq)) THEN --do not exit for 50us
busy <= '1';
IF(clk_count < freq) THEN --negative enable
e <= '0';
ELSIF(clk_count < (14 * freq)) THEN --positive enable half-cycle
e <= '1';
ELSIF(clk_count < (27 * freq)) THEN --negative enable half-cycle
e <= '0';
END IF;
clk_count := clk_count + 1;
state <= send;
ELSE
clk_count := 0;
state <= ready;
END IF;

END CASE;

--reset
IF(reset_n = '0') THEN
state <= power_up;
END IF;

END IF;
END PROCESS;
END controller;


CODE
--
-- Prints "123456789" on a HD44780 compatible 8-bit interface character LCD
-- module using the lcd_controller.vhd component.
--
--------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY lcd_example IS
PORT(
clk : IN STD_LOGIC; --system clock
rw, rs, e : OUT STD_LOGIC; --read/write, setup/data, and enable for lcd
lcd_data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); --data signals for lcd
END lcd_example;

ARCHITECTURE behavior OF lcd_example IS
SIGNAL lcd_enable : STD_LOGIC;
SIGNAL lcd_bus : STD_LOGIC_VECTOR(9 DOWNTO 0);
SIGNAL lcd_busy : STD_LOGIC;
COMPONENT lcd_controller IS
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --active low reinitializes lcd
lcd_enable : IN STD_LOGIC; --latches data into lcd controller
lcd_bus : IN STD_LOGIC_VECTOR(9 DOWNTO 0); --data and control signals
busy : OUT STD_LOGIC; --lcd controller busy/idle feedback
rw, rs, e : OUT STD_LOGIC; --read/write, setup/data, and enable for lcd
lcd_data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); --data signals for lcd
END COMPONENT;
BEGIN

--instantiate the lcd controller
dut: lcd_controller
PORT MAP(clk => clk, reset_n => '1', lcd_enable => lcd_enable, lcd_bus => lcd_bus,
busy => lcd_busy, rw => rw, rs => rs, e => e, lcd_data => lcd_data);

PROCESS(clk)
VARIABLE char : INTEGER RANGE 0 TO 10 := 0;
BEGIN
IF(clk'EVENT AND clk = '1') THEN
IF(lcd_busy = '0' AND lcd_enable = '0') THEN
lcd_enable <= '1';
IF(char < 10) THEN
char := char + 1;
END IF;
CASE char IS
WHEN 1 => lcd_bus <= "1000110001";
WHEN 2 => lcd_bus <= "1000110010";
WHEN 3 => lcd_bus <= "1000110011";
WHEN 4 => lcd_bus <= "1000110100";
WHEN 5 => lcd_bus <= "1000110101";
WHEN 6 => lcd_bus <= "1000110110";
WHEN 7 => lcd_bus <= "1000110111";
WHEN 8 => lcd_bus <= "1000111000";
WHEN 9 => lcd_bus <= "1000111001";
WHEN OTHERS => lcd_enable <= '0';
END CASE;
ELSE
lcd_enable <= '0';
END IF;
END IF;
END PROCESS;

END behavior;

Эскизы прикрепленных изображений
Прикрепленное изображение
 


--------------------
If it doesn't work in simulation, it won't work on the board.

"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
Go to the top of the page
 
+Quote Post
artur
сообщение Sep 6 2016, 19:03
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 18
Регистрация: 11-09-15
Пользователь №: 88 369



Цитата(Maverick @ Sep 5 2016, 07:43) *
может пример поможет, также смотрим state flow


CODE
-- LCD INITIALIZATION SETTINGS: to change, comment/uncomment lines:
--
-- Function Set
-- 2-line mode, display on Line 93 lcd_data <= "00111100";
-- 1-line mode, display on Line 94 lcd_data <= "00110100";
-- 1-line mode, display off Line 95 lcd_data <= "00110000";
-- 2-line mode, display off Line 96 lcd_data <= "00111000";
-- Display ON/OFF
-- display on, cursor off, blink off Line 104 lcd_data <= "00001100";
-- display on, cursor off, blink on Line 105 lcd_data <= "00001101";
-- display on, cursor on, blink off Line 106 lcd_data <= "00001110";
-- display on, cursor on, blink on Line 107 lcd_data <= "00001111";
-- display off, cursor off, blink off Line 108 lcd_data <= "00001000";
-- display off, cursor off, blink on Line 109 lcd_data <= "00001001";
-- display off, cursor on, blink off Line 110 lcd_data <= "00001010";
-- display off, cursor on, blink on Line 111 lcd_data <= "00001011";
-- Entry Mode Set
-- increment mode, entire shift off Line 127 lcd_data <= "00000110";
-- increment mode, entire shift on Line 128 lcd_data <= "00000111";
-- decrement mode, entire shift off Line 129 lcd_data <= "00000100";
-- decrement mode, entire shift on Line 130 lcd_data <= "00000101";
--
--------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY lcd_controller IS
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --active low reinitializes lcd
lcd_enable : IN STD_LOGIC; --latches data into lcd controller
lcd_bus : IN STD_LOGIC_VECTOR(9 DOWNTO 0); --data and control signals
busy : OUT STD_LOGIC := '1'; --lcd controller busy/idle feedback
rw, rs, e : OUT STD_LOGIC; --read/write, setup/data, and enable for lcd
lcd_data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); --data signals for lcd
END lcd_controller;

ARCHITECTURE controller OF lcd_controller IS
TYPE CONTROL IS(power_up, initialize, ready, send);
SIGNAL state : CONTROL;
CONSTANT freq : INTEGER := 50; --system clock frequency in MHz
BEGIN
PROCESS(clk)
VARIABLE clk_count : INTEGER := 0; --event counter for timing
BEGIN
IF(clk'EVENT and clk = '1') THEN

CASE state IS

--wait 50 ms to ensure Vdd has risen and required LCD wait is met
WHEN power_up =>
busy <= '1';
IF(clk_count < (50000 * freq)) THEN --wait 50 ms
clk_count := clk_count + 1;
state <= power_up;
ELSE --power-up complete
clk_count := 0;
rs <= '0';
rw <= '0';
lcd_data <= "00110000";
state <= initialize;
END IF;

--cycle through initialization sequence
WHEN initialize =>
busy <= '1';
clk_count := clk_count + 1;
IF(clk_count < (10 * freq)) THEN --function set
lcd_data <= "00111100"; --2-line mode, display on
--lcd_data <= "00110100"; --1-line mode, display on
--lcd_data <= "00110000"; --1-line mdoe, display off
--lcd_data <= "00111000"; --2-line mode, display off
e <= '1';
state <= initialize;
ELSIF(clk_count < (60 * freq)) THEN --wait 50 us
lcd_data <= "00000000";
e <= '0';
state <= initialize;
ELSIF(clk_count < (70 * freq)) THEN --display on/off control
lcd_data <= "00001100"; --display on, cursor off, blink off
--lcd_data <= "00001101"; --display on, cursor off, blink on
--lcd_data <= "00001110"; --display on, cursor on, blink off
--lcd_data <= "00001111"; --display on, cursor on, blink on
--lcd_data <= "00001000"; --display off, cursor off, blink off
--lcd_data <= "00001001"; --display off, cursor off, blink on
--lcd_data <= "00001010"; --display off, cursor on, blink off
--lcd_data <= "00001011"; --display off, cursor on, blink on
e <= '1';
state <= initialize;
ELSIF(clk_count < (120 * freq)) THEN --wait 50 us
lcd_data <= "00000000";
e <= '0';
state <= initialize;
ELSIF(clk_count < (130 * freq)) THEN --display clear
lcd_data <= "00000001";
e <= '1';
state <= initialize;
ELSIF(clk_count < (2130 * freq)) THEN --wait 2 ms
lcd_data <= "00000000";
e <= '0';
state <= initialize;
ELSIF(clk_count < (2140 * freq)) THEN --entry mode set
lcd_data <= "00000110"; --increment mode, entire shift off
--lcd_data <= "00000111"; --increment mode, entire shift on
--lcd_data <= "00000100"; --decrement mode, entire shift off
--lcd_data <= "00000101"; --decrement mode, entire shift on
e <= '1';
state <= initialize;
ELSIF(clk_count < (2200 * freq)) THEN --wait 60 us
lcd_data <= "00000000";
e <= '0';
state <= initialize;
ELSE --initialization complete
clk_count := 0;
busy <= '0';
state <= ready;
END IF;

--wait for the enable signal and then latch in the instruction
WHEN ready =>
IF(lcd_enable = '1') THEN
busy <= '1';
rs <= lcd_bus(9);
rw <= lcd_bus(8);
lcd_data <= lcd_bus(7 DOWNTO 0);
clk_count := 0;
state <= send;
ELSE
busy <= '0';
rs <= '0';
rw <= '0';
lcd_data <= "00000000";
clk_count := 0;
state <= ready;
END IF;

--send instruction to lcd
WHEN send =>
busy <= '1';
IF(clk_count < (50 * freq)) THEN --do not exit for 50us
busy <= '1';
IF(clk_count < freq) THEN --negative enable
e <= '0';
ELSIF(clk_count < (14 * freq)) THEN --positive enable half-cycle
e <= '1';
ELSIF(clk_count < (27 * freq)) THEN --negative enable half-cycle
e <= '0';
END IF;
clk_count := clk_count + 1;
state <= send;
ELSE
clk_count := 0;
state <= ready;
END IF;

END CASE;

--reset
IF(reset_n = '0') THEN
state <= power_up;
END IF;

END IF;
END PROCESS;
END controller;


CODE
--
-- Prints "123456789" on a HD44780 compatible 8-bit interface character LCD
-- module using the lcd_controller.vhd component.
--
--------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY lcd_example IS
PORT(
clk : IN STD_LOGIC; --system clock
rw, rs, e : OUT STD_LOGIC; --read/write, setup/data, and enable for lcd
lcd_data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); --data signals for lcd
END lcd_example;

ARCHITECTURE behavior OF lcd_example IS
SIGNAL lcd_enable : STD_LOGIC;
SIGNAL lcd_bus : STD_LOGIC_VECTOR(9 DOWNTO 0);
SIGNAL lcd_busy : STD_LOGIC;
COMPONENT lcd_controller IS
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --active low reinitializes lcd
lcd_enable : IN STD_LOGIC; --latches data into lcd controller
lcd_bus : IN STD_LOGIC_VECTOR(9 DOWNTO 0); --data and control signals
busy : OUT STD_LOGIC; --lcd controller busy/idle feedback
rw, rs, e : OUT STD_LOGIC; --read/write, setup/data, and enable for lcd
lcd_data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); --data signals for lcd
END COMPONENT;
BEGIN

--instantiate the lcd controller
dut: lcd_controller
PORT MAP(clk => clk, reset_n => '1', lcd_enable => lcd_enable, lcd_bus => lcd_bus,
busy => lcd_busy, rw => rw, rs => rs, e => e, lcd_data => lcd_data);

PROCESS(clk)
VARIABLE char : INTEGER RANGE 0 TO 10 := 0;
BEGIN
IF(clk'EVENT AND clk = '1') THEN
IF(lcd_busy = '0' AND lcd_enable = '0') THEN
lcd_enable <= '1';
IF(char < 10) THEN
char := char + 1;
END IF;
CASE char IS
WHEN 1 => lcd_bus <= "1000110001";
WHEN 2 => lcd_bus <= "1000110010";
WHEN 3 => lcd_bus <= "1000110011";
WHEN 4 => lcd_bus <= "1000110100";
WHEN 5 => lcd_bus <= "1000110101";
WHEN 6 => lcd_bus <= "1000110110";
WHEN 7 => lcd_bus <= "1000110111";
WHEN 8 => lcd_bus <= "1000111000";
WHEN 9 => lcd_bus <= "1000111001";
WHEN OTHERS => lcd_enable <= '0';
END CASE;
ELSE
lcd_enable <= '0';
END IF;
END IF;
END PROCESS;

END behavior;



спасибо
Go to the top of the page
 
+Quote Post
artur
сообщение Sep 11 2016, 08:07
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 18
Регистрация: 11-09-15
Пользователь №: 88 369



Цитата(Maverick @ Sep 5 2016, 07:43) *
может пример поможет, также смотрим state flow


CODE
-- LCD INITIALIZATION SETTINGS: to change, comment/uncomment lines:
--
-- Function Set
-- 2-line mode, display on Line 93 lcd_data <= "00111100";
-- 1-line mode, display on Line 94 lcd_data <= "00110100";
-- 1-line mode, display off Line 95 lcd_data <= "00110000";
-- 2-line mode, display off Line 96 lcd_data <= "00111000";
-- Display ON/OFF
-- display on, cursor off, blink off Line 104 lcd_data <= "00001100";
-- display on, cursor off, blink on Line 105 lcd_data <= "00001101";
-- display on, cursor on, blink off Line 106 lcd_data <= "00001110";
-- display on, cursor on, blink on Line 107 lcd_data <= "00001111";
-- display off, cursor off, blink off Line 108 lcd_data <= "00001000";
-- display off, cursor off, blink on Line 109 lcd_data <= "00001001";
-- display off, cursor on, blink off Line 110 lcd_data <= "00001010";
-- display off, cursor on, blink on Line 111 lcd_data <= "00001011";
-- Entry Mode Set
-- increment mode, entire shift off Line 127 lcd_data <= "00000110";
-- increment mode, entire shift on Line 128 lcd_data <= "00000111";
-- decrement mode, entire shift off Line 129 lcd_data <= "00000100";
-- decrement mode, entire shift on Line 130 lcd_data <= "00000101";
--
--------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY lcd_controller IS
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --active low reinitializes lcd
lcd_enable : IN STD_LOGIC; --latches data into lcd controller
lcd_bus : IN STD_LOGIC_VECTOR(9 DOWNTO 0); --data and control signals
busy : OUT STD_LOGIC := '1'; --lcd controller busy/idle feedback
rw, rs, e : OUT STD_LOGIC; --read/write, setup/data, and enable for lcd
lcd_data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); --data signals for lcd
END lcd_controller;

ARCHITECTURE controller OF lcd_controller IS
TYPE CONTROL IS(power_up, initialize, ready, send);
SIGNAL state : CONTROL;
CONSTANT freq : INTEGER := 50; --system clock frequency in MHz
BEGIN
PROCESS(clk)
VARIABLE clk_count : INTEGER := 0; --event counter for timing
BEGIN
IF(clk'EVENT and clk = '1') THEN

CASE state IS

--wait 50 ms to ensure Vdd has risen and required LCD wait is met
WHEN power_up =>
busy <= '1';
IF(clk_count < (50000 * freq)) THEN --wait 50 ms
clk_count := clk_count + 1;
state <= power_up;
ELSE --power-up complete
clk_count := 0;
rs <= '0';
rw <= '0';
lcd_data <= "00110000";
state <= initialize;
END IF;

--cycle through initialization sequence
WHEN initialize =>
busy <= '1';
clk_count := clk_count + 1;
IF(clk_count < (10 * freq)) THEN --function set
lcd_data <= "00111100"; --2-line mode, display on
--lcd_data <= "00110100"; --1-line mode, display on
--lcd_data <= "00110000"; --1-line mdoe, display off
--lcd_data <= "00111000"; --2-line mode, display off
e <= '1';
state <= initialize;
ELSIF(clk_count < (60 * freq)) THEN --wait 50 us
lcd_data <= "00000000";
e <= '0';
state <= initialize;
ELSIF(clk_count < (70 * freq)) THEN --display on/off control
lcd_data <= "00001100"; --display on, cursor off, blink off
--lcd_data <= "00001101"; --display on, cursor off, blink on
--lcd_data <= "00001110"; --display on, cursor on, blink off
--lcd_data <= "00001111"; --display on, cursor on, blink on
--lcd_data <= "00001000"; --display off, cursor off, blink off
--lcd_data <= "00001001"; --display off, cursor off, blink on
--lcd_data <= "00001010"; --display off, cursor on, blink off
--lcd_data <= "00001011"; --display off, cursor on, blink on
e <= '1';
state <= initialize;
ELSIF(clk_count < (120 * freq)) THEN --wait 50 us
lcd_data <= "00000000";
e <= '0';
state <= initialize;
ELSIF(clk_count < (130 * freq)) THEN --display clear
lcd_data <= "00000001";
e <= '1';
state <= initialize;
ELSIF(clk_count < (2130 * freq)) THEN --wait 2 ms
lcd_data <= "00000000";
e <= '0';
state <= initialize;
ELSIF(clk_count < (2140 * freq)) THEN --entry mode set
lcd_data <= "00000110"; --increment mode, entire shift off
--lcd_data <= "00000111"; --increment mode, entire shift on
--lcd_data <= "00000100"; --decrement mode, entire shift off
--lcd_data <= "00000101"; --decrement mode, entire shift on
e <= '1';
state <= initialize;
ELSIF(clk_count < (2200 * freq)) THEN --wait 60 us
lcd_data <= "00000000";
e <= '0';
state <= initialize;
ELSE --initialization complete
clk_count := 0;
busy <= '0';
state <= ready;
END IF;

--wait for the enable signal and then latch in the instruction
WHEN ready =>
IF(lcd_enable = '1') THEN
busy <= '1';
rs <= lcd_bus(9);
rw <= lcd_bus(8);
lcd_data <= lcd_bus(7 DOWNTO 0);
clk_count := 0;
state <= send;
ELSE
busy <= '0';
rs <= '0';
rw <= '0';
lcd_data <= "00000000";
clk_count := 0;
state <= ready;
END IF;

--send instruction to lcd
WHEN send =>
busy <= '1';
IF(clk_count < (50 * freq)) THEN --do not exit for 50us
busy <= '1';
IF(clk_count < freq) THEN --negative enable
e <= '0';
ELSIF(clk_count < (14 * freq)) THEN --positive enable half-cycle
e <= '1';
ELSIF(clk_count < (27 * freq)) THEN --negative enable half-cycle
e <= '0';
END IF;
clk_count := clk_count + 1;
state <= send;
ELSE
clk_count := 0;
state <= ready;
END IF;

END CASE;

--reset
IF(reset_n = '0') THEN
state <= power_up;
END IF;

END IF;
END PROCESS;
END controller;


CODE
--
-- Prints "123456789" on a HD44780 compatible 8-bit interface character LCD
-- module using the lcd_controller.vhd component.
--
--------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY lcd_example IS
PORT(
clk : IN STD_LOGIC; --system clock
rw, rs, e : OUT STD_LOGIC; --read/write, setup/data, and enable for lcd
lcd_data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); --data signals for lcd
END lcd_example;

ARCHITECTURE behavior OF lcd_example IS
SIGNAL lcd_enable : STD_LOGIC;
SIGNAL lcd_bus : STD_LOGIC_VECTOR(9 DOWNTO 0);
SIGNAL lcd_busy : STD_LOGIC;
COMPONENT lcd_controller IS
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --active low reinitializes lcd
lcd_enable : IN STD_LOGIC; --latches data into lcd controller
lcd_bus : IN STD_LOGIC_VECTOR(9 DOWNTO 0); --data and control signals
busy : OUT STD_LOGIC; --lcd controller busy/idle feedback
rw, rs, e : OUT STD_LOGIC; --read/write, setup/data, and enable for lcd
lcd_data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)); --data signals for lcd
END COMPONENT;
BEGIN

--instantiate the lcd controller
dut: lcd_controller
PORT MAP(clk => clk, reset_n => '1', lcd_enable => lcd_enable, lcd_bus => lcd_bus,
busy => lcd_busy, rw => rw, rs => rs, e => e, lcd_data => lcd_data);

PROCESS(clk)
VARIABLE char : INTEGER RANGE 0 TO 10 := 0;
BEGIN
IF(clk'EVENT AND clk = '1') THEN
IF(lcd_busy = '0' AND lcd_enable = '0') THEN
lcd_enable <= '1';
IF(char < 10) THEN
char := char + 1;
END IF;
CASE char IS
WHEN 1 => lcd_bus <= "1000110001";
WHEN 2 => lcd_bus <= "1000110010";
WHEN 3 => lcd_bus <= "1000110011";
WHEN 4 => lcd_bus <= "1000110100";
WHEN 5 => lcd_bus <= "1000110101";
WHEN 6 => lcd_bus <= "1000110110";
WHEN 7 => lcd_bus <= "1000110111";
WHEN 8 => lcd_bus <= "1000111000";
WHEN 9 => lcd_bus <= "1000111001";
WHEN OTHERS => lcd_enable <= '0';
END CASE;
ELSE
lcd_enable <= '0';
END IF;
END IF;
END PROCESS;

END behavior;



Ошибку нашел :-), проблема была в неправильной комбинации при инициализации. Оказывается что уже давно все работало, из-за такой мелочи сидел почти месяц...
Хотел выставить видео, но оно оказалось слишком большое (43 мб).


Go to the top of the page
 
+Quote Post
iosifk
сообщение Sep 11 2016, 10:22
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 4 011
Регистрация: 8-09-05
Из: спб
Пользователь №: 8 369



Цитата(artur @ Sep 11 2016, 11:07) *
Ошибку нашел :-), проблема была в неправильной комбинации при инициализации. Оказывается что уже давно все работало, из-за такой мелочи сидел почти месяц...
Хотел выставить видео, но оно оказалось слишком большое (43 мб).


Даже добавлю. То что "Оказывается.." совсем не удивляет, ибо способ разработки совсем не лучший. А удивляет то, что я предлагаю показать как работать без ошибок, а Вы отказываетесь...
Но это уже Ваше дело...
Посмотрите хотя бы у меня в "Кратком Курсе" раздел "Дополнительно об автоматах"...


--------------------
www.iosifk.narod.ru
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 14:17
Рейтинг@Mail.ru


Страница сгенерированна за 0.01522 секунд с 7
ELECTRONIX ©2004-2016