設(shè)計(jì)思想
設(shè)計(jì)一個(gè)交流信號(hào)的檢測(cè)裝置,對(duì)輸入進(jìn)行前期處理,經(jīng)過(guò) A/D 采樣后數(shù)模轉(zhuǎn)換,將測(cè)量結(jié)果顯示出來(lái),并具有一定的測(cè)量輔助及擴(kuò)展功能。設(shè)計(jì)分別采用了 LM324 運(yùn)算放大器進(jìn)行信號(hào)放大,把被測(cè)輸入正弦波信號(hào)最小幅度為有效值 10 毫伏,頻率為 100HZ~10KHZ 的正弦信號(hào)通過(guò)兩級(jí)放大,放大成接近 2 伏但不超過(guò) 2 伏的正弦信號(hào)。
然后,分為兩支。一支接 LM2903 比較器以地為零點(diǎn)進(jìn)行過(guò)零比較,輸出數(shù)字信號(hào)接相應(yīng)的 FPGA 用以測(cè)量頻率。另一支接峰值保持電路用來(lái)保證采樣到波形的最大值,再接數(shù)模轉(zhuǎn)換器轉(zhuǎn)換成模擬量通過(guò)門電路轉(zhuǎn)換輸入到相應(yīng)的 FPGA 用以測(cè)量峰值,再配合用 VHDL 語(yǔ)言編的采用可編程邏輯器件完成數(shù)字電路的功能的程序?;揪涂梢暂^完整的實(shí)現(xiàn)題目要求了。
工作原理與功能
增益帶寬積
運(yùn)放的增益是隨信號(hào)的頻率變化而變化的。即輸入信號(hào)的頻率增大,其增益將逐漸減小,然而,其增益與其帶寬的乘積是一個(gè)常數(shù)。所謂運(yùn)放的帶寬是指其輸出電壓隨信號(hào)源頻率的增大而使其下降到最大值的 0.707 倍時(shí)的頻率范圍。增益帶寬積這個(gè)參數(shù)表述了某一型號(hào)運(yùn)放在高增益下必然降低帶寬,高帶寬必然降低增益的特性。
這種情況下運(yùn)放的帶寬增益積也只是個(gè)理論值。由于運(yùn)放輸入端參數(shù)、反饋電阻、輸入電阻、PCB 分布參數(shù),運(yùn)放對(duì)頻率響應(yīng)的變化,使運(yùn)放電路在輸入信號(hào)頻率沒(méi)有達(dá)到數(shù)據(jù)手冊(cè)中標(biāo)識(shí)的增益帶寬積時(shí),提前衰減到輸入信號(hào)的 0.707 倍。再者,由多次諧波造成的輸出電壓幅度大于正常的輸出電壓幅度。還要考慮到壓擺率對(duì)輸出信號(hào)造成的失真。所以,實(shí)際應(yīng)用中帶寬增益積不能達(dá)到資料手冊(cè)中的給出參數(shù)。這是在設(shè)計(jì)中應(yīng)該注意的。所以選擇運(yùn)放的帶寬增益積參數(shù)要高于運(yùn)放實(shí)際帶寬增益積的十倍比較合適。
比較器的作用
比較器是將一個(gè)模擬電壓信號(hào)與一個(gè)基準(zhǔn)電壓相比較的電路。常用的幅度比較電路有電壓幅度比較器,具有遲滯特性的比較器。這些比較器的閾值是固定的,有的只有一個(gè)閾值,有的具有兩個(gè)閾值。我們選擇如下圖的電路,過(guò)零比較,把正弦信號(hào)轉(zhuǎn)化成方波信號(hào),以便 FPGA 可以通過(guò)計(jì)數(shù)器測(cè)量頻率。
A/D 我們按照手冊(cè)中的基本電路圖編寫,并為了測(cè)得穩(wěn)定的峰值,在 A/D 的輸入端我們加入了峰值保持電路(如下圖),目的是能夠使采樣采到峰值并繼續(xù)保持下去。在 A/D 輸出端,我們考慮到由于 FPGA 輸入端只有 3.3V,所以在 A/D 的輸入端我們加入八進(jìn)八出的 74HC244N,目的是使 A/D 輸出的 5V 可以轉(zhuǎn)換到 FPGA 的 3.3V,防止 FPGA 燒壞。
硬件電路圖

兩級(jí)LM324運(yùn)算放大器電路圖

LM2903比較器電路圖

FPGA電路圖
系統(tǒng)框圖

利用ABB PLC 軟件編寫程序
數(shù)模轉(zhuǎn)換器
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity ad is
PORT(
clk : in std_logic;
data_ad : in std_logic_vector(7 downto 0);
douta,doutb,doutc,doutd : out std_logic_vector(4 downto 0)
);
end;
ARCHITECTURE behave of ad is
TYPE STATE_TYPE IS (s0,s1,s2,s3,s4,s5,s6,s7,s8);
signal state: STATE_TYPE;
signal a,b,c,d : std_logic_vector(9 downto 0);
signal dis_a,dis_b : std_logic_vector(4 downto 0);
signal dis_c,dis_d : std_logic_vector(4 downto 0);
signal data_transf_buff : std_logic_vector(10 downto 0);
begin
-------------------------------------
process (clk,state)
begin
if clk 'event and clk ='1' then
case state is
when s0 = >
data_transf_buff<="00000000000";
a(7 downto 0)<=data_ad;
state<=s1;
when s1 = >
b(7 downto 0)<=data_ad;
state<=s2;
when s2 = >
c(7 downto 0)<=data_ad;
state<=s3;
when s3 = >
d<= data_ad + a + b + c;
state<=s4;
-----------------------------------------------------------------
when s4 = >
dis_a <= "00000"; dis_b <= "00000";
dis_c <= "00000"; dis_d <= "00000";
data_transf_buff(10 downto 1)<=d;
state<=s5;
when s5 = >
if data_transf_buff >= "01111101000" then
data_transf_buff <= data_transf_buff - "01111101000";
dis_a <= dis_a + 1;
state<=s5;
else
state<=s6;
end if;
when s6 = >
if data_transf_buff >= "00001100100" then
data_transf_buff <= data_transf_buff - "00001100100";
dis_b <= dis_b + 1;
state<=s6;
else
state<=s7;
end if;
when s7 = >
if data_transf_buff >= "00000001010" then
data_transf_buff <= data_transf_buff - "00000001010";
dis_c <= dis_c + 1;
state<=s7;
else
dis_d <= data_transf_buff(4 downto 0);
state<=s8;
end if;
when s8 = >
douta <= dis_a; doutb <= dis_b;
doutc <= dis_c; doutd <= dis_d;
state <= s0;
end case;
end if;
end process;
end behave;
調(diào)頻
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity frequence is
port(
fin : in std_logic;
clk_1Hz : in std_logic;
douta : out std_logic_vector(4 downto 0);
doutb : out std_logic_vector(4 downto 0);
doutc : out std_logic_vector(4 downto 0);
doutd : out std_logic_vector(4 downto 0)
);
end;
architecture behav of frequence is
signal clk_half : std_logic;
signal r_1,r_2,r_3,r_4,r_5 : std_logic_vector(4 downto 0);
signal t_1,t_2,t_3,t_4,t_5 : std_logic_vector(4 downto 0);
begin
process(clk_1Hz)
begin
if rising_edge(clk_1Hz) then
clk_half<=NOT clk_half;
end if;
end process;
process(fin,clk_half)
begin
if rising_edge(fin) then
if clk_half='1' then r_1<=r_1+1;
if r_1 >"01001" then r_1<="00000"; r_2<=r_2+1; end if;
if r_2 >"01001" then r_2<="00000"; r_3<=r_3+1; end if;
if r_3 >"01001" then r_3<="00000"; r_4<=r_4+1; end if;
if r_4 >"01001" then r_4<="00000"; r_5<=r_5+1; end if;
if r_5 >"01001" then r_1<="01001"; r_2<="01001"; r_3<="01001";
r_4<="01001"; r_5<="01001"; end if;
elsif clk_half='0' then
r_1<="00000";r_2<="00000";r_3<="00000";r_4<="00000";r_5<="00000";
end if;
end if;
end process;
process(clk_half)
begin
if falling_edge(clk_half) then
t_1<=r_1; t_3<=r_3; t_5<=r_5;
t_2<=r_2; t_4<=r_4;
end if;
end process;
-------------------------------------------------------------------------------------------
process(t_1,t_2,t_3,t_4,t_5)
begin
if t_5="00000" then
if t_4="00000" then douta<="11111";
else douta<=t_4; end if;
if t_3="00000" then doutb<="11111";
else doutb<=t_3; end if;
if t_2="00000" then doutc<="11111";
else doutc<=t_2; end if;
doutd<=t_1;
else doutd<=t_2;doutc<=t_3;
doutb<=t_4+"10000";
douta<=t_5;
end if;
end process;
end;
計(jì)數(shù)器
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY lpm;
USE lpm.all;
ENTITY counter24 IS
PORT
(
clock : IN STD_LOGIC ;
cout : OUT STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (23 DOWNTO 0)
);
END counter24;
ARCHITECTURE SYN OF counter24 IS
SIGNAL sub_wire0 : STD_LOGIC ;
SIGNAL sub_wire1 : STD_LOGIC_VECTOR (23 DOWNTO 0);
COMPONENT lpm_counter
GENERIC (
lpm_direction : STRING;
lpm_modulus : NATURAL;
lpm_port_updown : STRING;
lpm_type : STRING;
lpm_width : NATURAL
);
PORT (
clock : IN STD_LOGIC ;
cout : OUT STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (23 DOWNTO 0)
);
END COMPONENT;
BEGIN
cout <= sub_wire0;
q <= sub_wire1(23 DOWNTO 0);
lpm_counter_component : lpm_counter
GENERIC MAP (
lpm_direction = > "UP",
lpm_modulus = > 12000000,
lpm_port_updown = > "PORT_UNUSED",
lpm_type = > "LPM_COUNTER",
lpm_width = > 24
)
PORT MAP (
clock = > clock,
cout = > sub_wire0,
q = > sub_wire1
);
END SYN;
顯示
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity display is
port(clk : in std_logic;
number_a : in std_logic_vector(4 downto 0);
number_b : in std_logic_vector(4 downto 0);
number_c : in std_logic_vector(4 downto 0);
number_d : in std_logic_vector(4 downto 0);
number_e : in std_logic_vector(4 downto 0);
number_f : in std_logic_vector(4 downto 0);
number_g : in std_logic_vector(4 downto 0);
number_h : in std_logic_vector(4 downto 0);
scale : out std_logic_vector(7 downto 0);
dout : out std_logic_vector(7 downto 0)
);
end;
architecture behav of display is
signal number : std_logic_vector(2 downto 0);
signal LED : std_logic_vector(4 downto 0);
signal clk_counter: std_logic_vector(5 downto 0);
signal clk_d : std_logic;
begin
process(clk)
begin
if rising_edge(clk) then
clk_counter<=clk_counter+1;
if clk_counter=0 then
clk_d<=not clk_d;
end if;
end if;
end process;
process(clk_d)
begin
if rising_edge(clk_d) then
number<=number+1;
case number(2 downto 0) is
when "000" = > LED<=number_a; scale<="00000001";
when "001" = > LED<=number_b; scale<="00000010";
when "010" = > LED<=number_c; scale<="00000100";
when "011" = > LED<=number_d; scale<="00001000";
when "100" = > LED<=number_e; scale<="00010000";
when "101" = > LED<=number_f; scale<="00100000";
when "110" = > LED<=number_g; scale<="01000000";
when "111" = > LED<=number_h; scale<="10000000";
when others = > scale<="00000000";
end case;
end if;
end process;
process(LED)
begin
case LED(4 downto 0) is
when "00000" = > dout <= "11000000";
when "00001" = > dout <= "11111001";
when "00010" = > dout <= "10100100";
when "00011" = > dout <= "10110000";
when "00100" = > dout <= "10011001";
when "00101" = > dout <= "10010010";
when "00110" = > dout <= "10000010";
when "00111" = > dout <= "11111000";
when "01000" = > dout <= "10000000";
when "01001" = > dout <= "10010000";
when "10000" = > dout <= "01000000";
when "10001" = > dout <= "01111001";
when "10010" = > dout <= "00100100";
when "10011" = > dout <= "00110000";
when "10100" = > dout <= "00011001";
when "10101" = > dout <= "00010010";
when "10110" = > dout <= "00000010";
when "10111" = > dout <= "01111000";
when "11000" = > dout <= "00000000";
when "11001" = > dout <= "00010000";
when "11111" = > dout <= "11111111";
when others = > dout <= "11111111";
end case;
end process;
end;
06
特色成果
本組在運(yùn)算放大器的設(shè)計(jì)中,充分考慮到被測(cè)輸入正弦波信號(hào)最小幅度為有效值 10 毫伏,而放大后輸入到數(shù)模轉(zhuǎn)換器的電壓不能超過(guò) 2 伏而要無(wú)限接近于 2 伏。所以,在設(shè)計(jì)時(shí),我們采用兩級(jí)放大,第一級(jí)放大 10 倍,第二級(jí)根據(jù)輸入信號(hào)的不同由一個(gè)小開(kāi)關(guān)控制。當(dāng)輸入信號(hào)為 1015mv 時(shí),采用 13 倍放大,當(dāng)輸入信號(hào)為 1620mv 時(shí),采用 10 倍放大。這樣,可以根據(jù)信號(hào)的峰值不同采用不同的放大級(jí)數(shù),有利于信號(hào)的放大不是真。
-
運(yùn)放電路
+關(guān)注
關(guān)注
39文章
366瀏覽量
36181 -
比較器
+關(guān)注
關(guān)注
14文章
1886瀏覽量
111435 -
LM324
+關(guān)注
關(guān)注
16文章
166瀏覽量
66727 -
數(shù)模轉(zhuǎn)換器
+關(guān)注
關(guān)注
14文章
1279瀏覽量
85205 -
FPGA芯片
+關(guān)注
關(guān)注
3文章
250瀏覽量
40858
發(fā)布評(píng)論請(qǐng)先 登錄
可編程邏輯器件
PLD可編程邏輯器件
可編程邏輯器件基礎(chǔ)及應(yīng)用實(shí)驗(yàn)指導(dǎo)書
什么是PLD(可編程邏輯器件)
EDA技術(shù)與應(yīng)用(可編程邏輯器件)
可編程邏輯器件FPGA/CPLD結(jié)構(gòu)與應(yīng)用
電可編程邏輯器件EPLD是如何設(shè)計(jì)的
可編程邏輯器件測(cè)試

怎樣設(shè)計(jì)一個(gè)基于可編程邏輯器件的信號(hào)檢測(cè)裝置?
評(píng)論