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

[Atmega][C][AVR Studio] Pętla w pętli

libed 20 Wrz 2009 17:56 4518 8
REKLAMA
  • #1 7038711
    libed
    Poziom 10  
    Czesc

    Zaczynam zabawe z programowaniem mikrokontrolerow. Na poczatek postanowilem pocwiczyc na uC Atmega8. Programuje go w AVR Studio 4.14 w jezyku C.

    Oczywiscie na pierwszy ogien poszlo zapalanie diod. No i wszystko dziala do momentu kiedy umieszczam pętle w petli:
    
    #include <util/delay.h> 
    #include <avr/io.h>
    
    
    
    void zmiana(){
    unsigned char i;
    i=1;
    	do
    	{
    	PORTB = ~i;
     	_delay_ms(200);
    	i *=2;              //mnozenie przez 2 zapala kolejne diody
    	}while(i<=128);
    }
     int main(void)
    {
    
    unsigned char j;
    
    DDRB = 0xFF; //  port B jako wyjścia
    
    
    for(j=0;j<5;j++)   //petla ktora nie dziala
    zmiana();            // wykonuje sie tylko raz a wedlug mnie powinna 5 razy
    
    return 0;
    }
    



    Ten prosty kod powoduje, ze zapala sie kolejna dioda. Funkcja "zmiana()" dziala ladnie, lecz tylko raz. a przeciez wywolywana jest 5 razy w petli for. Dlaczego tak sie dzieje?
    To samo jest gdy umieszcam jaka kolwiek petle w petli. program wykonuje wszystko tylko w petli najbardziej zagniezdzonej, i przez wszystko przechodzi tylko raz.
    Na poczatku mialem wszystko umieszczone pomiedzy while(1){} lecz prblem taki sam.
  • REKLAMA
  • Pomocny post
    #2 7038832
    SPAWN17
    Poziom 16  
    Gdyż program nie wychodzi z pętli w funkcji. Spróbuj zmienić negację na inne działanie. Powoduje ona błąd. Spróbuj przepisać program do postaci konsolowej i zobacz co zwraca cout. Ciekawy wynik daje też zabawa kalkulatorem w Windowsie.
  • REKLAMA
  • #4 7039768
    libed
    Poziom 10  
    Dzieki

    mieliscie racje na pewno co do, tego ze program nie wychodzil z tej petli.
    nie ma akurat tutaj nic do rzeczy bo to przeciez tylko przypisanie do portu. Chodzilo o typ zmiennej ktora byla licznikiem, zmienilem z char na int. Widocznie petle warunkowe nie sa w stanie porownywac do char'ow.
  • #5 7040178
    maciek_slon
    Poziom 29  
    Są w stanie :-) Po prostu char się przekręcał...

    Po kolei:

    i = 1 -- warunek i <= 128? tak, jedziemy dalej; i*=2 => i = 2;
    //itd itp
    // teraz ważny moment
    i = 128 -- warunek i<= 128? tak, więc następny krok: i*= 2 => 128 * 2 = 256, ale niestety uchar ma zakres 0-255, więc przekręca się na 0 i na owym zerze pozostaje, więc warunek jest zawsze spełniony :-)

    Dodano po 1 [minuty]:

    A, no i oczywiście chodziło mi o to, że to warunek w while nie działał, for działał bez zarzutów ;-)
  • REKLAMA
  • #6 7040332
    libed
    Poziom 10  
    no faktycznie masz racje. co Warszawiak to Warszawiak;P

    To jeszcze mi powiedz jedno. Idac dalej postanowilem napisac maly kalkulator binarny, taki ktory wynik bedzie wyswietlac mi na diodach. Oto kod:
    
    #include <util/delay.h> 
    #include <avr/io.h>
    #include <avr/sfr_defs.h>
    
    
    
    int main(void)
    {
    
    int zmienna1, zmienna2, suma;
    
    
    DDRB = 0xFF; // Ustawiamy port B jako wyjścia
    DDRD = 0x00;
    DDRC = 0xFC;
    
    PORTD = 0xFF;   ///Ustawienie w stan niski
    
    
    zmienna2 = 0x00;
    	while(1){
    	_delay_ms(500);
    	zmienna1 = _SFR_BYTE(PIND); //odczytywanie wartosci z portu/pinu D
    	_delay_ms(500);
    	PORTB = zmienna1;               //wyswietla co podpielismy na porcie D
    
    	if(bit_is_set(PINC, 5))            zatwierdzamy sygnalem na 5 pinie portu C
    	break;                                   wyjscie z petli
    	}
    
    	
    	PORTB = 0xFF;                       //male oddzielenie czasowe od wprowadzania nastepnej liczby
    	_delay_ms(500);                    //mrugniecie diodkami
    	PORTB = 0x00;
    	_delay_ms(500);
    	
    	while(1){
    	zmienna2 = _SFR_BYTE(PIND); //odczytywanie wartosci z portu/pinu D
    	_delay_ms(500);                   //to samo co poprzednio tylko drugi skladnik sumy
    	PORTB = zmienna2;
    
    	if(bit_is_set(PINC, 4))
    	break;
    	}
    
    suma = zmienna1 + zmienna2 ;            <<Sumowanie
    	while(1){
    
    	_delay_ms(500);
    	PORTB = suma;     
    	}
    return 0;
    }




    Dopiero przy testach okazalo sie ze wynik mojego dodawania zawsze jest o 1 za duzy.
    Kiedy dodalem binarnie 1 + 1 wynik wyniosl 11; 10 + 10 = 101...itd
    Dlaczego zapala sie o jedna diode do przodu? po tych testach doszedlem do wniosku ,ze trzeba od wyniku odjac 1 binarnie (stan 0 zapala diode wiec w kodzei jest + a nie - ).
    
    PORTB = suma+1;    
    


    Skad sie bierze ta roznica?
  • Pomocny post
    #7 7040788
    maciek_slon
    Poziom 29  
    No prosta sprawa :P

    Skoro stan '0' zapala diodę, to musisz zanegować odczytane wartości.

    Przykład na przykład:

    Wklepujesz 1+1 -> na porcie dla wklepanej jedynki masz stan taki: 11111110, po dodaniu takich dwóch liczb otrzymujesz wynik: 11111100, a więc zapalają się dwie ostatnie diody i udają, że wynikiem jest trzy :P

    A teraz negujemy:

    ~11111110 + ~11111110 = 00000001 + 00000001 = 00000010, i teraz znowu wynik negujemy -> 11111101 no i zapala nam się jedna dioda, dająca wynik 2 ;-)
  • REKLAMA
  • #8 7040934
    libed
    Poziom 10  
    Faktycznie, znowu racja. Jak ja moglem to przeoczyc, ze na wejsciu mam odwrotnie.
    Dobra masz u mnie pol litra. Dzieki
  • #9 9396392
    tombus
    Poziom 15  
    Niestety, ale muszę odgrzebać stary temat i chyba nie ma potrzeby stawiać nowego tematu.
    Mój problem dotyczy pętel oraz wykonywanych w niej funkcji. Rozkazy w funkcji "trasy()" nie działają. W innych pętlach korzystając już z tablicy trasa1_dd[] otrzymuję same zera. Czy problemem są wiele-zagnieżdżone pętle, czy typ tablic dd[3] i trasa1_dd[3]? Zapewne błąd wynika z mojej niewiedzy lub błędnie skonstruowanych pętel. Załączę fragment kodu:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
REKLAMA