28_基於FPGA的簡易電子密碼鎖


28_基於FPGA的簡易電子密碼鎖

實驗原理

設計一個密碼鎖的控制電路,當輸入正確密碼時,輸出開鎖信號,並同時用紅燈亮、綠燈熄滅表示開鎖;用綠燈亮、紅燈熄滅表示關鎖; 在鎖的控制電路中儲存一個可以修改的 4 位密碼;從第一個按鈕觸動后的 5 秒內若未將鎖打開,則電路自動復位並進入自鎖狀態,使之無法再打開,並由揚聲器發出持續 20 秒的報警信號。

硬件原理圖

實驗代碼

控制模塊

-- ******************************************************************************

-- 控制模塊

-- 操作步驟

-- 上電首先按下key5按鍵進行復位操作

-- (1)按下key3按鍵輸入第一個密碼,輸入完第一個密碼后按下key3;輸入第二個密碼,第二個密碼輸入完成后后按下key3

-- 輸入第三個密碼,第三個密碼輸入完成后后按下key3;輸入第四個密碼,第四個密碼輸入完成后后按下key3,輸入完成;

-- (2)只有密碼輸入正確后才能進行修改密碼;

-- (3)修改密碼操作如下:

-- 按下key1進入修改密碼狀態,然后通過key2數字選擇按鍵,每輸入一個密碼,按下key3按鍵一次,數碼管跳至下一位,輸入下一個密碼,

-- 4個密碼輸入完成后按下key4按鍵,確定輸入的密碼就會重新裝載進去。第三位數碼管會顯示當前輸入的密碼的次序。

-- 取消修改密碼按下key5

-- *******************************************************************************

library IEEE;

use IEEE.std_logic_1164.all;

use IEEE.std_logic_unsigned.all;

use IEEE.std_logic_arith.all;

entity control is

port(

clk:in std_logic; --50M時鍾輸入

reset_n:in std_logic; --復位信號輸入

set_signal:in std_logic; --設置密碼按鍵

select_signal:in std_logic; --

ok_signal:in std_logic; --

set_ok_signal:in std_logic; --

 

fm_time_over:in std_logic; --蜂鳴器20秒相應完成信號

fm_20:in std_logic;

password1_out:out std_logic_vector(3 downto 0); --

password2_out:out std_logic_vector(3 downto 0); --

password3_out:out std_logic_vector(3 downto 0); --

password4_out:out std_logic_vector(3 downto 0); --

ok_signal_counter_out:out std_logic_vector(2 downto 0);--四個數碼管的標號

motor_open:out std_logic; --電機開關標志

start_flag:out std_logic;

password_yes:out std_logic;

password_no:out std_logic;

password_set_out:out std_logic

);

end control;

architecture control_behave of control is

signal key_counter:std_logic_vector(3 downto 0); --按鍵按下次數計數器

signal password_set:std_logic; --設置密碼標志,'1'為設置密碼,'0'為沒有設置密碼

signal password_set_finish:std_logic; --密碼設置成功信號

signal ok_signal_counter:std_logic_vector(2 downto 0);--輸入密碼個數計數器

signal current_password1:std_logic_vector(3 downto 0);--當前第一個密碼

signal current_password2:std_logic_vector(3 downto 0);--當前第二個密碼

signal current_password3:std_logic_vector(3 downto 0);--當前第三個密碼

signal current_password4:std_logic_vector(3 downto 0);--當前第四個密碼

signal current_password1_temp:std_logic_vector(3 downto 0);--當前第一個密碼

signal current_password2_temp:std_logic_vector(3 downto 0);--當前第二個密碼

signal current_password3_temp:std_logic_vector(3 downto 0);--當前第三個密碼

signal current_password4_temp:std_logic_vector(3 downto 0);--當前第四個密碼

signal password1:std_logic_vector(3 downto 0); --輸入第一個密碼

signal password2:std_logic_vector(3 downto 0); --輸入第二個密碼

signal password3:std_logic_vector(3 downto 0); --輸入第三個密碼

signal password4:std_logic_vector(3 downto 0); --輸入第四個密碼

signal set_signal_re1:std_logic;

signal set_signal_re2:std_logic;

signal password_yes_temp:std_logic;

signal password_no_temp:std_logic;

signal start_flag_reg:std_logic;

type state is(

prepare,--准備狀態

start--開始狀態

);

signal current_state:state;--一開始處於准備狀態

 

type set_state is(

prepare,--准備狀態

start--開始狀態

);

signal current_set_state:set_state;--一開始處於准備狀態

begin

password_set_out <= not password_set;

ok_signal_counter_out <= ok_signal_counter;

start_flag <= start_flag_reg;

-- //****************************************************************************************************

-- // 模塊名稱:產生設置密碼信號password_set

-- // 功能描述:

-- //****************************************************************************************************

process(clk,reset_n)

begin

if(reset_n = '0')then

password_set <= '0';

current_set_state <= prepare;

 

current_password1 <= "0001";

current_password2 <= "0001";

current_password3 <= "0001";

current_password4 <= "0001";

 

elsif(clk'event and clk = '0')then--下降沿觸發

if((password_yes_temp = '1'and password_no_temp = '0') or password_set = '1')then--只有輸入密碼正確后才能修改密碼

case current_set_state is

when prepare=>

if(set_signal = '0')then

current_set_state <= start;

password_set <= '1';

else

current_set_state <= prepare;

password_set <= '0';

end if;

when start =>

if(set_ok_signal = '0')then--設置完成

--重新裝載密碼

current_password1 <= current_password1_temp;

current_password2 <= current_password2_temp;

current_password3 <= current_password3_temp;

current_password4 <= current_password4_temp;

current_set_state <= prepare;

password_set <= '0';

else

password_set <= '1';

current_set_state <= start;

end if;

when others=>null;

end case;

else

null;

end if;

end if;

end process;

-- //****************************************************************************************************

-- // 模塊名稱:違時信號的產生

-- // 功能描述:

-- //****************************************************************************************************

process(clk,reset_n)

begin

if(reset_n = '0')then

current_state <= prepare;

start_flag_reg <= '0';

elsif(clk'event and clk = '1')then--上升沿沿觸發

if(password_set = '0')then--非設置密碼狀態

case current_state is

when prepare=>

if(select_signal = '0')then

start_flag_reg <= '1';

current_state <= start;

else

start_flag_reg <= '0';

current_state <= prepare;

end if;

when start=>

if(ok_signal_counter = "100")then--輸入密碼完成

start_flag_reg <= '0';

current_state <= prepare;

elsif(fm_time_over = '1')then--蜂鳴器響應20s完成

start_flag_reg <= '0';

current_state <= prepare;

else--兩者未完成

start_flag_reg <= '1';

current_state <= start;

end if;

end case;

else

current_state <= prepare;

start_flag_reg <= '0';

end if;

end if;

end process;

-- //****************************************************************************************************

-- // 模塊名稱:產生按鍵輸入數字

-- // 功能描述:

-- //****************************************************************************************************

process(select_signal,reset_n)

begin

if(reset_n = '0')then

key_counter <= "0000";

elsif(select_signal'event and select_signal = '0')then--下降沿觸發

if(key_counter = "1001")then

key_counter <= "0000";

else

key_counter <= key_counter + '1';

end if;

end if;

end process;

-- //****************************************************************************************************

-- // 模塊名稱:統計輸入密碼的個數4

-- // 功能描述:

-- //****************************************************************************************************

process(ok_signal,reset_n)

begin

if(reset_n = '0')then

ok_signal_counter <= "000";

elsif(ok_signal'event and ok_signal = '0')then--下降沿觸發

if(fm_20 = '0')then--在不違時的情況下可以進行輸入密碼

if(ok_signal_counter = "100")then

ok_signal_counter <= "001";

--密碼輸入完成

else

ok_signal_counter <= ok_signal_counter + '1';

end if;

else

ok_signal_counter <= "000";

end if;

end if;

end process;

-- //****************************************************************************************************

-- // 模塊名稱:存儲輸入密碼的個數4

-- // 功能描述:

-- //****************************************************************************************************

process(clk,reset_n)

begin

if(reset_n = '0')then

----------------------------------

current_password1_temp <= "0000";

current_password2_temp <= "0000";

current_password3_temp <= "0000";

current_password4_temp <= "0000";

----------------------------------

password_yes_temp <= '0';

password_no_temp <= '1';

password1 <= "0000";

password2 <= "0000";

password3 <= "0000";

password4 <= "0000";

motor_open <= '1';--電機關

elsif(clk'event and clk = '1')then--上升沿觸發

if(fm_20 = '0')then--在不違時的情況下可以進行輸入密碼

case ok_signal_counter is

when "001"=>

if(password_set = '0')then--非設置密碼

password1 <= key_counter;

else--設置密碼

current_password1_temp <= key_counter;

password1 <= "0000";

motor_open <= '1';--電機關

password_yes_temp <= '0';

password_no_temp <= '0';

end if;

when "010"=>

if(password_set = '0')then--非設置密碼

password2 <= key_counter;

else--設置密碼

current_password2_temp <= key_counter;

password2 <= "0000";

motor_open <= '1';--電機關

password_yes_temp <= '0';

password_no_temp <= '0';

end if;

when "011"=>

if(password_set = '0')then--非設置密碼

password3 <= key_counter;

else--設置密碼

current_password3_temp <= key_counter;

password3 <= "0000";

motor_open <= '1';--電機關

password_yes_temp <= '0';

password_no_temp <= '0';

end if;

when "100"=>

if(password_set = '0')then--非設置密碼

password4 <= key_counter;

if(current_password1 = password1 and

current_password2 = password2 and

current_password3 = password3 and

current_password4 = password4)then

password_yes_temp <= '1';

password_no_temp <= '0';

motor_open <= '0';--電機開

else

password_yes_temp <= '0';

password_no_temp <= '1';

motor_open <= '1';--電機關

end if;

else--設置密碼

current_password4_temp <= key_counter;

password4 <= "0000";

motor_open <= '1';--電機關

password_yes_temp <= '0';

password_no_temp <= '0';

end if;

when others=>null;

end case;

else

password_yes_temp <= '0';

password_no_temp <= '1';

password1 <= "0000";

password2 <= "0000";

password3 <= "0000";

password4 <= "0000";

motor_open <= '1';--電機關

end if;

end if;

end process;

-- 當處於設置密碼狀態時,兩個燈是不亮的

password_yes <= not ((password_yes_temp) and (not password_set));--接綠色led141引腳

password_no <= not ((password_no_temp) and (not password_set));--接紅色led142引腳

 

-- //****************************************************************************************************

-- // 模塊名稱:數碼管顯示數字選擇模塊

-- // 功能描述:

-- //****************************************************************************************************

process(reset_n,password_set,

current_password1_temp,current_password2_temp,current_password3_temp,current_password4_temp,

password1,password2,password3,password4)

begin

if(reset_n = '0')then

password1_out <= "0000";

password2_out <= "0000";

password3_out <= "0000";

password4_out <= "0000";

elsif(password_set = '1')then--設置密碼

password1_out <= current_password1_temp;

password2_out <= current_password2_temp;

password3_out <= current_password3_temp;

password4_out <= current_password4_temp;

else--非設置密碼

password1_out <= password1;

password2_out <= password2;

password3_out <= password3;

password4_out <= password4;

end if;

end process;

 

 

end control_behave;

 

數碼管顯示模塊

-- ******************************************************************************

-- 計時模塊

-- *******************************************************************************

library IEEE;

use IEEE.std_logic_1164.all;

use IEEE.std_logic_unsigned.all;

use IEEE.std_logic_arith.all;

entity time_counter is

port(

clk:in std_logic; --50M時鍾輸入

reset_n:in std_logic; --復位信號輸入

password1_in:in std_logic_vector(3 downto 0); --

password2_in:in std_logic_vector(3 downto 0); --

password3_in:in std_logic_vector(3 downto 0); --

password4_in:in std_logic_vector(3 downto 0); --

ok_signal_counter_in:in std_logic_vector(2 downto 0);

 

seg_duan:out std_logic_vector(7 downto 0); --數碼管段信號輸出

seg_wei:out std_logic_vector(7 downto 0) --數碼管位信號輸出

);

end time_counter;

architecture time_counter_behave of time_counter is

signal clk_1hz: std_logic;

signal count: std_logic_vector(24 downto 0);

signal clk_scan: std_logic;

signal seg_select: std_logic_vector(2 downto 0);

signal scan_count: std_logic_vector(13 downto 0);

begin

-- //****************************************************************************************************

-- // 模塊名稱:50M時鍾分頻至1HZ模塊

-- // 功能描述:

-- //****************************************************************************************************

process(clk,reset_n)

begin

if(reset_n = '0')then

clk_1hz <= '0';

count <= "0000000000000000000000000";

elsif(clk'event and clk = '1')then--上升沿觸發

if(count = "1011111010111100001000000")then--

count <= "0000000000000000000000000";

clk_1hz <= not clk_1hz;

else

count <= count + '1';

end if;

end if;

end process;

-- //****************************************************************************************************

-- // 模塊名稱:數碼管掃描時鍾產生模塊

-- // 功能描述:

-- //****************************************************************************************************

process(clk,reset_n)

begin

if(reset_n = '0')then

scan_count <= "00000000000000";

clk_scan <= '0';

elsif(clk'event and clk = '1')then--上升沿觸發

if(scan_count = "10011100010000")then

scan_count <= "00000000000000";

clk_scan <= not clk_scan;

else

scan_count <= scan_count + '1';

end if;

end if;

end process;

process(clk_scan,reset_n)

begin

if(reset_n = '0')then

seg_select <= "000";

elsif(clk_scan'event and clk_scan = '1')then--上升沿觸發

seg_select <= seg_select + '1';

end if;

end process;

-- //****************************************************************************************************

-- // 模塊名稱:數碼管顯示模塊

-- // 功能描述:

-- //****************************************************************************************************

process(clk)

begin

if(clk'event and clk = '1')then--上升沿觸發

case seg_select is

when "000"=>--顯示第1個密碼

seg_wei <= "11111110";

case password4_in is

when "0000"=>seg_duan <= "11000000";--0

when "0001"=>seg_duan <= "11111001";--1

when "0010"=>seg_duan <= "10100100";--2

when "0011"=>seg_duan <= "10110000";--3

when "0100"=>seg_duan <= "10011001";--4

when "0101"=>seg_duan <= "10010010";--5

when "0110"=>seg_duan <= "10000010";--6

when "0111"=>seg_duan <= "11111000";--7

when "1000"=>seg_duan <= "10000000";--8

when "1001"=>seg_duan <= "10010000";--9

when others=>null;

end case;

when "001"=>--顯示第2個密碼

seg_wei <="11111101";

case password3_in is

when "0000"=>seg_duan <= "11000000";--0

when "0001"=>seg_duan <= "11111001";--1

when "0010"=>seg_duan <= "10100100";--2

when "0011"=>seg_duan <= "10110000";--3

when "0100"=>seg_duan <= "10011001";--4

when "0101"=>seg_duan <= "10010010";--5

when "0110"=>seg_duan <= "10000010";--6

when "0111"=>seg_duan <= "11111000";--7

when "1000"=>seg_duan <= "10000000";--8

when "1001"=>seg_duan <= "10010000";--9

when others=>null;

end case;

when "010"=>--顯示第3個密碼

seg_wei <="11111011";

case password2_in is

when "0000"=>seg_duan <= "11000000";--0

when "0001"=>seg_duan <= "11111001";--1

when "0010"=>seg_duan <= "10100100";--2

when "0011"=>seg_duan <= "10110000";--3

when "0100"=>seg_duan <= "10011001";--4

when "0101"=>seg_duan <= "10010010";--5

when "0110"=>seg_duan <= "10000010";--6

when "0111"=>seg_duan <= "11111000";--7

when "1000"=>seg_duan <= "10000000";--8

when "1001"=>seg_duan <= "10010000";--9

when others=>null;

end case;

when "011"=>--顯示第4個密碼

seg_wei <="11110111";

case password1_in is

when "0000"=>seg_duan <= "11000000";--0

when "0001"=>seg_duan <= "11111001";--1

when "0010"=>seg_duan <= "10100100";--2

when "0011"=>seg_duan <= "10110000";--3

when "0100"=>seg_duan <= "10011001";--4

when "0101"=>seg_duan <= "10010010";--5

when "0110"=>seg_duan <= "10000010";--6

when "0111"=>seg_duan <= "11111000";--7

when "1000"=>seg_duan <= "10000000";--8

when "1001"=>seg_duan <= "10010000";--9

when others=>null;

end case;

when "100"=>--

seg_wei <="11011111";--顯示當前輸入密碼的次序

case ('0' & ok_signal_counter_in) is

when "0000"=>seg_duan <= "11000000";--0

when "0001"=>seg_duan <= "11111001";--1

when "0010"=>seg_duan <= "10100100";--2

when "0011"=>seg_duan <= "10110000";--3

when "0100"=>seg_duan <= "10011001";--4

when "0101"=>seg_duan <= "10010010";--5

when "0110"=>seg_duan <= "10000010";--6

when "0111"=>seg_duan <= "11111000";--7

when "1000"=>seg_duan <= "10000000";--8

when "1001"=>seg_duan <= "10010000";--9

when others=>null;

end case;

when others=>null;

end case;

end if;

end process;

end time_counter_behave;

 

超時報警模塊

-- ******************************************************************************

-- 按鍵模塊,進行按鍵消抖和按鍵編碼

-- *******************************************************************************

library IEEE;

use IEEE.std_logic_1164.all;

use IEEE.std_logic_unsigned.all;

use IEEE.std_logic_arith.all;

entity bell is

port(

clk:in std_logic; --50M時鍾輸入

reset_n:in std_logic; --復位信號輸入

start_flag:in std_logic; --蜂鳴器開始相應信號

fm_time_over:out std_logic;

pwm_out:out std_logic; --蜂鳴器驅動脈沖

fm_20:out std_logic

);

end bell;

architecture bell_behave of bell is

signal count:std_logic_vector(14 downto 0);

signal pwm_signal:std_logic;

signal long_count:std_logic_vector(14 downto 0);

signal short_count:std_logic_vector(12 downto 0);

signal pwm_en:std_logic;

type state is(

prepare,--准備狀態

start,--開始狀態

stop

);

signal current_state:state;--一開始處於准備狀態

begin

fm_20 <= pwm_en;

-- //****************************************************************************************************

-- // 模塊名稱:蜂鳴器驅動脈沖產生模塊

-- // 功能描述:1KHz

-- //****************************************************************************************************

process(clk,reset_n)

begin

if(reset_n = '0')then

count <= "000000000000000";

pwm_signal <= '0';

elsif(clk'event and clk = '1')then--上升沿觸發

if(count = "110000110101000")then

count <= "000000000000000";

pwm_signal <= not pwm_signal;

else

count <= count + '1';

end if;

end if;

end process;

-- //****************************************************************************************************

-- // 模塊名稱:蜂鳴器響應時間產生模塊

-- // 功能描述:

-- //****************************************************************************************************

process(pwm_signal,reset_n)

begin

if(reset_n = '0')then

current_state <= prepare;

short_count <= "0000000000000";

long_count <= "000000000000000";

fm_time_over <= '0';

pwm_en <= '0';

elsif(pwm_signal'event and pwm_signal = '1')then--上升沿觸發

case current_state is

when prepare=>

if(start_flag = '1')then

if(short_count = "1101101011000")then--5s

short_count <= "0000000000000";

current_state <= start;

else

short_count <= short_count + '1';

current_state <= prepare;

end if;

else

current_state <= prepare;

short_count <= "0000000000000";

long_count <= "000000000000000";

fm_time_over <= '0';

pwm_en <= '0';

end if;

when start=>

if(long_count = "100111000100000")then--20s

long_count <= "000000000000000";

pwm_en <= '0';

fm_time_over <= '1';

current_state <= stop;

else

current_state <= start;

long_count <= long_count + '1';

pwm_en <= '1';

fm_time_over <= '0';

end if;

when stop=>

pwm_en <= '0';

fm_time_over <= '1';

current_state <= prepare;

short_count <= "0000000000000";

long_count <= "000000000000000";

end case;

end if;

end process;

pwm_out <= pwm_en and pwm_signal;

end bell_behave;

 

實驗操作

上電

接入5V電源,用配套的線,USB那端接電腦即可;

電源開關

按下電源開關

顯示

數碼管開始顯示

顯示的數碼管為"0000"

右邊的四個是顯示當前輸入的密碼,從左到右分別是第一個到第四個密碼

復位

按下復位按鍵,此時數碼管清零0000;

電子鎖自鎖

僅有紅燈亮着,表示電子鎖鎖住了

輸入錯誤密碼

正確密碼"1111",例如輸入錯誤密碼"2222"

Key2用於選擇輸入密碼數:0~9,選擇好后按下key1按鍵,表示確定。

第一步:按下key1按鍵輸入第一個密碼輸入完第一個密碼后按下key1。

第二步:開始輸入第二個密碼,輸入第二個密碼,第二個密碼輸入完成后按下key1。

第三步:開始輸入第三個密碼,輸入第三個密碼,第三個密碼輸入完成后按下key1。

第四步:開始輸入第四個密碼,輸入第四個密碼,第四個密碼輸入完成后按下key1,輸入完成;

這個過程的操作必須在5s內,否則就違時,蜂鳴器就會響20s。

完成后紅色燈還是亮着的,綠色燈沒有亮。

輸入正確密碼

輸入正確密碼"1111"

Key2用於選擇輸入密碼數:0~9,選擇好后按下key1按鍵,表示確定。

第一步:按下key1按鍵輸入第一個密碼,左邊的數碼管會顯示1,輸入完第一個密碼后按下key1。

第二步:開始輸入第二個密碼,輸入第二個密碼,第二個密碼輸入完成后按下key1。

第三步:開始輸入第三個密碼,輸入第三個密碼,第三個密碼輸入完成后按下key1。

第四步:開始輸入第四個密碼,輸入第四個密碼,第四個密碼輸入完成后按下key1,輸入完成;

這個過程的操作必須在5s內,否則就違時,蜂鳴器就會響20s。

完成后紅色燈滅,綠色燈亮;

 

修改密碼

只有在輸入正確密碼后,才能進行修改密碼;

第一步:按下key1按鍵,ledD4亮,表示可以進行修改密碼;

第二步:輸入新密碼,輸入新密碼與輸入密碼的過程一致,輸入完成后,讓左邊的數碼管顯示"1",然后按下key3按鍵,ledD4滅,表示確定輸入的新密碼,FPGA就會將新的密碼進行加載。

例如將新密碼改為"2222"

輸入過程紅燈和綠燈是不顯示的。

重新輸入修改后的密碼

輸入新的正確密碼"2222"

Key2用於選擇輸入密碼數:0~9,選擇好后按下key1按鍵,表示確定。

第一步:按下key1按鍵輸入第一個密碼,左邊的數碼管會顯示1,輸入完第一個密碼后按下key1。

第二步:開始輸入第二個密碼,輸入第二個密碼,第二個密碼輸入完成后按下key1。

第三步:開始輸入第三個密碼,輸入第三個密碼,第三個密碼輸入完成后按下key1。

第四步:開始輸入第四個密碼,輸入第四個密碼,第四個密碼輸入完成后按下key1;

這個過程的操作必須在5s內,否則就違時,蜂鳴器就會響20s。

完成后紅色燈滅,綠色燈亮;

 

輸入密碼時間超過5s

如果按下密碼選擇按鍵key1,然后在5s內沒有輸入好正確的密碼,則蜂鳴器會響起。

蜂鳴器響應20s

在違時后蜂鳴器會相應20s,且這個時間內是不能進行密碼輸入的;

 

 

 

大西瓜FPGA-->https://daxiguafpga.taobao.com

配套開發板:https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-24211932856.3.489d7241aCjspB&id=633897209972

博客資料、代碼、圖片、文字等屬大西瓜FPGA所有,切勿用於商業! 若引用資料、代碼、圖片、文字等等請注明出處,謝謝!

   

每日推送不同科技解讀,原創深耕解讀當下科技,敬請關注微信公眾號"科乎"。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM