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

[C dowolny procesor - preferowany ARM]Algorytm przycisku

bua 07 Wrz 2008 14:45 1906 2
  • #1 07 Wrz 2008 14:45
    bua
    Poziom 12  

    Witam.
    Chcialbym osiagnac taki efektek:

    dopuki nie zostal puszczony przycisk nie uwzgledniaj ze zostal wcisniety ponownie...

    prostrzymi slowami, nie chce takiego efektu jaki wystepuje na klawiaturze PC tzn. jezeli przycisniemy jakis znak np. "c" i go przytrzymamy w edytorze tekstowym bedzie on wypelnial kolejne liniki dopuki go nie zwolnimy...

    Moj algorytm wyglada nastepujaco(teoretynie powinien dzialac ale nie dziala):

    Code:
    while(1)
    
    {
            if(checkButton(1<<6, 0x3fc)) zrobCos();
            checkRelease(1<<6, 0x3fc);
    //1<<6 to nr. przycisku do sprawdzenia
    //0x3fc to mapa dla portu PIN (czyli ktore piny sprawdzac)

    }


    ponizszy kod ma ustawic przycisk na 1 w zmiennej PUSH_RELEASE
    gdy przycisk nie jest wcisniety( a jest wcisniety gdy PIN & button == 0 )
    Code:
    u32 PUSH_RELEASE = 0xffffffff;
    
    void checkRelease(u32 button, u32 PIN)
    {
        if(PIN & button)
            PUSH_RELEASE &= ~button;
        else
            PUSH_RELEASE |= button;
    };


    Code:
    int checkButton(u32 button, u32 gpio)
    
    {
         u32 val = GPIO3->DR[gpio]; /// odczytuje stan rejesru PIN
             if((val & button)|(PUSH_RELEASE&button)) {return 0;} else
             {
                 PUSH_RELEASE |= button;
                 return 1;
             }
    };


    Powyzej pominolem drgania stykow zeby nie zaciemniac kodu.
    w tej funkcji chodzi o to ze:

    (val & button) == 1 to guzik puszczony
    (val & button) == 0 to guzik wcisniety

    potem
    | (PUSH_RELEASE&button) ma dzialac tak ze
    jesli PUSH_RELEASE dla tego guzika jest 1 to cala funkcja (checkButton) ma zwrocic 0 jesli PUSH_RELEASE jest 0 to funckja ma zwrocic 1 i ustawic PUSH_RELEASE dla tego guzika na 1.

    mimo tego ze wydaje sie byc wszystko w porzadku cos tu nie dzaiala,
    i wcisniety guzik caly czas zwraca 1 dla funkcji (checkButton).

    prosze o rade.

    0 2
  • #2 07 Wrz 2008 14:51
    Freddie Chopin
    Specjalista - Mikrokontrolery

    masz tutaj moj kod, ktory robi dokladnie to co chcesz... ogolnie sprawa jest prostsza niz sie moze wydawac [;

    przyciski sprawdzane sa w przerwaniu timer'a

    Code:

    /*
    +———————————————————————————————————————————————————————————————————————————————+
    | Timer 8 match (_T8Interrupt)
    |
    | scanning of buttons and debouncing.
    +———————————————————————————————————————————————————————————————————————————————+
    */

    void __attribute__ ((interrupt,no_auto_psv)) _T8Interrupt(void)
    {
       u16_t port;
       static u16_t port_last=0;
       
       port=BUTT_PORT&BUTT_MASK;      // read only the inputs connected to buttons

       io_butts=port_last&(~port);            // button is flagged after release
          
       port_last=port;                     // store for next cycle
       
       _T8IF=0;                        // acknowledge the interrupt
    }


    io_butts to zmienna globalna, wskazujaca ktory przycisk byl nacisniety i puszczony (oczywiscie dopiero po puszczeniu). PORT_MASK to maska bitowa, bo na porcie sa jeszcze inne rzeczy, ktore mnie nie interesuja.

    kluczem jest ta linijka:

    io_butts=port_last&(~port);

    u mnie przycisk nacisniety to 1, zwolniony to 0 (zastosowane sa pulldowny). hipotetyczna sytuacja:
    cztery przyciski puszczone: 0000
    wciskamy jeden i trzymamy: 0010
    w pierwszym cyklu bedzie zmiana, ale poniewaz jest to zmiana w nie-interesujacym kierunku, nie bedzie ona uwzgledniona: port_last=0000, port=0010, tak wiec port_last&(~port) = 0000 & 1101 = 0000
    w kolejnych cyklach sytuacja podobna: port_last=0010, port=0010, wiec port_last&(~port)=0010&1101 = 0

    zwalniamy przycisk, wiec 0000
    w tym momencie nastepny cykl odswiezania wykona sie z takimi parametrami: port_last=0010, port=0000; dzieki temu port_last&(~port)=0010&1111=0010 i wlasnie o to chodzilo [;

    4\/3!!

    0
  • #3 07 Wrz 2008 16:10
    bua
    Poziom 12  

    Dzieki za odpowiedz.
    Udalo mi sie to jedank wlasnie uruchomic w duzo prostrzy sposob...
    mianowicie,
    mam globala ktory trzyma wartosci dla kazdego pinu, czy przycisk jest wcisniety czy nie,
    wartosci te sa ustawiane w momencie gdy jest sprawdzany stan przycisku, i jesli ostatnia wartoscia z "globala" bylo ze jest wcisniety,
    to zwraca ze przycisk nie zostal wcisniety...jesli w koncu zostanie zwolniony to w funcji gdzie sprawdza stan przycisku global jest czyszczony.

    pzsr

    0