logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[C]Obsługa przycisków w stoperze

okmijn 11 Lut 2009 12:00 2556 10
REKLAMA
  • #1 6133710
    okmijn
    Poziom 2  
    Witam.

    Mam na zajęcia zrealizować program stopera w programie AVR Studio... I mam problem z obsłużeniem 2 przycisków które nim sterują...

    Pierwszy przycisk SW_1 ma resetować stoper
    Drugi przycisk SW_2 ma go zatrzymywać (po pierwszym naciśnięciu) i startować dalej (po drugim naciśnięciu) i tak w kółko...

    Napisałem obsługę do przycisku SW_1 (w sposób pewnie toporny niektórzy uznają - ale działa )

    Na natomiast nie potrafię zapisać obsługi drugiego przycisku SW_2

    Zrobiłem w sumie zatrzymywanie czasu ale chyba nie tak to powinno wyglądać...




    MÓGŁBY MI KTOŚ POMÓC BO SAM NIE DAM RADY ....


    Oto kod programu głównego :

    
    
    #include <avr\io.h>                 // dostęp do rejestrów
    #include <inttypes.h>                // definicje typów uint8...
    #include <avr\signal.h>                 // definicje SIGNAL, INTERRUPT
    #include <avr\interrupt.h>         // funkcje sei(), cli()
    
    
    #include "makra.h"
    #include "harddef.h"
    #include "czas.h"
    
    #define T0_INIT (256-15)
    #define T1_INIT (65536-5000)
    
    uint8_t bufor;
    
    
    int main(void)
    {
            // Konfiguracja portów I/O
        DDR(LED) = 0xff;
        DDR(SEG) = 1<<SEG_1 | 1<<SEG_2 | 1<<SEG_3 | 1<<SEG_4;
        DDR(SW) &= ~(1<<SW_1 | 1<<SW_2);
    
    
        TCCR0 = 1<<CS02;
        TIMSK = 1<<TOIE0 | 1 << TOIE1;
    
        TCNT0 = T0_INIT;                     
        TCNT1 = T1_INIT;
               
        // ustawienie trybów pracy liczników     
        TCCR1A = 0x00;                       
        TCCR1B |= (1<<CS11);               
    
    
    
        // globalne odblokowanie przerwań
       
        sei();           
    
    
        // nieskończona pętla
        for(;;)
    
        reset();
       
        return 0;
    
    }
    
    
    // procedury obslugi przerwania
    
    SIGNAL(SIG_OVERFLOW0)   
    {
       
        pokaz_czas();
        TCNT0=T0_INIT;
    }
    
    
    SIGNAL (SIG_OVERFLOW1)
    {   
        akt_czas();
        TCNT1 = T1_INIT;
    }
    
    



    A to program do obsługi czasu:

    
    #include "czas.h"
    #include "harddef.h"
    #include "makra.h"
    #include "znaki.h"
    #include <avr/delay.h>  // funkcje opóźniające
    
    
    
    uint8_t jednostki_msekund =  0,    dziesiatki_msekund = 0,
            jednostki_sekund = 0,      dziesiatki_sekund = 0;
    
    int r,t1,t2,t3,t4;
    
    r=1;
    
    
    void akt_czas(void){
    (r==0){
    
    
    
    jednostki_msekund++;             // zwiększ licznik jednostek milisekund o 1
    if(jednostki_msekund == 10)         // jeśli licznik jednostek milisekund osiągnął wartość 10 to
      {       
      jednostki_msekund = 0;         // wyzeruj licznik jednostek milisekund
      dziesiatki_msekund++;         // zwiększ licznik dziesiątek milisekund o 1
      if(dziesiatki_msekund == 10)         // jeśli licznik dziesiątek milisekund osiągnął wartość 10 to
        {
        dziesiatki_msekund = 0;         // wyzeruj licznik dziesiątek milisekund
        jednostki_sekund++;         // zwiększ licznik dziesiątek sekund o 1
        if(jednostki_sekund == 10)         // jeśli licznik jednostek sekund osiągnął wartość 10 to
          {
          jednostki_sekund = 0;         // wyzeruj licznik jednostek sekund
          dziesiatki_sekund++;         // zwiększ licznik dziesiątek sekund o 1
          if(dziesiatki_sekund == 10)     // jeśli licznik dziesiątek sekund osiągnął wartość 6 to
            {
            dziesiatki_sekund = 0;       // wyzeruj licznik dziesiątek sekund
            }
          }
        }
      }
      t1=jednostki_msekund;
      t2=dziesiatki_msekund;
      t3=jednostki_sekund;
      t4=dziesiatki_sekund;
      }
    }
    
    void pokaz_czas(void){
       AktWysw++;
    
    if(!(PIN(SW) & 1<<SW_2))          //ZATRZYMANIE ODLICZANIA CZASU
    {
         switch(AktWysw){
           case 1:
           {
                PORT(LED)= Liczby[t1];            // na wyświetlaczu wyświetl odpowiedni znak pobrany z pliku znaki.h           
             PORT(SEG) = WSeg[3];            // włącz pierwszą cyfrę wyświetlcza
             break;                         // opuść instrukcję switch
           }
           case 2:
           {
            PORT(LED)= Liczby[t2];
             PORT(SEG) = WSeg[2];
             break;                         // opuść instrukcję switch
           }
        case 3:
         {
             PORT(LED)= Liczby[t3];
             PORT(SEG) = WSeg[1];
             break;                        // opuść instrukcję switch
         }
        case 4:               
         {
             PORT(LED)= Liczby[t4];
             PORT(SEG) = WSeg[0];
             break;                        // opuść instrukcję switch
         }
        case 5:
         {
             AktWysw=0;                // zeruj zmienną AktWysw
             break;                    // opuść instrukcję switch
         }
      }
            r=1;
       
    }
    else {
    switch(AktWysw){
           case 1:
           {
            PORT(LED)= Liczby[jednostki_msekund];
             PORT(SEG) = WSeg[3];
             break;                         // opuść instrukcję switch
           }
           case 2:
           {
            PORT(LED)= Liczby[dziesiatki_msekund];
             PORT(SEG) = WSeg[2];
             break;                         // opuść instrukcję switch
           }
        case 3:
         {
             PORT(LED)= Liczby[jednostki_sekund];
             PORT(SEG) = WSeg[1];
             break;                        // opuść instrukcję switch
         }
        case 4:               
         {
             PORT(LED)= Liczby[dziesiatki_sekund];
             PORT(SEG) = WSeg[0];
             break;                        // opuść instrukcję switch
         }
        case 5:
         {
             AktWysw=0;                // zeruj zmienną AktWysw
             break;                    // opuść instrukcję switch
         }
        }
    }
    }
    
    
                                                     // PRZYCISK RESETU
    void reset(void){
    
        if(!(PIN(SW) & 1<<SW_1))
    {
            jednostki_msekund =  0;
              dziesiatki_msekund = 0;
                     jednostki_sekund = 0;
                 dziesiatki_sekund = 0;
                   
            r=0;
        }
    } 
    



    BARDZO PROSZĘ O POMOC

    Na początku zrobiłem uruchamianie dalszego odliczania czasu przy 2 kliknięciu przycisku SW_2 na zasadzie przycisku RESET

    
    void pauza(void)
    
    {
    
    
    if(PIN(SW) & 1<<SW_2 & r==1)
        {
            r=2;
    
    if(!(PIN(SW) & 1<<SW_2) & r==2)
        {
            r=3;
    
    if(PIN(SW) & 1<<SW_2 & r==3)       
    {
            r=0;
        }
    }
    }
    } 
    
    




    ALE... Nie działa ponieważ z tego co wyczytałem chyba mam problem z tzw. DRGANIEM STYKÓW


    Poprawiłem tytuł - regulamin p.11.1
    [zumek]
  • REKLAMA
  • #2 6135095
    marenc
    Poziom 24  
    http://www.google.pl/ wpisujesz "drganie styków" i naciskasz przycisk "Szczęśliwy traf" ... zgadnij co się wyświetli? Odpowiedź na Twój problem...
  • #3 6135796
    okmijn
    Poziom 2  
    No dobra....

    Rozumiem że muszę np. sprawdzać stan przycisku co kilkadziesiąt ms i jeżeli dwa kolejne sprawdzenia stanu są takie same uznam że klawisz jest wciśnięty a jeżeli wciśnięcie nie zostanie potwierdzone, uznam że klawisz jest puszczony...

    Hmmmmm tylko jak mam to zrobić??? I gdzie to w ogóle wstawić?
  • REKLAMA
  • #4 6135810
    snow
    Poziom 31  
    W którejś obsłudze przerwań od timera. Ew. użyj Timera2 do obsługi klawiszy.
  • #5 6135819
    marenc
    Poziom 24  
    W obsłudze przerwania; w pętli głównej; w podprogramie obsługi klawiatury... jednym słowem tam gdzie jest taka potrzeba.

    Jak zrobić? W rejestrze PINx(x to litera danego portu) masz aktualny stan bitów portu. Odczytując wiesz, czy przycisk wciśnięty.
  • REKLAMA
  • #6 6136211
    okmijn
    Poziom 2  
    marenc napisał:


    Jak zrobić? W rejestrze PINx(x to litera danego portu) masz aktualny stan bitów portu. Odczytując wiesz, czy przycisk wciśnięty.


    Kurde nie czaje...
  • #7 6136289
    marenc
    Poziom 24  
    okmijn napisał:
    Kurde nie czaje...

    Jak napisałeś powyższy kod, skoro nie wiesz najbardziej podstawowej rzeczy? Obsługa portów I/O to rzecz, od której każdy zaczyna!

    
    if(PIN(SW)&(1<<SW_1))
    {
    
    _delay_ms(100);
    
    if(PIN(SW)&(1<<SW_1))
    {
    
    //Wywołanie funkcji obsługa naciśnięcia przycisku
    
    }
    
    }

    Powyższy kod zadziała, jeżeli przyciski podają stan wysoki na wejście. Nie dałeś schematu, nie dałeś deklaracji stałych - kod tylko ilustruje możliwe rozwiązanie, ale nie musi być sprawny!
  • #8 6136411
    okmijn
    Poziom 2  
    Aaaaaa... Nie zrozumiałem... OK

    Tylko że... Ja juz próbowałem coś właśnie takiego wykombinować...

    
    {
    	if(!(PIN(SW) & 1<<SW_2))
    	{
    		_delay_loop_2(0x00ff);
    
    		while(!(PIN(SW) & 1<<SW_2))
    
    			proc();
    	}
    }
    


    No i umie się wysypywało wszystko...
    Ponieważ właśnie raz czas mi startował raz nie...

    Nie wiem właśnie od czego to zależało?
    Wyglądało to tak jakbym raz trafiał z naciśnięciem przycisku a raz nie... Jakby program znajdował się w jakiejs procedurze i sobie cos tam robił a wtedy nacisnięcie przycisku nic nie dawalo...
  • REKLAMA
  • #9 6136442
    marenc
    Poziom 24  
    Na to jest kilka metod... Czekaj na wciśnięcie dowolne(jeżeli zmienna wyzerowana to wywołaj obsługe) i ustaw jakąś zmienną ... Wyzeruj tą zmienną po pewnym czasie.

    Takie rozwiązanie powinno być dobre. Zeruj zmienną conajmniej po 250ms od wykrycia wciśnięcia.
  • #10 6136528
    kolanopan
    Poziom 12  
    marenc napisał:
    Zeruj zmienną co najmniej po 250ms od wykrycia wciśnięcia.


    Fajnie i powinno działać ale traci się trochę z działania stopera, jeśli trzeba mierzyć coś szybkiego co trwa mniej niż 25 setnych?
    Jestem pewien ze każdy kto bawił się stoperem elektronicznym próbował uzyskać jak najmniejszy czas od startu do zatrzymania, coś ala miernik refleksu, jeśli zastosowane by było takie rozwiązanie z flagą i czasem 250ms to taka zabawa jest niemożliwa...
  • #11 6136566
    marenc
    Poziom 24  
    Jeżeli kolega nie jest w stanie napisać obsługi przycisku, to wbijanie mu potrzeby zastosowania przerwań nie ma sensu ;) nieprawdaż? :D
REKLAMA