Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

prowadzanie liczb 2-wu cyfrowych z klawiatury matrycowej

12 Wrz 2005 08:38 1667 8
  • Poziom 10  
    Witam.
    Nie mogę sobie poradziź z wprowadzaniem liczb dwucyfrowych z klawiatury matrycowej.
    Moja klawiatura jest obsługiwana z wykorzystaniem przerwania od Timera0.
    Jeśli możecie to prosze o pomoc i propozycje rozwiązania tego problemu.
    Poniżej zamieszczam część mojego kodu programu
    Code:

    .......
    [wyciety fragment]
    .......

    Do       'pętla nieskończona DO ... LOOP
       Cls
       Upperline
       Lcd Przycisk
       Lowerline
          Select Case Przycisk:

             Case 30:       '1
                Lcd "P1"
                   Cz = 1
                   X1 = 1
                   Gosub Zmierz_u

             Case 46:       '2
                Lcd "P2"
                   Cz = 2
                   X1 = 9
                   Gosub Zmierz_u

             Case 78:       '3
                Lcd "P3"
                   Cz = 3
                   X2 = 1
                   Gosub Zmierz_u

             Case 29:       '4
                Lcd "P4"
                   Cz = 4
                   X2 = 9
                   Gosub Zmierz_u

             Case 45:       '5
                Lcd "P5"
                   Cz = 5
                   X3 = 1
                   Gosub Zmierz_u

             Case 77:       '6
                Lcd "P6"
                   Cz = 6
                   X3 = 9
                   Gosub Zmierz_u

             Case 27:       '7
                Lcd "P7"
                   Cz = 7
                   X4 = 1
                   Gosub Zmierz_u

             Case 43:       '8
                Lcd "P8"
                   Cz = 8
                   X4 = 9
                   Gosub Zmierz_u

             Case 75:       '9
                Lcd "P9"
                   Cz = 9
                   X5 = 1
                   Gosub Zmierz_u

             Case 23:       '*
                Lcd "P*"
                   Gosub L_czujnik

             Case 39:       '0
                Lcd "P0"
                   Gosub Autor

             Case 71:       '#
                Lcd "<<"


          End Select

       Waitms 100       'czekaj 0,1 s
    Loop
    End

    '        ###################################################
    '        ############ P O D P R O G R A M Y ################
    '        ###################################################

    '_____________________________________________________________________________
    '
    'PROCEDURA OBSLUGI PRZERWANIA, W KTORYM OBSLUGIWANA JEST KLAWIATURA MATRYCOWA
    '_____________________________________________________________________________

    Mult_kl:

    Load Timer0 , 200       'wpisanie do licznika wart poczatkowej 56

    'zmienna I okresla nam numer kolumny
       For I = 1 To 3       'petla wykonywana 3 razy /przeszukuje po kolumnach I

          If I = 1 Then       'jesli I=1 czyli kolumna 1
             Set Ddrd.4       'zeruj linie KOL1
             Reset Ddrd.5       'ustaw linie kolumny 2
             Reset Ddrd.6       ' i 3
          End If

          If I = 2 Then       'jesli I=2 czyli kolumna 2
             Reset Ddrd.4       'zeruj linie KOL1
             Set Ddrd.5       'ustaw linie kolumny 2
             Reset Ddrd.6       ' i 3
          End If

          If I = 3 Then       'jesli I=3 czyli kolumna 3
             Reset Ddrd.4       'zeruj linie KOL1
             Reset Ddrd.5       'ustaw linie kolumny 2
             Set Ddrd.6       ' i 3
          End If

          'jesli wcisniety przycisk z wiersza 1,2,3 lub 4 czyli
          'jesli przy I=1, I=2 lub I=3 wejscia W1 lub W2 lub W3 lub W4
          'maja stany niskie (0) -> zostal nacisniety przyc., wtedy...

          If W1 = 0 Or W2 = 0 Or W3 = 0 Or W4 = 0 Then       'jesli nacisniety
                                                             'to wykonaj
             Temp1 = Pind And &B00001111
             'zapisanie do zmiennej TEMP1 wartosci czterech najmniej znaczaczych
             'bitow rejestru PIND linie W1, W2, W3, W4
             ' W1 = 14 ; W2 = 13 ; W3 = 11 ; W4 = 7

                Exit For       ' wyjscie z petli FOT ... NEXT

             Else       'w przeciwnym razie
               Temp1 = 0       'wyzerowanie zmiennej TEMP1
             End If

          Next I       'zwiekszenie o 1 wartosci I

          If Temp2 = Temp1 Then
             Przycisk = Temp1

                If I = 1 Then
                   Przycisk = Przycisk + Ddrd
                End If
                If I = 2 Then
                   Przycisk = Przycisk + Ddrd
                End If
                If I = 3 Then
                   Przycisk = Przycisk + Ddrd
                End If

    '============================================
    ' jesli bedzie wcisniety drugi klawisz

          Else
             Temp2 = Temp1
          End If

    '      Set Kol1       'przypiasnie lini KOL1 wartosci 1
    '      Set Kol2       'przypisanie lini KOL2 wartosci 1
    '      Set Kol3       'przypisanie lini KOL3 wartosci 1
    Return

    '_____________________________________________________________________________
    '
    'PROCEDURA OBSLUGI CZUJNIKOW TEMPERATURY = UNIWERSALNA =
    '_____________________________________________________________________________

    Zmierz_u:
    Do
      1wreset       'reset - pierwszy cykl rozkazowy
      1wwrite &H55       'polecenie MATCH ROM, bo więcej kostek

      Select Case Cz:

          Case 1 To 2:
             1wwrite Adr1(x1) , 8       ' adres jednej z kostek
          Case 3 To 4:
             1wwrite Adr2(x2) , 8       ' adres jednej z kostek
          Case 5 To 6:
             1wwrite Adr3(x3) , 8       ' adres jednej z kostek
          Case 7 To 8:
             1wwrite Adr4(x4) , 8       ' adres jednej z kostek
          Case 9 To 10:
             1wwrite Adr5(x5) , 8       ' adres jednej z kostek
          Case 11 To 12:
             1wwrite Adr6(x6) , 8       ' adres jednej z kostek
          Case 13 To 14:
             1wwrite Adr7(x7) , 8       ' adres jednej z kostek
          Case 15 To 16:
             1wwrite Adr8(x8) , 8       ' adres jednej z kostek
          Case 17 To 18:
             1wwrite Adr9(x9) , 8       ' adres jednej z kostek
          Case 19 To 20:
             1wwrite Adr10(x10) , 8       ' adres jednej z kostek

      End Select

      1wwrite &H44       'polecenie - dokonaj konwersji
        Waitms 750       'czas konwersji
      1wreset       'reset - drugi cykl rozkazowy
      1wwrite &H55       'polecenie MATCH ROM, bo więcej kostek

      Select Case Cz:

          Case 1 To 2:
             1wwrite Adr1(x1) , 8       ' adres jednej z kostek
          Case 3 To 4:
             1wwrite Adr2(x2) , 8       ' adres jednej z kostek
          Case 5 To 6:
             1wwrite Adr3(x3) , 8       ' adres jednej z kostek
          Case 7 To 8:
             1wwrite Adr4(x4) , 8       ' adres jednej z kostek
          Case 9 To 10:
             1wwrite Adr5(x5) , 8       ' adres jednej z kostek
          Case 11 To 12:
             1wwrite Adr6(x6) , 8       ' adres jednej z kostek
          Case 13 To 14:
             1wwrite Adr7(x7) , 8       ' adres jednej z kostek
          Case 15 To 16:
             1wwrite Adr8(x8) , 8       ' adres jednej z kostek
          Case 17 To 18:
             1wwrite Adr9(x9) , 8       ' adres jednej z kostek
          Case 19 To 20:
             1wwrite Adr10(x10) , 8       ' adres jednej z kostek

      End Select

      1wwrite &HBE       'polecenie odczytu DS18x20
      T = 1wread(2)       'od razu wpisz do zmiennej typu Integer
       Shift T , Right , 3       'odpowiednik dzielenia przez 8
       If T.12 = 1 Then       'jeśli temperatura ujemna
         T = T Or &B1110000000000000       'uzupełnij jedynki znaku
       End If
       T1 = T       'przepisz wynik do zmiennej Single
       Shift T1 , Right , 1       'SHIFT działa na zmiennej Single
       Cls
       Upperline
       Lcd "T" ; Cz ; "=" ; T1 ; Chr(0) ; "C"       'wyświetl  T0, T1

    'wyjscie z petli DO ... LOOP po nacisnieciu przyc. #
    Loop Until Przycisk = 71
    Return       'koniec
  • Poziom 19  
    Hmm, szczerze mowiac, ten program jest bardzo zagmatwany. Nie widze, gdzie jest przechowywany cala liczba wprowadzona z klawiatuy, ani w jakim formacie.

    Byc moze rozryzowanie sobie automatu na kartce pomoze rozwiazac taki problem.

    Ja proponuje cos typu:
    1) zmienna wskazujaca na obecna cyfre do wrpowadzania. - od razu flaga gotowosci
    2) tablica dwuelementowa na przechowywanie danych.

    Zakladajac, ze mamy fkcje zwracajaca po prostu numer klawisza, robimy cos takeigo: Wazne, by fkcja zwracala nam ten konkretny klawisz dopiero gdy zwolnimy przycisk. Wtedy bedziemy pewni, ze nei nacisnieto czegos tylko raz, a zostalo to wczytane razy dwa.

    1. czekamyna klawisz
    2. sprawdzamy - na przyklad # na kasowanie
    3. zwiekszamy licznik wcisniec
    4. zapisujemy dane
    5. czekamy na 2 klawisz
    6. sprawdzamy -||-
    7. zwiekszamy licznik
    8. zapisujemy dane
    9. zwiekszamy licznik

    GLowny program czeka az licznik bedzie rowny 2.

    Jesli nie chcesz zapisywac danych w tablicy dwuelementowej, to mozesz zrobic cos takeigo:

    x=czytaj_klaiwsz();
    x=x*10+czytaj_klawisz();
  • Poziom 27  
    Ja robiłem to w asemblerze w następujący sposób:
    Code:

    mov B,#0Ah    ;wpisujemy 10 do B
    mul AB            ;mnozymy A razy 10
    add A,<cyfra> ;dodajemy wczytana cyfre do A

    I generlanie działa to tak, jak wpisujemy liczbę dziesiętną, czyli wpisujemy cyfrę i przesuwamy o jedną pozycję dziesiętna w lewo (co odpowiada mnożeniu przez 10) i dodajemy następną cyfrę itd. Oczywiście dochodzi tutaj problem przekroczenia zakresu zmiennej 8-mio bitowej, ale można i z tym sobie poradzić.
  • Poziom 10  
    Główną procedują odczytu klawisza klawiatury jest podprogram Mult_kl
    Opis jej działania :
    W pierwszej pętli For.... NEXT I program przeszukuje po kolumnach klawiatury (3 kolumny klawiszy a 4 wiersze w klawiaturze).
    Jeśli program wykryje naciśnięty klawisz to ustawia odpowiednie rejestry DDRD. Następnie sprawda czy został nacisniety jakis klawisz
    Code:

    If W1 = 0 Or W2 = 0 Or W3 = 0 Or W4 = 0 Then       'jesli nacisniety
                                                                                 'to wykonaj
         Temp1 = Pind And &B00001111


    na podstawie 4 najmniej znaczacych bitow rozpoznaję czy jest wcisniety klawisz i zapisuję go do Temp1.

    Później zapisuje kod nacisnietego klawisza do zmiennej Przycisk
  • Poziom 19  
    Jak na moje oko, fkcja skanowania klawiatury powinna zrzucac tylko wartosc wcisnietego klawisza. Nie bawic sie juz z tym, ktory to klawisz. Poza tym - nie widze tu dla niej - co prawda nei znam bascoma ale kod jest przeciez czytelny - nie widze, by zwracala kiedykolwiek wartosc 0, czyli nic nie jest wcisniete.

    Nie znam tez fkcji zmiennej Temp2 - nie jest nigdzie inicjowana, nie wiem co zawiera.

    Moim zdaniem, wrzucanie mechanizmu wczytywania calej liczby do procki obslugujacej fizyczna klawiature jest zlym rozwiazaniem.
  • Poziom 26  
    ogólnie ja to widze ta że jak chcesz wprowadzać liczby 2-cyfrowe to musisz zrobić jedno założenie:

    albo wszystkie liczby będą 2-cyfrowe i jak chcesz wprowadzić liczbę do 0-9 to przedtem nadusić 0

    albo jeden z klawiszy będzie działał jako enter i to on będzie zatwierdzał liczbę

    jak odpowiesz na to pytanie to będe mógł ci pomóc.

    chciałem też dodać że procedura pobierania klawisza jest ładnie mówiąć dziwna :(
  • Poziom 19  
    Nie musi byc potwierdzenia. Niech tylko bedzie zalozenie, ze liczby sa zawsze dwucyfrowe, z poprzedzajacym zerem jak trzeba. A dodac do tego kasowanie na przyklad #, albo i ten enter *.
  • Poziom 26  
    wymyśliłem coś takiego ale nie testowane i niewiem czy działa ja niebędzie działać to powiedz jakie są objawy to ci coś pomoge.

    Code:
    dim liczba as byte
    
    dim wynik as byte
    dim tmp as byte
    tmp=0
    dim Przycisk as byte
    dim Przycisk2 as byte


    Mult_kl:

    'zapamiętuje wciśnięty klawisz i wpisuje 255 (jeśli nic nie jest wduszone to wartość ta zostanie)
    Przycisk2=Przycisk
    Przycisk=255

    set ddrd.4
    reset ddrd.5
    reset ddrd.6
    if pind.0=0 then Przycisk=1
    if pind.1=0 then Przycisk=4
    if pind.2=0 then Przycisk=7
    if pind.3=0 then Przycisk=128

    reset ddrd.4
    set ddrd.5
    reset ddrd.6
    if pind.0=0 then Przycisk=2
    if pind.1=0 then Przycisk=5
    if pind.2=0 then Przycisk=8
    if pind.3=0 then Przycisk=0

    reset ddrd.4
    reset ddrd.5
    set ddrd.6
    if pind.0=0 then Przycisk=3
    if pind.1=0 then Przycisk=6
    if pind.2=0 then Przycisk=9
    if pind.3=0 then Przycisk=64


    'czeka na puszczenie klawisza
    if przycisk=255 then
    if tmp=0 then
    'wprowadza pierwszą cyfre
            wynik=0
            tmp=1
            liczba=Przycisk2 * 10
    else
    'wprowadza drógą cyfre
            wynik=liczba + Przycisk2
            tmp=0
    end if
    end if

    return


    wynik tego będziesz miał w zmiennej "wynik"
  • Poziom 10  
    Póki co to nie mam na czym sprawdzić, ale sprawdzę ten programik w przyszłym tygodniu i dam wam znać jak to wszystko działa.


    hunterhouse dzięki za źródło


    Tymczasem, założenia programu są takie aby wprowadzać liczbę dwucyfrową poprzez wciśnięcia klawisza '*' i wtedy program czeka na dwa klawisze numeryczne. Po wprowadzeniu dwóch cyfr zatwierdzamy go klawiszem entera czyli '#'.