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

[MEGA128][C] Przerwania i reset procesora

brodda 07 Lip 2008 17:03 2046 19
REKLAMA
  • #1 5320304
    brodda
    Poziom 13  
    Witam serdecznie,

    Napisałem bardzo prosty program do migania diody oparty na timerze i przerwaniach. Procesor resetuje się w momencie uruchomienia przerwań i zaczyna wszystko od nowa. Jeśli chodzi o zasilanie, układ zasilany jest z akumulatora przy samym procesorze są kondensator 100nF i 4,7uF.

    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    int a,b;
    
    ISR(TIMER2_OVF_vect)
    {	
    	TCNT2 = 0x00;
    	PORTD ^= _BV(PD3);
    }
    
    
    	
    int main (void)
    {
    	
    	
    	DDRD  = 0x08;
    	PORTD |= _BV(PD3);
    	TCCR2 = 0x01;
    	TCNT2 = 0x00;
    	TIMSK = 0x80;
    	sei();
    	while(1); 
    }
    


    O dziwo wczoraj program działał, ale tylko w przypadku wyłączonego preskalera i wartości początkowej równej wyższej 0xCD. Co może być nie tak i dlaczego procesor raz działa a raz nie?
  • REKLAMA
  • REKLAMA
  • #3 5320337
    brodda
    Poziom 13  
    Zamiast przejść z funkcji sei() do pustej pętli i czekać na przerwanie program startuje od nowa. Korzystam z JTAG ICE, program leci krok po kroku.
  • Pomocny post
    #4 5320358
    Balu
    Poziom 38  
    A to jest ciekawe... bo...
    
    20:          TCNT2 = 0x00;
    +0000006C:   BC14        OUT     0x24,R1          Out to I/O location
    21:          TIMSK = 0x80;
    +0000006D:   E880        LDI     R24,0x80         Load immediate
    +0000006E:   BF87        OUT     0x37,R24         Out to I/O location
    22:          sei();
    +0000006F:   9478        SEI                      Global Interrupt Enable
    +00000070:   CFFF        RJMP    PC-0x0000        Relative jump
    +00000071:   94F8        CLI                      Global Interrupt Disable
    +00000072:   CFFF        RJMP    PC-0x0000        Relative jump
    


    Dodano po 5 [minuty]:

    Dobra już wiem :)
    dodaj za while(1) asm("nop");:)
    I już działa:)

    Dodano po 20 [sekundy]:

    (Swoją drogą ciekawe toto, bo nie widziałem takiego cuda wcześniej :) )
  • #5 5320385
    brodda
    Poziom 13  
    Fakt jest to ciekawe, ale w żaden sposób nie mogę z tego wyciągnąć z tego wniosków ani tym bardziej rozwiązać problemu. Dlaczego przerwania "same" się wyłączają?
  • #7 5321205
    brodda
    Poziom 13  
    Po dodaniu pustej instrukcji procesor wiesza się w momencie wystąpienia przerwania...

    Może inny przykład:
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    volatile int a,b;
    
    SIGNAL(SIG_OVERFLOW2)
    {	
    	TCNT2 = 0xCD;
    	a++;
    	if(a == 148)			//milisekunda
    	{
    		a = 0;
    		b++;
    	}
    	if(b == 1000)			//sekunda
    	{
    		b = 0;
    		PORTD &= ~_BV(PD3);
    	}
    	if(b == 25) PORTD |= _BV(PD3);
    }
    
    
    	
    int main (void)
    {
    	DDRD  = 0x08;
    	PORTD |= _BV(PD3);
    	TCCR2 = 0x01;
    	TCNT2 = 0xCD;
    	TIMSK = 0x40;
    	sei();
    	while(1);
    } 
    


    To działa na wewnętrznym kwarcu i na zewnętrznym (14,7 MHz) do momentu zmiany preskalera lub zmniejszeniu wartości początkowej rejestru TCNT2.

    Dziwny przypadek ;/
  • REKLAMA
  • #8 5321257
    Balu
    Poziom 38  
    Którego winavr używasz? Ja mam jakiś najnowszy, jeśli Ty też, może niech ktoś spróbuje starszym skompilować, bo faktycznie jakieś cyrki się robią;/

    Dodano po 24 [sekundy]:

    Dobra nie ten komp... mam wersję 20070525

    Dodano po 2 [minuty]:

    Dobra nie ten komp... mam wersję 20070525..
    Zaraz spróbuje na najnowszej...
    Bo to coś dziwne jest i nie wiem czemu:/
  • REKLAMA
  • #9 5321293
    brodda
    Poziom 13  
    Winavr w wersji 20080610 w starszej tez sie wysypywał...
  • Pomocny post
    #10 5321426
    zumek
    Poziom 39  
    brodda , a co z fusebitem M103C w Twojej M128 :?:

    Piotrek
  • #11 5321431
    Balu
    Poziom 38  
    Ok. Ja nie wiem, poddaje się, przeanalizowałem cały kod, ni chu chu nie wiem czemu nagle coś się wykrzacza i dlaczego:/

    Wygląda jakby gdzieś przez przypadek zdejmował jeden adres za dużo ze stosu *no albo cokolwiek* i robiąc reta wraca nie skąd przyszedł tylko skąd był call do maina, a za tym callem jest nic innego jak... rjmp do cli a potem rjmp do 0.

    Ale nie wiem;/
    Może ZbeeGin albo Zumek rzuci okiem... Bo <załamka>
  • #12 5321479
    brodda
    Poziom 13  
    zumek nie ma znaczenia czy jest włączony czy też nie - reakcja ta sama.

    zauważyłem, że po "resecie" program leci od nowa ale wartości w rejestrach sie nie zerują i timer liczy dalej do momentu wpisania wartości...
  • #14 5327016
    fazolek
    Poziom 12  
    Moim zdaniem sprawa prosta nie deklarujesz iom128.h Jeśli używasz AVR Studio to po włączeniu wybierasz nowy projekt na atmega 128 w avr-gcc w ten sposób dorzucą się biblioteki iom128.h po zapisaniu już w programie #include<avr/io.h>.
    Przypuszczalnie wcześniej robiłeś coś na innym procku i nie zmieniłeś tych bibliotek
    short recipe : lewy górny róg Project->Configuration Options->device: atmega128
    zakładam że tu było coś innego.
    po prostu masz źle zadeklarowanego procka na którym pracujesz w AVR Studio widać to w symulacji osobiście robie wszystko na atmega16 i nie sprawdzę ci tego w żaden sposób ale w symulacji właśnie o to się wykrzaczał
  • #16 5328438
    fazolek
    Poziom 12  
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    volatile int a,b;
    
    SIGNAL(TIMER2_OVF_vect)
    {   
       TCNT2 = 0xCD;
       a++;
       if(a == 148)         //milisekunda
       {
          a = 0;
          b++;
       }
       if(b == 1000)         //sekunda
       {
          b = 0;
          PORTD &= ~_BV(PD3);
       }
       if(b == 25) PORTD |= _BV(PD3);
    }
    
    
       
    int main (void)
    {
       DDRD  = 0x08;
       PORTD |= _BV(PD3);
       TCCR2 = 0x02;
       TCNT2 = 0xCD;
       TIMSK = 0x40;
       sei();
       while(1)
       {PORTA^=0xff;
       }
       return 1;
       
    }
    



    mnie to działa wskakuje do przerwania dla obserwacji dodałem zmiane stanu pełnego portu. Pisze w AVR Studio 4 przy najnowszym avr-gcc.Pamiętam kiedyś miałem problem z tym, chodzi głównie o deklaracje końca stosu bo to właśnie z tego powodu wykrzacza. W asmie dawno nie pisałem (w C wygodniej :)) ale proponuje napisać to samo i daje głowę, że ruszy. Moim zdaniem problem jest tylko i wyłącznie z dołączanymi bibliotekami bo program jest OK w załączniku printscr, że działa

    Porszę używać znaczników [code]
    [zumek]
  • #17 5337036
    AlphaX
    Poziom 12  
    Ja mam podobny problem z ATmega 32 i z przerwaniem od przepelnienia licznika T1. Program caly czas siedzi w przerwaniu nie moze nie z niego wrocic. Kod wyglada mniejwiecej jak ponizej. jezeli w funkcji main w petli while jest printf to program wraca z przerwania. Jezeli wstawie tam np swiecenie diody to program krazy caly czas w przerwaniu. Moze mi ktos wyjasnic o co z tym chodzi?
    
    ISR(SIG_OVERFLOW1)
    { 
    
    	TCNT1 = 0xc2f7;//Wartość początkowa rejestru
    	PORTB |= 0x04;	
    	play_count++;
    	printf("%u,",play_count);
    
    }
    
    void main(void)
    {
    
    .......
    	GICR |= 0xc0;
    
    	sei();	//Włączenie obsługi przerwań
    
    	TIMSK = 0x04;//Włączenie obsługi przerwania od przepełnienia zegara T1
    	TCNT1 = 0xfc18;//Wartość początkowa rejestru
    	TCCR1A = 0x00;
    	TCCR1B = 0x05;//Włączenie zegara f=fosc
    	while(1)
    	{
    		play_count=0;
    
    		//printf("ble");
    	
    
    		
    		while(play_count < 128)
    		{
    			printf("%u,",play_count);                                   
    
    		}
    
    
    		printf("OK");
    			
    	}
    return 0;
    }
    
  • #18 5337778
    AlphaX
    Poziom 12  
    Problem jest chyba z optymalizacją kodu. Przy OPT=2 własnie tak sie dzieje. Jezeli ustwaie OPT=1 wszystko jest OK.
  • #19 5344578
    szelus
    Poziom 34  
    A play_count masz zadeklarowane jako volatile? Jeżeli nie, to się nie dziw...
  • #20 5344680
    BoskiDialer
    Poziom 34  
    Co do pierwszego postu:
    To jest wynik pisania czegoś takiego jak "TIMSK = 0x80;"
    W ten sposób załącza się przerwanie OCIE2:"Timer/Counter2 Output Compare Match Interrupt Enable" a nie TOIE2:"Timer/Counter2 Overflow Interrupt Enable", który jest bit niżej. W symulatorze dokładnie widać, że jest wykonywany nie ten wektor przerwania.
    [MEGA128][C] Przerwania i reset procesora
    Wejście do wektora przerwania który nie ma kodu powoduje skok pod __bad_interrupt, a to powoduje skok pod adres 0, czyli taki jak by programowy reset.
REKLAMA