Dodatki‎ > ‎

Przyciski

Wydawać by się mogło, że prostszego urządzenia peryferyjnego niż przycisk nie ma. Nie bardziej mylnego! Są oczywiście lepsze i gorsze przyciski, większość z nich niestety ma w środku element sprężysty (blaszkę, membranę, sprężynkę, ...). A jak to z elementami sprężystymi bywa - lubią sprężynować, czyli wpadać w drgania.
Te drgania trwają zwykle ułamek sekundy - na tyle krótko, że nie zaobserwujemy ich gołym okiem. Kiedy przełączane są większe prądy (urządzenia większej mocy), objawia się to iskrzeniem styków i ich stopniowym zużywaniem.
W przypadku przełączania małych prądów (a tak jest w przyciskach podłączanych do mikrokontrolera) iskrzenia co prawda nie widać, ale pozostaje problem drgań styków.
Można to częściowo wyeliminować stosując dodatkowo elementy RC (jako układ tzw. debouncera). Zainteresowani mogą zajrzeć na stronę  http://www.labbookpages.co.uk/electronics/debounce.html .
Jest tam przedstawiona istota problemu i kilka propozycji rozwiązań, zarówno sprzętowych, jak i programowych.

Jak zaobserwować to zjawisko?

Najprościej byłoby powiązać przycisk z przerwaniem (tzn. każdorazowe wciśnięcie lub zwolnienie przycisku będzie wywoływało ISR - funkcję obsługi tego przerwania). W ciele funkcji można inkrementować licznik i jego bieżący stan przykładowo wyświetlać na dostępnych kilku LEDach.
Da się wtedy zauważyć, że pojedyncze wciśnięcie guzika może zwiększyć wartość licznik o więcej niż 1.

Warto pamiętać o tym potencjalnym źródle problemów w waszych eksperymentalnych zestawach uruchomieniowych.

Przykład oprogramowania przycisku SW1 

(dla SW2 będzie analogicznie).

Funkcja sw1_pressed() zwraca 1 (prawda), jeśli przycisk został wciśnięty na przynajmniej 10 ms i zwolniony. Funkcja ta czeka na zwolnienie wciśniętego przycisku. Jeśli przycisk nie został wciśnięty, natychmiast zwracana jest wartość 0 (fałsz).

bool sw1_pressed() {
    if(sw1_GetVal()==0) { //wciśnięcie przycisku zwiera pin uC do masy (pojawia się stan logiczny 0)
        Cpu_Delay100US(100); //czekamy 10 ms na stabilizację styków
        if(sw1_GetVal()!=0) //jeśli po 10 ms nie jest wciśnięty...
            return 0; //... to kończymy zabawę (może to były zakłócenia na linii?)
        while(sw1_GetVal()==0){ } //użytkownik nadal dusi przycisk. Czekamy, aż przestanie...
        return 1; //...po czym zwracamy 'TRUE' 
    }
    return 0; //nic nie było, zwracamy 'FALSE'
}

byte cnt = 0; //licznik wciśnięć przycisku SW1
//gdzieś w funkcji main()
for(;;) { 
    if(sw1_pressed()) {
        cnt++;
        leds_PutVal(cnt); //wyświetlamy wartość licznika na czerwonych diodach
    }
}

ą
sw1.png
(6k)
Krzysztof Urbański,
19 lut 2012, 13:49
Comments