Użycie układu CPLD do sterowania siedmiosegmentowym wyświetlaczem LCDlcdc_i00.jpg
Bazując na powyższych rozważaniach można rozwiązać problem sterowania siedmiosegmentowym wyświetlaczem LCD z wykorzystaniem układów logiki programowalnej CPLD. Zasoby oferowane przez te układy w zupełności wystarczą do realizacji założonej funkcji. W przykładzie jest użyty układ XC2C256 w obudowie VQFP100 (o 100 wyprowadzeniach). Oczywiście zaproponowany układ jest bardzo przewymiarowany do tego zastosowania, ale jego użycie jest uzasadnione tym, … że jest przylutowany do zestawu uruchomieniowego składającego się z płyty bazowej ZL15PLD oraz modułu CPLD ZL14PLD (oferowanego przez sklep internetowy Kamami).
Z zestawu bazowego (ZL15PLD) wykorzystane będą:
- dwucyfrowy wyświetlacz LCD (do prezentacji działania obsługi wyświetlacza),
- zespół 8-bitowego przełącznika (do „zadawania” liczb do wyświetlania).
Z dokumentacji do wymienionego zestawu wynika, że:
lcdc_i01.PNG
wyświetlacz jest przyłączony do układu CPLD w następujący sposób:
Pin CPLD → Znaczenie
10 → Styk segmentu A cyfry jedności
11 → Styk segmentu B cyfry jedności
13 → Styk segmentu C cyfry jedności
14 → Styk segmentu D cyfry jedności
15 → Styk segmentu E cyfry jedności
16 → Styk segmentu F cyfry jedności
17 → Styk segmentu G cyfry jedności
18 → Styk segmentu DP cyfry jedności
1 → Styk segmentu A cyfry dziesiątek
2 → Styk segmentu B cyfry dziesiątek
3 → Styk segmentu C cyfry dziesiątek
4 → Styk segmentu D cyfry dziesiątek
6 → Styk segmentu E cyfry dziesiątek
7 → Styk segmentu F cyfry dziesiątek
9 → Styk segmentu G cyfry dziesiątek
8 → Styk segmentu DP cyfry dziesiątek
27 → Styk wspólnego tła (BP)
przełącznik DIP-SWITCH jest przyłączony w następujący sposób:
lcdc_i02.PNG
Pin CPLD → Znaczenie
39 → Bit 7 (najbardziej znaczący),
40 → Bit 6
41 → Bit 5
42 → Bit 4
43 → Bit 3
44 → Bit 2
46 → Bit 1
49 → Bit 0 (najmniej znaczący)
Za pomocą przełączników są podawane do sterownika kody dwóch liczb (jako dwie cyfry 4-bitowe), zadaniem układu jest realizacja obsługi pozwalająca na zobrazowanie zadanych liczb (jako liczby szesnastkowe). Do implementacji sterownika zastosowane jest bezpłatne oprogramowanie narzędziowe oferowane przez firmę XILINX.
Postać źródłowa (w języku opisu sprzętu VHDL; również w oprogramowaniu narzędziowym istnieje możliwość narysowania odpowiedniego schematu) jest następująca (moduł główny, plik LCD.VHD):
Kod: Zaznacz cały
library IEEE ;
use IEEE.STD_LOGIC_1164.ALL ;
use IEEE.STD_LOGIC_ARITH.ALL ;
use IEEE.STD_LOGIC_UNSIGNED.ALL ;
entity LCD is port ( Clk : in std_logic ;
Reset : in std_logic ;
SWKey : in std_logic_vector ( 7 downto 0 ) ;
LCD_BP : out std_logic ;
LCD1_A : out std_logic ;
LCD1_B : out std_logic ;
LCD1_C : out std_logic ;
LCD1_D : out std_logic ;
LCD1_E : out std_logic ;
LCD1_F : out std_logic ;
LCD1_G : out std_logic ;
LCD1_DP : out std_logic ;
LCD10_A : out std_logic ;
LCD10_B : out std_logic ;
LCD10_C : out std_logic ;
LCD10_D : out std_logic ;
LCD10_E : out std_logic ;
LCD10_F : out std_logic ;
LCD10_G : out std_logic ;
LCD10_DP : out std_logic ) ;
end LCD ;
architecture Behavioral of LCD is
constant FDivCntSizeParam : integer := 10 ;
component LCD2DigDisp port ( MClk : in std_logic ;
Tetr0 : in std_logic_vector ( 3 downto 0 ) ;
Tetr1 : in std_logic_vector ( 3 downto 0 ) ;
LCD_BP : out std_logic ;
LCD1_A : out std_logic ;
LCD1_B : out std_logic ;
LCD1_C : out std_logic ;
LCD1_D : out std_logic ;
LCD1_E : out std_logic ;
LCD1_F : out std_logic ;
LCD1_G : out std_logic ;
LCD1_DP : out std_logic ;
LCD10_A : out std_logic ;
LCD10_B : out std_logic ;
LCD10_C : out std_logic ;
LCD10_D : out std_logic ;
LCD10_E : out std_logic ;
LCD10_F : out std_logic ;
LCD10_G : out std_logic ;
LCD10_DP : out std_logic ) ;
end component ;
component FDivider generic ( constant CntSize : integer := 8 ) ;
port ( Clk : in std_logic ;
Reset : in std_logic ;
FDiv : out std_logic ) ;
end component ;
signal MClk : std_logic ;
signal LCDDig1 : std_logic_vector ( 3 downto 0 ) ;
signal LCDDig10 : std_logic_vector ( 3 downto 0 ) ;
begin
LCDDig1 <= SWKey ( 3 downto 0 ) ;
LCDDig10 <= SWKey ( 7 downto 4 ) ;
FDivInstance : FDivider generic map ( CntSize => FDivCntSizeParam )
port map ( Clk => Clk ,
Reset => Reset ,
FDiv => MClk ) ;
LCDMuxInstance : LCD2DigDisp port map ( MClk => MClk ,
Tetr0 => LCDDig1 ,
Tetr1 => LCDDig10 ,
LCD_BP => LCD_BP ,
LCD1_A => LCD1_A ,
LCD1_B => LCD1_B ,
LCD1_C => LCD1_C ,
LCD1_D => LCD1_D ,
LCD1_E => LCD1_E ,
LCD1_F => LCD1_F ,
LCD1_G => LCD1_G ,
LCD1_DP => LCD1_DP ,
LCD10_A => LCD10_A ,
LCD10_B => LCD10_B ,
LCD10_C => LCD10_C ,
LCD10_D => LCD10_D ,
LCD10_E => LCD10_E ,
LCD10_F => LCD10_F ,
LCD10_G => LCD10_G ,
LCD10_DP => LCD10_DP ) ;
end Behavioral ;
Zastosowany w powyższym module komponent dzielnika częstotliwości ma następującą postać (plik FDIVIDER.VHD):
Kod: Zaznacz cały
library IEEE ;
use IEEE.STD_LOGIC_1164.ALL ;
use IEEE.STD_LOGIC_ARITH.ALL ;
use IEEE.STD_LOGIC_UNSIGNED.ALL ;
entity FDivider is generic ( constant CntSize : integer := 8 ) ;
port ( Clk : in std_logic ;
Reset : in std_logic ;
FDiv : out std_logic ) ;
end FDivider ;
architecture Behavioral of FDivider is
signal FDivCnt : std_logic_vector ( CntSize - 1 downto 0 ) ;
begin
FDividerInstance : process ( Clk , Reset )
begin
if Reset = '0' then
FDivCnt <= ( others => '0' ) ;
else
if Clk'event and Clk = '0' then
FDivCnt <= FDivCnt + 1 ;
end if ;
end if ;
end process ;
FDiv <= FDivCnt ( FDivCnt'left ) ;
end Behavioral ;Użyty w module głównym komponent obsługi wyświetlacza ma następującą postać (plik LCD2DIGDISP.VHD):
Kod: Zaznacz cały
library IEEE ;
use IEEE.STD_LOGIC_1164.ALL ;
use IEEE.STD_LOGIC_ARITH.ALL ;
use IEEE.STD_LOGIC_UNSIGNED.ALL ;
entity LCD2DigDisp is port ( MClk : in std_logic ;
Tetr0 : in std_logic_vector ( 3 downto 0 ) ;
Tetr1 : in std_logic_vector ( 3 downto 0 ) ;
LCD_BP : out std_logic ;
LCD1_A : out std_logic ;
LCD1_B : out std_logic ;
LCD1_C : out std_logic ;
LCD1_D : out std_logic ;
LCD1_E : out std_logic ;
LCD1_F : out std_logic ;
LCD1_G : out std_logic ;
LCD1_DP : out std_logic ;
LCD10_A : out std_logic ;
LCD10_B : out std_logic ;
LCD10_C : out std_logic ;
LCD10_D : out std_logic ;
LCD10_E : out std_logic ;
LCD10_F : out std_logic ;
LCD10_G : out std_logic ;
LCD10_DP : out std_logic ) ;
end LCD2DigDisp ;
architecture Behavioral of LCD2DigDisp is
component LCDHexConv port ( Tetr : in std_logic_vector ( 3 downto 0 ) ;
Seg_A : out std_logic ;
Seg_B : out std_logic ;
Seg_C : out std_logic ;
Seg_D : out std_logic ;
Seg_E : out std_logic ;
Seg_F : out std_logic ;
Seg_G : out std_logic ) ;
end component ;
signal LCD1 : std_logic_vector ( 6 downto 0 ) ;
signal LCD10 : std_logic_vector ( 6 downto 0 ) ;
begin
Conv1Instance : LCDHexConv port map ( Tetr => Tetr0 ,
Seg_A => LCD1 ( 0 ) ,
Seg_B => LCD1 ( 1 ) ,
Seg_C => LCD1 ( 2 ) ,
Seg_D => LCD1 ( 3 ) ,
Seg_E => LCD1 ( 4 ) ,
Seg_F => LCD1 ( 5 ) ,
Seg_G => LCD1 ( 6 ) ) ;
Conv10Instance : LCDHexConv port map ( Tetr => Tetr1 ,
Seg_A => LCD10 ( 0 ) ,
Seg_B => LCD10 ( 1 ) ,
Seg_C => LCD10 ( 2 ) ,
Seg_D => LCD10 ( 3 ) ,
Seg_E => LCD10 ( 4 ) ,
Seg_F => LCD10 ( 5 ) ,
Seg_G => LCD10 ( 6 ) ) ;
LCD_BP <= MClk ;
LCD1_A <= LCD1 ( 0 ) xor MClk ;
LCD1_B <= LCD1 ( 1 ) xor MClk ;
LCD1_C <= LCD1 ( 2 ) xor MClk ;
LCD1_D <= LCD1 ( 3 ) xor MClk ;
LCD1_E <= LCD1 ( 4 ) xor MClk ;
LCD1_F <= LCD1 ( 5 ) xor MClk ;
LCD1_G <= LCD1 ( 6 ) xor MClk ;
LCD1_DP <= MClk ;
LCD10_A <= LCD10 ( 0 ) xor MClk ;
LCD10_B <= LCD10 ( 1 ) xor MClk ;
LCD10_C <= LCD10 ( 2 ) xor MClk ;
LCD10_D <= LCD10 ( 3 ) xor MClk ;
LCD10_E <= LCD10 ( 4 ) xor MClk ;
LCD10_F <= LCD10 ( 5 ) xor MClk ;
LCD10_G <= LCD10 ( 6 ) xor MClk ;
LCD10_DP <= MClk ;
end Behavioral ;Dekoder (kodu binarnego na postać wymaganą przez wyświetlacz) ma następująca postać (plik LCDHEXCONV.VHD):
Kod: Zaznacz cały
library IEEE ;
use IEEE.STD_LOGIC_1164.ALL ;
use IEEE.STD_LOGIC_ARITH.ALL ;
use IEEE.STD_LOGIC_UNSIGNED.ALL ;
entity LCDHexConv is port ( Tetr : in std_logic_vector ( 3 downto 0 ) ;
Seg_A : out std_logic ;
Seg_B : out std_logic ;
Seg_C : out std_logic ;
Seg_D : out std_logic ;
Seg_E : out std_logic ;
Seg_F : out std_logic ;
Seg_G : out std_logic ) ;
end LCDHexConv ;
architecture Behavioral of LCDHexConv is
signal Segments : std_logic_vector ( 6 downto 0 ) ;
signal Neg : std_logic ;
begin
Neg <= '1' ;
Seg_A <= Neg xor Segments ( 0 ) ;
Seg_B <= Neg xor Segments ( 1 ) ;
Seg_C <= Neg xor Segments ( 2 ) ;
Seg_D <= Neg xor Segments ( 3 ) ;
Seg_E <= Neg xor Segments ( 4 ) ;
Seg_F <= Neg xor Segments ( 5 ) ;
Seg_G <= Neg xor Segments ( 6 ) ;
-- przyporządkowanie segmentów w Segments
-- 0
-- ---
-- 5 | | 1
-- --- <- 6
-- 4 | | 2
-- ---
-- 3
with Tetr select
Segments <= "1000000" when "0000" , --0
"1111001" when "0001" , --1
"0100100" when "0010" , --2
"0110000" when "0011" , --3
"0011001" when "0100" , --4
"0010010" when "0101" , --5
"0000010" when "0110" , --6
"1111000" when "0111" , --7
"0000000" when "1000" , --8
"0010000" when "1001" , --9
"0001000" when "1010" , --A
"0000011" when "1011" , --b
"1000110" when "1100" , --C
"0100001" when "1101" , --d
"0000110" when "1110" , --E
"0001110" when "1111" , --F
"1111111" when others ;
end Behavioral ;Po zaprogramowaniu układu CPLD, można zaobserwować działanie sterownika. Manipulując odpowiednimi przełącznikami, na wyświetlaczu obrazowane są właściwe liczby.
lcdc_i03.jpg
lcdc_i04.jpg
lcdc_i05.jpg
lcdc_i06.jpg
lcdc_i07.jpg
lcdc_i08.jpg
lcdc_i09.jpg
Załącznik, projekt (WebPack, Xilinx)
lcd.zip