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

[ATmega8][C] Problem z przyciskiem

m3 01 Lut 2009 00:35 1494 13
REKLAMA
  • #1 6084540
    m3
    Poziom 12  
    Witam, piszę program na Atmega8 i mam problem z przyciskiem. Część kodu zaprezentowałem poniżej. Po przyciśnięciu przycisku na wyświetlaczu pojawiają się kolejne cyfry. Jednak musze przytrzymać przycisk z 2 sekundy żeby zmienna licznik wzrosła o jeden. Jeśli usunę tą druga pętlę if (sprawdzającą czy zmienna sprawdz = 1) wówczas przycisk działa normalnie. Jedno krótkie wciśniecie powoduje zwiększenie licznika... Co robie nie tak? Czy takie pętle inaczej się piszę w main-ie?


    
    int button_is_pressed(void)
    {
    	if(bit_is_clear(PINB, 0))
    	{
    		delay(25);
    		if(bit_is_clear(PINB, 0))
    		{
    		//	delay(50);
    			return 1;
    		}
    	}
    	return 0;
    }
    
    
    int main(void){
    
    ///konfiguracja dla przycisku
     DDRB &= ~_BV(0);
     PORTB |= _BV(0); 
    
    while(1)
    {
    
     if(button_is_pressed())
     {
     	licznik++;
    	itoa(licznik, result, 10);
    	gotox(0x4D);
    	writestr(result);
     }
     
     	if(sprawdz == 1)
    	{
    		// ..............
    
    	}
    } // while
    	return 0;
    } // main


    Dodano po 31 [minuty]:

    dodam że drugi if jest bardzo czasochłonny... w nim ma miejsce odczyt wyniku z czujnika, konwersje itd.
    nie da się skrócić tych czasów, bo tak wymaga producent czujnika...

    przez to cierpi m. in. obsługa przycisku... jak to zrobić żeby jednocześnie była możliwa obsługa czujnika i odczyt z czujnika?
  • REKLAMA
  • #2 6084887
    snow
    Poziom 31  
    Korzystaj z timerów, przerwań jeżeli coś ma być niezależne od głównego programu.
  • REKLAMA
  • #3 6085172
    m3
    Poziom 12  
    A mógłbyś mi to mniej więcej rozpisać, bo nie mam pojęcia jak to zrobić? :(

    Dodano po 3 [minuty]:

    Przyciski są podpięte do PD5, PD6, PD7 oraz PB0 (Atmega8).
  • #4 6085199
    snow
    Poziom 31  
    Podepnij sobie przycisk np. do wejścia INT któregoś i zrób wyzwalanie przerwania na zbocze opadające. Gdy zostanie ono wykryte program zwiększy wartość zmiennej o jeden, np dla INT0

    ISR(SIG_INTERRUPT0)
    {
    licznik++;
    }
  • REKLAMA
  • #5 6085216
    m3
    Poziom 12  
    No ok, a jeśli mam już gotową płytkę i przyciski są podpiętę na stałe do portów tak jak napisałem powyżej, to da się z tego jakoś wykaraskać czy sprawa jest już przegrana? ;/
  • #6 6085238
    snow
    Poziom 31  
    Nie, ale zapewne masz coś nie tak w warunku który wyrzucasz i działa dobrze - niestety co jest nie tak to nie wiadomo, na pewno nie jest to wina linii:

    // ..............


    którą pokazałeś.
  • #7 6085366
    m3
    Poziom 12  
    Chodzi o to że nie chciałem zaciemniać kodu... poniżej wstawiam jeszcze raz kod z brakującą częścią w drugim if-ie.
    
    int button_is_pressed(void)
    {
    	if(bit_is_clear(PINB, 0))
    	{
    		delay(25);
    		if(bit_is_clear(PINB, 0))
    		{
    		//	delay(50);
    			return 1;
    		}
    	}
    	return 0;
    }
    
    int main(void){
    
     unsigned char sprawdz;
     char temp1 = 0, temp2 = 0;
    
    /// RW = 0, mozna jedynie zapisywać dane do LCD
     DDRC |= _BV(RW);
     PORTC &= ~_BV(RW);
    
     delay(100);
    
    ///konfiguracja dla przycisku
     DDRB &= ~_BV(0);
     PORTB |= _BV(0); 
    
     delay(250); // przerwa na wzrost napięcia do 5 V
     initLCD();
    
    while(1)
    {
    
    
     if(button_is_pressed())
     {
     	licznik++;
    	itoa(licznik, result, 10);
    	gotox(0x4D);
    	writestr(result);
     }
     
    
     
     	sprawdz = RESET_PULSE();
     	if(sprawdz == 1)
    	{
    		//
    		RESET_PULSE();
    		send_byte(0xCC);
    		send_byte(0x44);
    		delay(750);
    
    		sprawdz = RESET_PULSE();
    		send_byte(0xCC);
    		send_byte(0xBE);
    
    		temp1 = read_byte(); // odczytanie LSB
    		temp2 = read_byte(); // odczytanie MSB
    
    		sprawdz = RESET_PULSE();
    
    		float temp=0;
    		temp=(float)(temp1+(temp2*256))/16;
    
    		dtostrf(temp, 1, 1, buf); //konwersja float na stringa
    
    		gotox(0x00);
    		writestr("Temp.: ");
    		writestr(buf);
    		delay(250);
    	}
    	else
    	if(sprawdz == 0)
    	{
    		gotox(0x00);
    		writestr("brak czujnika temp.");
    	}
    
    } // while
    	return 0;
    } // main


    Dodano po 1 [minuty]:

    Może chodzi o te delaye w pętli if:

    delay(250);
    delay(750);

    Łacznie trwają przynajmniej sekunde. Jeśli o to chodzi, to jak można by to obejść?
  • #8 6085427
    Freddie Chopin
    Specjalista - Mikrokontrolery
    przeciez juz ci powiedzieli... uzyc przerwan! sprawdzaj w przerwaniu od timera (np co 20ms) stan przyciskow i ewentualnie cos rob jesli masz taki plan. niemniej jednak byloby lepiej wrzucic obsluge tego termometru do przerwan (rowniez od timera)

    4\/3!!
  • #9 6085517
    m3
    Poziom 12  
    nie umiem tego zrobić więc proszę o fragment kodu do obsługi choćby jednego przycisku
  • #10 6085568
    snow
    Poziom 31  
    Dla przerwania np. od timera0:

    ISR(SIG_OVERFLOW0)
    {
    if(wycisnieto przycisk) licznik++;
    }


    oczywiście musisz poustawiać timer (prescaleri TCNTx) tak jak ci potrzeba - szczegóły w PDF'ie w części dotyczącej każdego Timera.
  • REKLAMA
  • #11 6087215
    m3
    Poziom 12  
    Czy chodziło o coś takiego jak poniżej?
    Co myślicie o wartościach:

    TCCR0 = 0x03;
    TCNT0 = 247;
    TIMSK = 1 << TOIE0;

    ??
    Zegar wewnętrzny 1MHz.

    
    #include <avr/interrupt.h>
    
    int button_is_pressed(void)
    {
       if(bit_is_clear(PINB, 0))
       {
          delay(25);
          if(bit_is_clear(PINB, 0))
          {
          //   delay(50);
             return 1;
          }
       }
       return 0;
    }
    
    
    ISR(SIG_OVERFLOW0)
    {
    
     if(button_is_pressed())
     {
     	licznik++;
    	itoa(licznik, result, 10);
    	gotox(0x4D);
    	writestr(result);
     }
    
    }
    
    
    
    int main(void){
    
     unsigned char sprawdz;
     char temp1 = 0, temp2 = 0;
    
    /// RW = 0, mozna jedynie zapisywać dane do LCD
     DDRC |= _BV(RW);
     PORTC &= ~_BV(RW);
    
     delay(100);
    
    ///konfiguracja dla przycisku
     DDRB &= ~_BV(0);
     PORTB |= _BV(0);
    
     delay(250); // przerwa na wzrost napięcia do 5 V
     initLCD();
    
     TCCR0 = 0x03;
     TCNT0 = 247;
     TIMSK = 1 << TOIE0;
     sei();
    
    while(1)
    {
        sprawdz = RESET_PULSE();
        if(sprawdz == 1)
       {
          //
          RESET_PULSE();
          send_byte(0xCC);
          send_byte(0x44);
          delay(750);
    
          sprawdz = RESET_PULSE();
          send_byte(0xCC);
          send_byte(0xBE);
    
          temp1 = read_byte(); // odczytanie LSB
          temp2 = read_byte(); // odczytanie MSB
    
          sprawdz = RESET_PULSE();
    
          float temp=0;
          temp=(float)(temp1+(temp2*256))/16;
    
          dtostrf(temp, 1, 1, buf); //konwersja float na stringa
    
          gotox(0x00);
          writestr("Temp.: ");
          writestr(buf);
          delay(250);
       }
       else
       if(sprawdz == 0)
       {
          gotox(0x00);
          writestr("brak czujnika temp.");
       }
    
    } // while
       return 0;
    } // main
    
  • #12 6087332
    Freddie Chopin
    Specjalista - Mikrokontrolery
    1. wpisales raz wartosc TCNT0 i myslisz ze juz sprawa zalatwiona?

    2. po co ci ta funkcja z oczekiwaniem w przerwaniu? twoje przerwanie juz jest oczekiwaniem - jesli co (np.) 20ms odczytujesz, to zgadnij jaki efekt uzyskasz oczekujac kolejne 25ms w funkcji obslugi przerwwania?

    reszta jest W MIARE ok (chyba), choc powinno byc to zrobione zupelnie inaczej.

    4\/3!!
  • #13 6087443
    m3
    Poziom 12  
    Dodałem drugie TCNT0 na początku przerwania.
    A dałbyś radę mi poprawić to co trzeba, bo już nie mam do tego sił? Dzięki z góry.
  • #14 6087766
    dawid512
    Poziom 32  
    Coś tego typu:
    ISR(SIG_OVERFLOW0)
    { 
    
    TCNT0 = 247;
    
      if(bit_is_clear(PINB, 0))
       { licznik++;
       itoa(licznik, result, 10);
       gotox(0x4D);
       writestr(result); 
       }
    }
REKLAMA