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.

Atmega32 C - klawiatura matrycowa 4x4 na przerwaniach

16 Wrz 2012 17:48 4239 16
  • Poziom 28  
    Mam problemy z klawiaturą matrycową którą właśnie robię na przerwaniach na podstawie tego schematu: http://www.btc.pl/pdf/zl3avr.pdf (Strona 2). Napisałem taki kod:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    I problem jest taki jak przytrzymamy klawisz to diodki powinny migać i tak się nie dzieje po prostu wtedy na diodach wyświetlany jest aktualny klawisz za to jak puścimy klawisz na diodach powinien być wyświetlany ostatni wciśnięty klawisz to wtedy się już nic nie świeci.
  • Poziom 38  
    Nie no to jakas sieczka jest

    delay ms(20) w przerwaniu? ta obsługa to chyba długa praca typu aby działało.

    Obsługę takiej klawiatury najlepiej zrobić w przerwaniu jakiego timera, np co 50ms.

    2 kolejne równe odczyty równoznaczne z wciśniętym klawiszem.
    Zadem problem dorobić opcje dla długiego przytrzymania klawisza. n kolejnych równych odczytów.

    A reszta to program główny i jedna zmienna volatile oznaczająca kod klawisza.
    kod = 0xff np to brak wciśniętego klawisza.
  • Poziom 28  
    Czyli zamiast robić na przerwaniu INT0 zrobić na timerze? Ale wtedy schemat by pozostał taki sam bo co wtedy zrobić z sygnałem z klawiatury do INT0? A kod do odczytu aktualnego klawisza jest w porządku?
  • Poziom 38  
    Czy w porządku nie wiem, nie analizuje go. Martwią mnie opóźnienia, ilość pętli for.
    Odczyt można zrobić bez pętli w ogóle w 2 krokach a potem tylko zdekodować klawisz. A przerwanie? cóż styk drga !!. można tą linie wykorzystać, ale jej przydatność jest znikoma kosztem jednego wolnego pinu procka.
  • Moderator Mikrokontrolery Projektowanie
    mi14chal napisał:
    Czyli zamiast robić na przerwaniu INT0 zrobić na timerze?

    Nie. Jeżeli chcesz to pozostaw przerwanie INT0, ale w funkcji obsługi przerwania ustawiaj jedynie flagę, a w main() umieść resztę kodu wraz z opóźnieniami i pętlami, czyli gdy flaga zostanie wykryta w main() to wołaj swoją funkcję checkKeyboard().

    I staraj się zawsze stosować zasadę, że przerwanie musi wykonywać się krótko.
  • Poziom 28  
    dondu napisał:
    ale w funkcji obsługi przerwania ustawiaj jedynie flagę, a w main() umieść resztę kodu


    Czyli rozumiem że najlepszą praktyką jest ustawianie w flagi w procedurze przerwania a resztę wykonywać w main? I tak robić dla każdego rodzaju przerwania?
  • Moderator Mikrokontrolery Projektowanie
    mi14chal napisał:
    Czyli rozumiem że najlepszą praktyką jest ustawianie w flagi w procedurze przerwania a resztę wykonywać w main?

    W Twoim przypadku na pewno.

    mi14chal napisał:
    I tak robić dla każdego rodzaju przerwania?

    Nie, tylko tam gdzie masz kod, który wykonuje się sporo czasu.
    Co znaczy "sporo czasu"? A to już zależy, od przypadku :)

    Innymi słowy chodzi o to, by nie utracić tych samych przerwań z powodu zbyt długiego wykonywania się aktualnie obsługiwanego przerwania, bo flaga przerwania np. INT0 nie jest licznikiem.
  • Użytkownik usunął konto  
  • Poziom 28  
    Tak więc przerobiłem kod tak jak mówiliście i wygląda teraz tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Ale dalej jest problem że jak przycisk jest przyciśnięty to diody nie migają z aktualnym wciśniętym klawiszem tylko jest wyświetlany ostatni przyciśnięty przycisk dopiero jak zwolnię przycisk na diodach jest wyświetlany ostatni przycisk. Ale przykładowo jeżeli funkcję checkKeyboard() zamienię na taką:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    To wtedy kod na migania diod działa. Ale jak dodam do tego kodu jakąkolwiek instrukcję ze zmianą DDRB albo PORTB to wtedy już nie działa miganie diod i dzieje się tak jak wyżej opisałem. Sprawdzałem również na innej Atmedze i jest tak samo, tak więc nie rozumiem co mają zmiany na DDRB i PORTB do nie działania migania diod.


    Bo co ciekawe jak użyje przykładu wykorzystania klawiatury z tej książki http://www.btc.pl/index.php?ukey=product&productID=16758 można zobaczyć jak wygląda kod który jest w asmie i jak go zmodyfikuje żeby diody migały to wtedy działa a ja bym też chciał żeby to w c działało. Jakieś pomysły czemu w c to nie chce działać a w asmie już tak?
  • Poziom 28  
    tadzik85 napisał:
    Odczyt można zrobić bez pętli w ogóle w 2 krokach a potem tylko zdekodować klawisz.


    No to może pokażesz jak to zrobić bo chciałbym to zobaczyć skoro z moim sposobem są problemy.
  • Poziom 38  
    pseudo kod

    Kod: c
    Zaloguj się, aby zobaczyć kod


    przerwanie od timera

    Kod: c
    Zaloguj się, aby zobaczyć kod


    klawisz musi byc typu volatile
  • Poziom 28  
    tadzik85 napisał:
    key= troszke logiczny operacji (logika ujemna)


    No tylko jakich konkretnie operacji logicznych trzeba użyć? Bo już próbuje i nie mogę znaleźć poprawnego rozwiązania.
  • Poziom 38  
    O dziwo zwykły OR wystarczy.
  • Poziom 28  
    Niestety nie wystarczy.
  • Poziom 38  
    Czego ty jeszcze tu nie rozumiesz hm?
  • Poziom 28  
    Podam przykład dla wiersza pierwszego odczyt wiersza wynosi 0001 i kolumna czwarta 1000 jak teraz da się OR to uzyskamy wynik 1001 czyli 9 i ten sam wynik również uzyskamy gdy będzie wiersz czwarty i kolumna pierwsza. Jest jeszcze kilka taki przypadków kiedy wynik będzie ten sam.
  • Poziom 38  
    złe myślenie.

    1 odczyt wierszy - portu dla jednego przycisku aktywowanego da 0b11101111
    2 odczyt kolumn da 0b11111101

    or da 0b11101101

    teraz w programie głównym sprawdzić czy są 2 zera jeśli tak
    zdekoduj klawisz. nr bitu = 0 w górnej połowie wyniku *4 + nr bitu =0 w dolnej połowie bajtu

    lub za pomocą pętli

    key=0
    for(kolumna 1 = 0 , kolumna <4, kolumna ++)
    {
    key += 4
    if(w1=0)
    key+1;
    ......
    }