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.

[Amega16][C]Dziwne zachowanie przycisków.

Kikot 07 Paź 2008 16:27 759 6
  • #1 07 Paź 2008 16:27
    Kikot
    Poziom 9  

    Witam

    Tym razem mam problem z przyciskami nie wiem co się dzieje napisałem ten program już jakiś czas temu i ładnie działał z tego co pamiętam. Teraz mi wariuje, najpierw wkleję kod.

    Code:
    define      P_PORT   PORTD   //Port przyciskow
    
    #define      P_DDR   DDRD   //Kierunek transmisji
    #define    P_PIN   PIND   //Piny przyciskow

    //Porty poszczegolnych przyciskow
    #define      UP      PD0
    #define      DOWN   PD1
    #define      ENTER   PD2
    #define      EXIT   PD3


    Code:
    void Przyciski_start(void)
    
    {
       P_DDR &= ~_BV(UP) & ~_BV(DOWN) & ~_BV(ENTER) & ~_BV(EXIT);   //ustawiamy porty jako wejscai
       P_PORT |= _BV(UP) | _BV(DOWN) | _BV(ENTER) | _BV(EXIT);       //ustawiamy stan wysoki
    }

    char Przycisk(void)
    {
       int w = 0;                              //zmienna sygnalizujaca wcisniecie przycisku   
       if (bit_is_clear(P_PIN, UP))               //sprawdzamy stan na danym pinie, niski wchodzimy dalej
       {
          delay_ms(100);                        //czekamy na uspokojenie drgan stykow
          if (bit_is_clear(P_PIN, UP))            //ponownie sprawdzamy stan na pinie
          {
             w = 1;                           //oznaczamy wcisniecie
             return 'U';                        //zwracamy odpowiedni znak
             P_PORT |= _BV(UP);
          }
       }
       
       if ((bit_is_clear(P_PIN, DOWN)) && (w == 0))   //dodatkowo sprawdzamy wartosc zmiennej w
       {
          delay_ms(100);
          if (bit_is_clear(P_PIN, DOWN))
          {




             w = 1;
             return 'D';
             P_PORT |= _BV(DOWN);
          }
       }
          
       if ((bit_is_clear(P_PIN, ENTER)) && (w == 0))
       {
          delay_ms(100);
          if (bit_is_clear(P_PIN, ENTER))
          {
             w = 1;
             return 'E';
             P_PORT |= _BV(ENTER);
          }
       }
             
       if ((bit_is_clear(P_PIN, EXIT)) && (w == 0))
       {
          delay_ms(100);
          if (bit_is_clear(P_PIN, EXIT))
          {
             w = 1;
             return 'X';
             P_PORT |= _BV(EXIT);
          }
       }
       if (w == 0)
          return 0;
       
    }

    int main()
    {    
       char x;
       LCD_start();
       Przyciski_start();
       while (1)
       {
          x = 0;
          x = Przycisk();
          if (x == 'U')
          {
             LCD_clear();
             LCD_putstr("jo");
          }
          if (x == 'X');
          {
          //   LCD_clear();
             LCD_putstrxy("kicha",1,1);
          }
          delay_ms(100);
       }

    }


    a program zachowuje się tak jak by ciągle wciśnięty był przycisk 'X', 'E' 'D' dobrze reaguje tylko na U. Wyświetla mi non stop "kicha" gdy nacisnę 'U' widać czyszczenie ekranu(mignięcie) a zaraz pojawia się ponownie
    "jo" i "kicha". Czy coś jest nie tak z kodem a może mam źle polutowane przyciski.

    Pozdrawiam

    Poprawiłem tytuł - regulamin 11.1
    [zumek]

    0 6
  • #2 07 Paź 2008 16:36
    Freddie Chopin
    Specjalista - Mikrokontrolery

    ale ten kod jest bezsensownie napisany [; tak czy siak powinno dzialac. mysle ze zanim napisales tego posta to fajnie byloby jednak sprawdzic te przyciski... chyba ze oczekujesz iz bedziemy glosowac czy masz prawo uzywac omomierza...

    4\/3!!

    0
  • #3 07 Paź 2008 16:45
    Kikot
    Poziom 9  

    Dlaczego bezsensownie chodzi ci P_PORT |= _BV(...); w if-ach i o x = 0 w pętli while bo nie wiem co jeszcze może być bezsensownie to dodałem gdy nie wiedziałem co może być tu źle. W pierwszej wersji tego nie było. Oczekiwałem stwierdzenie czy ten program jest ok czy nie i nie oczekuje iż będziecie głosować bo to nie wybory :D

    0
  • #4 07 Paź 2008 16:56
    Freddie Chopin
    Specjalista - Mikrokontrolery

    w obsludze przycisku ta linijka w kazdym z warunkow:

    w = 1;

    jest po prostu bezsensowna - po co ustawiasz zmienna, skoro zaraz za tym wychodzisz z funkcji?

    dalej - procedura jest bezsensownie rozbudowana. wystarczy sprawdzic JEDNA instrukcja, czy wcisniety jest ktorykolwiek przycisk, poczekac ile tam chcesz, potem sprawdz jeszcze raz czy odczytana wartosc jest taka sama, a nastepnie prostym switch'em wybrac ktory to byl i go zwrocic.

    pozatym po co te przyporzadkowania ze ten przycisk to literka U, a tamten to E? tez bezsensu, bo funkcja moglaby po prostu zwracac odczytany stan portu (ewentualnie odwrocone bity, bo przyciski masz widze dolaczajace do masy),a kod glowny by sobie porownywal czy kod ktory dostal odpowiada przyciskowi...

    dalej...

    ciekawi mnie, jak wg ciebie ma sie wykonac to:

    return 'U'; //zwracamy odpowiedni znak
    P_PORT |= _BV(UP);

    ze niby instrukcja return nie opuszcza od razu funkcji? nie mowiac juz o tym ze chcesz niby ustawic stan na porcie ktory jest wejsciowy... ciekawe jak <: to nie jest zadne ustawianie stanu wysokiego, tylko wlaczanie pullupow. ponowne ich wlaczanie... nic nie zmienia.

    dalej:

    && (w == 0)

    to jest porazka <: slyszales o konstrukcji if... else if... else if... ?

    w ogole zmienna w jest zbedna, a obsluga przyciskow wg mnie miesci sie w jakichs 6 linijkach i robi to samo, tylko lepiej.

    x=0 jak juz sam zauwazyles jest bezsensowne.

    pozatym wez mi wytlumacz tak szczerze... czemu jeszcze nie sprawdziles tych przyciskow?

    4\/3!!

    0
  • #5 07 Paź 2008 17:39
    skynet_2
    Poziom 26  

    Cytat:

    ciekawi mnie, jak wg ciebie ma sie wykonac to:

    return 'U'; //zwracamy odpowiedni znak
    P_PORT |= _BV(UP);


    mniej więcej tak :D
    Code:
    +00000055:   9508        RET                      Subroutine return

    i dalej
    Code:
    +00000808:   FFFF        ???                      Data or unknown opcode


    też byłem ciekaw co 'U' zrobi ale żeś był szybszy :D

    Kikot poczytaj sobie http://pl.wikibooks.org/wiki/C
    i dalej http://pl.wikibooks.org/wiki/C/Funkcje#Tworzenie_funkcji

    0
  • #6 07 Paź 2008 19:35
    Kikot
    Poziom 9  

    Czyli coś jak to??

    Code:

    char Przycisk(void)
    {
       char x = 0;
       x = PIND & 0x0F;     //sprawdzam tylko porty przyciskow
       delay_ms(100);
       if ((x != 0x0F) && (x == (PIND & 0x0F)))    //tu sprawdzam czy coś zostało przyciśnięte i czy stan na porcie dalej taki sam
       {
          return (~PIND & 0x0F);   
       }
       else
          return 0;
       
    }


    i w main() sprawdzam czy 1, 2, 4, 8.

    nic tak nie pomaga jak dobra krytyka :)
    Dzięki za odpowiedz


    Jest ok działa, przycisk na porcie PD3 jest walnięty ciągle daje 0 a gdy robię PIND & 0x07 jest ok trzy pozostałe działają jeszcze raz dzięki za pomoc.

    0
  • #7 07 Paź 2008 23:55
    Freddie Chopin
    Specjalista - Mikrokontrolery

    no jest lepiej, ale moze byc jeszcze lepiej.

    x != 0x0F

    zbedne - jesli nic nie zostalo przycisniete to funkcja i tak zwroci (po odpowiednim maskowaniu) same zera. a ze maskowanie jest, to problem z glowy.

    return (~PIND & 0x0F);

    zbedne - wystarczy zwrocic x - w koncu jesli warunek zostal spelniony to x jest wlasnie rowne temu co zwracasz - wystarczy odwracanie wartosci przeniesc na sam poczatek lancucha.

    innymi slowy - odczytujesz odwrocony stan portu (zamaskowanego oczywiscie!) - jesli wcisniete to masz tam jedynke, jesli puszczone, to zero. od razu masz zalatwiona sprawe zwracania zera w przypadku gdy nic nie zostalo nacisniete. potem tylko porownujesz x z tym co odczytasz ponownie (tak samo) i zwracasz x lub 0.

    przypisanie 0 do x'a - po co? jesli optymalizacja ci tego nie usunie, to generujesz tylko bezsensowny kod.

    4\/3!!

    0