Serwis Edukacyjny
w I-LO w Tarnowie
obrazek

Materiały dla uczniów liceum

  Wyjście       Spis treści       Wstecz       Dalej  

Autor artykułu: mgr Jerzy Wałaszek

©2020 mgr Jerzy Wałaszek
I LO w Tarnowie

Bity w elektronice

Czytnik klawiatury numerycznej

SPIS TREŚCI
Podrozdziały

Opis

obrazek

W tym artykule zaprojektujemy prosty czytnik klawiatury numerycznej (trochę mniej skomplikowanej od tej po lewej stronie). Nasz układ będzie odczytywał wciśnięcia pojedynczych klawiszy numerycznych 0,1,...,9 i zamieniał je na kod binarny 8421, który pojawi się na wyjściu urządzenia.

Kod 8421 jest naturalnym, czterobitowym kodem. Jeśli bity zapiszemy numerując je od ostatniego:

b 8 b 4 b 2 b 1

to bit o stanie 1 posiada wartość:

b 8 = 8, b 4 = 4, b 2 = 2 i b 1 = 1

stąd nazwa kodu 8421. Bit o stanie 0 ma wartość 0. Na przykład zapis:

0110

oznacza liczbę 6, ponieważ:

b 8 = 0, b 4 = 4, b 2 = 2 i b 1 = 0

 Gdy zsumujemy poszczególne wagi, otrzymamy 6. Poniższa tabelka podaje wartości kolejnych cyfr dziesiętnych w kodzie 8421.

Kod 8421 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001
Cyfra 0 1 2 3 4 5 6 7 8 9

Umówimy się, iż nasz czytnik będzie dawał na wyjściu kod 1111, gdy żaden klawisz nie jest naciśnięty. Łatwo zauważyć, iż  kod 1111 nie reprezentuje w kodzie 8421 żadnej cyfry dziesiętnej - jest to zatem "bezpieczna" wartość. Każdy klawisz będzie zwykłym przyciskiem, który, w przypadku naciśnięcia, zewrze linię klawisza do masy, czyli wymusi poziom logiczny 0. Gdy klawisz nie jest naciśnięty, włącznik jest rozwarty i dzięki opornikowi podciągającemu (ang. pull-up resistor)  1k na linii klawisza utrzymuje się poziom logiczny 1:

Przycisk zwolniony Przycisk wciśnięty
Na początek:  podrozdziału   strony 

Określenie funkcji logicznych

Najpierw wytłumaczmy, czym jest logika ujemna (ang. negative logic). W normalnej logice stosujemy następujące przypisania:

false → 0
true → 1

Na tej umowie opierają się wszystkie funkcje logiczne:

a ¬a
0 1
1 0
a b a∨b
0 0 0
0 1 1
1 0 1
1 1 1
a b a∧b
0 0 0
0 1 0
1 0 0
1 1 1

Zapiszmy wartości funkcji oznaczając wartość true przez T, a wartość false przez F:

a ¬a
0 T
1 F
a b a∨b
0 0 F
0 1 T
1 0 T
1 1 T
a b a∧b
0 0 F
0 1 F
1 0 F
1 1 T

Teraz umówmy się, że wartości funkcji będziemy interpretować odwrotnie, tzn.:

false → 1
true → 0

Otrzymamy:

a ¬a
0 F
1 T
a b a∨b
0 0 T
0 1 F
1 0 F
1 1 F
a b a∧b
0 0 T
0 1 T
1 0 T
1 1 F

Teraz to samo zróbmy z argumentami:

a ¬a
T F
F T
a b a∨b
T T T
T F F
F T F
F F F
a b a∧b
T T T
T F T
F T T
F F F

Zwróć uwagę, iż przy takiej interpretacji 0 i 1 funkcja negacji się nie zmienia, lecz funkcje alternatywy i koniunkcji zamieniły się ze sobą, tzn. z alternatywy otrzymujemy koniunkcję, a z koniunkcji alternatywę. Otrzymaliśmy logikę ujemną. Nie jest ona czymś zupełnie innym. Po prostu czasem wygodniej jest interpretować stan niski jako stan aktywny, a stan wysoki, jako nieaktywny. Tak jest w przypadku naszej klawiatury: wciśnięcie przycisku będzie dawało stan niski, a zwolnienie stan wysoki.

Klawiatura będzie zbudowana z 10 przycisków. Schemat jest następujący:

Naszym zadaniem będzie zbudowanie kodera, który przetworzy naciśnięcia klawiszy w kod 8421. Na wejściu kod będzie otrzymywał informację z klawiatury, na wyjściu mamy otrzymać numer naciśniętego klawisza w kodzie 8421, przy czym brak naciśnięcia klawisza powinien dawać kod 1111 (dziesiętnie 15 – nie jest wartością żadnej cyfry, zatem jest bezpieczny).

Ułóżmy tabelkę stanów wejściowych oraz wyjściowych naszego kodera:

Wejścia Wyjścia
K0 K1 K2 K3 K4 K5 K6 K7 K8 K9 Y8 Y4 Y2 Y1
1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1 1 0 0 0 0
1 0 1 1 1 1 1 1 1 1 0 0 0 1
1 1 0 1 1 1 1 1 1 1 0 0 1 0
1 1 1 0 1 1 1 1 1 1 0 0 1 1
1 1 1 1 0 1 1 1 1 1 0 1 0 0
1 1 1 1 1 0 1 1 1 1 0 1 0 1
1 1 1 1 1 1 0 1 1 1 0 1 1 0
1 1 1 1 1 1 1 0 1 1 0 1 1 1
1 1 1 1 1 1 1 1 0 1 1 0 0 0
1 1 1 1 1 1 1 1 1 0 1 0 0 1

Zwróć uwagę, iż tabelka ta jest niepełna, ponieważ nie uwzględnia sytuacji, gdy zostały naciśnięte dwa lub więcej klawiszy. Aby nie komplikować projektu, umówmy się, że do takich sytuacji nie będzie dochodziło. W naszym koderze będziemy reagować na stany niskie wejść. Ponieważ zawsze tylko jedno wejście może być w stanie niskim, to rozpiszmy wg podanej wyżej tabelki, kiedy poszczególne wyjścia przyjmują stan niski 0:

Wyjście w stanie 0 Dla stanu 0 na wejściach
Y1 K0,K2,K4,K6,K8
Y2 K0,K1,K4,K5,K8,K9
Y4 K0,K1,K2,K3,K8,K9
Y8 K0,K1,K2,K3,K4,K5,K6,K7

Możemy teraz zapisać funkcję wyjść:

Stosujemy prawa De Morgana i otrzymujemy:

We wzorach otrzymaliśmy koniunkcje. Będą potrzebne 4 ośmiowejściowe bramki AND (nieużywane wejścia podłączamy do napięcia zasilającego poprzez opornik 1k). Ponieważ bramki NAND są bardziej dostępne, przeprojektujemy funkcje tak, aby otrzymać zaprzeczone koniunkcje (czyli NAND):

Na początek:  podrozdziału   strony 

Budowa sieci logicznej

Na podstawie otrzymanych wzorów funkcji budujemy sieć logiczną z bramek NAND. Rozpoczynamy od sygnałów wejściowych. Linie sygnałowe umieścimy pionowo, gdyż tak będzie wygodniej podłączać je do wejść bramek:

Teraz dołączamy bramki NAND realizujące kolejne funkcje. Wyjścia bramek NAND muszą być zanegowane, aby otrzymać koniunkcję. Nieużywane wejścia podłączamy poprzez opornik 1k do napięcia zasilającego:









Sieć logiczna kodera 1 z 10 na 8421 jest gotowa.

Na początek:  podrozdziału   strony 

Symulacja  w języku C++

Numerujemy bramki.

Określamy sieć połączeń:

YB1 = NAND(1,1,1,K0,K2,K4,K6,K8)
YB2 = NAND(1,1,K0,K1,K4,K5,K8,K9)
YB3 = NAND(1,1,K0,K1,K2,K3,K8,K9)
YB4 = NAND(K0,K1,K2,K3,K4,K5,K6,K7)
YB5 = NAND(YB1,YB1)
YB6 = NAND(YB2,YB2)
YB7 = NAND(YB3,YB3)
YB8 = NAND(YB4,YB4)
Y1 = YB5
Y2 = YB6
Y4 = YB7
Y8 = YB8

Na wejścia sieci K0...K9 podajemy sygnały zgodnie z poniższą tabelką. Na wyjściach powinniśmy otrzymać kody 8421 wciśniętych klawiszy.

Wejścia Wyjścia
K0 K1 K2 K3 K4 K5 K6 K7 K8 K9 Y8 Y4 Y2 Y1
1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1 1 0 0 0 0
1 0 1 1 1 1 1 1 1 1 0 0 0 1
1 1 0 1 1 1 1 1 1 1 0 0 1 0
1 1 1 0 1 1 1 1 1 1 0 0 1 1
1 1 1 1 0 1 1 1 1 1 0 1 0 0
1 1 1 1 1 0 1 1 1 1 0 1 0 1
1 1 1 1 1 1 0 1 1 1 0 1 1 0
1 1 1 1 1 1 1 0 1 1 0 1 1 1
1 1 1 1 1 1 1 1 0 1 1 0 0 0
1 1 1 1 1 1 1 1 1 0 1 0 0 1
C++
// Symulacja sieci logicznej kodera 1 z 10 na 8421
// (C)2020 mgr Jerzy Wałaszek
// I LO w Tarnowie

#include <iostream>

using namespace std;

// Funkcje bramek

int NAND2(int a, int b)
{
    return !(a && b);
}

int NAND8(int a,int b,int c,int d,int e,int f,int g,int h)
{
    return !(a && b && c && d && e && f && g && h);
}

int main( )
{
  // Stany wejściowe oraz stany wyjściowe
  int K0,K1,K2,K3,K4,K5,K6,K7,K8,K9,Y1,Y2,Y4,Y8;

  // Stany wyjściowe bramek
  int YB1,YB2,YB3,YB4,YB5,YB6,YB7,YB8;

  // Zmienne pomocnicze
  int m,i;

  m = 0x3ff; // Ustawiamy maskę, m = 1111111111 (binarnie)

  cout << "K0 K1 K2 K3 K4 K5 K6 K7 K8 K9 | Y8 Y4 Y2 Y1\n"
          "------------------------------+------------\n";
  // Wykonujemy 11 obiegów pętli
  for(i = 0; i < 11; i++)
  {
    // Z maski pobieramy kolejne bity i wstawiamy je do K0...K9
    K0 = (m & 0x200) > 0;
    K1 = (m & 0x100) > 0;
    K2 = (m & 0x080) > 0;
    K3 = (m & 0x040) > 0;
    K4 = (m & 0x020) > 0;
    K5 = (m & 0x010) > 0;
    K6 = (m & 0x008) > 0;
    K7 = (m & 0x004) > 0;
    K8 = (m & 0x002) > 0;
    K9 = (m & 0x001) > 0;

    // Maskę przesuwamy o 1 bit w prawo
    m >>= 1;

    // Ustawiamy na 1 bit nr 10
    m |= 0x400; // m = 101111111111
                // m = 110111111111
                // m = 111011111111 ...

    // Symulujemy sieć
    YB1 = NAND8(1,1,1,K0,K2,K4,K6,K8);
    YB2 = NAND8(1,1,K0,K1,K4,K5,K8,K9);
    YB3 = NAND8(1,1,K0,K1,K2,K3,K8,K9);
    YB4 = NAND8(K0,K1,K2,K3,K4,K5,K6,K7);
    YB5 = NAND2(YB1,YB1);
    YB6 = NAND2(YB2,YB2);
    YB7 = NAND2(YB3,YB3);
    YB8 = NAND2(YB4,YB4);
    Y1 = YB5;
    Y2 = YB6;
    Y4 = YB7;
    Y8 = YB8;

    // Wyświetlamy wyniki
    cout << " "
         << K0 << "  "
         << K1 << "  "
         << K2 << "  "
         << K3 << "  "
         << K4 << "  "
         << K5 << "  "
         << K6 << "  "
         << K7 << "  "
         << K8 << "  "
         << K9 << " | "
         << Y8 << "  "
         << Y4 << "  "
         << Y2 << "  "
         << Y1 << endl;
  }
  cout << endl;
  return 0;
}
Wynik:
K0 K1 K2 K3 K4 K5 K6 K7 K8 K9 | Y8 Y4 Y2 Y1
------------------------------+------------
 1  1  1  1  1  1  1  1  1  1 | 1  1  1  1
 0  1  1  1  1  1  1  1  1  1 | 0  0  0  0
 1  0  1  1  1  1  1  1  1  1 | 0  0  0  1
 1  1  0  1  1  1  1  1  1  1 | 0  0  1  0
 1  1  1  0  1  1  1  1  1  1 | 0  0  1  1
 1  1  1  1  0  1  1  1  1  1 | 0  1  0  0
 1  1  1  1  1  0  1  1  1  1 | 0  1  0  1
 1  1  1  1  1  1  0  1  1  1 | 0  1  1  0
 1  1  1  1  1  1  1  0  1  1 | 0  1  1  1
 1  1  1  1  1  1  1  1  0  1 | 1  0  0  0
 1  1  1  1  1  1  1  1  1  0 | 1  0  0  1
Na początek:  podrozdziału   strony 

Symulacja interaktywna

W symulatorze pominięta jest sekcja klawiatury. Przyciski sterują bezpośrednio wejściami transkodera. Początkowo wszystkie przyciski ustawione są w stan wysoki, co odpowiada nieaktywnemu stanowi przycisków klawiatury. Kliknięcie przycisku zmienia jego stan na przeciwny. Pamiętaj, iż nasza sieć działa poprawnie tylko z jednym stanem wejściowym 0 (czarny kolor przycisku) i pozostałymi stanami 1 (kolor czerwony).

Symulator
Na początek:  podrozdziału   strony 

Spis elementów

Obciążenia wnoszone przez poszczególne wejścia sieci są następujące:

K0 = 4
K1 = 3
K2 = 3
K3 = 2
K4 = 3
K5 = 2
K6 = 2
K7 = 1
K8 = 3
K9 = 2

Sieć wykorzystuje 1 opornik 1kΩ oraz 8 bramek: 4 bramki NAND 8 wejściowe oraz 4 bramki NAND 2 wejściowe:

SN7400 × 1
 obrazek
SN7430 × 4
 obrazek

Scalony dekoder klawiatury - SN74147

Jeśli klawiatura wyposażona jest tylko w 9 klawiszy (od 1 do 9), to zamiast bramek można zastosować scalony konwerter 1 z 9 na kod 8421. Układ ten ma symbol SN74147 i pracuje w logice ujemnej (aktywny jest stan 0).

SN74147 - transkoder 1 z 9 na kod 8421
 obrazek

Układ osiada 9 wejść ponumerowanych od 1 do 9. Do wejść tych podłączamy linie klawiszy w identyczny sposób, jak w naszym rozwiązaniu. Na 4 wyjściach D, C, B i A pojawia się zanegowany kod 8421 naciśniętego klawisza. Tabelka stanów dla układu SN74147 jest następująca:

Wejścia Wyjścia
1 2 3 4 5 6 7 8 9 D C B A
1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1 1 1 1 0
X 0 1 1 1 1 1 1 1 1 1 0 1
X X 0 1 1 1 1 1 1 1 1 0 0
X X X 0 1 1 1 1 1 1 0 1 1
X X X X 0 1 1 1 1 1 0 1 0
X X X X X 0 1 1 1 1 0 0 1
X X X X X X 0 1 1 1 0 0 0
X X X X X X X 0 1 0 1 1 1
X X X X X X X X 0 0 1 1 0

Stan X oznacza 0 lub 1, czyli stan wejść poprzedzających dany klawisz jest bez znaczenia. W przypadku jednoczesnego naciśnięcia dwóch lub więcej klawiszy układ SN74147 zwraca kod najstarszego klawisza (zatem układ ten działa lepiej od naszej sieci).

Na początek:  podrozdziału   strony 

Zespół Przedmiotowy
Chemii-Fizyki-Informatyki

w I Liceum Ogólnokształcącym
im. Kazimierza Brodzińskiego
w Tarnowie
ul. Piłsudskiego 4
©2020 mgr Jerzy Wałaszek

Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.

Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl

Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.