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

[ATmega32][C/AVR-GCC] obsługa przycisku

whisbrakey 19 Gru 2008 12:13 4655 4
REKLAMA
  • #1 5877039
    whisbrakey
    Poziom 2  
    Program po naciśnięciu przycisku ma zmieniać stan diody na przeciwny. Na logikę wydaje się dobry. Ale w praktyce to nie działa. Mógłby ktoś napisać dlaczego?
    Po usunięciu tego fragmentu:
    	
    	_delay_ms(30);
       	 if (bit_is_set(PINB, 2))
    

    Gdy przycisk jest naciśnięty dioda mruga cały czas w rytm owych 30 ms. Nie jestem w stanie zrozumieć dlaczego.

    // główny moduł projektu
    #define _MAIN_MOD_ 1
    #define __AVR_ATmega32__
    #define DIODE PA1
    //włączenie diody
    #define DIODE_OFF (PORTA &=~_BV(DIODE))
    //wyłączenie diody
    #define DIODE_ON (PORTA |=_BV(DIODE))
    //przełączenie diody na stan przeciwny
    #define DIODE_XOR (PORTA ^=_BV(DIODE))
    //taktowanie uC
    #define F_CPU 16E6
    
    // pliki dołączone ( include ) :
    #include <avr/io.h>
    #include <util/delay.h>
    
    
    int main(void)
    {
    
     DDRB=0x00;       // port B jest portem wejściowym
     PORTB=0xff;
     
     DDRA=0xff;       //port A jest portem wejściowym
     PORTA=0x00;
     
     volatile unsigned char i;    // flaga określająca poprzedni stan diody
     
     DIODE_ON; //wstępne włączenie diody
     
     while (1)
     {
    
    if (bit_is_clear(PINB, 2) && (i==0))
    {
       _delay_ms(30);
       if (bit_is_clear(PINB, 2))
       	  {
    		 DIODE_XOR;
       		 i=1;
           }
    }
    if (bit_is_set(PINB,2) && (i=1));
    {	
    //--------------------------------------------------------------------
    	_delay_ms(30);
       	 if (bit_is_set(PINB, 2))
    //--------------------------------------------------------------------
       	  {
       		 i=0;
           }
    }
    }
    }
    
  • REKLAMA
  • #2 5877145
    dawid512
    Poziom 32  
    DDRA=0xff;       //port A jest portem wejściowym 
    wg. mnie wyjściowym.
    volatile unsigned char i;    // flaga określająca poprzedni stan diody 
    nie korzystasz z przerwań więc po co volatile?
    Po za tym po co sprawdzasz poprzedni stan diody skoro stosujesz negacje?

    Wydaje mi się że tego typu warunek w zupełności wystarczy:
    
    if (bit_is_clear(PINB, 2))
    {
     _delay_ms(100);     
    DIODE_XOR;        
           } 
    
    
  • REKLAMA
  • #3 5877252
    whisbrakey
    Poziom 2  
    dawid512 napisał:
    DDRA=0xff;       //port A jest portem wejściowym 
    wg. mnie wyjściowym.

    Oczywiście wyjściowy.

    Cytat:
    Wydaje mi się że tego typu warunek w zupełności wystarczy:
    
    if (bit_is_clear(PINB, 2))
    {
     _delay_ms(100);     
    DIODE_XOR;        
           } 
    
    

    Pzycisk musi być niezawodny, więc takie rozwiązanie odpada. Flagę "i "stosuje po to, aby zapobiec przełączaniu się diody przy dłuższym przytrzymaniu przycisku. Defacto ta flaga nie określa poprzedniego stanu diody, tylko pamięta, czy przycisk był wcześniej naciśnięty, czy nie, więc mój komentarz może być mylący. Poza tym ten warunek, który podałeś nie rozwiązuje problemu eliminacji drgań styków.

    Jeszcze jedno pytanie. Dlaczego wszędzie dla takich flag jak u mnie "i" stosuje się typ unsigned char, a nie np int?
  • REKLAMA
  • Pomocny post
    #4 5877279
    dawid512
    Poziom 32  
    Unsigned char to jeden bajt zaś int nie może być mniejszy niż 2 bajty. Opóźnienie 100ms w warunku eliminuje drgania styków. Dla zabezpieczenia można oczywiście dodać flagę a następnie sprawdzać jej stan w momencie sprawdzania warunku.
  • #5 5877310
    whisbrakey
    Poziom 2  
    a nie powinno to wyglądać tak:

    if (bit_is_clear(PINB, 2))
    {
     _delay_ms(100);  
           if (bit_is_clear(PINB, 2))   
           DIODE_XOR;       
    } 


    Po tych 100 ms musi jeszcze raz sprawdzić, czy przycisk na pewno jest naciśnięty.

    Dodano po 4 [minuty]:

    Dobra już wiem, co miałem źle. Prosty oczywisty błąd:
    zamiast if (bit_is_set(PINB,2) && (i=1));
    powinno być: if (bit_is_set(PINB,2) && (i==1));
    Ehh i problem rozwiązany...
    Dzięki za zainteresowanie!
REKLAMA