Bogusław Kempny

Klawiatura numeryczna

×
Autor adres English
Początek HC-SR04 LCD Kamera fork() sms strfry() GPIO impulsy Klawiatura Brama GPIO PWM SG90 RFID Grafolog RCP Shutdown Temperatura ....











Za kilka złotych kupić można taką prostą klawiaturkę:

Może nie nadaje się do ciężkiej pracy, masowego wprowadzania danych nie wytrzyma, ale do sporadycznego użytku się nadaje.

Nie ma w niej żednej elektroniki, co jest jej zaletą (nie przegrzeje się, nie zamarznie), ale też wadą, bo odczytać ją musimy zewnętrznym programem sterującym ośmioma wyprowadzeniami.

Możemy dodać trochę elektroniki, zredukujemy wtedy liczbę obsługiwanych sygnałów, ale czy warto?
Może jepiej wtedy kupić droższą zabawkę, ale już z interfejsem USB?

Jak to działa? Baaardzo prosto. Mamy cztery linie podłączone do wierszy klawiatury i cztery do jej kolumn. Naciskając na przykład klawisz "4" zwieramy linię drugiego wersza z linią pierwszej kolumny.

Wystarczy podawać na kolejne linie wierszy jedynkę logiczną i sprawdzać czy pojawiła się na jakiejś linii kolumn. A że nie ma tu elektroniki, ta jedynka logiczna może być dowolnym sygnałem, CMOS, TTL, 12V, cokolwiek nam odpowiada. No, może z pewnymi ograniczeniami, 3 kV byłoby raczej przesadą, z oczywistych powodów.

No to podłączamy. Wybieramy 8 pinów GPIO których nie zaprzęgliśmy dotąd do innej pracy i podłączamy do kolejnych wyprowadzeń klawiatury.
Ja wybrałem GPIO22 - GPIO29. Fizycznie leżą blisko siebie, więc kabelki są mniej poplątane.

Po podłączeniu wygląda to tak:

Niestety przy takim wyborze pinów nie można podłączyć wtyku klawiatury bezpośrednio do grzebienia GPIO, potrzebny jest kabelek przedłużający.

Gdybyśmy wybrali piny GPIO 6, 10, 11, 31 i 22, 23, 24, 25, tasiemkę od klawiatury moglibyśmy podłączyć bezpośrednio, ale musielibyśmy wymienić w niej wtyczkę z ośmiostykowej na dwie czterostykowe.

Jak w innych opisach, przygotowałem gotowy, działający, przykładowy program keyb.c i prosty skrypt do jego skompilowania ck

No to teraz jak to działa.
Definiujemy, do których pinów GPIO podłączyliśmy wyprowadzenia wierszy i kolumn klawiatury:


#define IN1 26
#define IN2 27
#define IN3 28
#define IN4 29

#define OU1 22
#define OU2 23
#define OU3 24
#define OU4 25


void Delay();
W tej zmiennej zapamiętamy ostatnio naciśnięty i jeszcze nie puszczony klawisz - nie chcemy przecież po jednym naciśnięciu klawisza tysięcy odczytów!
int last;
No i główna procedura:
int main (void)
{
  int k;

  if (wiringPiSetup () == -1)
  exit (1) ;
Piny GPIO podłączone do wierszy klawiatury programujemy na wyjście i ustawiamy na nich zero logiczne:
    pinMode(IN1, OUTPUT);
    digitalWrite (IN1, 0);
    pinMode(IN2, OUTPUT);
    digitalWrite (IN2, 0);
    pinMode(IN3, OUTPUT);
    digitalWrite (IN3, 0);
    pinMode(IN4, OUTPUT);
    digitalWrite (IN4, 0);
Piny kolumn ustawiamy na wejście i wbudowanym rezystorem przywieramy je do masy:
    pinMode(OU1, INPUT);
    pullUpDnControl (OU1, PUD_DOWN) ;
    pinMode(OU2, INPUT);
    pullUpDnControl (OU2, PUD_DOWN) ;
    pinMode(OU3, INPUT);
    pullUpDnControl (OU3, PUD_DOWN) ;
    pinMode(OU4, INPUT);
    pullUpDnControl (OU4, PUD_DOWN) ;
Teraz w nie kończącej się petli czytamy klawiaturę wyświetlając jaki klawisz naciśnięto:
  for(;;)
 {
   if (k=read_key() ) printf("%c", k);
 }
}
Sam odczyt klawiszy wykonuje funkcja read_key którą opiszemy dalej.
No to teraz właściwe czytanie klawiatury.
int read_key()
{
  int kod=0;
Na linii pierwszego wiersza ustawiamy logiczna jedynkę i czekamy 5 mikrosekund, żeby ten sygnał na pewno fizycznie się pojawił i był stabilny:
 
  digitalWrite (IN1, 1);
  Delay(5);
Teraz sprawdzamy, czy na którejś linii kolumn pojawiła się jedynka logiczna. Jeśli tak, to znaczy że naciśnięto klawisz zwierający pierwszy wiersz z testowaną kolumną, w zmiennej kod zapisujemy kod ASCII naciśniętego klawisza.
 
  if (digitalRead(OU1)==1) {kod=0x44;}
  if (digitalRead(OU2)==1) {kod=0x23;}
  if (digitalRead(OU3)==1) {kod=0x30;}
  if (digitalRead(OU4)==1) {kod=0x2A;}
  digitalWrite (IN1, 0);
Ustawiamy na testowanej linii zero logiczne i powtarzamy sprawdzanie dla kolejnych linii wierszy klawiatury.
  digitalWrite (IN2, 1);
  Delay(5);
  if (digitalRead(OU1)==1) {kod=0x43;}
  if (digitalRead(OU2)==1) {kod=0x39;}
  if (digitalRead(OU3)==1) {kod=0x38;}
  if (digitalRead(OU4)==1) {kod=0x37;}
  digitalWrite (IN2, 0);

  digitalWrite (IN3, 1);
  Delay(5);
  if (digitalRead(OU1)==1) {kod=0x42;}
  if (digitalRead(OU2)==1) {kod=0x36;}
  if (digitalRead(OU3)==1) {kod=0x35;}
  if (digitalRead(OU4)==1) {kod=0x34;}
  digitalWrite (IN3, 0);

  digitalWrite (IN4, 1);
  Delay(5);
  if (digitalRead(OU1)==1) {kod=0x41;}
  if (digitalRead(OU2)==1) {kod=0x33;}
  if (digitalRead(OU3)==1) {kod=0x32;}
  if (digitalRead(OU4)==1) {kod=0x31;}
  digitalWrite (IN4, 0);
No i prawie gotowe. W zmiennej kod mamy kod ASCII naciśniętego klawisza. Teraz juz tylko sprawdzenie czy przypadkiem tego klawisza juz poprzednio nie odczytaliśmy:
  if (kod != last)
Jeśli to pierwsze wykrycie naciśnięcia tego klawisza, zapamiętujemy ten fakt w zmiennej last i zwracamy kod ASCII:
   {
    last = kod;
    return kod ;
   }
  else
W przeciwnym wypadku (nie naciśnięto żadnego klawisza lub naciśnięty jest jeszcze poprzednio zapisany), zwracamy wartość 0:
   {
    return 0;
   }
}
No i procedura opóźnienia, niewrażliwa na przerwania (nie używamy ich w tym programie, ale mogą zostac użyte w jakimś innym), opisana już przy okazji opisu czujnika HC-SR04
void Delay(int microsec)
{
 struct timespec tim;
 tim.tv_sec = 0;
 tim.tv_nsec = microsec * 1000;
     while(nanosleep(&tim,&tim)==-1)
          continue;
}