Вот посмотрите мою реализацию опроса 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;