Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не работает сканер кнопок.
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
itscasus
Всем привет. Требуется определить нажатие на кнопки с помощью плис. И по spi отправить мк. С языком пока не разбирался. Попробовал реализовать с помощью мегафункций алтеровских. Кнопки подключил к параллельному входу lpm_shiftreg, по приходу clk от spi, 1 такт расходую на load в сдвигающий регистр, остальные 7 на сдвиг на MISO выход. Добавил на все кнопки AND, типа прерывания при нажатии кнопки для мк. Вывод MISO устанавливаю в третье состояние.
Ну так вот, все это не работает. Вопрос, а правильно ли я сделал схему для опроса кнопок или это не рабочий алгоритм.
Inanity
Цитата(itscasus @ Oct 5 2013, 18:10) *
Ну так вот, все это не работает. Вопрос, а правильно ли я сделал схему для опроса кнопок или это не рабочий алгоритм.


"Не работает" - понятие очень растяжимое. А симуляцию делать пробовали? Ещё, как вы решаете проблему дребезга контактов?
count_enable
Да, пожалуйста больше информации. Уверены что SPI работает как надо? Сначала сделайте например зажигание светодиодов от кнопок.
Цитата
С языком пока не разбирался
- вот с этого и надо начинать! Verilog простой, решить задачу отправки кнопок по SPI на нём это один экран кода.
itscasus
Завтра попробую выложить схему. Verilog буду изучать для следующей схемы.
А с дребезгом борюсь в мк с помощью задержки чтения в 1мс, после прихода сигнала прерывания с плис. Но на осциллографе на пине MISO ничего нет.
zombi
Я бы сделал иначе.
Мк SPI мастер.
В плис реализовал бы обычную 74HC597.
И пусть мк опрашивает плис с удобной для него частотой и борется с дребезгом.
stu
самое простое для ПЛИС в виде антидребезга это счетчик на длительность нажатия. Т.е. если после нажатия прошло к примеру 10 мс, то значит кнопка нажата и счетчик досчитывает до конца и останавливается, а иначе счетчик не досчитывает и interrupt на МК не дергаем.
itscasus
Здравствуйте, пришлось отложить на некоторое время плисину. Выкладываю схему. В ней состояние кнопок загружается по прерыванию в регистр-защелку (LPM_FF) по переднему фронту. Для создания фронта используется XOR, когда на входе '0', XOR перекл. из 0 в 1. Прерывания (внизу картинки обрезано) реализованы по лог.И, если хоть одна кнопка нажата, уровень спадает до лог '0'. Прерывание вывел на вывод плис для мк.
Далее 14 разрядов загружаются в сдвиговый регистр PISO(LPM_SHIFTREG) при чтении по SPI. Вот здесь, скорее всего, что-то и не работает.
Для load (LPM_SHIFTREG) реализована задержка на 1 clock. Вначале на clock инверт. 1. Когда идут клоки, перекл. в 0. И только на след. импульсе в 1. Соответственно 1 импульс клока идет на загрузку в сдвиг.рег. (load=1), остальные на сдвиг.
Вроде бы ничего сложного нет. Но на осциллограмме ничего нет с MISО. Но прерывание срабатывает. НЕ знаю что делать, ЗАциклился уже.
А с дребезгом борюсь в мк. После прерывания, задержка 100 мс, а затем считываю state bottom.
Да мк мастер, SPI перекл. по заднему фронту, захват по переднему, полярность положительная. По spi идут 24 импульса клока. В середине картинки схема рабочая.

Жду любых советов.
Нажмите для просмотра прикрепленного файла
zombi
Цитата(itscasus @ Oct 24 2013, 14:47) *
Жду любых советов.

Выход DFF number14 всегда в лог.1
И всё остальное как-то странно...
Александр77
И входы асинхронного сброса\установки этого триггера, не мешало бы притянуть к питанию
zombi
Цитата(Александр77 @ Oct 24 2013, 20:06) *
И входы асинхронного сброса\установки этого триггера, не мешало бы притянуть к питанию

Не подключённые выводы таких триггеров подключаются к питанию автоматически.

Тут дело в другом.

Мне вся схема вообще не нравится.
Ну допустим при нажатии одной кнопки кое как и пройдёт прерывание, а если не отпуская эту кнопку нажать ещё и другую то прерывания не будет.
И зачем там XOR вообще нужен?

Цитата(itscasus @ Oct 24 2013, 14:47) *
Да мк мастер, SPI ...

И на кой тогда прерывание от плис нужно?
Сделайте в мк таймер на 1-2мс и пусть он считывает состояние кнопок.
А заодно и антидребезгом занимается.
Типа 3-4 раза подряд одно и тоже значит правильно.
МК то какой? laughing.gif

Цитата(itscasus @ Oct 24 2013, 14:47) *
НЕ знаю что делать, ЗАциклился уже.

Радикально менять всю идеологию и реализацию biggrin.gif
Caruso
Вот посмотрите мою реализацию опроса 10 кнопок. Правда она на VHDL.
Аппаратно входы плис притянуты к питанию. Как только случается нажатие, соответствующий вход сажается на землю.
Частота опроса кнопок задается входом En. Я использую частоту En (100 Гц).
Алгоритм таков: если 3 раза подряд считали одинаковое состояние кнопок, то считаем что такое состояние достоверное. Сравниваем текущее достоверное состояние с предыдущим достоверным. Если есть отличия, то генерируем импульс IntSw (прерывание). Т. о. при нажатии на одну кнопку прерывание intSw будет возникать 2 раза:один раз когда нажали и еще один раз когда отпустили.

CODE
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Switch4 is
Port ( Clk : in STD_LOGIC;
Reset : in STD_LOGIC;
En : in STD_LOGIC; -- По сигналу En считываем состояние тумблеров и записывеим последовательно в 3 буферных регистра. Частота 100 Гц.
intSw : out STD_LOGIC; -- Положительный импульс. Сигнализирует о том, что один или несколько тумблеров изменили свое состояние.
Sw : out STD_LOGIC_VECTOR (9 downto 0);
SwExt : in STD_LOGIC_VECTOR (9 downto 0));
end Switch4;

architecture Behavioral of Switch4 is

signal bSwCurent : std_logic_vector (9 downto 0);
signal bSw1 : std_logic_vector (9 downto 0);
signal bSw2 : std_logic_vector (9 downto 0);
signal bSw3 : std_logic_vector (9 downto 0);
signal bSw : std_logic_vector (9 downto 0);
signal bSwOld : std_logic_vector (9 downto 0);



begin

bSwCurent <= SwExt;
bSw <= (not(bSw1 xor bSw2)) and (not(bSw2 xor bSw3)); -- Если в трех буферных регистрах находятся одинаковые данные, то считаем, что дребезг закончен и данные достоверны.

process (Reset, Clk)
begin
if Reset = '1' then bSw1 <=(others=>'1');
bSw2 <=(others=>'1');
bSw3 <=(others=>'1');
elsif (Clk = '1' and Clk'event) then
if En = '0' then bSw1 <= bSwCurent;
bSw2 <= bSw1;
bSw3 <= bSw2;
end if;
end if;
end process;


-- Если данные достоверны (bSw = "1111111111") т. е. дребезг подавлен
-- и данные отличаются от прежнего состояния, тогда вызываем 'прерывание' и выдвигаем данные для считывания.
process (Reset, Clk)
begin
if Reset = '1' then bSwOld <=(others=>'1'); intSw <= '0'; Sw <=(others=>'1');
elsif (Clk = '0' and Clk'event) then
if ((bSw3 /= bSwOld) and (bSw = "1111111111")) then Sw <= bSw3; bSwOld <= bSw3; intSw <= '1';
else intSw <= '0';
end if;
end if;
end process;

end Behavioral;
itscasus
Спасибо Caruso, за свою реализацию, я пока реализую символьно.
Цитата
И зачем там XOR вообще нужен?

Чтобы создать фронт для защелкивания: кода нет int (1), на выходе 0, при прерыв. 1 - вот и фронт...
Прерывание, я думаю, не помешает.
Сейчас буду переделывать, хотя переделывать нечего, куда еще проще: защелка и сдвиговый регистр с прерыв. на И?
Не знаю что с load делать.
zombi
Цитата(itscasus @ Oct 25 2013, 12:18) *
Чтобы создать фронт для защелкивания: кода нет int (1), на выходе 0, при прерыв. 1 - вот и фронт...

Просто инвертор получается biggrin.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.